From 6d7fe3271f0d12711639876ab049cd574cf2aeae Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Tue, 24 Mar 2026 04:26:26 +0900 Subject: [PATCH 001/195] fix cursor thing for x11/gdi, also format --- examples/gldemos/cube.c | 116 ++++++++++++++------------- include/Mw/LowLevel/Cocoa.h | 151 +++++++++++++++++------------------ include/Mw/Widget/OpenGL.h | 12 +-- pl/rules.pl | 4 +- src/backend/gdi.c | 2 +- src/backend/x11.c | 2 +- src/widget/opengl_cocoa.m | 155 ++++++++++++++++++------------------ tools/readme.pl | 3 +- 8 files changed, 224 insertions(+), 221 deletions(-) diff --git a/examples/gldemos/cube.c b/examples/gldemos/cube.c index 2d1954c5a..de0b84078 100644 --- a/examples/gldemos/cube.c +++ b/examples/gldemos/cube.c @@ -12,78 +12,82 @@ static double deg = 0; static void draw(void) { - int i; - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + int i; + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glPushMatrix(); - glRotatef(deg, 1, 0, 0); - glRotatef(deg, 0, 1, 0); - glRotatef(deg, 0, 0, 1); + glPushMatrix(); + glRotatef(deg, 1, 0, 0); + glRotatef(deg, 0, 1, 0); + glRotatef(deg, 0, 0, 1); - for (i = 0; i < 6; i++) { - if (i == 0) - glColor3f(1, 0, 0); - if (i == 1) - glColor3f(0, 1, 0); - if (i == 2) - glColor3f(1, 1, 0); - if (i == 3) - glColor3f(0, 0, 1); - if (i == 4) - glColor3f(1, 0, 1); - if (i == 5) - glColor3f(0, 1, 1); + for(i = 0; i < 6; i++) { + if(i == 0) + glColor3f(1, 0, 0); + if(i == 1) + glColor3f(0, 1, 0); + if(i == 2) + glColor3f(1, 1, 0); + if(i == 3) + glColor3f(0, 0, 1); + if(i == 4) + glColor3f(1, 0, 1); + if(i == 5) + glColor3f(0, 1, 1); - glBegin(GL_QUADS); - glNormal3f(0, 1, 0); - glVertex3f(-1, 1, -1); - glVertex3f(-1, 1, 1); - glVertex3f(1, 1, 1); - glVertex3f(1, 1, -1); - glEnd(); + glBegin(GL_QUADS); + glNormal3f(0, 1, 0); + glVertex3f(-1, 1, -1); + glVertex3f(-1, 1, 1); + glVertex3f(1, 1, 1); + glVertex3f(1, 1, -1); + glEnd(); - if (i < 3) - glRotatef(90, 0, 0, 1); - if (i == 3) - glRotatef(90, 1, 0, 0); - if (i == 4) - glRotatef(180, 0, 0, 1); - } - glPopMatrix(); + if(i < 3) + glRotatef(90, 0, 0, 1); + if(i == 3) + glRotatef(90, 1, 0, 0); + if(i == 4) + glRotatef(180, 0, 0, 1); + } + glPopMatrix(); } -static void idle(void) { deg += 1.0; } +static void idle(void) { + deg += 1.0; +} static void reshape(int width, int height) { - GLfloat lpos[4]; + GLfloat lpos[4]; - lpos[0] = 1; - lpos[1] = 1; - lpos[2] = 1; - lpos[3] = 0; + lpos[0] = 1; + lpos[1] = 1; + lpos[2] = 1; + lpos[3] = 0; - glViewport(0, 0, width, height); + glViewport(0, 0, width, height); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluPerspective(60, (double)width / height, 1, 100); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(60, (double)width / height, 1, 100); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - gluLookAt(2, 2, 2, 0, 0, 0, 0, 1, 0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt(2, 2, 2, 0, 0, 0, 0, 1, 0); - glLightfv(GL_LIGHT0, GL_POSITION, lpos); + glLightfv(GL_LIGHT0, GL_POSITION, lpos); } static void init(void) { - glEnable(GL_DEPTH_TEST); - glEnable(GL_LIGHTING); - glEnable(GL_LIGHT0); - glEnable(GL_COLOR_MATERIAL); - glEnable(GL_CULL_FACE); - glEnable(GL_NORMALIZE); + glEnable(GL_DEPTH_TEST); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_COLOR_MATERIAL); + glEnable(GL_CULL_FACE); + glEnable(GL_NORMALIZE); - glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); } -static void key(int k) { (void)k; } +static void key(int k) { + (void)k; +} diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index 19e0bc3c1..7d1b217fe 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -23,9 +23,9 @@ // Note: implements NSApplicationDelegate @interface MilskoCocoaApplicationDelegate : NSObject { - NSApplication *appl; + NSApplication* appl; } -- (MilskoCocoaApplicationDelegate *)initWithAppl:(NSApplication *)appl; +- (MilskoCocoaApplicationDelegate*)initWithAppl:(NSApplication*)appl; @end @interface MilskoCocoaWindow : NSWindow { @@ -34,9 +34,9 @@ // Note: implements NSWindowDelegate @interface MilskoCocoaWindowDelegate : NSObject { - MilskoCocoaWindow *w; + MilskoCocoaWindow* w; } -- (MilskoCocoaWindowDelegate *)initWithWin:(MilskoCocoaWindow *)win; +- (MilskoCocoaWindowDelegate*)initWithWin:(MilskoCocoaWindow*)win; @end /* @@ -52,139 +52,138 @@ retrieved appropriately. */ @interface MilskoFakePointer : NSView { - void *ptr; + void* ptr; } -- (void)setPointer:(void *)ptr; -- (void *)pointer; +- (void)setPointer:(void*)ptr; +- (void*)pointer; @end @interface MilskoCocoaPixmap : NSObject { - MwBool valid; - int width; - int height; - unsigned char *buf; - NSImage *image; - NSBitmapImageRep *rep; + MwBool valid; + int width; + int height; + unsigned char* buf; + NSImage* image; + NSBitmapImageRep* rep; } -+ (MilskoCocoaPixmap *)newWithWidth:(int)width height:(int)height; -- (void)updateWithData:(unsigned char *)data; ++ (MilskoCocoaPixmap*)newWithWidth:(int)width height:(int)height; +- (void)updateWithData:(unsigned char*)data; - (void)destroy; /* using @property to create instance variables fucks up 10.4 gcc for some * reason? */ -- (NSImage *)image; +- (NSImage*)image; @end @interface MilskoCocoaView : NSView { - NSBitmapImageRep *rep; - NSGraphicsContext *context; - MwBool valid; - CGColorSpaceRef space; - CGDataProviderRef provider; - float width; - float height; + NSBitmapImageRep* rep; + NSGraphicsContext* context; + MwBool valid; + CGColorSpaceRef space; + CGDataProviderRef provider; + float width; + float height; } - (void)initRepAndContextWithWidth:(float)w Height:(float)h; -- (NSGraphicsContext *)context; +- (NSGraphicsContext*)context; - (void)destroy; -- (NSBitmapImageRep *)getRep; +- (NSBitmapImageRep*)getRep; @end @interface MilskoCocoa : NSObject { - NSApplication *application; - MwBool _forceRender; - MilskoCocoaWindow *window; - NSRect rect; - MilskoCocoaView *view; - MwLL parent; - MilskoFakePointer *handle; - unsigned int strHash; - NSEvent *lastEvent; + NSApplication* application; + MwBool _forceRender; + MilskoCocoaWindow* window; + NSRect rect; + MilskoCocoaView* view; + MwLL parent; + MilskoFakePointer* handle; + unsigned int strHash; + NSEvent* lastEvent; - MilskoCocoaPixmap *cursorPixmap; - NSCursor *cursor; - NSModalSession modalSession; - - MwBool pointerLocked; - MwBool mouseMoved; + MilskoCocoaPixmap* cursorPixmap; + NSCursor* cursor; + NSModalSession modalSession; + MwBool pointerLocked; + MwBool mouseMoved; } -+ (MilskoCocoa *)newWithParent:(MwLL)parent - x:(int)x - y:(int)y - width:(int)width - height:(int)height - handle:(MwLL)handle; -- (void)polygonWithPoints:(MwPoint *)points - points_count:(int)points_count - color:(MwLLColor)color; -- (void)lineWithPoints:(MwPoint *)points color:(MwLLColor)color; -- (void)getX:(int *)x Y:(int *)y W:(unsigned int *)w H:(unsigned int *)h; ++ (MilskoCocoa*)newWithParent:(MwLL)parent + x:(int)x + y:(int)y + width:(int)width + height:(int)height + handle:(MwLL)handle; +- (void)polygonWithPoints:(MwPoint*)points + points_count:(int)points_count + color:(MwLLColor)color; +- (void)lineWithPoints:(MwPoint*)points color:(MwLLColor)color; +- (void)getX:(int*)x Y:(int*)y W:(unsigned int*)w H:(unsigned int*)h; - (void)setX:(int)x Y:(int)y; - (void)setW:(int)w H:(int)h; - (int)pending; -- (void)eventProcess:(NSEvent *)ev; -- (void)handleKeyEvent:(NSEvent *)ev ll:(MwLL)ll; -- (void)handleMouseEvent:(NSEvent *)ev ll:(MwLL)ll; +- (void)eventProcess:(NSEvent*)ev; +- (void)handleKeyEvent:(NSEvent*)ev ll:(MwLL)ll; +- (void)handleMouseEvent:(NSEvent*)ev ll:(MwLL)ll; - (void)getNextEvent; -- (void)setTitle:(const char *)title; -- (void)drawPixmap:(MwLLPixmap)pixmap rect:(MwRect *)rect; +- (void)setTitle:(const char*)title; +- (void)drawPixmap:(MwLLPixmap)pixmap rect:(MwRect*)rect; - (void)setIcon:(MwLLPixmap)pixmap; - (void)forceRender; -- (void)setCursor:(MwCursor *)image mask:(MwCursor *)mask; -- (void)detachWithPoint:(MwPoint *)point; +- (void)setCursor:(MwCursor*)image mask:(MwCursor*)mask; +- (void)detachWithPoint:(MwPoint*)point; - (void)show:(int)show; - (void)makePopupWithParent:(MwLL)parent; - (void)setSizeHintsWithMinX:(int)minx - MinY:(int)miny - MaxX:(int)maxx - MaxY:(int)maxy; + MinY:(int)miny + MaxX:(int)maxx + MaxY:(int)maxy; - (void)makeBorderless:(int)toggle; - (void)focus; - (void)grabPointer:(int)toggle; -- (void)setClipboard:(const char *)text; +- (void)setClipboard:(const char*)text; - (void)makeToolWindow; -- (void)getCursorCoord:(MwPoint *)point; -- (void)getScreenSize:(MwRect *)rect; +- (void)getCursorCoord:(MwPoint*)point; +- (void)getScreenSize:(MwRect*)rect; - (void)destroy; - (void)sendClipboardEvent; - (MwLL)getParent; -- (NSView *)getView; -- (MilskoCocoaWindow *)getWindow; +- (NSView*)getView; +- (MilskoCocoaWindow*)getWindow; -- (MilskoFakePointer *)getHandle; -+ (void)eventCanceller:(MilskoCocoa *)this; +- (MilskoFakePointer*)getHandle; ++ (void)eventCanceller:(MilskoCocoa*)this; @end #define OBJC(x) x #else -#define OBJC(x) void * +#define OBJC(x) void* #endif MWDECL int MwLLCocoaCallInit(void); struct _MwLLCocoa { - struct _MwLLCommon common; - OBJC(MilskoCocoa *) - real; + struct _MwLLCommon common; + OBJC(MilskoCocoa*) + real; }; struct _MwLLCocoaColor { - struct _MwLLCommonColor common; + struct _MwLLCommonColor common; }; struct _MwLLCocoaPixmap { - struct _MwLLCommonPixmap common; - OBJC(MilskoCocoaPixmap *) - real; + struct _MwLLCommonPixmap common; + OBJC(MilskoCocoaPixmap*) + real; }; #endif diff --git a/include/Mw/Widget/OpenGL.h b/include/Mw/Widget/OpenGL.h index c3fab76ed..3f7a0c451 100644 --- a/include/Mw/Widget/OpenGL.h +++ b/include/Mw/Widget/OpenGL.h @@ -43,7 +43,7 @@ MWDECL MwClass MwOpenGLClass; * @param handle Widget */ MwInline void MwOpenGLMakeCurrent(MwWidget handle) { - MwVaWidgetExecute(handle, "mwOpenGLMakeCurrent", NULL); + MwVaWidgetExecute(handle, "mwOpenGLMakeCurrent", NULL); } /*! @@ -52,10 +52,10 @@ MwInline void MwOpenGLMakeCurrent(MwWidget handle) { * @param name Name * @return Procedure */ -MwInline void *MwOpenGLGetProcAddress(MwWidget handle, const char *name) { - void *out; - MwVaWidgetExecute(handle, "mwOpenGLGetProcAddress", &out, name); - return out; +MwInline void* MwOpenGLGetProcAddress(MwWidget handle, const char* name) { + void* out; + MwVaWidgetExecute(handle, "mwOpenGLGetProcAddress", &out, name); + return out; } /*! @@ -63,7 +63,7 @@ MwInline void *MwOpenGLGetProcAddress(MwWidget handle, const char *name) { * @param handle Widget */ MwInline void MwOpenGLSwapBuffer(MwWidget handle) { - MwVaWidgetExecute(handle, "mwOpenGLSwapBuffer", NULL); + MwVaWidgetExecute(handle, "mwOpenGLSwapBuffer", NULL); } #ifdef __cplusplus diff --git a/pl/rules.pl b/pl/rules.pl index a35a6c3e6..a4ba7bfc8 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -37,7 +37,7 @@ if (grep(/^wayland$/, @backends)) { } scan_wayland_protocol("stable", "xdg-shell", ""); - scan_wayland_protocol("stable", "viewporter", ""); + scan_wayland_protocol("stable", "viewporter", ""); scan_wayland_protocol("stable", "tablet", "-v2"); scan_wayland_protocol("staging", "xdg-toplevel-icon", "-v1"); scan_wayland_protocol("staging", "cursor-shape", "-v1"); @@ -55,7 +55,7 @@ if (grep(/^cocoa$/, @backends)) { new_object("src/widget/opengl_cocoa.m"); } - # tim cook my man literally everybody and their mother who knows what opengl is knows its deprecated on macos and i'm not having you spam the console with this +# tim cook my man literally everybody and their mother who knows what opengl is knows its deprecated on macos and i'm not having you spam the console with this add_cflags("-DGL_SILENCE_DEPRECATION"); $gl_libs = "-framework OpenGL"; diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 4601b79da..d6ad07a53 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -621,7 +621,7 @@ HCURSOR MwLLGDICreateCursor(MwCursor* image, MwCursor* mask) { } } - cursor = CreateCursor(GetModuleHandle(NULL), xs, ys, MwCursorDataHeight, MwCursorDataHeight, dmask, dimage); + cursor = CreateCursor(GetModuleHandle(NULL), xs - image->x, ys + (MwCursorDataHeight + image->y), MwCursorDataHeight, MwCursorDataHeight, dmask, dimage); free(dimage); free(dmask); diff --git a/src/backend/x11.c b/src/backend/x11.c index f7c6fe4bd..cd9e8825f 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -849,7 +849,7 @@ Cursor MwLLX11CreateCursor(Display* display, MwCursor* image, MwCursor* mask) { XPutImage(display, pimage, imagegc, cimage, 0, 0, 0, 0, MwCursorDataHeight, MwCursorDataHeight); XPutImage(display, pmask, maskgc, cmask, 0, 0, 0, 0, MwCursorDataHeight, MwCursorDataHeight); - cur = XCreatePixmapCursor(display, pimage, pmask, &cfg, &cbg, xs, ys); + cur = XCreatePixmapCursor(display, pimage, pmask, &cfg, &cbg, xs - image->x, ys + (MwCursorDataHeight + image->y)); XFreePixmap(display, pimage); XFreePixmap(display, pmask); diff --git a/src/widget/opengl_cocoa.m b/src/widget/opengl_cocoa.m index 503fe5e7b..2397a8473 100644 --- a/src/widget/opengl_cocoa.m +++ b/src/widget/opengl_cocoa.m @@ -7,124 +7,125 @@ #import @interface MacOpenGLWidget : NSObject { - NSOpenGLPixelFormat *pixelFormat; - NSOpenGLContext *glc; - MilskoCocoa *_win; + NSOpenGLPixelFormat* pixelFormat; + NSOpenGLContext* glc; + MilskoCocoa* _win; } -- (MacOpenGLWidget *)initWithWindow:(MilskoCocoa *)w; +- (MacOpenGLWidget*)initWithWindow:(MilskoCocoa*)w; - (void)destroy; - (void)makeCurrent; - (void)swapBuffer; -- (void *)getProcAddressWithName:(const char *)name; +- (void*)getProcAddressWithName:(const char*)name; @end static int create(MwWidget handle) { - void *r = NULL; - MwWidget w = handle; + void* r = NULL; + MwWidget w = handle; - int x = MwGetInteger(w, MwNx); - int y = MwGetInteger(w, MwNy); - int width = MwGetInteger(w, MwNwidth); - int height = MwGetInteger(w, MwNheight); + int x = MwGetInteger(w, MwNx); + int y = MwGetInteger(w, MwNy); + int width = MwGetInteger(w, MwNwidth); + int height = MwGetInteger(w, MwNheight); - printf("%d %d\n", width, height); + printf("%d %d\n", width, height); - handle->internal = - [[MacOpenGLWidget alloc] initWithWindow:handle->lowlevel->cocoa.real]; - handle->lowlevel->common.copy_buffer = 0; + handle->internal = + [[MacOpenGLWidget alloc] initWithWindow:handle->lowlevel->cocoa.real]; + handle->lowlevel->common.copy_buffer = 0; - MwSetDefault(handle); + MwSetDefault(handle); - while (w->parent != NULL) - w = w->parent; + while(w->parent != NULL) + w = w->parent; - w->berserk++; + w->berserk++; - return 0; + return 0; } static void destroy(MwWidget handle) { - [(MacOpenGLWidget *)handle->internal destroy]; + [(MacOpenGLWidget*)handle->internal destroy]; } static void mwOpenGLMakeCurrentImpl(MwWidget handle) { - [(MacOpenGLWidget *)handle->internal makeCurrent]; + [(MacOpenGLWidget*)handle->internal makeCurrent]; } static void mwOpenGLSwapBufferImpl(MwWidget handle) { - [(MacOpenGLWidget *)handle->internal swapBuffer]; + [(MacOpenGLWidget*)handle->internal swapBuffer]; } -static void *mwOpenGLGetProcAddressImpl(MwWidget handle, const char *name) { - return [(MacOpenGLWidget *)handle->internal getProcAddressWithName:name]; +static void* mwOpenGLGetProcAddressImpl(MwWidget handle, const char* name) { + return [(MacOpenGLWidget*)handle->internal getProcAddressWithName:name]; } -static void func_handler(MwWidget handle, const char *name, void *out, - va_list va) { - if (strcmp(name, "mwOpenGLMakeCurrent") == 0) { - mwOpenGLMakeCurrentImpl(handle); - } - if (strcmp(name, "mwOpenGLSwapBuffer") == 0) { - mwOpenGLSwapBufferImpl(handle); - } - if (strcmp(name, "mwOpenGLGetProcAddress") == 0) { - const char *_name = va_arg(va, const char *); - *(void **)out = mwOpenGLGetProcAddressImpl(handle, _name); - } +static void func_handler(MwWidget handle, const char* name, void* out, + va_list va) { + if(strcmp(name, "mwOpenGLMakeCurrent") == 0) { + mwOpenGLMakeCurrentImpl(handle); + } + if(strcmp(name, "mwOpenGLSwapBuffer") == 0) { + mwOpenGLSwapBufferImpl(handle); + } + if(strcmp(name, "mwOpenGLGetProcAddress") == 0) { + const char* _name = va_arg(va, const char*); + *(void**)out = mwOpenGLGetProcAddressImpl(handle, _name); + } } @implementation MacOpenGLWidget -- (MacOpenGLWidget *)initWithWindow:(MilskoCocoa *)w { - NSOpenGLPixelFormatAttribute pixelFormatAttributes[] = { - NSOpenGLPFAColorSize, 24, - NSOpenGLPFAStencilSize, 8, - NSOpenGLPFAAlphaSize, 8, - NSOpenGLPFADoubleBuffer, NSOpenGLPFAAccelerated, - NSOpenGLPFANoRecovery, 0}; - self->pixelFormat = - [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttributes]; - self->glc = - [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil]; - [self->glc setView:[w getView]]; - self->_win = w; - return self; +- (MacOpenGLWidget*)initWithWindow:(MilskoCocoa*)w { + NSOpenGLPixelFormatAttribute pixelFormatAttributes[] = { + NSOpenGLPFAColorSize, 24, + NSOpenGLPFAStencilSize, 8, + NSOpenGLPFAAlphaSize, 8, + NSOpenGLPFADoubleBuffer, NSOpenGLPFAAccelerated, + NSOpenGLPFANoRecovery, 0}; + self->pixelFormat = + [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttributes]; + self->glc = + [[NSOpenGLContext alloc] initWithFormat:pixelFormat + shareContext:nil]; + [self->glc setView:[w getView]]; + self->_win = w; + return self; }; - (void)destroy { }; - (void)makeCurrent { - [self->glc makeCurrentContext]; + [self->glc makeCurrentContext]; }; - (void)swapBuffer { - [self->glc flushBuffer]; + [self->glc flushBuffer]; }; -- (void *)getProcAddressWithName:(const char *)name { - if (NSIsSymbolNameDefined(name)) { - return NSAddressOfSymbol(NSLookupAndBindSymbol(name)); - } else { - return NULL; - } +- (void*)getProcAddressWithName:(const char*)name { + if(NSIsSymbolNameDefined(name)) { + return NSAddressOfSymbol(NSLookupAndBindSymbol(name)); + } else { + return NULL; + } }; @end -MwClassRec MwOpenGLClassRec = {create, /* 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, NULL, NULL, NULL}; -MwClass MwOpenGLClass = &MwOpenGLClassRec; \ No newline at end of file +MwClassRec MwOpenGLClassRec = {create, /* 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, NULL, NULL, NULL}; +MwClass MwOpenGLClass = &MwOpenGLClassRec; \ No newline at end of file diff --git a/tools/readme.pl b/tools/readme.pl index 7070312dd..653184c1b 100755 --- a/tools/readme.pl +++ b/tools/readme.pl @@ -58,8 +58,7 @@ l( l(""); c("Requirements"); l(""); -l( -" Milsko requires either"); +l(" Milsko requires either"); l(" * A Windows environment with GDI (so anything NT or 9x)"); l(" * A MacOS environment with Cocoa (10.4 or above supported)"); l(" * A Unix-like environment with X11 for runtime."); From 6c65e58e372c8a1512910ec5e2a74606077f0d6e Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Tue, 24 Mar 2026 04:27:57 +0900 Subject: [PATCH 002/195] fix --- src/text/text.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/text/text.c b/src/text/text.c index 8d19de838..98849156c 100644 --- a/src/text/text.c +++ b/src/text/text.c @@ -70,8 +70,7 @@ void* MwFontLoad(unsigned char* data, unsigned int size) { } void MwFontFree(void* handle) { - if(MwFLFontFree) - return MwFLFontFree(handle); + if(MwFLFontFree) MwFLFontFree(handle); } static void bitmap_MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color) { From efa6804f46573edcb09689e83f6a09ee41830eab Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 24 Mar 2026 04:34:10 +0900 Subject: [PATCH 003/195] fix math --- src/backend/gdi.c | 4 ++-- src/backend/x11.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/backend/gdi.c b/src/backend/gdi.c index d6ad07a53..5d89419d0 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -589,8 +589,8 @@ HCURSOR MwLLGDICreateCursor(MwCursor* image, MwCursor* mask) { int y, x, ys, xs; xs = -mask->x + image->x; - ys = MwCursorDataHeight + mask->y; - ys = MwCursorDataHeight + image->y - ys; + ys = mask->height + mask->y; + ys = image->height + image->y - ys; memset(dmask, 0xff, (MwCursorDataHeight / 8) * MwCursorDataHeight); memset(dimage, 0, (MwCursorDataHeight / 8) * MwCursorDataHeight); diff --git a/src/backend/x11.c b/src/backend/x11.c index cd9e8825f..de69fffb9 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -811,8 +811,8 @@ Cursor MwLLX11CreateCursor(Display* display, MwCursor* image, MwCursor* mask) { XColor cfg, cbg; xs = -mask->x + image->x; - ys = MwCursorDataHeight + mask->y; - ys = MwCursorDataHeight + image->y - ys; + ys = mask->height + mask->y; + ys = image->height + image->y - ys; memset(cimage->data, 0, cimage->bytes_per_line * cimage->height); memset(cmask->data, 0, cmask->bytes_per_line * cmask->height); From 3d83e0ca64b1092350833bbe5c1d8d6be4024795 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Mon, 23 Mar 2026 12:35:29 -0700 Subject: [PATCH 004/195] wayland: fix cursor --- src/backend/wayland.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 2e32ceda6..611a82c1b 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -2040,7 +2040,7 @@ static void MwLLForceRenderImpl(MwLL handle) { } static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { - int x, y; + int x, y, xs, ys; if(handle->wayland.cursor.setup) { buffer_destroy(&handle->wayland.cursor); @@ -2049,11 +2049,15 @@ static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { buffer_setup(&handle->wayland.cursor, image->width, image->height); memset(handle->wayland.cursor.buf, 0, handle->wayland.cursor.buf_size); + xs = -mask->x + image->x; + ys = MwCursorDataHeight + mask->y; + ys = MwCursorDataHeight + image->y - ys; + for(y = 0; y < mask->height; y++) { unsigned int d = mask->data[y]; for(x = mask->width - 1; x >= 0; x--) { int px = 0; - int idx = ((y * mask->width) + x) * 4; + int idx = (((y + ys) * mask->width) + (x + xs)) * 4; if(d & 1) { handle->wayland.cursor.buf[idx + 3] = 255; @@ -2065,7 +2069,7 @@ static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { unsigned int d = image->data[y]; for(x = image->width - 1; x >= 0; x--) { int px = 0; - int idx = ((y * image->width) + x) * 4; + int idx = (((y + ys) * image->width) + (x + xs)) * 4; if(d & 1) { px = 255; From 56cb0d4841dc44c6916587404244b6f0db25a59e Mon Sep 17 00:00:00 2001 From: Nishi Date: Tue, 24 Mar 2026 04:56:08 +0900 Subject: [PATCH 005/195] wayland: fix cursor --- src/backend/wayland.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 611a82c1b..cb35c2068 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -2050,14 +2050,14 @@ static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { memset(handle->wayland.cursor.buf, 0, handle->wayland.cursor.buf_size); xs = -mask->x + image->x; - ys = MwCursorDataHeight + mask->y; - ys = MwCursorDataHeight + image->y - ys; + ys = mask->height + mask->y; + ys = image->height + image->y - ys; for(y = 0; y < mask->height; y++) { unsigned int d = mask->data[y]; for(x = mask->width - 1; x >= 0; x--) { int px = 0; - int idx = (((y + ys) * mask->width) + (x + xs)) * 4; + int idx = ((y * image->width) + x) * 4; if(d & 1) { handle->wayland.cursor.buf[idx + 3] = 255; @@ -2084,7 +2084,7 @@ static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { handle->wayland.cursor.surface = wl_compositor_create_surface(handle->wayland.compositor); - wl_surface_attach(handle->wayland.cursor.surface, handle->wayland.cursor.shm_buffer, 0, 0); + wl_surface_attach(handle->wayland.cursor.surface, handle->wayland.cursor.shm_buffer, xs + image->x, ys + image->height + image->y); wl_surface_commit(handle->wayland.cursor.surface); /* If there's currently a pointer, set it up. (Otherwise, it'll be setup during the pointer enter event) */ From f4072bcb3f83f29583405650c51c867dfb85d0f6 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 23 Mar 2026 13:38:26 -0700 Subject: [PATCH 006/195] fix clipboard --- examples/basic/clipboard.c | 3 ++- src/backend/wayland.c | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/examples/basic/clipboard.c b/examples/basic/clipboard.c index 57d579256..c792db8ca 100644 --- a/examples/basic/clipboard.c +++ b/examples/basic/clipboard.c @@ -29,7 +29,6 @@ void clipboard(MwWidget handle, void* user_data, void* call_data) { (void)handle; (void)user_data; - printf("got: %s\n", clipboard); if(clipboard != NULL) { MwVaApply(text, MwNtext, clipboard, NULL); MwForceRender(text); @@ -52,6 +51,8 @@ int main() { MwAddUserHandler(window, MwNresizeHandler, resize, NULL); MwAddUserHandler(window, MwNclipboardHandler, clipboard, NULL); + MwAddUserHandler(instructions, MwNclipboardHandler, clipboard, NULL); + MwAddUserHandler(text, MwNclipboardHandler, clipboard, NULL); resize(window, NULL, NULL); diff --git a/src/backend/wayland.c b/src/backend/wayland.c index cb35c2068..2f01c478e 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -228,8 +228,6 @@ static void wl_clipboard_read(wl_clipboard_device_context_t* ctx) { arrpush(buf, 0); close(fds[0]); - printf("sending: %s\n", buf); - MwLLDispatch(ctx->ll, clipboard, buf); arrfree(buf); @@ -470,7 +468,10 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri p.point = self->wayland.cur_mouse_pos; - if(self->wayland.framebuffer.surface == self->wayland.curSurface || self->wayland.backbuffer.surface == self->wayland.curSurface) { + // p.point.x > x && p.point.x < x + self->wayland.ww && p.point.y > y && p.point.y < y + self->wayland.wh + if( + self->wayland.framebuffer.surface == self->wayland.curSurface || + self->wayland.backbuffer.surface == self->wayland.curSurface) { int i; switch(button) { From ea2d62f2e104b76816ef1b916e02ab368a526a83 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 23 Mar 2026 14:28:49 -0700 Subject: [PATCH 007/195] more wayland fixes --- examples/basic/rotate.c | 1 + include/Mw/LowLevel/Wayland.h | 2 ++ src/backend/wayland.c | 36 +++++++++++++++++++++-------------- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/examples/basic/rotate.c b/examples/basic/rotate.c index 574eb2d6f..68c9133bf 100644 --- a/examples/basic/rotate.c +++ b/examples/basic/rotate.c @@ -49,6 +49,7 @@ void resize(MwWidget w, void* user, void* client) { (void)user; (void)client; + printf("H\n"); ww = MwGetInteger(w, MwNwidth); wh = MwGetInteger(w, MwNheight); } diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 00556dada..2a16f50ff 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -144,6 +144,8 @@ struct _MwLLWayland { MwBool detatching; MwPoint detach_point; + MwBool did_initial_resize; + /* Map of Wayland interfaces to their relevant setup functions. */ struct { const char* key; diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 2f01c478e..1588cdf7b 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1165,10 +1165,10 @@ static void region_setup(MwLL handle) { wl_region_add(handle->wayland.region, 0, 0, width, height); } if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { - wl_surface_set_opaque_region(handle->wayland.backbuffer.surface, handle->wayland.region); + wl_surface_set_opaque_region(handle->wayland.backbuffer.surface, handle->wayland.o_region); wl_surface_set_input_region(handle->wayland.backbuffer.surface, handle->wayland.region); } - wl_surface_set_opaque_region(handle->wayland.framebuffer.surface, handle->wayland.region); + wl_surface_set_opaque_region(handle->wayland.framebuffer.surface, handle->wayland.o_region); wl_surface_set_input_region(handle->wayland.framebuffer.surface, handle->wayland.region); } @@ -1249,6 +1249,11 @@ static void setup_toplevel(MwLL r, int x, int y) { return; } + /* 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) { + r->wayland.has_decorations = MwTRUE; + } + r->wayland.toplevel->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); /* Create a wl_surface, a xdg_surface and a xdg_toplevel */ @@ -1282,7 +1287,7 @@ static void setup_toplevel(MwLL r, int x, int y) { } /* setup decorations if we can */ - if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL) { + if(r->wayland.has_decorations) { zxdg_decoration_manager_v1_context_t* dec = WAYLAND_GET_INTERFACE(r->wayland, zxdg_decoration_manager_v1)->context; dec->decoration = zxdg_decoration_manager_v1_get_toplevel_decoration( @@ -1290,15 +1295,12 @@ static void setup_toplevel(MwLL r, int x, int y) { zxdg_toplevel_decoration_v1_set_mode( dec->decoration, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); - - r->wayland.has_decorations = MwTRUE; } else { /* otherwise set up viewporter */ struct wp_viewporter* wp = WAYLAND_GET_INTERFACE(r->wayland, wp_viewporter)->context; r->wayland.vp = wp_viewporter_get_viewport(wp, r->wayland.framebuffer.surface); wp_viewport_set_source(r->wayland.vp, r->wayland.x, r->wayland.y, r->wayland.ww, r->wayland.wh); wp_viewport_set_destination(r->wayland.vp, r->wayland.ww - (CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT), r->wayland.wh - (CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM)); - r->wayland.has_decorations = MwFALSE; wl_subsurface_set_position(r->wayland.toplevel->ssurface, CSD_BORDER_FRAME_LEFT, CSD_BORDER_FRAME_TOP); } @@ -1510,14 +1512,14 @@ static void clip(MwLL handle) { cairo_rectangle(handle->wayland.front_cairo, 0, 0, (parent->wayland.ww + handle->wayland.x), (parent->wayland.wh + handle->wayland.y)); cairo_clip(handle->wayland.front_cairo); } - if(topmost && handle->wayland.type == MWLL_WAYLAND_SUBLEVEL) { - cairo_reset_clip(handle->wayland.front_cairo); - while(topmost->wayland.parent) topmost = topmost->wayland.parent; - left_offset = topmost->wayland.has_decorations ? 0 : (CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT); - top_offset = topmost->wayland.has_decorations ? 0 : (CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM); - cairo_rectangle(handle->wayland.front_cairo, 0, 0, (topmost->wayland.ww + handle->wayland.x) - left_offset, (topmost->wayland.wh + handle->wayland.y) - top_offset); - cairo_clip(handle->wayland.front_cairo); - } + // if(topmost && handle->wayland.type == MWLL_WAYLAND_SUBLEVEL) { + // cairo_reset_clip(handle->wayland.front_cairo); + // while(topmost->wayland.parent) topmost = topmost->wayland.parent; + // left_offset = topmost->wayland.has_decorations ? 0 : (CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT); + // top_offset = topmost->wayland.has_decorations ? 0 : (CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM); + // cairo_rectangle(handle->wayland.front_cairo, 0, 0, (topmost->wayland.ww + handle->wayland.x) - left_offset, (topmost->wayland.wh + handle->wayland.y) - top_offset); + // cairo_clip(handle->wayland.front_cairo); + // } } static void wl_logger(const char* fmt, va_list args) { @@ -1872,6 +1874,12 @@ static int MwLLPendingImpl(MwLL handle) { }; int pending = 0; + if(!handle->wayland.did_initial_resize) { + MwLLDispatch(handle, resize, NULL); + handle->wayland.did_initial_resize = 1; + return 1; + } + if(!handle->wayland.always_render) wl_display_prepare_read(handle->wayland.display); if(!poll(&fd, 1, timeout.tv_nsec)) { wl_display_cancel_read(handle->wayland.display); From 682d84879bea449d76c113831a12ce6b403e1196 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 23 Mar 2026 14:54:36 -0700 Subject: [PATCH 008/195] wayland: cap x/y for viewporter to 0,0 --- src/backend/wayland.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 1588cdf7b..ec82081cf 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1299,7 +1299,7 @@ static void setup_toplevel(MwLL r, int x, int y) { /* otherwise set up viewporter */ struct wp_viewporter* wp = WAYLAND_GET_INTERFACE(r->wayland, wp_viewporter)->context; r->wayland.vp = wp_viewporter_get_viewport(wp, r->wayland.framebuffer.surface); - wp_viewport_set_source(r->wayland.vp, r->wayland.x, r->wayland.y, r->wayland.ww, r->wayland.wh); + wp_viewport_set_source(r->wayland.vp, (r->wayland.x >= 0) ? r->wayland.x : 0, (r->wayland.y >= 0) ? r->wayland.y : 0, r->wayland.ww, r->wayland.wh); wp_viewport_set_destination(r->wayland.vp, r->wayland.ww - (CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT), r->wayland.wh - (CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM)); wl_subsurface_set_position(r->wayland.toplevel->ssurface, CSD_BORDER_FRAME_LEFT, CSD_BORDER_FRAME_TOP); From 8ccf819b572b2591259e83a68c89e650711d6c8c Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 23 Mar 2026 14:56:27 -0700 Subject: [PATCH 009/195] wayland: positive width/height --- src/backend/wayland.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index ec82081cf..f1ad80db3 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1001,7 +1001,11 @@ static void xdg_toplevel_configure(void* data, region_setup(self); if(self->wayland.type == MWLL_WAYLAND_TOPLEVEL && !self->wayland.has_decorations) { - wp_viewport_set_destination(self->wayland.vp, self->wayland.ww - (CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT), self->wayland.wh - (CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM)); + MwU32 vwidth = self->wayland.ww - (CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT); + MwU32 vheight = self->wayland.wh - (CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM); + if(vwidth < 0) vwidth = 0; + if(vheight < 0) vheight = 0; + wp_viewport_set_destination(self->wayland.vp, vwidth, vheight); } MwLLDispatch(self, resize, NULL); @@ -1299,8 +1303,12 @@ static void setup_toplevel(MwLL r, int x, int y) { /* otherwise set up viewporter */ struct wp_viewporter* wp = WAYLAND_GET_INTERFACE(r->wayland, wp_viewporter)->context; r->wayland.vp = wp_viewporter_get_viewport(wp, r->wayland.framebuffer.surface); - wp_viewport_set_source(r->wayland.vp, (r->wayland.x >= 0) ? r->wayland.x : 0, (r->wayland.y >= 0) ? r->wayland.y : 0, r->wayland.ww, r->wayland.wh); - wp_viewport_set_destination(r->wayland.vp, r->wayland.ww - (CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT), r->wayland.wh - (CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM)); + MwU32 vwidth = r->wayland.ww - (CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT); + MwU32 vheight = r->wayland.wh - (CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM); + if(vwidth < 0) vwidth = 0; + if(vheight < 0) vheight = 0; + wp_viewport_set_source(r->wayland.vp, r->wayland.x, r->wayland.y, r->wayland.ww, r->wayland.wh); + wp_viewport_set_destination(r->wayland.vp, vwidth, vheight); wl_subsurface_set_position(r->wayland.toplevel->ssurface, CSD_BORDER_FRAME_LEFT, CSD_BORDER_FRAME_TOP); } From 24ae1c4e11f610d95215939b5d8cd7e77c78be5a Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 23 Mar 2026 15:32:28 -0700 Subject: [PATCH 010/195] wayland: have backbuffer be larger then framebuffer instead of other way around --- src/backend/wayland.c | 63 +++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index f1ad80db3..05b7b927b 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1001,8 +1001,8 @@ static void xdg_toplevel_configure(void* data, region_setup(self); if(self->wayland.type == MWLL_WAYLAND_TOPLEVEL && !self->wayland.has_decorations) { - MwU32 vwidth = self->wayland.ww - (CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT); - MwU32 vheight = self->wayland.wh - (CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM); + MwU32 vwidth = self->wayland.ww; + MwU32 vheight = self->wayland.wh; if(vwidth < 0) vwidth = 0; if(vheight < 0) vheight = 0; wp_viewport_set_destination(self->wayland.vp, vwidth, vheight); @@ -1123,9 +1123,15 @@ static void backbuffer_setup(struct _MwLLWayland* wayland) { if(wayland->type != MWLL_WAYLAND_TOPLEVEL) { return; } - buffer_setup(&wayland->backbuffer, wayland->ww, wayland->wh); + MwU32 w = wayland->ww; + MwU32 h = wayland->wh; + if(!wayland->has_decorations) { + w += (CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT); + h += (CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM); + } + buffer_setup(&wayland->backbuffer, w, h); - wayland->back_cs = cairo_image_surface_create_for_data(wayland->backbuffer.buf, CAIRO_FORMAT_ARGB32, wayland->ww, wayland->wh, 4 * wayland->ww); + wayland->back_cs = cairo_image_surface_create_for_data(wayland->backbuffer.buf, CAIRO_FORMAT_ARGB32, w, h, 4 * w); wayland->back_cairo = cairo_create(wayland->back_cs); memset(wayland->backbuffer.buf, 0, wayland->backbuffer.buf_size); @@ -1301,13 +1307,17 @@ static void setup_toplevel(MwLL r, int x, int y) { dec->decoration, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); } else { /* otherwise set up viewporter */ - struct wp_viewporter* wp = WAYLAND_GET_INTERFACE(r->wayland, wp_viewporter)->context; - r->wayland.vp = wp_viewporter_get_viewport(wp, r->wayland.framebuffer.surface); - MwU32 vwidth = r->wayland.ww - (CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT); - MwU32 vheight = r->wayland.wh - (CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM); + struct wp_viewporter* wp = WAYLAND_GET_INTERFACE(r->wayland, wp_viewporter)->context; + MwI32 x = r->wayland.x; + MwI32 y = r->wayland.y; + MwU32 vwidth = r->wayland.ww; + MwU32 vheight = r->wayland.wh; + r->wayland.vp = wp_viewporter_get_viewport(wp, r->wayland.framebuffer.surface); + if(x < 0) x = 0; + if(y < 0) y = 0; if(vwidth < 0) vwidth = 0; if(vheight < 0) vheight = 0; - wp_viewport_set_source(r->wayland.vp, r->wayland.x, r->wayland.y, r->wayland.ww, r->wayland.wh); + wp_viewport_set_source(r->wayland.vp, wl_fixed_from_int(x), wl_fixed_from_int(y), wl_fixed_from_int(r->wayland.ww), wl_fixed_from_int(r->wayland.wh)); wp_viewport_set_destination(r->wayland.vp, vwidth, vheight); wl_subsurface_set_position(r->wayland.toplevel->ssurface, CSD_BORDER_FRAME_LEFT, CSD_BORDER_FRAME_TOP); @@ -1678,14 +1688,7 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { handle->wayland.wh = 10; goto refresh; } - if(handle->wayland.parent) { - if(handle->wayland.parent->wayland.type == MWLL_WAYLAND_TOPLEVEL && !handle->wayland.parent->wayland.has_decorations) { - if(w >= handle->wayland.parent->wayland.ww - (CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT)) - w = handle->wayland.parent->wayland.ww - (CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT); - if(h >= handle->wayland.parent->wayland.wh - (CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM)) - h = handle->wayland.parent->wayland.wh - (CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM); - } - } + handle->wayland.ww = w; handle->wayland.wh = h; @@ -1719,34 +1722,36 @@ static void MwLLBeginDrawImpl(MwLL handle) { return; } if(!handle->wayland.has_decorations) { - int x, y; + int x, y; + MwU32 w = handle->wayland.ww + CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT; + MwU32 h = handle->wayland.wh + CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM; cairo_set_line_width(handle->wayland.back_cairo, 4.0); - for(x = 0; x < handle->wayland.ww; x++) { - float placeholder = (float)x / (float)handle->wayland.ww; + for(x = 0; x < w; x++) { + float placeholder = (float)x / (float)w; cairo_set_source_rgb(handle->wayland.back_cairo, placeholder, 0.25, 0.25); - cairo_move_to(handle->wayland.back_cairo, handle->wayland.ww - x, 0); - cairo_line_to(handle->wayland.back_cairo, handle->wayland.ww - x, CSD_BORDER_FRAME_TOP); + cairo_move_to(handle->wayland.back_cairo, w - x, 0); + cairo_line_to(handle->wayland.back_cairo, w - x, CSD_BORDER_FRAME_TOP); cairo_stroke(handle->wayland.back_cairo); cairo_move_to(handle->wayland.back_cairo, x, CSD_BORDER_FRAME_TOP); - cairo_line_to(handle->wayland.back_cairo, x, handle->wayland.wh); + cairo_line_to(handle->wayland.back_cairo, x, h); cairo_stroke(handle->wayland.back_cairo); } cairo_set_source_rgba(handle->wayland.back_cairo, 1, 1, 1, 0.5); cairo_move_to(handle->wayland.back_cairo, 0, 0); - cairo_line_to(handle->wayland.back_cairo, 0, handle->wayland.wh); + cairo_line_to(handle->wayland.back_cairo, 0, h); cairo_stroke(handle->wayland.back_cairo); cairo_move_to(handle->wayland.back_cairo, 0, 0); - cairo_line_to(handle->wayland.back_cairo, handle->wayland.ww, 0); + cairo_line_to(handle->wayland.back_cairo, w, 0); cairo_stroke(handle->wayland.back_cairo); cairo_set_source_rgba(handle->wayland.back_cairo, 0, 0, 0, 0.5); - cairo_move_to(handle->wayland.back_cairo, 0, handle->wayland.wh); - cairo_line_to(handle->wayland.back_cairo, handle->wayland.ww, handle->wayland.wh); + cairo_move_to(handle->wayland.back_cairo, 0, h); + cairo_line_to(handle->wayland.back_cairo, w, h); cairo_stroke(handle->wayland.back_cairo); - cairo_move_to(handle->wayland.back_cairo, handle->wayland.ww, 0); - cairo_line_to(handle->wayland.back_cairo, handle->wayland.ww, handle->wayland.wh); + cairo_move_to(handle->wayland.back_cairo, w, 0); + cairo_line_to(handle->wayland.back_cairo, w, h); cairo_stroke(handle->wayland.back_cairo); if(strlen(handle->wayland.title) != 0) { From d4913576358f14d6431e603a78d27377d2940212 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 23 Mar 2026 15:45:48 -0700 Subject: [PATCH 011/195] wayland: csd fixes --- src/backend/wayland.c | 45 ++++++++++++++----------------------------- 1 file changed, 14 insertions(+), 31 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 05b7b927b..9a2ca75a7 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -203,7 +203,7 @@ static void wl_clipboard_read(wl_clipboard_device_context_t* ctx) { if(ctx->ll->wayland.supports_zwp) { zwp_primary_selection_offer_v1_receive(ctx->offer.zwp, "text/plain", fds[1]); - } else { + } else if(ctx->offer.wl) { wl_data_offer_receive(ctx->offer.wl, "text/plain", fds[1]); } close(fds[1]); @@ -395,19 +395,19 @@ static void pointer_leave(void* data, struct wl_pointer* wl_pointer, MwU32 seria static void xdg_borderless_step(MwLL self, MwLLMouse p, MwU32 serial) { if(self->wayland.type == MWLL_WAYLAND_TOPLEVEL && self->wayland.backbuffer.surface == self->wayland.curSurface) { - if(p.point.y >= self->wayland.wh - 5) { - if(p.point.x >= self->wayland.ww - 5) { + if(p.point.y >= (self->wayland.wh + CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM) - 5) { + if(p.point.x >= (self->wayland.ww + CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT) - 5) { xdg_toplevel_resize(self->wayland.toplevel->xdg_top_level, self->wayland.pointer_seat, serial, XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT); } else { xdg_toplevel_resize(self->wayland.toplevel->xdg_top_level, self->wayland.pointer_seat, serial, XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM); } } else if(p.point.y <= 5) { - if(p.point.x >= self->wayland.ww - 5) { + if(p.point.x >= (self->wayland.ww + CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT) - 5) { xdg_toplevel_resize(self->wayland.toplevel->xdg_top_level, self->wayland.pointer_seat, serial, XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT); } else { xdg_toplevel_resize(self->wayland.toplevel->xdg_top_level, self->wayland.pointer_seat, serial, XDG_TOPLEVEL_RESIZE_EDGE_TOP); } - } else if(p.point.x >= self->wayland.ww - 5) { + } else if(p.point.x >= (self->wayland.ww + CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT) - 5) { xdg_toplevel_resize(self->wayland.toplevel->xdg_top_level, self->wayland.pointer_seat, serial, XDG_TOPLEVEL_RESIZE_EDGE_RIGHT); } else if(p.point.x <= 5) { xdg_toplevel_resize(self->wayland.toplevel->xdg_top_level, self->wayland.pointer_seat, serial, XDG_TOPLEVEL_RESIZE_EDGE_LEFT); @@ -1000,14 +1000,6 @@ static void xdg_toplevel_configure(void* data, framebuffer_setup(&self->wayland); region_setup(self); - if(self->wayland.type == MWLL_WAYLAND_TOPLEVEL && !self->wayland.has_decorations) { - MwU32 vwidth = self->wayland.ww; - MwU32 vheight = self->wayland.wh; - if(vwidth < 0) vwidth = 0; - if(vheight < 0) vheight = 0; - wp_viewport_set_destination(self->wayland.vp, vwidth, vheight); - } - MwLLDispatch(self, resize, NULL); MwLLDispatch(self, draw, NULL); }; @@ -1171,9 +1163,15 @@ static void region_setup(MwLL handle) { if(height - handle->wayland.y > parent->wayland.wh) { height = parent->wayland.wh - handle->wayland.y; } + } else { + if(!handle->wayland.has_decorations) { + width += CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT; + height += CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM; + } } wl_region_add(handle->wayland.region, 0, 0, width, height); } + if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { wl_surface_set_opaque_region(handle->wayland.backbuffer.surface, handle->wayland.o_region); wl_surface_set_input_region(handle->wayland.backbuffer.surface, handle->wayland.region); @@ -1306,20 +1304,6 @@ static void setup_toplevel(MwLL r, int x, int y) { zxdg_toplevel_decoration_v1_set_mode( dec->decoration, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); } else { - /* otherwise set up viewporter */ - struct wp_viewporter* wp = WAYLAND_GET_INTERFACE(r->wayland, wp_viewporter)->context; - MwI32 x = r->wayland.x; - MwI32 y = r->wayland.y; - MwU32 vwidth = r->wayland.ww; - MwU32 vheight = r->wayland.wh; - r->wayland.vp = wp_viewporter_get_viewport(wp, r->wayland.framebuffer.surface); - if(x < 0) x = 0; - if(y < 0) y = 0; - if(vwidth < 0) vwidth = 0; - if(vheight < 0) vheight = 0; - wp_viewport_set_source(r->wayland.vp, wl_fixed_from_int(x), wl_fixed_from_int(y), wl_fixed_from_int(r->wayland.ww), wl_fixed_from_int(r->wayland.wh)); - wp_viewport_set_destination(r->wayland.vp, vwidth, vheight); - wl_subsurface_set_position(r->wayland.toplevel->ssurface, CSD_BORDER_FRAME_LEFT, CSD_BORDER_FRAME_TOP); } } @@ -1692,10 +1676,6 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { handle->wayland.ww = w; handle->wayland.wh = h; - // if(handle->wayland.wh >= (CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM)) { - // handle->wayland.wh -= (CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM); - // } - if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL && handle->wayland.configured) { xdg_surface_set_window_geometry(handle->wayland.toplevel->xdg_surface, 0, 0, handle->wayland.ww, handle->wayland.wh); } @@ -1714,6 +1694,8 @@ refresh: backbuffer_destroy(&handle->wayland); backbuffer_setup(&handle->wayland); MwLLDispatch(handle, draw, NULL); + + handle->wayland.events_pending = 1; } static void MwLLBeginDrawImpl(MwLL handle) { @@ -1721,6 +1703,7 @@ static void MwLLBeginDrawImpl(MwLL handle) { handle->wayland.selected_cairo = handle->wayland.front_cairo; return; } + if(!handle->wayland.has_decorations) { int x, y; MwU32 w = handle->wayland.ww + CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT; From b9933b70e254eacc0de932112950b50293f35a3d Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 23 Mar 2026 15:56:01 -0700 Subject: [PATCH 012/195] wayland: on resize, fire draw before resize --- src/backend/wayland.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 9a2ca75a7..dbb2bd28d 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1000,8 +1000,8 @@ static void xdg_toplevel_configure(void* data, framebuffer_setup(&self->wayland); region_setup(self); - MwLLDispatch(self, resize, NULL); MwLLDispatch(self, draw, NULL); + MwLLDispatch(self, resize, NULL); }; /* Empty function for satisfying zxdg_toplevel's requirements */ From 5e823b5a25782b0dfe151e77e2e4cee373e10e48 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Mon, 23 Mar 2026 19:30:21 -0700 Subject: [PATCH 013/195] wayland: gl improvements --- src/backend/wayland.c | 4 ++-- src/widget/opengl.c | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index dbb2bd28d..dab1a1b0a 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -441,13 +441,13 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time MwLL topmost = self->wayland.parent; while(topmost->wayland.parent) topmost = topmost->wayland.parent; /* also we only wanna do it every 50ms */ - if((self->wayland.last_time + 50) <= time && !topmost->wayland.events_pending) { + if((self->wayland.last_time + 50) <= time && !topmost->wayland.events_pending && !topmost->wayland.always_render) { MwLLDispatch(self, draw, NULL); self->wayland.last_time = time; } } else { /* if there's no parent just impose the requirement on the widget itself */ - if((self->wayland.last_time + 50) <= time && !self->wayland.events_pending) { + if((self->wayland.last_time + 50) <= time && !self->wayland.events_pending && !self->wayland.always_render) { MwLLDispatch(self, draw, NULL); self->wayland.last_time = time; } diff --git a/src/widget/opengl.c b/src/widget/opengl.c index 6d67344ce..7d685ada6 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -168,11 +168,10 @@ static int create(MwWidget handle) { waylandopengl_t* o = r = malloc(sizeof(*o)); MwLL topmost_parent = handle->lowlevel->wayland.parent; handle->lowlevel->wayland.always_render = MwTRUE; - topmost_parent->wayland.always_render = MwTRUE; while(topmost_parent->wayland.parent != NULL) { - topmost_parent = topmost_parent->wayland.parent; topmost_parent->wayland.always_render = MwTRUE; + topmost_parent = topmost_parent->wayland.parent; } display = From 57609f182388abc17f8d218c1e020ecbf90336c7 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 24 Mar 2026 13:31:49 -0700 Subject: [PATCH 014/195] fire a draw/resize event manually to children when resizing --- examples/basic/rotate.c | 1 - src/backend/wayland.c | 72 +++++++++++++++++++++++++++++++++++------ 2 files changed, 63 insertions(+), 10 deletions(-) diff --git a/examples/basic/rotate.c b/examples/basic/rotate.c index 68c9133bf..574eb2d6f 100644 --- a/examples/basic/rotate.c +++ b/examples/basic/rotate.c @@ -49,7 +49,6 @@ void resize(MwWidget w, void* user, void* client) { (void)user; (void)client; - printf("H\n"); ww = MwGetInteger(w, MwNwidth); wh = MwGetInteger(w, MwNheight); } diff --git a/src/backend/wayland.c b/src/backend/wayland.c index dab1a1b0a..b2bbe8f94 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -98,6 +98,51 @@ static void wl_flush(MwLL handle) { } } +/* Recursively dispatch a draw event to a widget and its children */ +static void recursive_dispatch_draw_n_resize(MwLL handle) { + MwWidget h = (MwWidget)handle->common.user; + MwLLDispatch(handle, draw, NULL); + MwLLDispatch(handle, resize, NULL); + if(h) { + int i; + for(i = 0; i < arrlen(h->children); i++) { + MwDispatch(h->children[i], draw); + MwDispatch(h->children[i], resize); + if(arrlen(h->children[i]->children) > 0) { + recursive_dispatch_draw_n_resize(h->children[i]->lowlevel); + } + } + } +}; + +/* 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, struct wl_data_offer* wl_data_offer, const char* mime_type) { @@ -424,6 +469,8 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time wl_fixed_t surface_x, wl_fixed_t surface_y) { MwLL self = data; MwLLMouse p; + int i = 0; + MwWidget h = (MwWidget)self->common.user; WAYLAND_EVENT_OP_START(self); @@ -680,9 +727,9 @@ static void keyboard_key(void* data, } if(state == WL_KEYBOARD_KEY_STATE_PRESSED) { - MwLLDispatch(self, key, &key); + recursive_dispatch_key(self, &key); } else { - MwLLDispatch(self, key_released, &key); + recursive_dispatch_key_released(self, &key); } } } @@ -970,8 +1017,9 @@ static void xdg_toplevel_configure(void* data, struct xdg_toplevel* xdg_toplevel, MwI32 width, MwI32 height, struct wl_array* states) { - MwLL self = data; - int i; + MwLL self = data; + int i; + MwWidget h = ((MwWidget)self->common.user); /* Yes, somehow this can get called before */ if(!self->wayland.configured) { @@ -1000,8 +1048,7 @@ static void xdg_toplevel_configure(void* data, framebuffer_setup(&self->wayland); region_setup(self); - MwLLDispatch(self, draw, NULL); - MwLLDispatch(self, resize, NULL); + recursive_dispatch_draw_n_resize(self); }; /* Empty function for satisfying zxdg_toplevel's requirements */ @@ -1652,6 +1699,9 @@ static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsign } static void MwLLSetXYImpl(MwLL handle, int x, int y) { + int i = 0; + MwWidget h = (MwWidget)handle->common.user; + region_invalidate(handle); handle->wayland.x = x; handle->wayland.y = y; @@ -1664,6 +1714,8 @@ static void MwLLSetXYImpl(MwLL handle, int x, int y) { } static void MwLLSetWHImpl(MwLL handle, int w, int h) { + int i = 0; + MwWidget widget = (MwWidget)handle->common.user; region_invalidate(handle); /* Prevent an integer underflow when the w/h is too low */ @@ -1694,7 +1746,6 @@ refresh: backbuffer_destroy(&handle->wayland); backbuffer_setup(&handle->wayland); MwLLDispatch(handle, draw, NULL); - handle->wayland.events_pending = 1; } @@ -1871,7 +1922,7 @@ static int MwLLPendingImpl(MwLL handle) { int pending = 0; if(!handle->wayland.did_initial_resize) { - MwLLDispatch(handle, resize, NULL); + recursive_dispatch_draw_n_resize(handle); handle->wayland.did_initial_resize = 1; return 1; } @@ -1901,6 +1952,7 @@ static int MwLLPendingImpl(MwLL handle) { } static void MwLLNextEventImpl(MwLL handle) { + int i = 0; if(!handle->wayland.always_render) { if(handle->wayland.did_event_loop_early) { handle->wayland.did_event_loop_early = MwFALSE; @@ -1910,7 +1962,9 @@ static void MwLLNextEventImpl(MwLL handle) { } if(handle->wayland.force_render) { - if(!handle->wayland.events_pending) MwLLDispatch(handle, draw, NULL); + if(!handle->wayland.events_pending) { + MwLLDispatch(handle, draw, NULL); + } if(handle->wayland.configured) update_buffer(&handle->wayland.framebuffer); handle->wayland.force_render = 0; } From 1ad75eca90e76ba44c73fd691f84e00d031f1859 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 24 Mar 2026 14:41:20 -0700 Subject: [PATCH 015/195] only draw on the parent and resize on the child in draw_n_resize --- src/backend/wayland.c | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index b2bbe8f94..8d39d6b97 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -102,11 +102,9 @@ static void wl_flush(MwLL handle) { static void recursive_dispatch_draw_n_resize(MwLL handle) { MwWidget h = (MwWidget)handle->common.user; MwLLDispatch(handle, draw, NULL); - MwLLDispatch(handle, resize, NULL); if(h) { int i; for(i = 0; i < arrlen(h->children); i++) { - MwDispatch(h->children[i], draw); MwDispatch(h->children[i], resize); if(arrlen(h->children[i]->children) > 0) { recursive_dispatch_draw_n_resize(h->children[i]->lowlevel); @@ -483,23 +481,6 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time MwLLDispatch(currentlyHeldWidget, down, &p); } - /* We want to send a draw call whenever we move the cursor, BUT only if the topmost parent doesn't already have events pedngin. */ - if(self->wayland.parent) { - MwLL topmost = self->wayland.parent; - while(topmost->wayland.parent) topmost = topmost->wayland.parent; - /* also we only wanna do it every 50ms */ - if((self->wayland.last_time + 50) <= time && !topmost->wayland.events_pending && !topmost->wayland.always_render) { - MwLLDispatch(self, draw, NULL); - self->wayland.last_time = time; - } - } else { - /* if there's no parent just impose the requirement on the widget itself */ - if((self->wayland.last_time + 50) <= time && !self->wayland.events_pending && !self->wayland.always_render) { - MwLLDispatch(self, draw, NULL); - self->wayland.last_time = time; - } - } - WAYLAND_EVENT_OP_END(self); }; From 9a23045c30b40e21ea621fce93612ec43d2ffdb2 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 24 Mar 2026 14:43:38 -0700 Subject: [PATCH 016/195] change draw_n_resize to just resize --- src/backend/wayland.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 8d39d6b97..37a1f29e1 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -99,15 +99,14 @@ static void wl_flush(MwLL handle) { } /* Recursively dispatch a draw event to a widget and its children */ -static void recursive_dispatch_draw_n_resize(MwLL handle) { +static void recursive_dispatch_resize(MwLL handle) { MwWidget h = (MwWidget)handle->common.user; - MwLLDispatch(handle, draw, NULL); if(h) { int i; for(i = 0; i < arrlen(h->children); i++) { MwDispatch(h->children[i], resize); if(arrlen(h->children[i]->children) > 0) { - recursive_dispatch_draw_n_resize(h->children[i]->lowlevel); + recursive_dispatch_resize(h->children[i]->lowlevel); } } } @@ -1028,8 +1027,10 @@ static void xdg_toplevel_configure(void* data, framebuffer_destroy(&self->wayland); framebuffer_setup(&self->wayland); region_setup(self); + MwLLDispatch(self, resize, NULL); - recursive_dispatch_draw_n_resize(self); + MwLLDispatch(self, draw, NULL); + recursive_dispatch_resize(self); }; /* Empty function for satisfying zxdg_toplevel's requirements */ @@ -1903,7 +1904,7 @@ static int MwLLPendingImpl(MwLL handle) { int pending = 0; if(!handle->wayland.did_initial_resize) { - recursive_dispatch_draw_n_resize(handle); + recursive_dispatch_resize(handle); handle->wayland.did_initial_resize = 1; return 1; } From e86d6acdf37037c5f9445f884c0c5c9286d2713e Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 24 Mar 2026 14:52:53 -0700 Subject: [PATCH 017/195] we can just draw even if events are pending --- src/backend/wayland.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 37a1f29e1..2b581c693 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -535,10 +535,6 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri } } - if(!self->wayland.always_render) { - MwLLDispatch(self, draw, NULL); - } - if(!self->wayland.has_decorations) { xdg_borderless_step(self, p, serial); } @@ -1894,7 +1890,7 @@ static void MwLLFreeColorImpl(MwLLColor color) { static int MwLLPendingImpl(MwLL handle) { struct timespec timeout = { - .tv_nsec = 100, + .tv_nsec = 1, .tv_sec = 0, }; struct pollfd fd = { @@ -1906,7 +1902,6 @@ static int MwLLPendingImpl(MwLL handle) { if(!handle->wayland.did_initial_resize) { recursive_dispatch_resize(handle); handle->wayland.did_initial_resize = 1; - return 1; } if(!handle->wayland.always_render) wl_display_prepare_read(handle->wayland.display); @@ -1925,9 +1920,9 @@ static int MwLLPendingImpl(MwLL handle) { return pending; } - wl_surface_commit(handle->wayland.framebuffer.surface); + update_buffer(&handle->wayland.framebuffer); if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { - wl_surface_commit(handle->wayland.backbuffer.surface); + update_buffer(&handle->wayland.backbuffer); } return handle->wayland.force_render || handle->wayland.events_pending || pending; @@ -1944,9 +1939,9 @@ static void MwLLNextEventImpl(MwLL handle) { } if(handle->wayland.force_render) { - if(!handle->wayland.events_pending) { - MwLLDispatch(handle, draw, NULL); - } + // if(!handle->wayland.events_pending) { + MwLLDispatch(handle, draw, NULL); + // } if(handle->wayland.configured) update_buffer(&handle->wayland.framebuffer); handle->wayland.force_render = 0; } From 47746ff30e6fa5ef41cd6dbe1bb7caa0731b048d Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 24 Mar 2026 17:38:21 -0700 Subject: [PATCH 018/195] dynamically load wayland and its dependencies, fix warnings --- include/Mw/LowLevel/Wayland.h | 275 ++++++++++++++++++++++++++++++++-- pl/rules.pl | 5 +- pl/utils.pl | 29 ++++ src/backend/wayland.c | 192 +++++++++++++++++------- src/widget/opengl.c | 95 +++++++++++- 5 files changed, 522 insertions(+), 74 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 2a16f50ff..a6f225437 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -7,22 +7,279 @@ #ifndef __MW_LOWLEVEL_WAYLAND_H__ #define __MW_LOWLEVEL_WAYLAND_H__ -#include "Mw/BaseTypes.h" #include #include #include +#include -#include - -#include #include #include #include MWDECL int MwLLWaylandCallInit(void); +#define CSD_BORDER_FRAME_LEFT 5 +#define CSD_BORDER_FRAME_RIGHT 5 +#define CSD_BORDER_FRAME_TOP 24 +#define CSD_BORDER_FRAME_BOTTOM 5 + +struct _MwLLWayland; + +#include + +#if WAYLAND_LOAD_OPENGL +#include +#include +#endif + +typedef struct wayland_call_table { + void* lib; + void* xkb_lib; + void* cairo_lib; +#if WAYLAND_LOAD_OPENGL +#endif + + int (*wl_display_dispatch_pending)(struct wl_display* display); + void (*wl_display_disconnect)(struct wl_display* display); + void (*wl_display_cancel_read)(struct wl_display* display); + int (*wl_display_prepare_read)(struct wl_display* display); + int (*wl_display_read_events)(struct wl_display* display); + int (*wl_display_flush)(struct wl_display* display); + int (*wl_display_get_fd)(struct wl_display* display); + int (*wl_display_roundtrip)(struct wl_display* display); + int (*wl_proxy_add_listener)(struct wl_proxy* proxy, void (**implementation)(void), void* data); + void (*wl_proxy_destroy)(struct wl_proxy* proxy); + void (*wl_log_set_handler_client)(wl_log_func_t handler); + struct wl_proxy* (*wl_proxy_marshal_flags)(struct wl_proxy* proxy, uint32_t opcode, + const struct wl_interface* interface, + uint32_t version, + uint32_t flags, ...); + struct wl_display* (*wl_display_connect)(const char* name); + uint32_t (*wl_proxy_get_version)(struct wl_proxy* proxy); + + struct xkb_context* (*xkb_context_new)(enum xkb_context_flags flags); + void (*xkb_context_unref)(struct xkb_context* context); + struct xkb_state* (*xkb_state_new)(struct xkb_keymap* keymap); + void (*xkb_state_unref)(struct xkb_state* state); + struct xkb_keymap* (*xkb_keymap_new_from_string)(struct xkb_context* context, const char* string, enum xkb_keymap_format format, enum xkb_keymap_compile_flags flags); + xkb_level_index_t (*xkb_keymap_num_levels_for_key)(struct xkb_keymap* keymap, xkb_keycode_t key, xkb_layout_index_t layout); + int (*xkb_keymap_key_get_syms_by_level)(struct xkb_keymap* keymap, xkb_keycode_t key, xkb_layout_index_t layout, xkb_level_index_t level, const xkb_keysym_t** syms_out); + xkb_layout_index_t (*xkb_state_key_get_layout)(struct xkb_state* state, xkb_keycode_t key); + void (*xkb_keymap_unref)(struct xkb_keymap* keymap); + + void (*cairo_set_line_width)(cairo_t* cr, + double width); + void (*cairo_scale)(cairo_t* cr, + double sx, + double sy); + cairo_t* (*cairo_create)(cairo_surface_t* target); + void (*cairo_move_to)(cairo_t* cr, + double x, + double y); + + void (*cairo_rectangle)(cairo_t* cr, + double x, + double y, + double width, + double height); + void (*cairo_new_path)(cairo_t* cr); + void (*cairo_set_line_cap)(cairo_t* cr, + cairo_line_cap_t line_cap); + void (*cairo_set_source_rgba)(cairo_t* cr, + double red, + double green, + double blue, + double alpha); + void (*cairo_set_source_rgb)(cairo_t* cr, + double red, + double green, + double blue); + void (*cairo_reset_clip)(cairo_t* cr); + unsigned char* (*cairo_image_surface_get_data)(cairo_surface_t* surface); + void (*cairo_line_to)(cairo_t* cr, + double x, + double y); + void (*cairo_surface_destroy)(cairo_surface_t* surface); + cairo_surface_t* (*cairo_image_surface_create_for_data)(unsigned char* data, + cairo_format_t format, + int width, + int height, + int stride); + cairo_surface_t* (*cairo_image_surface_create)(cairo_format_t format, + int width, + int height); + void (*cairo_destroy)(cairo_t* cr); + cairo_pattern_t* (*cairo_get_source)(cairo_t* cr); + void (*cairo_close_path)(cairo_t* cr); + void (*cairo_paint)(cairo_t* cr); + void (*cairo_surface_flush)(cairo_surface_t* surface); + void (*cairo_clip)(cairo_t* cr); + void (*cairo_surface_mark_dirty)(cairo_surface_t* surface); + void (*cairo_stroke)(cairo_t* cr); + void (*cairo_set_source_surface)(cairo_t* cr, + cairo_surface_t* surface, + double x, + double y); + void (*cairo_fill)(cairo_t* cr); + void (*cairo_pattern_set_filter)(cairo_pattern_t* pattern, + cairo_filter_t filter); + +} wayland_call_table_t; + +extern wayland_call_table_t wl_call_tbl; + +/* defined inline right here so that it doesn't conflict with the other macros */ +MwInline int wayland_load_funcs() { + wl_call_tbl.lib = MwDynamicOpen("libwayland-client.so"); + if(!wl_call_tbl.lib) { + printf("(libwayland-client.so not found, falling back to X11)\n"); + return 1; + } + wl_call_tbl.xkb_lib = MwDynamicOpen("libxkbcommon.so"); + if(!wl_call_tbl.xkb_lib) { + printf("(libxkbcommon.so not found, cannot use Wayland backend.)\n"); + return 1; + } + wl_call_tbl.cairo_lib = MwDynamicOpen("libcairo.so"); + if(!wl_call_tbl.cairo_lib) { + printf("(libcairo.so not found, cannot use Wayland backend.)\n"); + return 1; + } +#define WAYLAND_FUNC(x) \ + wl_call_tbl.x = MwDynamicSymbol(wl_call_tbl.lib, #x); \ + if(!wl_call_tbl.x) { \ + printf("WARNING: Could use Wayland backend if " #x " was found.\n"); \ + return 1; \ + }; + + WAYLAND_FUNC(wl_display_dispatch_pending) + WAYLAND_FUNC(wl_display_disconnect) + WAYLAND_FUNC(wl_display_cancel_read) + WAYLAND_FUNC(wl_display_prepare_read) + WAYLAND_FUNC(wl_display_read_events) + WAYLAND_FUNC(wl_display_flush) + WAYLAND_FUNC(wl_display_get_fd) + WAYLAND_FUNC(wl_display_roundtrip) + WAYLAND_FUNC(wl_proxy_add_listener) + WAYLAND_FUNC(wl_proxy_destroy) + WAYLAND_FUNC(wl_log_set_handler_client) + WAYLAND_FUNC(wl_proxy_marshal_flags) + WAYLAND_FUNC(wl_display_connect) + WAYLAND_FUNC(wl_proxy_get_version) + +#undef WAYLAND_FUNC + +#define XKB_FUNC(x) \ + wl_call_tbl.x = MwDynamicSymbol(wl_call_tbl.xkb_lib, #x); \ + if(!wl_call_tbl.x) { \ + printf("WARNING: Could use Wayland backend if " #x " was found. Do you have libxkbcommon?\n"); \ + return 1; \ + }; + + XKB_FUNC(xkb_state_unref) + XKB_FUNC(xkb_context_new) + XKB_FUNC(xkb_context_unref) + XKB_FUNC(xkb_state_new) + XKB_FUNC(xkb_keymap_new_from_string) + XKB_FUNC(xkb_keymap_unref) + XKB_FUNC(xkb_keymap_num_levels_for_key) + XKB_FUNC(xkb_keymap_key_get_syms_by_level) + XKB_FUNC(xkb_state_key_get_layout) +#undef XKB_FUNC + +#define CAIRO_FUNC(x) \ + wl_call_tbl.x = MwDynamicSymbol(wl_call_tbl.cairo_lib, #x); \ + if(!wl_call_tbl.x) { \ + printf("WARNING: Could use Wayland backend if " #x " was found. Do you have libcairo?\n"); \ + return 1; \ + }; + + CAIRO_FUNC(cairo_set_line_width); + CAIRO_FUNC(cairo_scale); + CAIRO_FUNC(cairo_create); + CAIRO_FUNC(cairo_move_to); + CAIRO_FUNC(cairo_rectangle); + CAIRO_FUNC(cairo_new_path); + CAIRO_FUNC(cairo_set_line_cap); + CAIRO_FUNC(cairo_set_source_rgba); + CAIRO_FUNC(cairo_set_source_rgb); + CAIRO_FUNC(cairo_reset_clip); + CAIRO_FUNC(cairo_image_surface_get_data); + CAIRO_FUNC(cairo_line_to); + CAIRO_FUNC(cairo_surface_destroy); + CAIRO_FUNC(cairo_image_surface_create_for_data); + CAIRO_FUNC(cairo_image_surface_create); + CAIRO_FUNC(cairo_destroy); + CAIRO_FUNC(cairo_get_source); + CAIRO_FUNC(cairo_close_path); + CAIRO_FUNC(cairo_paint); + CAIRO_FUNC(cairo_surface_flush); + CAIRO_FUNC(cairo_clip); + CAIRO_FUNC(cairo_surface_mark_dirty); + CAIRO_FUNC(cairo_stroke); + CAIRO_FUNC(cairo_set_source_surface); + CAIRO_FUNC(cairo_fill); + CAIRO_FUNC(cairo_pattern_set_filter); +#undef CAIRO_FUNC + + return 0; +} + +#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_cancel_read wl_call_tbl.wl_display_cancel_read +#define wl_display_prepare_read wl_call_tbl.wl_display_prepare_read +#define wl_display_read_events wl_call_tbl.wl_display_read_events +#define wl_display_flush wl_call_tbl.wl_display_flush +#define wl_display_get_fd wl_call_tbl.wl_display_get_fd +#define wl_display_roundtrip wl_call_tbl.wl_display_roundtrip +#define wl_proxy_add_listener wl_call_tbl.wl_proxy_add_listener +#define wl_proxy_destroy wl_call_tbl.wl_proxy_destroy +#define wl_log_set_handler_client wl_call_tbl.wl_log_set_handler_client +#define wl_proxy_marshal_flags wl_call_tbl.wl_proxy_marshal_flags +#define wl_display_connect wl_call_tbl.wl_display_connect +#define wl_proxy_get_version wl_call_tbl.wl_proxy_get_version + +#define xkb_state_unref wl_call_tbl.xkb_state_unref +#define xkb_context_new wl_call_tbl.xkb_context_new +#define xkb_context_unref wl_call_tbl.xkb_context_unref +#define xkb_state_new wl_call_tbl.xkb_state_new +#define xkb_keymap_new_from_string wl_call_tbl.xkb_keymap_new_from_string +#define xkb_keymap_unref wl_call_tbl.xkb_keymap_unref +#define xkb_keymap_num_levels_for_key wl_call_tbl.xkb_keymap_num_levels_for_key +#define xkb_keymap_key_get_syms_by_level wl_call_tbl.xkb_keymap_key_get_syms_by_level +#define xkb_state_key_get_layout wl_call_tbl.xkb_state_key_get_layout + +#define cairo_set_line_width wl_call_tbl.cairo_set_line_width +#define cairo_scale wl_call_tbl.cairo_scale +#define cairo_create wl_call_tbl.cairo_create +#define cairo_move_to wl_call_tbl.cairo_move_to +#define cairo_rectangle wl_call_tbl.cairo_rectangle +#define cairo_new_path wl_call_tbl.cairo_new_path +#define cairo_set_line_cap wl_call_tbl.cairo_set_line_cap +#define cairo_set_source_rgba wl_call_tbl.cairo_set_source_rgba +#define cairo_set_source_rgb wl_call_tbl.cairo_set_source_rgb +#define cairo_reset_clip wl_call_tbl.cairo_reset_clip +#define cairo_image_surface_get_data wl_call_tbl.cairo_image_surface_get_data +#define cairo_line_to wl_call_tbl.cairo_line_to +#define cairo_surface_destroy wl_call_tbl.cairo_surface_destroy +#define cairo_image_surface_create_for_data wl_call_tbl.cairo_image_surface_create_for_data +#define cairo_image_surface_create wl_call_tbl.cairo_image_surface_create +#define cairo_destroy wl_call_tbl.cairo_destroy +#define cairo_get_source wl_call_tbl.cairo_get_source +#define cairo_close_path wl_call_tbl.cairo_close_path +#define cairo_paint wl_call_tbl.cairo_paint +#define cairo_surface_flush wl_call_tbl.cairo_surface_flush +#define cairo_clip wl_call_tbl.cairo_clip +#define cairo_surface_mark_dirty wl_call_tbl.cairo_surface_mark_dirty +#define cairo_stroke wl_call_tbl.cairo_stroke +#define cairo_set_source_surface wl_call_tbl.cairo_set_source_surface +#define cairo_fill wl_call_tbl.cairo_fill +#define cairo_pattern_set_filter wl_call_tbl.cairo_pattern_set_filter + #ifndef WL_PROTOCOLS_DEFINED #define WL_PROTOCOLS_DEFINED +#include "Wayland/wayland-core-protocol.h" #include "Wayland/xdg-shell-client-protocol.h" #include "Wayland/viewporter-client-protocol.h" #include "Wayland/xdg-decoration-client-protocol.h" @@ -31,16 +288,6 @@ MWDECL int MwLLWaylandCallInit(void); #include "Wayland/xdg-toplevel-icon-client-protocol.h" #endif -#define CSD_BORDER_FRAME_LEFT 5 -#define CSD_BORDER_FRAME_RIGHT 5 -#define CSD_BORDER_FRAME_TOP 24 -#define CSD_BORDER_FRAME_BOTTOM 5 - -#define CSD_LEFT_OFFSET(handle) handle->wayland.has_decorations ? 0 : CSD_BORDER_FRAME_LEFT -#define CSD_TOP_OFFSET(handle) handle->wayland.has_decorations ? 0 : CSD_BORDER_FRAME_TOP - -struct _MwLLWayland; - typedef struct wayland_protocol { void* listener; void* context; diff --git a/pl/rules.pl b/pl/rules.pl index a4ba7bfc8..81a1ecec7 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -29,13 +29,12 @@ if (grep(/^gdi$/, @backends)) { if (grep(/^wayland$/, @backends)) { add_cflags("-DUSE_WAYLAND"); new_object("src/backend/wayland.c"); - add_cflags(`pkg-config --cflags cairo wayland-client xkbcommon`); - add_libs(`pkg-config --libs cairo wayland-client xkbcommon`); if (param_get("opengl")) { - add_libs(`pkg-config --libs egl wayland-egl`); + add_cflags("-DWAYLAND_LOAD_OPENGL"); } + scan_wayland_protocol_core(); scan_wayland_protocol("stable", "xdg-shell", ""); scan_wayland_protocol("stable", "viewporter", ""); scan_wayland_protocol("stable", "tablet", "-v2"); diff --git a/pl/utils.pl b/pl/utils.pl index f2f722b05..77131a007 100644 --- a/pl/utils.pl +++ b/pl/utils.pl @@ -58,6 +58,35 @@ sub use_backend { } } + +sub scan_wayland_protocol_core { + my $proto_c = "src/backend/wayland-core-protocol.c"; + + if ( + system( +"wayland-scanner private-code /usr/share/wayland/wayland.xml ${proto_c}" + ) != 0 + ) + { + print( +"^ Error on getting private code for /usr/share/wayland/wayland.xml\n" + ); + } + else { + new_object($proto_c); + } + if ( + system( +"wayland-scanner client-header /usr/share/wayland/wayland.xml include/Mw/LowLevel/Wayland/wayland-core-protocol.h" + ) + ) + { + print( +"^ Error on getting client header for /usr/share/wayland/wayland.xml\n" + ); + } +} + sub scan_wayland_protocol { my $tier = $_[0]; my $proto = $_[1]; diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 2b581c693..34c87cf22 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -19,6 +19,8 @@ #include #endif +wayland_call_table_t wl_call_tbl; + /* 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) \ do { \ @@ -57,6 +59,8 @@ static void new_protocol(void* data, struct wl_registry* registry, MwU32 name, const char* interface, MwU32 version) { MwLL self = data; + (void)version; + (void)registry; WAYLAND_EVENT_OP_START(self); @@ -76,6 +80,9 @@ static void new_protocol(void* data, struct wl_registry* registry, static void protocol_removed(void* data, struct wl_registry* registry, MwU32 name) { + (void)data; + (void)registry; + (void)name; printf("%d destroyed\n", name); }; @@ -155,6 +162,7 @@ static void wl_data_device_data_offer(void* data, struct wl_data_device* wl_data_device, struct wl_data_offer* offer) { wl_clipboard_device_context_t* self = data; + (void)wl_data_device; wl_data_offer_add_listener(offer, &offer_listener, data); @@ -169,6 +177,11 @@ static void wl_data_device_enter(void* data, wl_fixed_t y, struct wl_data_offer* id) { MwLL self = data; + (void)wl_data_device; + (void)surface; + (void)x; + (void)y; + (void)id; WAYLAND_EVENT_OP_START(self); @@ -189,14 +202,24 @@ static void wl_data_device_motion(void* data, uint32_t time, wl_fixed_t x, wl_fixed_t y) { + (void)data; + (void)wl_data_device; + (void)time; + (void)x; + (void)y; }; static void wl_data_device_drop(void* data, struct wl_data_device* wl_data_device) { + (void)data; + (void)wl_data_device; }; static void wl_data_device_selection(void* data, struct wl_data_device* wl_data_device, struct wl_data_offer* id) { + (void)data; + (void)wl_data_device; + (void)id; }; struct wl_data_device_listener wl_data_device_listener = { @@ -212,6 +235,7 @@ static void zwp_primary_selection_device_v1_data_offer(void* data, struct zwp_primary_selection_device_v1* zwp_primary_selection_device_v1, struct zwp_primary_selection_offer_v1* offer) { wl_clipboard_device_context_t* self = data; + (void)zwp_primary_selection_device_v1; self->offer.zwp = offer; }; @@ -219,6 +243,9 @@ static void zwp_primary_selection_device_v1_data_offer(void* data, static void zwp_primary_selection_device_v1_selection(void* data, struct zwp_primary_selection_device_v1* zwp_primary_selection_device_v1, struct zwp_primary_selection_offer_v1* id) { + (void)data; + (void)zwp_primary_selection_device_v1; + (void)id; }; struct zwp_primary_selection_device_v1_listener zwp_primary_selection_device_v1_listener = { @@ -232,7 +259,6 @@ static void wl_clipboard_read(wl_clipboard_device_context_t* ctx) { char* buf = NULL; struct timeval timeout; int rc = 0; - int n; if(pipe(fds) != 0) { return; @@ -254,7 +280,6 @@ static void wl_clipboard_read(wl_clipboard_device_context_t* ctx) { wl_display_roundtrip(ctx->ll->wayland.display); while(MwTRUE) { - char ch; rc = select(fds[0] + 1, &set, NULL, NULL, &timeout); if(rc <= 0) { break; @@ -279,12 +304,17 @@ static void wl_clipboard_read(wl_clipboard_device_context_t* ctx) { static void wl_data_source_listener_target(void* data, struct wl_data_source* wl_data_source, const char* mime_type) { + (void)data; + (void)wl_data_source; + (void)mime_type; }; static void wl_data_source_listener_send(void* data, struct wl_data_source* wl_data_source, const char* mime_type, int32_t fd) { MwLL self = data; + (void)wl_data_source; + (void)mime_type; WAYLAND_EVENT_OP_START(self); if(self->wayland.clipboard_buffer != NULL) { @@ -328,6 +358,8 @@ static void zwp_primary_selection_source_v1_send(void* data, const char* mime_type, int32_t fd) { MwLL self = data; + (void)wl_data_source; + (void)mime_type; WAYLAND_EVENT_OP_START(self); @@ -341,6 +373,7 @@ static void zwp_primary_selection_source_v1_send(void* data, 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); @@ -380,6 +413,7 @@ 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; if(wayland->clipboard_manager.wl != NULL && !wayland->supports_zwp) { wl_data_device_manager_destroy(wayland->clipboard_manager.wl); wl_data_source_destroy(wayland->clipboard_source.wl); @@ -411,7 +445,8 @@ 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) { - // zwp_primary_selection_device_manager_v1_destroy(wayland->clipboard_manager.zwp); + (void)wayland; + (void)data; } /* `wl_pointer.enter` callback */ @@ -419,6 +454,8 @@ static void pointer_enter(void* data, struct wl_pointer* wl_pointer, MwU32 seria struct wl_surface* surface, wl_fixed_t surface_x, wl_fixed_t surface_y) { MwLL self = data; + (void)surface_x; + (void)surface_y; WAYLAND_EVENT_OP_START(self); self->wayland.curSurface = surface; @@ -433,6 +470,10 @@ static void pointer_enter(void* data, struct wl_pointer* wl_pointer, MwU32 seria /* `wl_pointer.leave` callback */ static void pointer_leave(void* data, struct wl_pointer* wl_pointer, MwU32 serial, struct wl_surface* surface) { + (void)data; + (void)wl_pointer; + (void)serial; + (void)surface; }; static void xdg_borderless_step(MwLL self, MwLLMouse p, MwU32 serial) { @@ -466,8 +507,8 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time wl_fixed_t surface_x, wl_fixed_t surface_y) { MwLL self = data; MwLLMouse p; - int i = 0; - MwWidget h = (MwWidget)self->common.user; + (void)time; + (void)wl_pointer; WAYLAND_EVENT_OP_START(self); @@ -488,8 +529,9 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri MwLL self = data; MwLLMouse p; - int x = self->wayland.x; - int y = self->wayland.y; + (void)wl_pointer; + (void)serial; + (void)time; WAYLAND_EVENT_OP_START(self); @@ -544,7 +586,13 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri /* `wl_pointer.axis` callback */ static void pointer_axis(void* data, struct wl_pointer* wl_pointer, MwU32 time, - MwU32 axis, wl_fixed_t value) {}; + MwU32 axis, wl_fixed_t value) { + (void)data; + (void)wl_pointer; + (void)time; + (void)axis; + (void)value; +}; struct wl_pointer_listener pointer_listener = { .enter = pointer_enter, @@ -561,6 +609,7 @@ static void keyboard_keymap(void* data, int32_t fd, MwU32 size) { MwLL self = data; + (void)wl_keyboard; if(self->wayland.type == MWLL_WAYLAND_TOPLEVEL) { struct _MwLLWaylandTopLevel* wayland = self->wayland.toplevel; @@ -589,6 +638,9 @@ static void keyboard_enter(void* data, struct wl_surface* surface, struct wl_array* keys) { MwLL self = data; + (void)wl_keyboard; + (void)surface; + (void)keys; WAYLAND_EVENT_OP_START(self); @@ -605,6 +657,9 @@ static void keyboard_leave(void* data, MwU32 serial, struct wl_surface* surface) { MwLL self = data; + (void)wl_keyboard; + (void)serial; + (void)surface; WAYLAND_EVENT_OP_START(self); @@ -621,6 +676,9 @@ static void keyboard_key(void* data, MwU32 key, MwU32 state) { MwLL self = data; + (void)wl_keyboard; + (void)serial; + (void)time; WAYLAND_EVENT_OP_START(self); @@ -726,6 +784,10 @@ static void keyboard_modifiers(void* data, MwU32 mods_locked, MwU32 group) { MwLL self = data; + (void)wl_keyboard; + (void)serial; + (void)group; + (void)mods_latched; WAYLAND_EVENT_OP_START(self); @@ -746,7 +808,11 @@ struct wl_keyboard_listener keyboard_listener = { /* `wl_seat.name` callback */ static void -wl_seat_name(void* data, struct wl_seat* wl_seat, const char* name) {}; +wl_seat_name(void* data, struct wl_seat* wl_seat, const char* name) { + (void)data; + (void)wl_seat; + (void)name; +}; /* `wl_seat.capabilities` callback */ static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat, @@ -797,14 +863,28 @@ static void output_geometry(void* data, int32_t subpixel, const char* make, const char* model, - int32_t transform) {}; + int32_t transform) { + (void)data; + (void)wl_output; + (void)x; + (void)y; + (void)physical_width; + (void)physical_height; + (void)subpixel; + (void)make; + (void)model; + (void)transform; +}; static void output_mode(void* data, struct wl_output* wl_output, uint32_t flags, int32_t width, int32_t height, int32_t refresh) { - MwLL self = data; + MwLL self = data; + (void)wl_output; + (void)flags; + (void)refresh; self->wayland.mw = width; self->wayland.mh = height; }; @@ -818,6 +898,7 @@ struct wl_output_listener output_listener = { void xdg_wm_base_ping(void* data, struct xdg_wm_base* xdg_wm_base, MwU32 serial) { + (void)data; xdg_wm_base_pong(xdg_wm_base, serial); }; @@ -835,6 +916,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) { + (void)wayland; free(data->listener); } @@ -847,6 +929,8 @@ static wayland_protocol_t* wl_output_setup(MwU32 name, MwLL ll) { } static void wl_output_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { + (void)wayland; + (void)data; } /* wl_compositor setup function */ @@ -857,6 +941,8 @@ 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; } /* wl_subcompositor setup function */ @@ -871,6 +957,7 @@ 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)data; wl_subcompositor_destroy(wayland->sublevel->subcompositor); } @@ -888,6 +975,7 @@ 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); } @@ -900,7 +988,8 @@ static wayland_protocol_t* wp_viewporter_setup(MwU32 name, struct _MwLLWayland* } static void wp_viewporter_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { - // free(data->listener); + (void)wayland; + (void)data; } /* the two decoration manager constructs */ @@ -924,6 +1013,8 @@ 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) { + (void)wayland; + (void)data; } /* Standard Wayland event loop. */ @@ -931,7 +1022,6 @@ static int event_loop(MwLL handle) { struct pollfd fd; struct timespec timeout; struct _MwLLWayland* wayland = &handle->wayland; - int res; timeout.tv_nsec = 1; timeout.tv_sec = 0; @@ -977,7 +1067,6 @@ static int event_loop(MwLL handle) { /* make the fuck sure that we're configurd */ static void hang_until_configured(MwLL handle) { - int i = 0; while(!handle->wayland.configured) { if(wl_display_roundtrip(handle->wayland.display) == -1) { printf("roundtrip failed\n"); @@ -993,9 +1082,9 @@ static void xdg_toplevel_configure(void* data, struct xdg_toplevel* xdg_toplevel, MwI32 width, MwI32 height, struct wl_array* states) { - MwLL self = data; - int i; - MwWidget h = ((MwWidget)self->common.user); + MwLL self = data; + (void)states; + (void)xdg_toplevel; /* Yes, somehow this can get called before */ if(!self->wayland.configured) { @@ -1029,16 +1118,11 @@ static void xdg_toplevel_configure(void* data, recursive_dispatch_resize(self); }; -/* Empty function for satisfying zxdg_toplevel's requirements */ -static void decoration_configure( - void* data, struct zxdg_toplevel_decoration_v1* zxdg_toplevel_decoration_v1, - MwU32 mode) { -} - /* `xdg_surface.close` callback */ 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); @@ -1069,6 +1153,8 @@ 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; } static void update_buffer(struct _MwLLWaylandShmBuffer* buffer) { @@ -1077,7 +1163,6 @@ static void update_buffer(struct _MwLLWaylandShmBuffer* buffer) { } static void buffer_setup(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height) { - int x, y; int stride = width * 4; char temp_name[] = "/tmp/milsko-wl-shm-XXXXXX"; @@ -1215,6 +1300,7 @@ 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); } @@ -1256,8 +1342,6 @@ static void setup_callbacks(struct _MwLLWayland* wayland) { /* Toplevel setup function */ static void setup_toplevel(MwLL r, int x, int y) { - int i; - r->wayland.type = MWLL_WAYLAND_TOPLEVEL; r->wayland.toplevel = malloc(sizeof(struct _MwLLWaylandTopLevel)); r->wayland.x = x; @@ -1335,8 +1419,6 @@ static void setup_toplevel(MwLL r, int x, int y) { /* Toplevel destroy function */ static void destroy_toplevel(MwLL r) { - int i; - 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); @@ -1428,6 +1510,7 @@ static void popup_configure(void* data, int32_t width, int32_t height) { MwLL self = data; + (void)xdg_popup; self->wayland.x = x; self->wayland.y = y; @@ -1437,6 +1520,8 @@ static void popup_configure(void* data, static void popup_done(void* data, struct xdg_popup* xdg_popup) { + (void)data; + (void)xdg_popup; }; struct xdg_popup_listener popup_listener = { @@ -1446,7 +1531,6 @@ struct xdg_popup_listener popup_listener = { /* Popup setup function */ static void setup_popup(MwLL r, int x, int y) { - int i; struct xdg_surface* xdg_surface; MwLL topmost_parent = r->wayland.parent; @@ -1529,24 +1613,12 @@ static void destroy_popup(MwLL r) { } static void clip(MwLL handle) { - MwLL parent = handle->wayland.parent; - MwLL topmost = parent; - int left_offset = 0; - int top_offset = 0; - + MwLL parent = handle->wayland.parent; if(parent && handle->wayland.type == MWLL_WAYLAND_SUBLEVEL) { cairo_reset_clip(handle->wayland.front_cairo); cairo_rectangle(handle->wayland.front_cairo, 0, 0, (parent->wayland.ww + handle->wayland.x), (parent->wayland.wh + handle->wayland.y)); cairo_clip(handle->wayland.front_cairo); } - // if(topmost && handle->wayland.type == MWLL_WAYLAND_SUBLEVEL) { - // cairo_reset_clip(handle->wayland.front_cairo); - // while(topmost->wayland.parent) topmost = topmost->wayland.parent; - // left_offset = topmost->wayland.has_decorations ? 0 : (CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT); - // top_offset = topmost->wayland.has_decorations ? 0 : (CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM); - // cairo_rectangle(handle->wayland.front_cairo, 0, 0, (topmost->wayland.ww + handle->wayland.x) - left_offset, (topmost->wayland.wh + handle->wayland.y) - top_offset); - // cairo_clip(handle->wayland.front_cairo); - // } } static void wl_logger(const char* fmt, va_list args) { @@ -1560,8 +1632,6 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { memset(r, 0, sizeof(*r)); MwLLCreateCommon(r); - wl_log_set_handler_client(wl_logger); - /* Wayland does not report global coordinates ever. Compositors are not even expected to have knowledge of this. */ r->common.coordinate_type = MwCoordinatesLocal; @@ -1677,9 +1747,6 @@ static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsign } static void MwLLSetXYImpl(MwLL handle, int x, int y) { - int i = 0; - MwWidget h = (MwWidget)handle->common.user; - region_invalidate(handle); handle->wayland.x = x; handle->wayland.y = y; @@ -1692,8 +1759,6 @@ static void MwLLSetXYImpl(MwLL handle, int x, int y) { } static void MwLLSetWHImpl(MwLL handle, int w, int h) { - int i = 0; - MwWidget widget = (MwWidget)handle->common.user; region_invalidate(handle); /* Prevent an integer underflow when the w/h is too low */ @@ -1734,7 +1799,7 @@ static void MwLLBeginDrawImpl(MwLL handle) { } if(!handle->wayland.has_decorations) { - int x, y; + int x; MwU32 w = handle->wayland.ww + CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT; MwU32 h = handle->wayland.wh + CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM; cairo_set_line_width(handle->wayland.back_cairo, 4.0); @@ -1870,6 +1935,7 @@ 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)); + (void)handle; c->common.red = r; c->common.blue = b; @@ -1879,6 +1945,7 @@ static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { } static void MwLLColorUpdateImpl(MwLL handle, MwLLColor c, int r, int g, int b) { + (void)handle; c->common.red = r; c->common.blue = b; c->common.green = g; @@ -1929,7 +1996,6 @@ static int MwLLPendingImpl(MwLL handle) { } static void MwLLNextEventImpl(MwLL handle) { - int i = 0; if(!handle->wayland.always_render) { if(handle->wayland.did_event_loop_early) { handle->wayland.did_event_loop_early = MwFALSE; @@ -1961,6 +2027,7 @@ static void MwLLSetTitleImpl(MwLL handle, const char* title) { static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, int width, int height) { MwLLPixmap r = malloc(sizeof(*r)); + (void)handle; r->common.width = width; r->common.height = height; @@ -2030,7 +2097,6 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { if(WAYLAND_GET_INTERFACE(handle->wayland, xdg_toplevel_icon_manager_v1) != NULL) { - void* map; struct xdg_toplevel_icon_manager_v1* icon_manager = WAYLAND_GET_INTERFACE(handle->wayland, xdg_toplevel_icon_manager_v1)->context; struct xdg_toplevel_icon_v1* icon = xdg_toplevel_icon_manager_v1_create_icon(icon_manager); MwU64 size = pixmap->common.width * pixmap->common.height * 4; @@ -2092,7 +2158,6 @@ static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { for(y = 0; y < mask->height; y++) { unsigned int d = mask->data[y]; for(x = mask->width - 1; x >= 0; x--) { - int px = 0; int idx = ((y * image->width) + x) * 4; if(d & 1) { @@ -2135,6 +2200,7 @@ static void MwLLDetachImpl(MwLL handle, MwPoint* point) { } static void MwLLShowImpl(MwLL handle, int show) { + (void)show; switch(handle->wayland.type) { case MWLL_WAYLAND_UNKNOWN: case MWLL_WAYLAND_TOPLEVEL: @@ -2147,6 +2213,9 @@ static void MwLLShowImpl(MwLL handle, int show) { } static void MwLLMakePopupImpl(MwLL handle, MwLL parent) { + (void)handle; + (void)parent; + /* Wayland doesn't have "popups" in the Milsko sense persay. xdg_popup is closer to ToolWindow and as such is what we use there. So just like the Mac backend, this is just left alone. */ } static void MwLLSetSizeHintsImpl(MwLL handle, int minx, int miny, int maxx, int maxy) { @@ -2157,6 +2226,7 @@ static void MwLLSetSizeHintsImpl(MwLL handle, int minx, int miny, int maxx, int } static void MwLLMakeBorderlessImpl(MwLL handle, int toggle) { + (void)toggle; if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { if(WAYLAND_GET_INTERFACE(handle->wayland, zxdg_decoration_manager_v1) != NULL) { zxdg_decoration_manager_v1_context_t* dec = WAYLAND_GET_INTERFACE(handle->wayland, zxdg_decoration_manager_v1)->context; @@ -2171,10 +2241,14 @@ static void MwLLMakeBorderlessImpl(MwLL handle, int toggle) { } static void MwLLFocusImpl(MwLL handle) { + (void)handle; printf("[WARNING] MwLLFocus not supported on Wayland\n"); } static void MwLLGrabPointerImpl(MwLL handle, int toggle) { + (void)handle; + (void)toggle; + printf("[WARNING] MwLLGrabPointer not supported on Wayland\n"); } static void MwLLSetClipboardImpl(MwLL handle, const char* text) { @@ -2200,6 +2274,7 @@ static void MwLLSetClipboardImpl(MwLL handle, const char* text) { } static void MwLLGetClipboardImpl(MwLL handle) { + (void)handle; /* no-op */ return; } @@ -2255,11 +2330,16 @@ static void MwLLEndStateChangeImpl(MwLL handle) { static int MwLLWaylandCallInitImpl(void) { #ifdef __linux__ - if(strcmp(getenv("XDG_SESSION_TYPE"), "wayland")) { - return 1; + if(strcmp(getenv("XDG_SESSION_TYPE"), "wayland") == 0) { + if(wayland_load_funcs()) { + return 1; + } + wl_log_set_handler_client(wl_logger); + + return 0; } #endif - return 0; + return 1; } #include "call.c" diff --git a/src/widget/opengl.c b/src/widget/opengl.c index 7d685ada6..59e3a4052 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -57,6 +57,47 @@ typedef struct waylandopengl { EGLContext egl_context; EGLSurface egl_surface; EGLConfig egl_config; + + void* gllib; + void* wlgllib; + EGLBoolean (*eglGetConfigs)(EGLDisplay display, + EGLConfig* configs, + EGLint config_size, + EGLint* num_config); + EGLBoolean (*eglInitialize)(EGLDisplay display, + EGLint* major, + EGLint* minor); + EGLContext (*eglCreateContext)(EGLDisplay display, + EGLConfig config, + EGLContext share_context, + EGLint const* attrib_list); + EGLBoolean (*eglMakeCurrent)(EGLDisplay display, + EGLSurface draw, + EGLSurface read, + EGLContext context); + void* (*eglGetProcAddress)(char const* procname); + EGLBoolean (*eglSwapBuffers)(EGLDisplay display, + EGLSurface surface); + EGLBoolean (*eglSwapInterval)(EGLDisplay display, + EGLint interval); + EGLint (*eglGetError)(void); + EGLBoolean (*eglBindAPI)(EGLenum api); + EGLDisplay (*eglGetDisplay)(NativeDisplayType native_display); + EGLSurface (*eglCreateWindowSurface)(EGLDisplay display, + EGLConfig config, + NativeWindowType native_window, + EGLint const* attrib_list); + EGLBoolean (*eglChooseConfig)(EGLDisplay display, + EGLint const* attrib_list, + EGLConfig* configs, + EGLint config_size, + EGLint* num_config); + + struct wl_egl_window* (*wl_egl_window_create)(struct wl_surface* surface, + int width, int height); + void (*wl_egl_window_resize)(struct wl_egl_window* egl_window, + int width, int height, + int dx, int dy); } waylandopengl_t; #endif @@ -136,7 +177,6 @@ static int create(MwWidget handle) { #endif #ifdef USE_WAYLAND if(handle->lowlevel->common.type == MwLLBackendWayland) { - int err; EGLint numConfigs; EGLint majorVersion; EGLint minorVersion; @@ -174,6 +214,58 @@ static int create(MwWidget handle) { topmost_parent = topmost_parent->wayland.parent; } + o->gllib = MwDynamicOpen("libEGL.so"); + if(!o->gllib) { + printf("Could not load OpenGL widget under Wayland! libEGL.so missing.\n"); + return 1; + } + o->wlgllib = MwDynamicOpen("libwayland-egl.so"); + if(!o->gllib) { + printf("Could not load OpenGL widget under Wayland! libwayland-egl.so missing.\n"); + return 1; + } +#define EGL_FUNC(x) \ + o->x = MwDynamicSymbol(o->gllib, #x); \ + if(!o->x) { \ + printf("Could not load OpenGL widget under Wayland! " #x " missing.\n"); \ + return 1; \ + }; +#define WAYLAND_EGL_FUNC(x) \ + o->x = MwDynamicSymbol(o->wlgllib, #x); \ + if(!o->x) { \ + printf("Could not load OpenGL widget under Wayland! " #x " missing.\n"); \ + return 1; \ + }; + EGL_FUNC(eglGetConfigs) + EGL_FUNC(eglInitialize) + EGL_FUNC(eglCreateContext) + EGL_FUNC(eglMakeCurrent) + EGL_FUNC(eglGetProcAddress) + EGL_FUNC(eglSwapBuffers) + EGL_FUNC(eglSwapInterval) + EGL_FUNC(eglGetError) + EGL_FUNC(eglBindAPI) + EGL_FUNC(eglGetDisplay) + EGL_FUNC(eglCreateWindowSurface) + EGL_FUNC(eglChooseConfig) + WAYLAND_EGL_FUNC(wl_egl_window_create) + WAYLAND_EGL_FUNC(wl_egl_window_resize) + +#define eglGetConfigs o->eglGetConfigs +#define eglInitialize o->eglInitialize +#define eglCreateContext o->eglCreateContext +#define eglMakeCurrent o->eglMakeCurrent +#define eglGetProcAddress o->eglGetProcAddress +#define eglSwapBuffers o->eglSwapBuffers +#define eglSwapInterval o->eglSwapInterval +#define eglGetError o->eglGetError +#define wl_egl_window_create o->wl_egl_window_create +#define eglBindAPI o->eglBindAPI +#define eglGetDisplay o->eglGetDisplay +#define wl_egl_window_resize o->wl_egl_window_resize +#define eglCreateWindowSurface o->eglCreateWindowSurface +#define eglChooseConfig o->eglChooseConfig + display = eglGetDisplay((EGLNativeDisplayType)handle->lowlevel->wayland.display); if(display == EGL_NO_DISPLAY) { @@ -391,6 +483,7 @@ static void* mwOpenGLGetProcAddressImpl(MwWidget handle, const char* name) { #endif #ifdef USE_WAYLAND if(handle->lowlevel->common.type == MwLLBackendWayland) { + waylandopengl_t* o = handle->internal; return eglGetProcAddress(name); } #endif From 7162350e248b08190c3331526ac9530ab5350108 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 24 Mar 2026 17:39:25 -0700 Subject: [PATCH 019/195] use-experimental-wayland => use-wayland --- configure | 4 ++-- pl/ostype/Linux.pl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/configure b/configure index 5ffbe544d..1c06c0d65 100755 --- a/configure +++ b/configure @@ -58,7 +58,7 @@ my %features = ( "vulkan-string-helper" => "use Vulkan string helper", "shared" => "build shared library", "static" => "build static library", - "experimental-wayland" => "enable WIP wayland backend", + "wayland" => "enable ayland backend", ); my @features_keys = ( "1classic-theme", "1stb-image", @@ -66,7 +66,7 @@ my @features_keys = ( "1opengl", "2xrender", "1vulkan", "2vulkan-string-helper", "1shared", "1static", - "1experimental-wayland" + "1wayland" ); foreach my $l (@ARGV) { diff --git a/pl/ostype/Linux.pl b/pl/ostype/Linux.pl index 155cd4aaf..88adcf838 100644 --- a/pl/ostype/Linux.pl +++ b/pl/ostype/Linux.pl @@ -1,4 +1,4 @@ -if (param_get("experimental-wayland")) { +if (param_get("wayland")) { use_backend("wayland", "x11"); } else { From aad8d1b536d92a43ffc772547d9af283271d8219 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 24 Mar 2026 18:01:55 -0700 Subject: [PATCH 020/195] wayland: combo box consistently shows up now --- src/backend/wayland.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 34c87cf22..40a24739c 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -2322,6 +2322,21 @@ static void MwLLEndStateChangeImpl(MwLL handle) { setup_toplevel(handle, handle->wayland.detach_point.x, handle->wayland.detach_point.y); break; } + + // framebuffer_setup(&handle->wayland); + // backbuffer_setup(&handle->wayland); + + handle->wayland.region = wl_compositor_create_region(handle->wayland.compositor); + handle->wayland.o_region = wl_compositor_create_region(handle->wayland.compositor); + region_setup(handle); + + MwLLForceRender(handle); + if(handle->wayland.parent != NULL) { + MwLLForceRender(handle->wayland.parent); + } + + handle->wayland.events_pending = 1; + handle->wayland.detatching = MwFALSE; } From 2a7327f27a40e1b4031b45d61a597ba2101a084f Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 24 Mar 2026 19:42:34 -0700 Subject: [PATCH 021/195] wayland: update backbuffer on enddraw --- src/backend/wayland.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 40a24739c..b83c799e8 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1889,6 +1889,7 @@ static void MwLLEndDrawImpl(MwLL handle) { if(handle->wayland.configured) { update_buffer(&handle->wayland.framebuffer); if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { + update_buffer(&handle->wayland.backbuffer); } } } From 195cccd65a6417a6cf235a7eaba5b31ad4ff637e Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 24 Mar 2026 22:40:36 -0700 Subject: [PATCH 022/195] perfect MwLLDetach --- include/Mw/LowLevel/Wayland.h | 2 - src/backend/wayland.c | 69 +++++++++++++++++++++-------------- 2 files changed, 41 insertions(+), 30 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index a6f225437..778826140 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -479,8 +479,6 @@ struct _MwLLWayland { MwBool moving; - struct wl_surface* curSurface; - cairo_surface_t* front_cs; cairo_surface_t* back_cs; cairo_t* front_cairo; diff --git a/src/backend/wayland.c b/src/backend/wayland.c index b83c799e8..f400b3086 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -449,6 +449,8 @@ static void zwp_primary_selection_device_manager_v1_interface_destroy(struct _Mw (void)data; } +static struct wl_surface* curSurface; + /* `wl_pointer.enter` callback */ static void pointer_enter(void* data, struct wl_pointer* wl_pointer, MwU32 serial, struct wl_surface* surface, wl_fixed_t surface_x, @@ -458,7 +460,7 @@ static void pointer_enter(void* data, struct wl_pointer* wl_pointer, MwU32 seria (void)surface_y; WAYLAND_EVENT_OP_START(self); - self->wayland.curSurface = surface; + curSurface = surface; self->wayland.pointer_serial = serial; @@ -477,7 +479,7 @@ static void pointer_leave(void* data, struct wl_pointer* wl_pointer, MwU32 seria }; static void xdg_borderless_step(MwLL self, MwLLMouse p, MwU32 serial) { - if(self->wayland.type == MWLL_WAYLAND_TOPLEVEL && self->wayland.backbuffer.surface == self->wayland.curSurface) { + if(self->wayland.type == MWLL_WAYLAND_TOPLEVEL && self->wayland.backbuffer.surface == curSurface) { if(p.point.y >= (self->wayland.wh + CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM) - 5) { if(p.point.x >= (self->wayland.ww + CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT) - 5) { xdg_toplevel_resize(self->wayland.toplevel->xdg_top_level, self->wayland.pointer_seat, serial, XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT); @@ -539,8 +541,8 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri // p.point.x > x && p.point.x < x + self->wayland.ww && p.point.y > y && p.point.y < y + self->wayland.wh if( - self->wayland.framebuffer.surface == self->wayland.curSurface || - self->wayland.backbuffer.surface == self->wayland.curSurface) { + self->wayland.framebuffer.surface == curSurface || + self->wayland.backbuffer.surface == curSurface) { int i; switch(button) { @@ -1108,9 +1110,9 @@ static void xdg_toplevel_configure(void* data, backbuffer_destroy(&self->wayland); backbuffer_setup(&self->wayland); - framebuffer_destroy(&self->wayland); framebuffer_setup(&self->wayland); + region_setup(self); MwLLDispatch(self, resize, NULL); @@ -1261,7 +1263,7 @@ static void region_setup(MwLL handle) { return; } - wl_region_add(handle->wayland.o_region, 0, 0, 1, 1); + wl_region_add(handle->wayland.o_region, 0, 0, width, height); if(handle->wayland.type == MWLL_WAYLAND_POPUP) { wl_region_add(handle->wayland.region, 0, 0, width + abs(handle->wayland.x), height + abs(handle->wayland.y)); @@ -1626,12 +1628,7 @@ static void wl_logger(const char* fmt, va_list args) { raise(SIGTRAP); } -static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { - MwLL r; - r = malloc(sizeof(*r)); - memset(r, 0, sizeof(*r)); - MwLLCreateCommon(r); - +static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int height, enum _MwLLWaylandType ty) { /* Wayland does not report global coordinates ever. Compositors are not even expected to have knowledge of this. */ r->common.coordinate_type = MwCoordinatesLocal; @@ -1654,10 +1651,26 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r->wayland.y = y; r->wayland.parent = parent; - if(parent == NULL) { - setup_toplevel(r, x, y); + if(ty == MWLL_WAYLAND_UNKNOWN) { + if(parent == NULL) { + setup_toplevel(r, x, y); + } else { + setup_sublevel(parent, r, x, y); + } } else { - setup_sublevel(parent, r, x, y); + switch(ty) { + case MWLL_WAYLAND_UNKNOWN: + break; + case MWLL_WAYLAND_TOPLEVEL: + setup_toplevel(r, x, y); + break; + case MWLL_WAYLAND_SUBLEVEL: + setup_sublevel(parent, r, x, y); + break; + case MWLL_WAYLAND_POPUP: + setup_popup(r, x, y); + break; + } } framebuffer_setup(&r->wayland); @@ -1671,6 +1684,14 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { if(parent != NULL) { MwLLForceRender(parent); } +} +static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { + MwLL r; + r = malloc(sizeof(*r)); + memset(r, 0, sizeof(*r)); + MwLLCreateCommon(r); + + widget_setup(r, parent, x, y, width, height, MWLL_WAYLAND_UNKNOWN); return r; } @@ -1887,10 +1908,10 @@ static void MwLLBeginDrawImpl(MwLL handle) { static void MwLLEndDrawImpl(MwLL handle) { if(handle->wayland.configured) { - update_buffer(&handle->wayland.framebuffer); if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { update_buffer(&handle->wayland.backbuffer); } + update_buffer(&handle->wayland.framebuffer); } } @@ -2303,6 +2324,7 @@ static void MwLLEndStateChangeImpl(MwLL handle) { if(handle->wayland.detatching) { switch(handle->wayland.type) { case MWLL_WAYLAND_UNKNOWN: + break; case MWLL_WAYLAND_TOPLEVEL: destroy_toplevel(handle); break; @@ -2310,22 +2332,13 @@ static void MwLLEndStateChangeImpl(MwLL handle) { destroy_sublevel(handle); break; case MWLL_WAYLAND_POPUP: - return; + destroy_popup(handle); + break; } wl_flush(handle); - switch(handle->wayland.type_to_be) { - case MWLL_WAYLAND_POPUP: - setup_popup(handle, handle->wayland.detach_point.x, handle->wayland.detach_point.y); - break; - default: - setup_toplevel(handle, handle->wayland.detach_point.x, handle->wayland.detach_point.y); - break; - } - - // framebuffer_setup(&handle->wayland); - // backbuffer_setup(&handle->wayland); + widget_setup(handle, handle->wayland.parent, handle->wayland.detach_point.x, handle->wayland.detach_point.y, handle->wayland.ww, handle->wayland.wh, handle->wayland.type_to_be); handle->wayland.region = wl_compositor_create_region(handle->wayland.compositor); handle->wayland.o_region = wl_compositor_create_region(handle->wayland.compositor); From a826ce5e12ad22949d4861c2b3c2aab2de9ae74d Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 24 Mar 2026 23:08:43 -0700 Subject: [PATCH 023/195] GOD IS GOOD --- src/backend/wayland.c | 76 ++++++++++++++++++++++++++++++------------- 1 file changed, 54 insertions(+), 22 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index f400b3086..26b359110 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1238,7 +1238,7 @@ static void backbuffer_setup(struct _MwLLWayland* wayland) { wayland->back_cs = cairo_image_surface_create_for_data(wayland->backbuffer.buf, CAIRO_FORMAT_ARGB32, w, h, 4 * w); wayland->back_cairo = cairo_create(wayland->back_cs); - memset(wayland->backbuffer.buf, 0, wayland->backbuffer.buf_size); + memset(wayland->backbuffer.buf, 255, wayland->backbuffer.buf_size); hang_until_configured((MwLL)wayland); update_buffer(&wayland->backbuffer); }; @@ -1532,13 +1532,14 @@ struct xdg_popup_listener popup_listener = { }; /* Popup setup function */ -static void setup_popup(MwLL r, int x, int y) { +static void setup_popup(MwLL r, int x, int y, MwLL parent) { struct xdg_surface* xdg_surface; MwLL topmost_parent = r->wayland.parent; - r->wayland.type = MWLL_WAYLAND_POPUP; - r->wayland.x = x; - r->wayland.y = y; + r->wayland.type = MWLL_WAYLAND_POPUP; + r->wayland.x = x; + r->wayland.y = y; + r->wayland.popup = malloc(sizeof(struct _MwLLWaylandPopup)); while(topmost_parent->wayland.type != MWLL_WAYLAND_TOPLEVEL) { topmost_parent = topmost_parent->wayland.parent; @@ -1548,12 +1549,11 @@ static void setup_popup(MwLL r, int x, int y) { r->wayland.y += ceil((float)CSD_BORDER_FRAME_TOP / 2.); } - r->wayland.popup = malloc(sizeof(struct _MwLLWaylandPopup)); - memset(r->wayland.popup, 0, sizeof(struct _MwLLWaylandPopup)); - r->wayland.popup->topmost_parent = topmost_parent; - setup_callbacks(&r->wayland); + /* Connect to the Wayland compositor */ + r->wayland.display = parent->wayland.display; + /* Do a roundtrip to ensure all interfaces are setup. */ r->wayland.registry = wl_display_get_registry(r->wayland.display); wl_registry_add_listener(r->wayland.registry, &r->wayland.registry_listener, r); @@ -1563,7 +1563,12 @@ static void setup_popup(MwLL r, int x, int y) { return; } - r->wayland.popup->xdg_wm_base = WAYLAND_GET_INTERFACE(topmost_parent->wayland, xdg_wm_base)->context; + /* 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) { + r->wayland.has_decorations = MwTRUE; + } + + r->wayland.popup->xdg_wm_base = WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context; r->wayland.popup->xdg_positioner = xdg_wm_base_create_positioner(r->wayland.popup->xdg_wm_base); @@ -1577,7 +1582,7 @@ static void setup_popup(MwLL r, int x, int y) { r->wayland.framebuffer.surface = wl_compositor_create_surface(r->wayland.compositor); r->wayland.popup->xdg_surface = - xdg_wm_base_get_xdg_surface(r->wayland.popup->xdg_wm_base, r->wayland.framebuffer.surface); + xdg_wm_base_get_xdg_surface(WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context, r->wayland.framebuffer.surface); r->wayland.popup->xdg_popup = xdg_surface_get_popup( r->wayland.popup->xdg_surface, @@ -1587,16 +1592,13 @@ static void setup_popup(MwLL r, int x, int y) { xdg_popup_add_listener(r->wayland.popup->xdg_popup, &popup_listener, r); r->wayland.popup->xdg_surface_listener.configure = xdg_surface_configure; - xdg_surface_add_listener(r->wayland.popup->xdg_surface, &r->wayland.popup->xdg_surface_listener, r); /* Perform the initial commit and wait for the first configure event */ wl_surface_commit(r->wayland.framebuffer.surface); - event_loop(r); - - // framebuffer_destroy(&r->wayland); - framebuffer_setup(&r->wayland); - backbuffer_setup(&r->wayland); + while(!r->wayland.configured) { + event_loop(r); + } } /* Popup destroy function */ @@ -1668,7 +1670,7 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh setup_sublevel(parent, r, x, y); break; case MWLL_WAYLAND_POPUP: - setup_popup(r, x, y); + setup_popup(r, x, y, parent); break; } } @@ -1758,6 +1760,10 @@ static void MwLLDestroyImpl(MwLL handle) { shfree(handle->wayland.wl_protocol_setup_map); free(handle); + + if(currentlyHeldWidget == handle) { + currentlyHeldWidget = NULL; + } } static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h) { @@ -1799,7 +1805,7 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { if(handle->wayland.type == MWLL_WAYLAND_POPUP) { destroy_popup(handle); wl_flush(handle); - setup_popup(handle, handle->wayland.x, handle->wayland.y); + setup_popup(handle, handle->wayland.x, handle->wayland.y, handle->wayland.parent); } refresh: @@ -2322,6 +2328,11 @@ static void MwLLBeginStateChangeImpl(MwLL handle) { static void MwLLEndStateChangeImpl(MwLL handle) { if(handle->wayland.detatching) { + MwLL topmost_parent = handle->wayland.parent; + + while(topmost_parent->wayland.type != MWLL_WAYLAND_TOPLEVEL) { + topmost_parent = topmost_parent->wayland.parent; + } switch(handle->wayland.type) { case MWLL_WAYLAND_UNKNOWN: break; @@ -2338,11 +2349,32 @@ static void MwLLEndStateChangeImpl(MwLL handle) { wl_flush(handle); + handle->wayland.detach_point.x += 4; + handle->wayland.detach_point.y += 4; + widget_setup(handle, handle->wayland.parent, handle->wayland.detach_point.x, handle->wayland.detach_point.y, handle->wayland.ww, handle->wayland.wh, handle->wayland.type_to_be); - handle->wayland.region = wl_compositor_create_region(handle->wayland.compositor); - handle->wayland.o_region = wl_compositor_create_region(handle->wayland.compositor); - region_setup(handle); + if(handle->common.user) { + MwWidget w = handle->common.user; + int i; + for(i = 0; i < arrlen(w->children); i++) { + if(w->children[i]->lowlevel->wayland.type == MWLL_WAYLAND_SUBLEVEL) { + MwLL child = w->children[i]->lowlevel; + child->wayland.sublevel->parent_xdg_surface = handle->wayland.popup->xdg_surface; + wl_subsurface_destroy(child->wayland.sublevel->subsurface); + wl_flush(handle); + + child->wayland.sublevel->subsurface = wl_subcompositor_get_subsurface(child->wayland.sublevel->subcompositor, child->wayland.framebuffer.surface, handle->wayland.framebuffer.surface); + wl_subsurface_set_desync(child->wayland.sublevel->subsurface); + wl_subsurface_set_position(child->wayland.sublevel->subsurface, child->wayland.x, child->wayland.y); + + wl_subsurface_place_above(child->wayland.sublevel->subsurface, handle->wayland.framebuffer.surface); + MwLLEndStateChangeImpl(w->children[i]->lowlevel); + + currentlyHeldWidget = NULL; + } + } + } MwLLForceRender(handle); if(handle->wayland.parent != NULL) { From 9757623d3c28996363f630008e20699981b670f4 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 24 Mar 2026 23:24:20 -0700 Subject: [PATCH 024/195] make always_render a global variable, MwWaylandAlwaysRender --- include/Mw/LowLevel/Wayland.h | 4 +--- src/backend/wayland.c | 11 ++++++----- src/widget/opengl.c | 11 +++-------- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 778826140..95e84eb94 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -127,7 +127,7 @@ typedef struct wayland_call_table { } wayland_call_table_t; extern wayland_call_table_t wl_call_tbl; - +extern MwBool MwWaylandAlwaysRender; /* defined inline right here so that it doesn't conflict with the other macros */ MwInline int wayland_load_funcs() { wl_call_tbl.lib = MwDynamicOpen("libwayland-client.so"); @@ -405,8 +405,6 @@ struct _MwLLWayland { wayland_protocol_t* value; }* wl_protocol_map; - MwBool always_render; - MwBool has_decorations; char title[255]; diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 26b359110..5e4e76792 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -20,6 +20,7 @@ #endif wayland_call_table_t wl_call_tbl; +MwBool MwWaylandAlwaysRender = MwFALSE; /* 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) \ @@ -770,7 +771,7 @@ static void keyboard_key(void* data, } } - if(!self->wayland.always_render) { + if(!MwWaylandAlwaysRender) { MwLLDispatch(self, draw, NULL); } @@ -1999,17 +2000,17 @@ static int MwLLPendingImpl(MwLL handle) { handle->wayland.did_initial_resize = 1; } - if(!handle->wayland.always_render) wl_display_prepare_read(handle->wayland.display); + if(!MwWaylandAlwaysRender) wl_display_prepare_read(handle->wayland.display); if(!poll(&fd, 1, timeout.tv_nsec)) { wl_display_cancel_read(handle->wayland.display); } else { - if(!handle->wayland.always_render) wl_display_read_events(handle->wayland.display); + if(!MwWaylandAlwaysRender) wl_display_read_events(handle->wayland.display); if((pending = wl_display_dispatch_pending(handle->wayland.display)) < 0) { wl_display_cancel_read(handle->wayland.display); } } - if(handle->wayland.always_render) { + if(MwWaylandAlwaysRender) { handle->wayland.did_event_loop_early = MwTRUE; event_loop(handle); return pending; @@ -2024,7 +2025,7 @@ static int MwLLPendingImpl(MwLL handle) { } static void MwLLNextEventImpl(MwLL handle) { - if(!handle->wayland.always_render) { + if(!MwWaylandAlwaysRender) { if(handle->wayland.did_event_loop_early) { handle->wayland.did_event_loop_early = MwFALSE; } else { diff --git a/src/widget/opengl.c b/src/widget/opengl.c index 59e3a4052..0afbe9ac7 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -205,14 +205,9 @@ static int create(MwWidget handle) { 1, EGL_NONE}; EGLDisplay display; - waylandopengl_t* o = r = malloc(sizeof(*o)); - MwLL topmost_parent = handle->lowlevel->wayland.parent; - handle->lowlevel->wayland.always_render = MwTRUE; - - while(topmost_parent->wayland.parent != NULL) { - topmost_parent->wayland.always_render = MwTRUE; - topmost_parent = topmost_parent->wayland.parent; - } + waylandopengl_t* o = r = malloc(sizeof(*o)); + MwLL topmost_parent = handle->lowlevel->wayland.parent; + MwWaylandAlwaysRender = MwTRUE; o->gllib = MwDynamicOpen("libEGL.so"); if(!o->gllib) { From f4e2ec8fa93b0f7f8f8fe326aacafb9c2d0d8a72 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 24 Mar 2026 23:44:30 -0700 Subject: [PATCH 025/195] h --- include/Mw/LowLevel/Wayland.h | 4 ++++ pl/rules.pl | 1 + src/backend/wayland.c | 25 +++++++++++++++++-------- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 95e84eb94..bc8ce1ff2 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -285,6 +285,7 @@ MwInline int wayland_load_funcs() { #include "Wayland/xdg-decoration-client-protocol.h" #include "Wayland/cursor-shape-client-protocol.h" #include "Wayland/primary-selection-client-protocol.h" +#include "Wayland/pointer-constraints-client-protocol.h" #include "Wayland/xdg-toplevel-icon-client-protocol.h" #endif @@ -418,6 +419,9 @@ struct _MwLLWayland { struct wp_viewport* vp; + struct zwp_pointer_constraints_v1* pointer_constraints; + struct zwp_locked_pointer_v1* locked_pointer; + /* 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.*/ diff --git a/pl/rules.pl b/pl/rules.pl index 81a1ecec7..5433a1764 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -42,6 +42,7 @@ if (grep(/^wayland$/, @backends)) { scan_wayland_protocol("staging", "cursor-shape", "-v1"); scan_wayland_protocol("unstable", "xdg-decoration", "-unstable-v1"); scan_wayland_protocol("unstable", "primary-selection", "-unstable-v1"); + scan_wayland_protocol("unstable", "pointer-constraints", "-unstable-v1"); $gl_libs = "-lGL -lGLU"; } diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 5e4e76792..4d7f72aca 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -5,11 +5,6 @@ #include "../../external/stb_ds.h" -/* TODO: - * - MwLLMakePopupImpl - * - MwLLShowImpl - */ - /* TODO: find out what FreeBSD and such wants us to include */ #ifdef __FreeBSD__ /* XXX: Untested (nishi) */ @@ -450,6 +445,17 @@ static void zwp_primary_selection_device_manager_v1_interface_destroy(struct _Mw (void)data; } +/* zwp_primary_selection_device_manager_v1 setup function */ +static wayland_protocol_t* zwp_pointer_constraints_v1_setup(MwU32 name, struct _MwLLWayland* wayland) { + wayland->pointer_constraints = wl_registry_bind(wayland->registry, name, &zwp_pointer_constraints_v1_interface, 1); + return NULL; +} + +static void zwp_pointer_constraints_v1_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { + (void)wayland; + (void)data; +} + static struct wl_surface* curSurface; /* `wl_pointer.enter` callback */ @@ -1329,6 +1335,7 @@ static void setup_callbacks(struct _MwLLWayland* wayland) { WL_INTERFACE(wl_output); WL_INTERFACE(wl_data_device_manager); WL_INTERFACE(zwp_primary_selection_device_manager_v1); + WL_INTERFACE(zwp_pointer_constraints_v1); if(wayland->type == MWLL_WAYLAND_TOPLEVEL) { WL_INTERFACE(xdg_wm_base); WL_INTERFACE(wp_viewporter); @@ -2275,9 +2282,11 @@ static void MwLLFocusImpl(MwLL handle) { } static void MwLLGrabPointerImpl(MwLL handle, int toggle) { - (void)handle; - (void)toggle; - printf("[WARNING] MwLLGrabPointer not supported on Wayland\n"); + if(handle->wayland.pointer_constraints) { + handle->wayland.locked_pointer = zwp_pointer_constraints_v1_lock_pointer(handle->wayland.pointer_constraints, handle->wayland.framebuffer.surface, handle->wayland.pointer, handle->wayland.region, ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT); + } else { + printf("[WARNING] MwLLGrabPointer not supported in Wayland session, zwp_pointer_constraints_v1 required.\n"); + } } static void MwLLSetClipboardImpl(MwLL handle, const char* text) { From 4b2bf63889e9a2bc05cc153ec7660497b1ae0024 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 25 Mar 2026 00:31:23 -0700 Subject: [PATCH 026/195] wayland: support pointer locking --- include/Mw/LowLevel/Wayland.h | 2 ++ src/backend/wayland.c | 47 ++++++++++++++++++++++++----------- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index bc8ce1ff2..c24ce3cec 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -419,8 +419,10 @@ struct _MwLLWayland { struct wp_viewport* vp; + MwBool do_lock_pointer; struct zwp_pointer_constraints_v1* pointer_constraints; struct zwp_locked_pointer_v1* locked_pointer; + MwBool pointer_constrained; /* 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.*/ diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 4d7f72aca..1d1d2b8ac 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -514,22 +514,35 @@ static MwLL currentlyHeldWidget = NULL; /* `wl_pointer.motion` callback */ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time, wl_fixed_t surface_x, wl_fixed_t surface_y) { - MwLL self = data; + MwLL self = data; + MwLL topmost_parent = self; MwLLMouse p; (void)time; (void)wl_pointer; WAYLAND_EVENT_OP_START(self); + while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; self->wayland.cur_mouse_pos.x = wl_fixed_to_int(surface_x); self->wayland.cur_mouse_pos.y = wl_fixed_to_int(surface_y); - p.point = self->wayland.cur_mouse_pos; + if(self->wayland.do_lock_pointer) { + self->wayland.cur_mouse_pos.x -= topmost_parent->wayland.ww / 2.; + self->wayland.cur_mouse_pos.y -= topmost_parent->wayland.wh / 2.; + } + p.point = self->wayland.cur_mouse_pos; MwLLDispatch(self, move, &p); if(currentlyHeldWidget) { MwLLDispatch(currentlyHeldWidget, down, &p); } + if(self->wayland.do_lock_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); + zwp_locked_pointer_v1_set_cursor_position_hint(topmost_parent->wayland.locked_pointer, wl_fixed_from_double(topmost_parent->wayland.ww / 2.), wl_fixed_from_double(topmost_parent->wayland.wh / 2.)); + wl_surface_commit(topmost_parent->wayland.backbuffer.surface); + zwp_locked_pointer_v1_destroy(topmost_parent->wayland.locked_pointer); + } + WAYLAND_EVENT_OP_END(self); }; @@ -1125,6 +1138,11 @@ static void xdg_toplevel_configure(void* data, MwLLDispatch(self, draw, NULL); recursive_dispatch_resize(self); + + if(self->wayland.pointer_constrained) { + zwp_locked_pointer_v1_set_cursor_position_hint(self->wayland.locked_pointer, wl_fixed_from_double(self->wayland.ww / 2.), wl_fixed_from_double(self->wayland.wh / 2.)); + wl_surface_commit(self->wayland.framebuffer.surface); + } }; /* `xdg_surface.close` callback */ @@ -1166,7 +1184,8 @@ static void wl_shm_interface_destroy(struct _MwLLWayland* wayland, wayland_proto (void)data; } -static void update_buffer(struct _MwLLWaylandShmBuffer* buffer) { +static void update_buffer(MwLL self, struct _MwLLWaylandShmBuffer* buffer) { + (void)self; // for later, just in case. wl_surface_attach(buffer->surface, buffer->shm_buffer, 0, 0); wl_surface_commit(buffer->surface); } @@ -1222,7 +1241,7 @@ static void framebuffer_setup(struct _MwLLWayland* wayland) { memset(wayland->framebuffer.buf, 0, wayland->framebuffer.buf_size); hang_until_configured((MwLL)wayland); - update_buffer(&wayland->framebuffer); + update_buffer((MwLL)wayland, &wayland->framebuffer); }; static void framebuffer_destroy(struct _MwLLWayland* wayland) { buffer_destroy(&wayland->framebuffer); @@ -1247,7 +1266,7 @@ static void backbuffer_setup(struct _MwLLWayland* wayland) { memset(wayland->backbuffer.buf, 255, wayland->backbuffer.buf_size); hang_until_configured((MwLL)wayland); - update_buffer(&wayland->backbuffer); + update_buffer((MwLL)wayland, &wayland->backbuffer); }; static void backbuffer_destroy(struct _MwLLWayland* wayland) { buffer_destroy(&wayland->backbuffer); @@ -1913,7 +1932,7 @@ static void MwLLBeginDrawImpl(MwLL handle) { MwLLDestroyPixmap(p); free(px); } - update_buffer(&handle->wayland.backbuffer); + update_buffer(handle, &handle->wayland.backbuffer); wl_surface_commit(handle->wayland.backbuffer.surface); } @@ -1923,9 +1942,9 @@ static void MwLLBeginDrawImpl(MwLL handle) { static void MwLLEndDrawImpl(MwLL handle) { if(handle->wayland.configured) { if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { - update_buffer(&handle->wayland.backbuffer); + update_buffer(handle, &handle->wayland.backbuffer); } - update_buffer(&handle->wayland.framebuffer); + update_buffer(handle, &handle->wayland.framebuffer); } } @@ -2023,9 +2042,9 @@ static int MwLLPendingImpl(MwLL handle) { return pending; } - update_buffer(&handle->wayland.framebuffer); + update_buffer(handle, &handle->wayland.framebuffer); if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { - update_buffer(&handle->wayland.backbuffer); + update_buffer(handle, &handle->wayland.backbuffer); } return handle->wayland.force_render || handle->wayland.events_pending || pending; @@ -2044,7 +2063,7 @@ static void MwLLNextEventImpl(MwLL handle) { // if(!handle->wayland.events_pending) { MwLLDispatch(handle, draw, NULL); // } - if(handle->wayland.configured) update_buffer(&handle->wayland.framebuffer); + if(handle->wayland.configured) update_buffer(handle, &handle->wayland.framebuffer); handle->wayland.force_render = 0; } if(handle->wayland.events_pending) { @@ -2127,7 +2146,7 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { cairo_surface_destroy(cs); MwLLForceRender(handle); - update_buffer(&handle->wayland.framebuffer); + update_buffer(handle, &handle->wayland.framebuffer); wl_surface_damage(handle->wayland.framebuffer.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); } static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { @@ -2159,7 +2178,7 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { handle->wayland.icon->buf[i + 3] = 255; } - if(handle->wayland.configured) update_buffer(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, 1); @@ -2283,7 +2302,7 @@ static void MwLLFocusImpl(MwLL handle) { static void MwLLGrabPointerImpl(MwLL handle, int toggle) { if(handle->wayland.pointer_constraints) { - handle->wayland.locked_pointer = zwp_pointer_constraints_v1_lock_pointer(handle->wayland.pointer_constraints, handle->wayland.framebuffer.surface, handle->wayland.pointer, handle->wayland.region, ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT); + handle->wayland.do_lock_pointer = toggle; } else { printf("[WARNING] MwLLGrabPointer not supported in Wayland session, zwp_pointer_constraints_v1 required.\n"); } From fa9ad8b9848d60ed2ccae17c8a890edc18c799bf Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 25 Mar 2026 00:43:35 -0700 Subject: [PATCH 027/195] enable wayland by default on linux builds --- configure | 6 +++++- src/backend/wayland.c | 14 ++++++++++---- src/widget/opengl.c | 5 ++--- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/configure b/configure index 1c06c0d65..3cfe05055 100755 --- a/configure +++ b/configure @@ -46,6 +46,10 @@ param_set("vulkan-string-helper", 1); param_set("shared", 1); param_set("static", 1); param_set("examples", 1); +print($target); +if($target eq "Linux") { + param_set("wayland", 1); +} my %features = ( "classic-theme" => "use classic theme", @@ -58,7 +62,7 @@ my %features = ( "vulkan-string-helper" => "use Vulkan string helper", "shared" => "build shared library", "static" => "build static library", - "wayland" => "enable ayland backend", + "wayland" => "enable wayland backend", ); my @features_keys = ( "1classic-theme", "1stb-image", diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 1d1d2b8ac..5ba779b1c 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -2026,11 +2026,17 @@ static int MwLLPendingImpl(MwLL handle) { handle->wayland.did_initial_resize = 1; } - if(!MwWaylandAlwaysRender) wl_display_prepare_read(handle->wayland.display); - if(!poll(&fd, 1, timeout.tv_nsec)) { - wl_display_cancel_read(handle->wayland.display); + if(!MwWaylandAlwaysRender) { + wl_display_prepare_read(handle->wayland.display); + if(!poll(&fd, 1, timeout.tv_nsec)) { + wl_display_cancel_read(handle->wayland.display); + } else { + wl_display_read_events(handle->wayland.display); + if((pending = wl_display_dispatch_pending(handle->wayland.display)) < 0) { + wl_display_cancel_read(handle->wayland.display); + } + } } else { - if(!MwWaylandAlwaysRender) wl_display_read_events(handle->wayland.display); if((pending = wl_display_dispatch_pending(handle->wayland.display)) < 0) { wl_display_cancel_read(handle->wayland.display); } diff --git a/src/widget/opengl.c b/src/widget/opengl.c index 0afbe9ac7..bf06981b9 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -205,9 +205,8 @@ static int create(MwWidget handle) { 1, EGL_NONE}; EGLDisplay display; - waylandopengl_t* o = r = malloc(sizeof(*o)); - MwLL topmost_parent = handle->lowlevel->wayland.parent; - MwWaylandAlwaysRender = MwTRUE; + waylandopengl_t* o = r = malloc(sizeof(*o)); + MwWaylandAlwaysRender = MwTRUE; o->gllib = MwDynamicOpen("libEGL.so"); if(!o->gllib) { From aa6d1f43d3e37d16b6c0ee676118542dccf8eeb0 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Wed, 25 Mar 2026 17:06:44 +0900 Subject: [PATCH 028/195] fix --- src/widget/vulkan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widget/vulkan.c b/src/widget/vulkan.c index e2dfa4c8b..92f319265 100644 --- a/src/widget/vulkan.c +++ b/src/widget/vulkan.c @@ -231,7 +231,7 @@ static MwErrorEnum vulkan_instance_setup(MwWidget handle, vulkan_t* o) { arrput(enabledExtensions, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME); /* take this opprutunity to set the widget to always render */ - handle->lowlevel->wayland.always_render = MwTRUE; + MwWaylandAlwaysRender = MwTRUE; while(topmost_parent->wayland.parent != NULL) { topmost_parent = topmost_parent->wayland.parent; From c05843a04b99e755b5c2abb1927432b16efcb76b Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Wed, 25 Mar 2026 17:09:36 +0900 Subject: [PATCH 029/195] ugh --- src/widget/vulkan.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/widget/vulkan.c b/src/widget/vulkan.c index 92f319265..a67c47440 100644 --- a/src/widget/vulkan.c +++ b/src/widget/vulkan.c @@ -227,16 +227,9 @@ static MwErrorEnum vulkan_instance_setup(MwWidget handle, vulkan_t* o) { #endif #ifdef USE_WAYLAND if(handle->lowlevel->common.type == MwLLBackendWayland) { - MwLL topmost_parent = handle->lowlevel->wayland.parent; - arrput(enabledExtensions, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME); /* take this opprutunity to set the widget to always render */ MwWaylandAlwaysRender = MwTRUE; - - while(topmost_parent->wayland.parent != NULL) { - topmost_parent = topmost_parent->wayland.parent; - topmost_parent->wayland.always_render = MwTRUE; - } } #endif From 6bb72c224b6ccad718d689901e2c4d1656ed1fa7 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 25 Mar 2026 14:06:50 -0700 Subject: [PATCH 030/195] support wayland backend on cmake --- CMakeLists.txt | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 09a5bd90c..743824f91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,10 @@ option(MW_BUILD_SHARED "Build a shared library" ON) option(MW_BUILD_STATIC "Build a static library" OFF) option(MW_INSTALL_HEADERS "Install headers" ON) +if(${CMAKE_SYSTEM_NAME} STREQUAL Linux) +option(MW_USE_WAYLAND "Enable Wayland backend" ON) +endif() + file( GLOB SOURCES @@ -127,6 +131,97 @@ if(MW_USE_FREETYPE2) list(APPEND LIBRARIES ${FT2_LIBRARIES}) endif() +if(MW_USE_WAYLAND) + function(scan_wayland_protocol_core) + execute_process( + COMMAND wayland-scanner private-code /usr/share/wayland/wayland.xml ${CMAKE_CURRENT_SOURCE_DIR}/src/backend/wayland-core-protocol.c + OUTPUT_VARIABLE WAYLAND_SCANNER_OUTPUT + ERROR_VARIABLE WAYLAND_SCANNER_ERROR + ECHO_OUTPUT_VARIABLE + ECHO_ERROR_VARIABLE + COMMAND_ECHO STDOUT + ) + target_sources( + Mw + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src/backend/wayland-core-protocol.c + ) + execute_process( + COMMAND wayland-scanner client-header /usr/share/wayland/wayland.xml ${CMAKE_CURRENT_SOURCE_DIR}/include/Mw/LowLevel/Wayland/wayland-core-protocol.h + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE WAYLAND_SCANNER_OUTPUT + ERROR_VARIABLE WAYLAND_SCANNER_ERROR + ECHO_OUTPUT_VARIABLE + ECHO_ERROR_VARIABLE + COMMAND_ECHO STDOUT + ) + endfunction() + + function(scan_wayland_protocol tier proto ver) + SET(proto_c ${CMAKE_CURRENT_SOURCE_DIR}/src/backend/wayland-${proto}-protocol.c) + execute_process( + COMMAND wayland-scanner private-code /usr/share/wayland-protocols/${tier}/${proto}/${proto}${ver}.xml ${proto_c} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE WAYLAND_SCANNER_OUTPUT + ERROR_VARIABLE WAYLAND_SCANNER_ERROR + ECHO_OUTPUT_VARIABLE + ECHO_ERROR_VARIABLE + COMMAND_ECHO STDOUT + ) + target_sources( + Mw + PRIVATE + ${proto_c} + ) + execute_process( + COMMAND wayland-scanner client-header /usr/share/wayland-protocols/${tier}/${proto}/${proto}${ver}.xml ${CMAKE_CURRENT_SOURCE_DIR}/include/Mw/LowLevel/Wayland/${proto}-client-protocol.h + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE WAYLAND_SCANNER_OUTPUT + ERROR_VARIABLE WAYLAND_SCANNER_ERROR + ECHO_OUTPUT_VARIABLE + ECHO_ERROR_VARIABLE + COMMAND_ECHO STDOUT + ) + endfunction() + + check_include_files(wayland-client.h HAVE_WL_H) + check_include_files(xkbcommon/xkbcommon.h HAVE_XKBCOMMON_H) + check_include_files(cairo/cairo.h HAVE_CAIRO_H) + if(HAVE_WL_H) + if(HAVE_XKBCOMMON_H) + if(HAVE_CAIRO_H) + scan_wayland_protocol_core() + scan_wayland_protocol("stable" "xdg-shell" "") + scan_wayland_protocol("stable" "viewporter" "") + scan_wayland_protocol("stable" "tablet" "-v2") + scan_wayland_protocol("staging" "xdg-toplevel-icon" "-v1") + scan_wayland_protocol("staging" "cursor-shape" "-v1") + scan_wayland_protocol("unstable" "xdg-decoration" "-unstable-v1") + scan_wayland_protocol("unstable" "primary-selection" "-unstable-v1") + scan_wayland_protocol("unstable" "pointer-constraints" "-unstable-v1") + + target_sources( + Mw + PRIVATE + src/backend/wayland.c + ) + target_compile_definitions( + Mw + PRIVATE + USE_WAYLAND + ) + message(STATUS "Wayland backend has been enabled") + else() + message(WARNING "Wayland backend has been disabled") + endif() + else() + message(WARNING "Wayland backend has been disabled") + endif() + else() + message(WARNING "Wayland backend has been disabled") + endif() +endif() + target_include_directories( Mw PUBLIC From 82999d716a435ab770355ae0fe9ae02370cc5435 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 25 Mar 2026 17:49:28 -0700 Subject: [PATCH 031/195] apple: move all event stuff into callback system, fix cmake support for apple, add gl/vk examples to cmake --- .clangd | 1 + .gitignore | 1 + CMakeLists.txt | 24 +- configure | 7 +- examples/CMakeLists.txt | 6 + examples/basic/CMakeLists.txt | 2 +- examples/gldemos/CMakeLists.txt | 27 ++ examples/vkdemos/CMakeLists.txt | 22 ++ include/Mw/LowLevel/Cocoa.h | 56 +-- src/backend/cocoa.m | 630 +++++++++++++++++--------------- 10 files changed, 457 insertions(+), 319 deletions(-) create mode 100644 examples/gldemos/CMakeLists.txt create mode 100644 examples/vkdemos/CMakeLists.txt diff --git a/.clangd b/.clangd index c2520c5c5..1058f6f19 100644 --- a/.clangd +++ b/.clangd @@ -1,2 +1,3 @@ Completion: HeaderInsertion: Never +ClangFormat: Tab diff --git a/.gitignore b/.gitignore index 153abcca4..22460554b 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ examples/*/*.exe /build compile_flags.txt .cache +.DS_Store diff --git a/CMakeLists.txt b/CMakeLists.txt index 743824f91..7bf75294a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,11 +15,16 @@ option(MW_CLASSIC_THEME "Use classic theme" OFF) option(MW_BUILD_EXAMPLES "Build examples" OFF) option(MW_USE_STB_IMAGE "Use stb_image" ON) option(MW_USE_STB_TRUETYPE "Use stb_truetype" OFF) -option(MW_USE_FREETYPE2 "Use FreeType 2" ON) option(MW_BUILD_SHARED "Build a shared library" ON) option(MW_BUILD_STATIC "Build a static library" OFF) option(MW_INSTALL_HEADERS "Install headers" ON) +if(${CMAKE_SYSTEM_NAME} STREQUAL Darwin) +option(MW_USE_FREETYPE2 "Use FreeType 2" OFF) +else() +option(MW_USE_FREETYPE2 "Use FreeType 2" ON) +endif() + if(${CMAKE_SYSTEM_NAME} STREQUAL Linux) option(MW_USE_WAYLAND "Enable Wayland backend" ON) endif() @@ -47,10 +52,13 @@ if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD") endif() if(MW_TRY_OPENGL) - check_include_files(GL/gl.h HAVE_GL_GL_H) - if(HAVE_GL_GL_H) + find_package(OpenGL) + if(OpenGL_FOUND) set(MW_BUILD_OPENGL ON) - list(APPEND SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/opengl.c") + list(APPEND SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/opengl.c") + if(APPLE) + list(APPEND SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/opengl_cocoa.m") + endif() message(STATUS "OpenGL widget has been enabled") else() message(WARNING "OpenGL widget has been disabled") @@ -222,6 +230,14 @@ if(MW_USE_WAYLAND) endif() endif() +if(APPLE AND MW_BUILD_OPENGL) + target_compile_definitions( + Mw + PRIVATE + GL_SILENCE_DEPRECATION + ) +endif() + target_include_directories( Mw PUBLIC diff --git a/configure b/configure index 3cfe05055..cb465378b 100755 --- a/configure +++ b/configure @@ -38,7 +38,6 @@ require("./pl/utils.pl"); param_set("classic-theme", 0); param_set("stb-image", 1); param_set("stb-truetype", 0); -param_set("freetype2", 1); param_set("xrender", 1); param_set("opengl", 0); param_set("vulkan", 0); @@ -46,11 +45,15 @@ param_set("vulkan-string-helper", 1); param_set("shared", 1); param_set("static", 1); param_set("examples", 1); -print($target); if($target eq "Linux") { param_set("wayland", 1); } +if($target ne "Darwin") { + param_set("freetype2", 1); +} + + my %features = ( "classic-theme" => "use classic theme", "stb-image" => "use stb_image, instead use libjpeg/libpng", diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 6f4cd2f5a..5baed4a88 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1 +1,7 @@ add_subdirectory(basic) +if(${MW_TRY_OPENGL}) +add_subdirectory(gldemos) +endif() +if(${MW_TRY_VULKAN}) +add_subdirectory(vkdemos) +endif() diff --git a/examples/basic/CMakeLists.txt b/examples/basic/CMakeLists.txt index b4eb0a1cd..acda320d2 100644 --- a/examples/basic/CMakeLists.txt +++ b/examples/basic/CMakeLists.txt @@ -6,7 +6,7 @@ file( foreach(PATH IN LISTS EXAMPLES_BASIC_SOURCES) get_filename_component(TARGET ${PATH} NAME_WE) - add_executable(${TARGET} ${PATH}) + add_executable(${TARGET} WIN32 MACOSX_BUNDLE ${PATH}) target_link_libraries( ${TARGET} PRIVATE diff --git a/examples/gldemos/CMakeLists.txt b/examples/gldemos/CMakeLists.txt new file mode 100644 index 000000000..9afda19fb --- /dev/null +++ b/examples/gldemos/CMakeLists.txt @@ -0,0 +1,27 @@ +file( + GLOB + EXAMPLES_GL_SOURCES + *.c +) +find_package(OpenGL) + +foreach(PATH IN LISTS EXAMPLES_GL_SOURCES) + get_filename_component(TARGET ${PATH} NAME_WE) + if(${TARGET} STREQUAL "glutlayer") + continue() + endif() + add_executable(${TARGET} WIN32 MACOSX_BUNDLE ${PATH}) + target_link_libraries( + ${TARGET} + PRIVATE + Mw + OpenGL::GL + ) + if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") + target_link_libraries( + ${TARGET} + PRIVATE + m + ) + endif() +endforeach() diff --git a/examples/vkdemos/CMakeLists.txt b/examples/vkdemos/CMakeLists.txt new file mode 100644 index 000000000..354bf3634 --- /dev/null +++ b/examples/vkdemos/CMakeLists.txt @@ -0,0 +1,22 @@ +file( + GLOB + EXAMPLES_VULKAN_SOURCES + *.c +) + +foreach(PATH IN LISTS EXAMPLES_VULKAN_SOURCES) + get_filename_component(TARGET ${PATH} NAME_WE) + add_executable(${TARGET} WIN32 MACOSX_BUNDLE ${PATH}) + target_link_libraries( + ${TARGET} + PRIVATE + Mw + ) + if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") + target_link_libraries( + ${TARGET} + PRIVATE + m + ) + endif() +endforeach() diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index 7d1b217fe..da104f018 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -21,11 +21,17 @@ #import #endif +@interface MilskoCocoaApplication : NSApplication { + MwBool doPending; +} +- (MwBool)pending; +@end + // Note: implements NSApplicationDelegate @interface MilskoCocoaApplicationDelegate : NSObject { - NSApplication* appl; + MilskoCocoaApplication* appl; } -- (MilskoCocoaApplicationDelegate*)initWithAppl:(NSApplication*)appl; +- (MilskoCocoaApplicationDelegate*)initWithAppl:(MilskoCocoaApplication*)appl; @end @interface MilskoCocoaWindow : NSWindow { @@ -80,32 +86,39 @@ @end @interface MilskoCocoaView : NSView { - NSBitmapImageRep* rep; - NSGraphicsContext* context; - MwBool valid; - CGColorSpaceRef space; - CGDataProviderRef provider; - float width; - float height; + NSBitmapImageRep* rep; + NSGraphicsContext* context; + MwBool valid; + CGColorSpaceRef space; + CGDataProviderRef provider; + NSRect givenRect; + float x; + float y; + float width; + float height; + MwBool _child; + IBOutlet NSViewController* viewController; } - (void)initRepAndContextWithWidth:(float)w Height:(float)h; - (NSGraphicsContext*)context; - (void)destroy; - (NSBitmapImageRep*)getRep; +- (void)setChild; @end @interface MilskoCocoa : NSObject { - NSApplication* application; - MwBool _forceRender; - MilskoCocoaWindow* window; - NSRect rect; - MilskoCocoaView* view; - MwLL parent; - MilskoFakePointer* handle; - unsigned int strHash; - NSEvent* lastEvent; + MilskoCocoaApplication* application; + MwBool _forceRender; + MwBool _eventsPending; + MilskoCocoaWindow* window; + NSRect rect; + MilskoCocoaView* view; + MwLL parent; + MilskoFakePointer* handle; + unsigned int strHash; + NSEvent* lastEvent; MilskoCocoaPixmap* cursorPixmap; NSCursor* cursor; @@ -129,9 +142,6 @@ - (void)setX:(int)x Y:(int)y; - (void)setW:(int)w H:(int)h; - (int)pending; -- (void)eventProcess:(NSEvent*)ev; -- (void)handleKeyEvent:(NSEvent*)ev ll:(MwLL)ll; -- (void)handleMouseEvent:(NSEvent*)ev ll:(MwLL)ll; - (void)getNextEvent; - (void)setTitle:(const char*)title; - (void)drawPixmap:(MwLLPixmap)pixmap rect:(MwRect*)rect; @@ -158,6 +168,10 @@ - (MwLL)getParent; - (NSView*)getView; - (MilskoCocoaWindow*)getWindow; +- (void)nudge; + +- (void)pushCursor; +- (void)popCursor; - (MilskoFakePointer*)getHandle; + (void)eventCanceller:(MilskoCocoa*)this; diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 725642d35..d3fec7ebb 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -1,5 +1,9 @@ #include "Mw/BaseTypes.h" +#include "Mw/LowLevel.h" #include +#include +#include "../../external/stb_ds.h" +#include "Mw/TypeDefs.h" #ifdef __clang__ #pragma clang push @@ -22,15 +26,44 @@ static NSPoint pointFlip(NSPoint point) { } static NSRect localRectFlip(NSRect originFrame, NSView* view) { - float viewHeight = [view bounds].size.height; - NSRect destinationFrame = NSMakeRect( - originFrame.origin.x, - [view bounds].size.height - (originFrame.origin.y + originFrame.size.height), - originFrame.size.width, - originFrame.size.height); + float viewHeight = [view bounds].size.height; + NSRect destinationFrame = + NSMakeRect(originFrame.origin.x, + [view bounds].size.height - + (originFrame.origin.y + originFrame.size.height), + originFrame.size.width, originFrame.size.height); return destinationFrame; } +/* 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); + } + } + } +}; + @implementation MilskoCocoaPixmap + (MilskoCocoaPixmap*)newWithWidth:(int)width height:(int)height { @@ -85,6 +118,8 @@ static NSRect localRectFlip(NSRect originFrame, NSView* view) { [self->image removeRepresentation:self->rep]; [self->image dealloc]; [self->rep dealloc]; + self->image = NULL; + self->rep = NULL; } - (NSImage*)image { return self->image; @@ -103,16 +138,18 @@ static NSRect localRectFlip(NSRect originFrame, NSView* view) { [c retain]; /* - * MacOS doesn't really have a "default" window position, you're actually meant to center the window yourself, - * so if the user passes MwDEFAULT respond appropriately. Also for child windows just have it be 0. + * MacOS doesn't really have a "default" window position, you're actually + * meant to center the window yourself, so if the user passes MwDEFAULT + * respond appropriately. Also for child windows just have it be 0. */ if(x == MwDEFAULT) { x = r ? ([[NSScreen mainScreen] frame].size.width / 2.) - (width / 2.) : 0; } if(y == MwDEFAULT) { - y = r ? ([[NSScreen mainScreen] frame].size.height / 2.) - (height / 2.) : 0; + y = r ? ([[NSScreen mainScreen] frame].size.height / 2.) - (height / 2.) + : 0; } - c->application = [NSApplication sharedApplication]; + c->application = [MilskoCocoaApplication sharedApplication]; c->rect = NSMakeRect(x, y, width, height); if(parent == NULL) { @@ -130,7 +167,6 @@ static NSRect localRectFlip(NSRect originFrame, NSView* view) { [c->window makeKeyAndOrderFront:c->application]; [c->window makeFirstResponder:c->view]; - [c->window setAcceptsMouseMovedEvents:MwTRUE]; c->view = [[MilskoCocoaView alloc] initWithFrame:c->rect]; [c->view retain]; @@ -140,29 +176,31 @@ static NSRect localRectFlip(NSRect originFrame, NSView* view) { [c->application setActivationPolicy:0 /* NSApplicationActivationPolicyRegular */]; } - [c->application activateIgnoringOtherApps:true]; + [c->application activateIgnoringOtherApps:MwTRUE]; [c->application setDelegate:[[MilskoCocoaApplicationDelegate alloc] initWithAppl:c->application]]; [c->application retain]; + + [c->view addTrackingRect:c->rect owner:c->view userData:NULL assumeInside:MwFALSE]; } else { MilskoCocoa* p = parent->cocoa.real; c->window = p->window; - if(parent) { - MilskoCocoa* topmost = p; - NSRect rect = localRectFlip(c->rect, p->view); - printf("%0.2f %0.2f %0.2f %0.2f\n", c->rect.origin.x, c->rect.origin.y, c->rect.size.width, c->rect.size.height); - c->view = [[MilskoCocoaView alloc] initWithFrame:rect]; - [c->view setBounds:c->rect]; - } else { - c->view = [[MilskoCocoaView alloc] initWithFrame:c->rect]; - } + NSRect rect = localRectFlip(c->rect, p->view); + c->view = [[MilskoCocoaView alloc] initWithFrame:rect]; + [c->view setBounds:c->rect]; + [c->view retain]; [c->view setNeedsDisplay:TRUE]; + [c->view setChild]; + + [c->view addTrackingRect:c->rect owner:c->view userData:NULL assumeInside:MwFALSE]; + [p->view addSubview:c->view]; [p->window setContentView:p->view]; } + [c->window setAcceptsMouseMovedEvents:MwTRUE]; c->handle = [[MilskoFakePointer alloc] initWithFrame:NSMakeRect(0, 0, 1, 1)]; [c->handle retain]; @@ -208,11 +246,11 @@ static NSRect localRectFlip(NSRect originFrame, NSView* view) { NSRectFill(self->view.bounds); for(i = 0; i < points_count; i++) { if(i == 0) { - [path moveToPoint:NSMakePoint(points[i].x, _rect.size.height - - points[i].y)]; + [path moveToPoint:NSMakePoint(points[i].x, + _rect.size.height - points[i].y)]; } else { - [path lineToPoint:NSMakePoint(points[i].x, _rect.size.height - - points[i].y)]; + [path lineToPoint:NSMakePoint(points[i].x, + _rect.size.height - points[i].y)]; } } @@ -262,6 +300,7 @@ static NSRect localRectFlip(NSRect originFrame, NSView* view) { frame = localRectFlip(frame, parent->cocoa.real->view); [self->view setBounds:frame]; } + self->_eventsPending = MwTRUE; }; - (void)setW:(int)w H:(int)h { NSRect frame = [self->window frame]; @@ -276,23 +315,28 @@ static NSRect localRectFlip(NSRect originFrame, NSView* view) { } else { [self->window setFrame:frame display:YES animate:false]; } + self->_eventsPending = MwTRUE; }; - (int)pending { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + MwBool isPending = [self->application pending]; [NSApp runModalSession:self->modalSession]; [pool release]; - return 1; + return _forceRender || _eventsPending || isPending; }; - (void)getNextEvent { - [self eventProcess:self->lastEvent]; - + MwLL h = [self->handle pointer]; if(_forceRender) { - MwLL h = [self->handle pointer]; MwLLDispatch(h, draw, NULL); [self->view setNeedsDisplay:true]; _forceRender = MwFALSE; } + if(_eventsPending) { + MwLLDispatch(h, draw, NULL); + [self->view setNeedsDisplay:true]; + _eventsPending = MwFALSE; + } [self sendClipboardEvent]; if(self->pointerLocked && [self->window isMainWindow] && self->lastEvent) { @@ -306,258 +350,6 @@ static NSRect localRectFlip(NSRect originFrame, NSView* view) { [self->application updateWindows]; }; -- (void)eventProcess:(NSEvent*)ev { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSWindow* win = [ev window]; - MwLL h; - MwBool doSendEvent = MwTRUE; - - if(!win) { - [pool release]; - return; - } - - if([[[win contentView] subviews] count] == 0) { - printf("no subviews on %p\n", win); - [pool release]; - return; - } else { - h = [((MilskoFakePointer*)[[[win contentView] subviews] - objectAtIndex:0]) pointer]; - } - - switch([ev type]) { - case NSLeftMouseDragged: - case NSRightMouseDragged: - case NSOtherMouseDragged: - case NSMouseMoved: { - MwPoint pos; - NSPoint pos_translated = pointFlip([ev locationInWindow]); - pos.x = pos_translated.x; - pos.y = pos_translated.y; - MwLLDispatch(h, move, &pos); - break; - } - case NSLeftMouseDown: - case NSRightMouseDown: - case NSOtherMouseDown: - case NSLeftMouseUp: - case NSRightMouseUp: - case NSOtherMouseUp: { - [self handleMouseEvent:ev ll:h]; - break; - } - - case NSMouseEntered: - MwLLDispatch(h, focus_in, NULL); - [self->cursor push]; - break; - case NSMouseExited: - MwLLDispatch(h, focus_out, NULL); - [self->cursor pop]; - break; - case NSKeyDown: - case NSKeyUp: { - [self handleKeyEvent:ev ll:h]; - break; - } - case NSCursorUpdate: - [self->cursor set]; - break; - case NSScrollWheel: - break; - default: - /* mute bizarre "unknown subtype" errors that flood the console */ - break; - }; - if(doSendEvent) { - [win sendEvent:ev]; - } - [pool release]; -} - -- (void)handleMouseEvent:(NSEvent*)ev ll:(MwLL)ll { - MwLLMouse mouse; - MwBool isDown = MwTRUE; - NSPoint mousePoint = [ev locationInWindow]; - mousePoint.y = [[ev window] frame].size.height - mousePoint.y; - MwLL this = [self->handle pointer]; - - switch([ev type]) { - case NSLeftMouseUp: - isDown = MwFALSE; - case NSEventTypeLeftMouseDragged: - case NSLeftMouseDown: - mouse.button = MwLLMouseLeft; - break; - case NSRightMouseUp: - isDown = MwFALSE; - case NSRightMouseDown: - case NSEventTypeRightMouseDragged: - mouse.button = MwLLMouseRight; - break; - case NSOtherMouseUp: - isDown = MwFALSE; - case NSOtherMouseDown: - case NSEventTypeOtherMouseDragged: - mouse.button = MwLLMouseMiddle; - break; - default: - break; - } - mouse.point.x = mousePoint.x; - mouse.point.y = mousePoint.y; - - printf("%s at %d %d\n", isDown ? "down" : "up", mouse.point.x, mouse.point.y); - - if(isDown) { - MwLLDispatch(ll, down, &mouse); - } else { - MwLLDispatch(ll, up, &mouse); - } -} - -- (void)handleKeyEvent:(NSEvent*)ev ll:(MwLL)ll { - int ch; - MwLL this = [self->handle pointer]; - enum { - kVK_ANSI_A = 0x00, - kVK_ANSI_S = 0x01, - kVK_ANSI_D = 0x02, - kVK_ANSI_F = 0x03, - kVK_ANSI_H = 0x04, - kVK_ANSI_G = 0x05, - kVK_ANSI_Z = 0x06, - kVK_ANSI_X = 0x07, - kVK_ANSI_C = 0x08, - kVK_ANSI_V = 0x09, - kVK_ANSI_B = 0x0B, - kVK_ANSI_Q = 0x0C, - kVK_ANSI_W = 0x0D, - kVK_ANSI_E = 0x0E, - kVK_ANSI_R = 0x0F, - kVK_ANSI_Y = 0x10, - kVK_ANSI_T = 0x11, - kVK_ANSI_1 = 0x12, - kVK_ANSI_2 = 0x13, - kVK_ANSI_3 = 0x14, - kVK_ANSI_4 = 0x15, - kVK_ANSI_6 = 0x16, - kVK_ANSI_5 = 0x17, - kVK_ANSI_Equal = 0x18, - kVK_ANSI_9 = 0x19, - kVK_ANSI_7 = 0x1A, - kVK_ANSI_Minus = 0x1B, - kVK_ANSI_8 = 0x1C, - kVK_ANSI_0 = 0x1D, - kVK_ANSI_RightBracket = 0x1E, - kVK_ANSI_O = 0x1F, - kVK_ANSI_U = 0x20, - kVK_ANSI_LeftBracket = 0x21, - kVK_ANSI_I = 0x22, - kVK_ANSI_P = 0x23, - kVK_ANSI_L = 0x25, - kVK_ANSI_J = 0x26, - kVK_ANSI_Quote = 0x27, - kVK_ANSI_K = 0x28, - kVK_ANSI_Semicolon = 0x29, - kVK_ANSI_Backslash = 0x2A, - kVK_ANSI_Comma = 0x2B, - kVK_ANSI_Slash = 0x2C, - kVK_ANSI_N = 0x2D, - kVK_ANSI_M = 0x2E, - kVK_ANSI_Period = 0x2F, - kVK_ANSI_Grave = 0x32, - kVK_Return = 0x24, - kVK_Space = 0x31, - kVK_Escape = 0x35, - kVK_Shift = 0x38, - kVK_Control = 0x3B, - kVK_RightShift = 0x3C, - kVK_RightControl = 0x3E, - kVK_LeftArrow = 0x7B, - kVK_RightArrow = 0x7C, - kVK_DownArrow = 0x7D, - kVK_UpArrow = 0x7E - }; -#define KEY_CASE(x, y) \ - case x: \ - ch = y; \ - break; - switch([ev keyCode]) { - KEY_CASE(kVK_ANSI_A, 'a') - KEY_CASE(kVK_ANSI_B, 'b') - KEY_CASE(kVK_ANSI_C, 'c') - KEY_CASE(kVK_ANSI_D, 'd') - KEY_CASE(kVK_ANSI_E, 'e') - KEY_CASE(kVK_ANSI_F, 'f') - KEY_CASE(kVK_ANSI_G, 'g') - KEY_CASE(kVK_ANSI_H, 'h') - KEY_CASE(kVK_ANSI_I, 'i') - KEY_CASE(kVK_ANSI_J, 'j') - KEY_CASE(kVK_ANSI_K, 'k') - KEY_CASE(kVK_ANSI_L, 'l') - KEY_CASE(kVK_ANSI_M, 'm') - KEY_CASE(kVK_ANSI_N, 'n') - KEY_CASE(kVK_ANSI_O, 'o') - KEY_CASE(kVK_ANSI_P, 'p') - KEY_CASE(kVK_ANSI_Q, 'q') - KEY_CASE(kVK_ANSI_R, 'r') - KEY_CASE(kVK_ANSI_S, 's') - KEY_CASE(kVK_ANSI_T, 't') - KEY_CASE(kVK_ANSI_U, 'u') - KEY_CASE(kVK_ANSI_V, 'v') - KEY_CASE(kVK_ANSI_W, 'w') - KEY_CASE(kVK_ANSI_X, 'x') - KEY_CASE(kVK_ANSI_Y, 'y') - KEY_CASE(kVK_ANSI_Z, 'z') - KEY_CASE(kVK_ANSI_0, '0') - KEY_CASE(kVK_ANSI_1, '1') - KEY_CASE(kVK_ANSI_2, '2') - KEY_CASE(kVK_ANSI_3, '3') - KEY_CASE(kVK_ANSI_4, '4') - KEY_CASE(kVK_ANSI_5, '5') - KEY_CASE(kVK_ANSI_6, '6') - KEY_CASE(kVK_ANSI_7, '7') - KEY_CASE(kVK_ANSI_8, '8') - KEY_CASE(kVK_ANSI_9, '9') - KEY_CASE(kVK_ANSI_Quote, '\"') - KEY_CASE(kVK_ANSI_Grave, '`') - KEY_CASE(kVK_ANSI_Backslash, '/') - KEY_CASE(kVK_ANSI_Comma, ',') - KEY_CASE(kVK_ANSI_Equal, '=') - KEY_CASE(kVK_Escape, MwLLKeyEscape) - KEY_CASE(kVK_ANSI_LeftBracket, '[') - KEY_CASE(kVK_ANSI_Minus, '-') - KEY_CASE(kVK_ANSI_Period, '.') - KEY_CASE(kVK_Return, MwLLKeyEnter) - KEY_CASE(kVK_ANSI_RightBracket, ']') - KEY_CASE(kVK_ANSI_Semicolon, ';') - KEY_CASE(kVK_ANSI_Slash, '\\') - KEY_CASE(kVK_Space, ' ') - KEY_CASE(kVK_Control, MwLLKeyControl) - KEY_CASE(kVK_RightControl, MwLLKeyControl) - KEY_CASE(kVK_Shift, MwLLKeyLeftShift) - KEY_CASE(kVK_RightShift, MwLLKeyRightShift) - KEY_CASE(kVK_DownArrow, MwLLKeyDown) - KEY_CASE(kVK_LeftArrow, MwLLKeyLeft) - KEY_CASE(kVK_RightArrow, MwLLKeyRight) - KEY_CASE(kVK_UpArrow, MwLLKeyUp) - } - switch([ev type]) { - case NSKeyDown: - MwLLDispatch(this, key, &ch); - MwLLDispatch(ll, key, &ch); - break; - case NSKeyUp: - MwLLDispatch(this, key_released, &ch); - MwLLDispatch(ll, key_released, &ch); - break; - default: - break; - } -} - - (void)sendClipboardEvent { /*NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSPasteboard* pasteboard = [NSPasteboard generalPasteboard]; @@ -772,14 +564,42 @@ static NSRect localRectFlip(NSRect originFrame, NSView* view) { return window; } +- (void)nudge { + self->_eventsPending = MwTRUE; +} + +- (void)pushCursor { + [self->cursor push]; +} +- (void)popCursor { + [self->cursor pop]; +} + - (MilskoFakePointer*)getHandle { return handle; } @end +@implementation MilskoCocoaApplication +- (void)sendEvent:(NSEvent*)event { + self->doPending = MwTRUE; + [super sendEvent:event]; +} +- (MwBool)pending { + if(self->doPending) { + self->doPending = MwFALSE; + return MwTRUE; + } + return MwFALSE; +} +@end + @implementation MilskoCocoaView - (id)initWithFrame:(NSRect)frame { + givenRect = frame; + x = frame.origin.x; + y = frame.origin.y; width = frame.size.width; height = frame.size.height; self = [super initWithFrame:frame]; @@ -792,9 +612,15 @@ static NSRect localRectFlip(NSRect originFrame, NSView* view) { [self initRepAndContextWithWidth:width Height:height]; } + self->_child = MwFALSE; + return self; } +- (void)setChild { + self->_child = MwTRUE; +} + - (NSGraphicsContext*)context { return self->context; } @@ -871,16 +697,238 @@ static NSRect localRectFlip(NSRect originFrame, NSView* view) { self->height = newSize.height; } -- (void)displayRect:(NSRect)rect { - (void)rect; -}; - -- (BOOL)acceptsFirstResponder { - return MwTRUE; +- (BOOL)canBecomeKeyView { + return YES; } -- (BOOL)performKeyEquivalent:(NSEvent*)event { - (void)event; - return MwTRUE; +- (BOOL)acceptsFirstResponder { + return YES; +} + +- (NSView*)hitTest:(NSPoint)aPoint { + if(self->_child) { + return NSPointInRect(aPoint, givenRect) ? self : nil; + } else { + return [super hitTest:aPoint]; + } +} + +- (void)handleKeyEvent:(NSEvent*)ev ll:(MwLL)ll down:(MwBool)isDown { + int ch; + enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_Return = 0x24, + kVK_Space = 0x31, + kVK_Escape = 0x35, + kVK_Shift = 0x38, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightControl = 0x3E, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E + }; +#define KEY_CASE(x, y) \ + case x: \ + ch = y; \ + break; + switch([ev keyCode]) { + KEY_CASE(kVK_ANSI_A, 'a') + KEY_CASE(kVK_ANSI_B, 'b') + KEY_CASE(kVK_ANSI_C, 'c') + KEY_CASE(kVK_ANSI_D, 'd') + KEY_CASE(kVK_ANSI_E, 'e') + KEY_CASE(kVK_ANSI_F, 'f') + KEY_CASE(kVK_ANSI_G, 'g') + KEY_CASE(kVK_ANSI_H, 'h') + KEY_CASE(kVK_ANSI_I, 'i') + KEY_CASE(kVK_ANSI_J, 'j') + KEY_CASE(kVK_ANSI_K, 'k') + KEY_CASE(kVK_ANSI_L, 'l') + KEY_CASE(kVK_ANSI_M, 'm') + KEY_CASE(kVK_ANSI_N, 'n') + KEY_CASE(kVK_ANSI_O, 'o') + KEY_CASE(kVK_ANSI_P, 'p') + KEY_CASE(kVK_ANSI_Q, 'q') + KEY_CASE(kVK_ANSI_R, 'r') + KEY_CASE(kVK_ANSI_S, 's') + KEY_CASE(kVK_ANSI_T, 't') + KEY_CASE(kVK_ANSI_U, 'u') + KEY_CASE(kVK_ANSI_V, 'v') + KEY_CASE(kVK_ANSI_W, 'w') + KEY_CASE(kVK_ANSI_X, 'x') + KEY_CASE(kVK_ANSI_Y, 'y') + KEY_CASE(kVK_ANSI_Z, 'z') + KEY_CASE(kVK_ANSI_0, '0') + KEY_CASE(kVK_ANSI_1, '1') + KEY_CASE(kVK_ANSI_2, '2') + KEY_CASE(kVK_ANSI_3, '3') + KEY_CASE(kVK_ANSI_4, '4') + KEY_CASE(kVK_ANSI_5, '5') + KEY_CASE(kVK_ANSI_6, '6') + KEY_CASE(kVK_ANSI_7, '7') + KEY_CASE(kVK_ANSI_8, '8') + KEY_CASE(kVK_ANSI_9, '9') + KEY_CASE(kVK_ANSI_Quote, '\"') + KEY_CASE(kVK_ANSI_Grave, '`') + KEY_CASE(kVK_ANSI_Backslash, '/') + KEY_CASE(kVK_ANSI_Comma, ',') + KEY_CASE(kVK_ANSI_Equal, '=') + KEY_CASE(kVK_Escape, MwLLKeyEscape) + KEY_CASE(kVK_ANSI_LeftBracket, '[') + KEY_CASE(kVK_ANSI_Minus, '-') + KEY_CASE(kVK_ANSI_Period, '.') + KEY_CASE(kVK_Return, MwLLKeyEnter) + KEY_CASE(kVK_ANSI_RightBracket, ']') + KEY_CASE(kVK_ANSI_Semicolon, ';') + KEY_CASE(kVK_ANSI_Slash, '\\') + KEY_CASE(kVK_Space, ' ') + KEY_CASE(kVK_Control, MwLLKeyControl) + KEY_CASE(kVK_RightControl, MwLLKeyControl) + KEY_CASE(kVK_Shift, MwLLKeyLeftShift) + KEY_CASE(kVK_RightShift, MwLLKeyRightShift) + KEY_CASE(kVK_DownArrow, MwLLKeyDown) + KEY_CASE(kVK_LeftArrow, MwLLKeyLeft) + KEY_CASE(kVK_RightArrow, MwLLKeyRight) + KEY_CASE(kVK_UpArrow, MwLLKeyUp) + } + if(isDown) { + recursive_dispatch_key(ll, &ch); + } else { + recursive_dispatch_key_released(ll, &ch); + } + [ll->cocoa.real nudge]; +} +- (void)mouseEntered:(NSEvent*)ev { + MwLL h = [((MilskoFakePointer*)[[self subviews] objectAtIndex:0]) pointer]; + MwLLDispatch(h, focus_in, NULL); + [h->cocoa.real pushCursor]; + [super mouseEntered:ev]; +} +- (void)mouseExited:(NSEvent*)ev { + MwLL h = [((MilskoFakePointer*)[[self subviews] objectAtIndex:0]) pointer]; + MwLLDispatch(h, focus_out, NULL); + [h->cocoa.real popCursor]; + [super mouseExited:ev]; +} +- (void)keyDown:(NSEvent*)ev { + MwLL h = [((MilskoFakePointer*)[[self subviews] objectAtIndex:0]) pointer]; + [self handleKeyEvent:ev ll:h down:MwTRUE]; + [super keyDown:ev]; +} +- (void)keyUp:(NSEvent*)ev { + MwLL h = [((MilskoFakePointer*)[[self subviews] objectAtIndex:0]) pointer]; + [self handleKeyEvent:ev ll:h down:MwFALSE]; + [super keyUp:ev]; +} + +- (void)mouseMoved:(NSEvent*)ev { + MwLLMouse mouse; + NSPoint mousePoint = [ev locationInWindow]; + MwLL this = [((MilskoFakePointer*)[[self subviews] objectAtIndex:0]) pointer]; + mousePoint.y = [[ev window] frame].size.height - mousePoint.y; + mouse.button = MwLLMouseLeft; + mouse.point.x = mousePoint.x; + mouse.point.y = mousePoint.y; + MwLLDispatch(this, move, &mouse); + [this->cocoa.real nudge]; + [super mouseMoved:ev]; +} +- (void)mouseDown:(NSEvent*)ev { + MwLLMouse mouse; + NSPoint mousePoint = [ev locationInWindow]; + MwLL this = [((MilskoFakePointer*)[[self subviews] objectAtIndex:0]) pointer]; + mousePoint.y = [[ev window] frame].size.height - mousePoint.y; + mouse.button = MwLLMouseLeft; + mouse.point.x = mousePoint.x; + mouse.point.y = mousePoint.y; + MwLLDispatch(this, down, &mouse); + [this->cocoa.real nudge]; + [super mouseDown:ev]; +} + +- (void)mouseUp:(NSEvent*)ev { + MwLLMouse mouse; + NSPoint mousePoint = [ev locationInWindow]; + MwLL this = [((MilskoFakePointer*)[[self subviews] objectAtIndex:0]) pointer]; + mousePoint.y = [[ev window] frame].size.height - mousePoint.y; + mouse.button = MwLLMouseLeft; + mouse.point.x = mousePoint.x; + mouse.point.y = mousePoint.y; + MwLLDispatch(this, up, &mouse); + [this->cocoa.real nudge]; + [super mouseUp:ev]; +} +- (void)rightMouseDown:(NSEvent*)ev { + MwLLMouse mouse; + NSPoint mousePoint = [ev locationInWindow]; + MwLL this = [((MilskoFakePointer*)[[self subviews] objectAtIndex:0]) pointer]; + mousePoint.y = [[ev window] frame].size.height - mousePoint.y; + mouse.button = MwLLMouseRight; + mouse.point.x = mousePoint.x; + mouse.point.y = mousePoint.y; + MwLLDispatch(this, down, &mouse); + [this->cocoa.real nudge]; + [super rightMouseDown:ev]; +} + +- (void)rightMouseUp:(NSEvent*)ev { + MwLLMouse mouse; + NSPoint mousePoint = [ev locationInWindow]; + MwLL this = [((MilskoFakePointer*)[[self subviews] objectAtIndex:0]) pointer]; + mousePoint.y = [[ev window] frame].size.height - mousePoint.y; + mouse.button = MwLLMouseRight; + mouse.point.x = mousePoint.x; + mouse.point.y = mousePoint.y; + MwLLDispatch(this, up, &mouse); + [this->cocoa.real nudge]; + [super rightMouseUp:ev]; } @end From 74779c8f4233192f9fa47771a11de395ead0f734 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 25 Mar 2026 18:21:27 -0700 Subject: [PATCH 032/195] apple: better polygons, revealing a bigger issue maybe --- src/backend/cocoa.m | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index d3fec7ebb..114cb3a5e 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -243,14 +243,16 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { [NSGraphicsContext setCurrentContext:ctx]; [nscolor setFill]; - NSRectFill(self->view.bounds); for(i = 0; i < points_count; i++) { - if(i == 0) { - [path moveToPoint:NSMakePoint(points[i].x, - _rect.size.height - points[i].y)]; + NSPoint p = NSMakePoint(points[i].x, [self->view frame].size.height - points[i].y); + if((i % 3) == 0) { + if(i != 0) { + [path lineToPoint:p]; + [path fill]; + } + [path moveToPoint:p]; } else { - [path lineToPoint:NSMakePoint(points[i].x, - _rect.size.height - points[i].y)]; + [path lineToPoint:p]; } } From bcb108ae5f52a5c3b6a3cbee4c6b8f96f1f5cb8f Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 25 Mar 2026 18:47:58 -0700 Subject: [PATCH 033/195] apple: 'more correct' polygons weren't correct at all --- src/backend/cocoa.m | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 114cb3a5e..57dea3be2 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -245,11 +245,7 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { [nscolor setFill]; for(i = 0; i < points_count; i++) { NSPoint p = NSMakePoint(points[i].x, [self->view frame].size.height - points[i].y); - if((i % 3) == 0) { - if(i != 0) { - [path lineToPoint:p]; - [path fill]; - } + if(i == 0) { [path moveToPoint:p]; } else { [path lineToPoint:p]; From 0bbbc51bb9f9418cbcd7c531125efc5dcb5f9557 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 25 Mar 2026 18:53:13 -0700 Subject: [PATCH 034/195] apple: fix polygon/pixmap coordinates, add line function --- src/backend/cocoa.m | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 57dea3be2..1632271e5 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -34,6 +34,9 @@ static NSRect localRectFlip(NSRect originFrame, NSView* view) { originFrame.size.width, originFrame.size.height); return destinationFrame; } +static NSPoint localPointFlip(NSPoint point, NSView* view) { + return localRectFlip(NSMakeRect(point.x, point.y, 0, 0), view).origin; +} /* Recursively dispatch a key event to a widget and its children */ static void recursive_dispatch_key(MwLL handle, int* k) { @@ -244,7 +247,7 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { [nscolor setFill]; for(i = 0; i < points_count; i++) { - NSPoint p = NSMakePoint(points[i].x, [self->view frame].size.height - points[i].y); + NSPoint p = localPointFlip(NSMakePoint(points[i].x, points[i].y), self->view); if(i == 0) { [path moveToPoint:p]; } else { @@ -262,8 +265,41 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { [pool release]; }; - (void)lineWithPoints:(MwPoint*)points color:(MwLLColor)color { - (void)points; - (void)color; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSGraphicsContext* ctx = [self->view context]; + if(ctx) { + int i; + NSBezierPath* path = [NSBezierPath bezierPath]; + /* whatever rect we use for coordinate flipping */ + NSRect _rect = parent ? [self->view bounds] : [self->window frame]; + + NSColor* nscolor = + [NSColor colorWithCalibratedRed:color->common.red / 255. + green:color->common.green / 255. + blue:color->common.blue / 255. + alpha:1.0]; + + [NSGraphicsContext saveGraphicsState]; + [NSGraphicsContext setCurrentContext:ctx]; + + [nscolor setFill]; + for(i = 0; i < 2; i++) { + NSPoint p = localPointFlip(NSMakePoint(points[i].x, points[i].y), self->view); + if(i == 0) { + [path moveToPoint:p]; + } else { + [path lineToPoint:p]; + } + } + + [path closePath]; + [path stroke]; + + [NSGraphicsContext restoreGraphicsState]; + + [self->view setNeedsDisplay:YES]; + } + [pool release]; }; - (void)getX:(int*)x Y:(int*)y W:(unsigned int*)w H:(unsigned int*)h { NSRect frame; @@ -394,7 +430,7 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { [NSGraphicsContext setCurrentContext:ctx]; [[p image] - drawInRect:NSMakeRect(_rect->x, _rect->y, _rect->width, _rect->height) + drawInRect:localRectFlip(NSMakeRect(_rect->x, _rect->y, _rect->width, _rect->height), self->view) fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0]; From 90706b184f0c9e936c1481933fa2c584e91ae95a Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 25 Mar 2026 19:09:01 -0700 Subject: [PATCH 035/195] apple: assorted fixes --- src/backend/cocoa.m | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 1632271e5..7a138af40 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -1,9 +1,6 @@ -#include "Mw/BaseTypes.h" -#include "Mw/LowLevel.h" #include -#include #include "../../external/stb_ds.h" -#include "Mw/TypeDefs.h" +#include "Mw/LowLevel/Cocoa.h" #ifdef __clang__ #pragma clang push @@ -904,9 +901,8 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { - (void)mouseMoved:(NSEvent*)ev { MwLLMouse mouse; - NSPoint mousePoint = [ev locationInWindow]; + NSPoint mousePoint = pointFlip([ev locationInWindow]); MwLL this = [((MilskoFakePointer*)[[self subviews] objectAtIndex:0]) pointer]; - mousePoint.y = [[ev window] frame].size.height - mousePoint.y; mouse.button = MwLLMouseLeft; mouse.point.x = mousePoint.x; mouse.point.y = mousePoint.y; @@ -914,6 +910,10 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { [this->cocoa.real nudge]; [super mouseMoved:ev]; } +- (BOOL)mouseDownCanMoveWindow { + return NO; +} + - (void)mouseDown:(NSEvent*)ev { MwLLMouse mouse; NSPoint mousePoint = [ev locationInWindow]; @@ -990,11 +990,12 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { - (NSSize)windowWillResize:(NSWindow*)win toSize:(NSSize)frameSize; { if([[[win contentView] subviews] count] >= 1) { - MilskoFakePointer* ptr = [[[win contentView] subviews] objectAtIndex:0]; - MwLL h = [ptr pointer]; - - MwLLDispatch(h, resize, NULL); - MwLLDispatch(h, draw, NULL); + NSView* ptr = [[[win contentView] subviews] objectAtIndex:0]; + if([ptr isKindOfClass:[MilskoFakePointer class]]) { + MwLL h = [(MilskoFakePointer*)ptr pointer]; + MwLLDispatch(h, resize, NULL); + // MwLLDispatch(h, draw, NULL); + } } return frameSize; } @@ -1159,6 +1160,7 @@ static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, (void)handle; MwLLPixmap r = malloc(sizeof(*r)); + memset(r, 0, sizeof(*r)); r->common.raw = malloc(4 * width * height); memcpy(r->common.raw, data, 4 * width * height); @@ -1169,7 +1171,6 @@ static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, r->cocoa.real = [MilskoCocoaPixmap newWithWidth:width height:height]; MwLLPixmapUpdate(r); - free(r->common.raw); return r; } From 6ba77904d62df440f79c4b349b4afb3c1eb3db83 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 25 Mar 2026 21:06:32 -0700 Subject: [PATCH 036/195] fix hitTest --- src/backend/cocoa.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 7a138af40..04ce17edf 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -737,7 +737,7 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { - (NSView*)hitTest:(NSPoint)aPoint { if(self->_child) { - return NSPointInRect(aPoint, givenRect) ? self : nil; + return NSPointInRect(aPoint, [self bounds]) ? self : nil; } else { return [super hitTest:aPoint]; } From 70f7f8f0842f33e4c28c091ee9f812cd6e22ebd7 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Fri, 27 Mar 2026 11:05:15 +0900 Subject: [PATCH 037/195] fix box bug --- src/widget/box.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/widget/box.c b/src/widget/box.c index 99f3e0772..4c4ae687c 100644 --- a/src/widget/box.c +++ b/src/widget/box.c @@ -53,6 +53,7 @@ static void layout(MwWidget handle) { sz -= s + Margin; } else { sum += n; + sz -= Margin; } } From 8d7016367e8f2f40b9d91899250e1999fa1a5304 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 26 Mar 2026 14:40:21 -0700 Subject: [PATCH 038/195] experimental rounded corners idea --- include/Mw/Draw.h | 6 +- include/Mw/LowLevel.h | 9 +- include/Mw/LowLevel/Wayland.h | 3 + src/backend/wayland.c | 3 + src/draw.c | 232 ++++++++++++++++++++++++++++------ src/widget/box.c | 2 +- src/widget/combobox.c | 2 +- src/widget/frame.c | 2 +- src/widget/image.c | 2 +- src/widget/listbox.c | 6 +- src/widget/menu.c | 2 +- src/widget/progressbar.c | 2 +- src/widget/separator.c | 2 +- src/widget/submenu.c | 2 +- src/widget/treeview.c | 8 +- src/widget/window.c | 2 +- 16 files changed, 223 insertions(+), 62 deletions(-) diff --git a/include/Mw/Draw.h b/include/Mw/Draw.h index b90d4e423..4fb74c201 100644 --- a/include/Mw/Draw.h +++ b/include/Mw/Draw.h @@ -53,7 +53,7 @@ MWDECL void MwDrawRect(MwWidget handle, MwRect* rect, MwLLColor color); * @param rect Rectangle area * @param color Color */ -MWDECL void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color); +MWDECL void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color, int rounded); /*! * @brief Draws a frame @@ -63,7 +63,7 @@ MWDECL void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color); * @param invert Invert the 3D border color or not * @warning `rect` gets changed to the area of rectangle inside */ -MWDECL void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert); +MWDECL void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int rounded); /*! * @brief Does the DrawFrame/DrawRect combo used for drawing widget. @@ -95,7 +95,7 @@ MWDECL void MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int i * @param same Same as dark color * @warning `rect` gets changed to the area of rectangle inside */ -MWDECL void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border, int diff, int same); +MWDECL void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border, int diff, int same, int rounded); /*! * @brief Creates a pixmap from image diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index 9766d052f..d7ddb4b45 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -34,10 +34,11 @@ enum MwLLBackends { }; struct _MwLLCommon { - void* user; - int copy_buffer; - int type; - int coordinate_type; + void* user; + int copy_buffer; + int type; + int coordinate_type; + MwBool supports_transparency; MwLLHandler handler; }; diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index c24ce3cec..de7828ad5 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -123,6 +123,7 @@ typedef struct wayland_call_table { void (*cairo_fill)(cairo_t* cr); void (*cairo_pattern_set_filter)(cairo_pattern_t* pattern, cairo_filter_t filter); + void (*cairo_set_antialias)(cairo_t*, cairo_antialias_t); } wayland_call_table_t; @@ -201,6 +202,7 @@ MwInline int wayland_load_funcs() { CAIRO_FUNC(cairo_rectangle); CAIRO_FUNC(cairo_new_path); CAIRO_FUNC(cairo_set_line_cap); + CAIRO_FUNC(cairo_set_antialias); CAIRO_FUNC(cairo_set_source_rgba); CAIRO_FUNC(cairo_set_source_rgb); CAIRO_FUNC(cairo_reset_clip); @@ -257,6 +259,7 @@ MwInline int wayland_load_funcs() { #define cairo_rectangle wl_call_tbl.cairo_rectangle #define cairo_new_path wl_call_tbl.cairo_new_path #define cairo_set_line_cap wl_call_tbl.cairo_set_line_cap +#define cairo_set_antialias wl_call_tbl.cairo_set_antialias #define cairo_set_source_rgba wl_call_tbl.cairo_set_source_rgba #define cairo_set_source_rgb wl_call_tbl.cairo_set_source_rgb #define cairo_reset_clip wl_call_tbl.cairo_reset_clip diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 5ba779b1c..f747955e2 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1972,6 +1972,9 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { int i; + clip(handle); + + cairo_set_antialias(handle->wayland.front_cairo, CAIRO_ANTIALIAS_NONE); cairo_set_line_cap(handle->wayland.front_cairo, CAIRO_LINE_CAP_SQUARE); cairo_set_source_rgb(handle->wayland.front_cairo, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); cairo_new_path(handle->wayland.front_cairo); diff --git a/src/draw.c b/src/draw.c index 4286d6696..274623772 100644 --- a/src/draw.c +++ b/src/draw.c @@ -11,9 +11,12 @@ #include "../external/stb_ds.h" +#define BORDER_ROUNDNESS 10 +#define BORDER_SMOOTHNESS 50 + static int get_color_diff(MwWidget handle) { if(MwGetInteger(handle, MwNmodernLook)) { - return 46; + return 23; } else { return 80; } @@ -29,7 +32,7 @@ static int hex(const char* txt, int len) { n = c - 'a' + 10; } else if('A' <= c && c <= 'F') { n = c - 'A' + 10; - } else if('0' <= c && c <= '9') { + } else if('0' <= c && c <= 'g') { n = c - '0'; } r = r << 4; @@ -102,14 +105,15 @@ void MwDrawRect(MwWidget handle, MwRect* rect, MwLLColor color) { MwLLPolygon(handle->lowlevel, p, 4, color); } -void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color) { +void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color, int rounded) { MwLLPixmap pixmap; - int y; + int y, i; double darken = 0.; int ColorDiff = get_color_diff(handle); double darkenStep = (ColorDiff / 4.) / rect->height; unsigned long sz = 1 * rect->height * 4; unsigned char* data = malloc(sz); + MwRect r = *rect; memset(data, 0, sz); for(y = 0; y < rect->height; y++) { @@ -124,18 +128,64 @@ void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color) { } pixmap = MwLLCreatePixmap(handle->lowlevel, data, 1, rect->height); - MwLLDrawPixmap(handle->lowlevel, rect, pixmap); + if(rounded && rect->height >= (BORDER_ROUNDNESS * 2) && rect->width >= (BORDER_ROUNDNESS * 2)) { + int xt; + int x = rect->x + (BORDER_ROUNDNESS + 1); + int y = rect->y + (BORDER_ROUNDNESS + 1); + for(i = 0; i < BORDER_ROUNDNESS; i++) { + double point = ((i + (M_PI * 4)) / 7.); + double point2 = (((i + 1) + (M_PI * 4)) / 7.); + int x2 = x - (sin(point2) * BORDER_ROUNDNESS); + r.x = x - (sin(point) * BORDER_ROUNDNESS); + r.y = y + (cos(point) * BORDER_ROUNDNESS); + r.width = (x - (sin(point + 1) * BORDER_ROUNDNESS)) - r.x; + r.height = (rect->height - ((r.y - rect->y) * 2) - 1); + MwLLDrawPixmap(handle->lowlevel, &r, pixmap); + for(xt = x; xt < x2; xt++) { + r.x = xt; + r.y = y + (cos(point2) * BORDER_ROUNDNESS); + r.height = (rect->height - ((r.y - rect->y)) - 1); + MwLLDrawPixmap(handle->lowlevel, &r, pixmap); + } + } + r = *rect; + r.x += BORDER_ROUNDNESS; + r.width -= (BORDER_ROUNDNESS * 2); + r.height -= 1; + MwLLDrawPixmap(handle->lowlevel, &r, pixmap); + r = *rect; + x = (rect->x + rect->width) - (BORDER_ROUNDNESS + 2); + y = rect->y + (BORDER_ROUNDNESS + 1); + for(i = 0; i < BORDER_ROUNDNESS; i++) { + double point = ((i + (M_PI * 4)) / 7.); + double point2 = (((i + 1) + (M_PI * 4)) / 7.); + int x2 = x + (sin(point2) * BORDER_ROUNDNESS); + r.x = x + (sin(point) * BORDER_ROUNDNESS); + r.y = y + (cos(point) * BORDER_ROUNDNESS); + r.width = 1; + r.height = (rect->height - ((r.y - rect->y) * 2) - 1); + MwLLDrawPixmap(handle->lowlevel, &r, pixmap); + for(xt = x; xt < x2; xt++) { + r.x = xt; + r.y = y + (cos(point2) * BORDER_ROUNDNESS); + r.height = (rect->height - ((r.y - rect->y) * 2) - 2); + MwLLDrawPixmap(handle->lowlevel, &r, pixmap); + } + } + } else { + MwLLDrawPixmap(handle->lowlevel, &r, pixmap); + } MwLLDestroyPixmap(pixmap); free(data); } -void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert) { +void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int rounded) { int inv; if((inv = MwGetInteger(handle, MwNforceInverted)) != MwDEFAULT && inv) invert = 1; if(MwGetInteger(handle, MwNmodernLook)) { - MwDrawFrameEx(handle, rect, color, invert, MwDefaultBorderWidth(handle), 0, 0); + MwDrawFrameEx(handle, rect, color, invert, MwDefaultBorderWidth(handle), 0, 0, rounded); } else { int diff = get_color_diff(handle) / 3 * 2; @@ -143,11 +193,11 @@ void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert) { int i; int st = invert ? 1 : 0; for(i = st; i < st + 2; i++) { - if((i % 2) == 0) MwDrawFrameEx(handle, rect, color, invert, MwDefaultBorderWidth(handle) - 1, -diff, (handle->parent == NULL || handle->parent->lowlevel == NULL) ? 1 : 0); - if((i % 2) == 1) MwDrawFrameEx(handle, rect, color, invert, 1, diff, 0); + if((i % 2) == 0) MwDrawFrameEx(handle, rect, color, invert, MwDefaultBorderWidth(handle) - 1, -diff, (handle->parent == NULL || handle->parent->lowlevel == NULL) ? 1 : 0, 0); + if((i % 2) == 1) MwDrawFrameEx(handle, rect, color, invert, 1, diff, 0, 0); } } else { - MwDrawFrameEx(handle, rect, color, invert, 1, 0, 0); + MwDrawFrameEx(handle, rect, color, invert, 1, 0, 0, 0); } } } @@ -156,11 +206,11 @@ void MwDrawWidgetBack(MwWidget handle, MwRect* rect, MwLLColor color, int invert MwLLColor col; if(border) { - MwDrawFrame(handle, rect, color, invert); + MwDrawFrame(handle, rect, color, invert, handle->lowlevel->common.supports_transparency); } col = invert ? MwLightenColor(handle, color, -8, -8, -8) : color; if(MwGetInteger(handle, MwNmodernLook)) { - MwDrawRectFading(handle, rect, col); + MwDrawRectFading(handle, rect, col, handle->lowlevel->common.supports_transparency); } else { MwDrawRect(handle, rect, col); } @@ -234,54 +284,158 @@ void MwDrawDiamond(MwWidget handle, MwRect* rect, MwLLColor color, int invert) { MwLLFreeColor(darker); } -void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border, int diff, int same) { - MwPoint p[6]; +void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border, int diff, int same, int rounded) { + MwPoint p[7]; int ColorDiff = get_color_diff(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); + int i; + MwLLColor middle = MwLLAllocColor(handle->lowlevel, + (lighter->common.red * darker->common.red) / 255, + (lighter->common.green * darker->common.green) / 255, + (lighter->common.blue * darker->common.blue) / 255); - p[0].x = rect->x; - p[0].y = rect->y; + if(rounded) { + /* top left edge */ + for(i = 0; i < BORDER_SMOOTHNESS; i += 2) { + MwPoint line[2]; + double point = ((i + (M_PI * (BORDER_SMOOTHNESS / 2.))) / (BORDER_SMOOTHNESS)); + int x = rect->x + (BORDER_ROUNDNESS + 2); + int y = rect->y + (BORDER_ROUNDNESS + 2); - p[1].x = rect->x + rect->width; - p[1].y = rect->y; + line[0].x = x - (sin(point) * BORDER_ROUNDNESS); + line[0].y = y + (cos(point) * BORDER_ROUNDNESS); + line[1].x = x - (sin(point + 1) * BORDER_ROUNDNESS); + line[1].y = y + (cos(point + 1) * BORDER_ROUNDNESS); + MwLLLine(handle->lowlevel, line, invert ? darker : lighter); + } - p[2].x = rect->x + rect->width - border; - p[2].y = rect->y + border; + p[0].x = rect->x + BORDER_ROUNDNESS; + p[0].y = rect->y; - p[3].x = rect->x + border; - p[3].y = rect->y + border; + p[1].x = rect->x + rect->width - BORDER_ROUNDNESS; + p[1].y = rect->y; - p[4].x = rect->x + border; - p[4].y = rect->y + rect->height - border; + p[2].x = rect->x + rect->width - border - BORDER_ROUNDNESS; + p[2].y = rect->y + border; - p[5].x = rect->x; - p[5].y = rect->y + rect->height; + p[3].x = rect->x + border - BORDER_ROUNDNESS; + p[3].y = rect->y + border + BORDER_ROUNDNESS; + p[4].x = rect->x + border - BORDER_ROUNDNESS; + p[4].y = rect->y + rect->height - border - BORDER_ROUNDNESS; + + p[5].x = rect->x + BORDER_ROUNDNESS; + p[5].y = rect->y + rect->height - BORDER_ROUNDNESS; + MwLLPolygon(handle->lowlevel, p, 6, invert ? darker : lighter); + + /* top right edge */ + for(i = 0; i < BORDER_SMOOTHNESS; i += 2) { + MwPoint line[2]; + double point = ((i + (M_PI * (BORDER_SMOOTHNESS / 2.))) / (BORDER_SMOOTHNESS)); + int x = (rect->x + rect->width) - (BORDER_ROUNDNESS + 2); + int y = rect->y + (BORDER_ROUNDNESS + 2); + double placeholder = (sin(point) * BORDER_ROUNDNESS); + line[0].x = x + placeholder; + line[0].y = y + (cos(point) * BORDER_ROUNDNESS); + line[1].x = x + (sin(point + 1) * BORDER_ROUNDNESS); + line[1].y = y + (cos(point + 1) * BORDER_ROUNDNESS); + MwLLLine(handle->lowlevel, line, middle); + } + } else { + p[0].x = rect->x; + p[0].y = rect->y; + + p[1].x = rect->x + rect->width; + p[1].y = rect->y; + + p[2].x = rect->x + rect->width - border; + p[2].y = rect->y + border; + p[3].x = rect->x + border; + p[3].y = rect->y + border; + + p[4].x = rect->x + border; + p[4].y = rect->y + rect->height - border; + + p[5].x = rect->x; + p[5].y = rect->y + rect->height; + } MwLLPolygon(handle->lowlevel, p, 6, invert ? darker : lighter); - p[0].x = rect->x + rect->width; - p[0].y = rect->y; + if(rounded && rect->height >= (BORDER_ROUNDNESS * 2) && rect->width >= (BORDER_ROUNDNESS * 2)) { + /* bottom left edge */ + for(i = 0; i < BORDER_SMOOTHNESS; i += 2) { + MwPoint line[2]; + double point = ((i + (M_PI * (BORDER_SMOOTHNESS / 2.))) / (BORDER_SMOOTHNESS)); + int x = rect->x + (BORDER_ROUNDNESS + 2); + int y = (rect->y + rect->height) - (BORDER_ROUNDNESS + 2); - p[1].x = rect->x + rect->width - border; - p[1].y = rect->y + border; + line[0].x = x - (sin(point) * BORDER_ROUNDNESS); + line[0].y = y - (cos(point) * BORDER_ROUNDNESS); + line[1].x = x - (sin(point + 1) * BORDER_ROUNDNESS); + line[1].y = y - (cos(point + 1) * BORDER_ROUNDNESS); + MwLLLine(handle->lowlevel, line, middle); + } + p[0].x = rect->x + BORDER_ROUNDNESS; + p[0].y = rect->y + 1; - p[2].x = rect->x + rect->width - border; - p[2].y = rect->y + rect->height - border; + p[1].x = rect->x + rect->width - border; + p[1].y = rect->y + border + BORDER_ROUNDNESS; - p[3].x = rect->x + border; - p[3].y = rect->y + rect->height - border; + p[2].x = rect->x + rect->width - border; + p[2].y = rect->y + rect->height - border - BORDER_ROUNDNESS; - p[4].x = rect->x; - p[4].y = rect->y + rect->height; + p[3].x = rect->x + rect->width - border - BORDER_ROUNDNESS; + p[3].y = rect->y + rect->height - border; - p[5].x = rect->x + rect->width; - p[5].y = rect->y + rect->height; + p[4].x = rect->x + border + BORDER_ROUNDNESS; + p[4].y = rect->y + rect->height - border; - MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker); + p[5].x = rect->x + BORDER_ROUNDNESS; + p[5].y = rect->y + rect->height - BORDER_ROUNDNESS; + + p[6].x = rect->x + rect->width - BORDER_ROUNDNESS; + p[6].y = rect->y + rect->height - BORDER_ROUNDNESS; + + MwLLPolygon(handle->lowlevel, p, 7, invert ? lighter : darker); + + /* bottom right edge */ + for(i = 0; i < BORDER_SMOOTHNESS; i += 2) { + MwPoint line[2]; + double point = ((i + (M_PI * (BORDER_SMOOTHNESS / 2.))) / (BORDER_SMOOTHNESS)); + int x = (rect->x + rect->width) - (BORDER_ROUNDNESS + 2); + int y = (rect->y + rect->height) - (BORDER_ROUNDNESS + 2); + + line[0].x = x + (sin(point) * BORDER_ROUNDNESS); + line[0].y = y - (cos(point) * BORDER_ROUNDNESS); + line[1].x = x + (sin(point + 1) * BORDER_ROUNDNESS); + line[1].y = y - (cos(point + 1) * BORDER_ROUNDNESS); + MwLLLine(handle->lowlevel, line, middle); + } + } else { + p[0].x = rect->x + rect->width; + p[0].y = rect->y; + + p[1].x = rect->x + rect->width - border; + p[1].y = rect->y + border; + + p[2].x = rect->x + rect->width - border; + p[2].y = rect->y + rect->height - border; + + p[3].x = rect->x + border; + p[3].y = rect->y + rect->height - border; + + p[4].x = rect->x; + p[4].y = rect->y + rect->height; + + p[5].x = rect->x + rect->width; + p[5].y = rect->y + rect->height; + MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker); + } MwLLFreeColor(lighter); MwLLFreeColor(darker); + MwLLFreeColor(middle); rect->x += border; rect->y += border; diff --git a/src/widget/box.c b/src/widget/box.c index 4c4ae687c..d8d474519 100644 --- a/src/widget/box.c +++ b/src/widget/box.c @@ -24,7 +24,7 @@ static void draw(MwWidget handle) { r.height = MwGetInteger(handle, MwNheight); if(MwGetInteger(handle, MwNhasBorder)) { - MwDrawFrame(handle, &r, base, MwGetInteger(handle, MwNinverted)); + MwDrawFrame(handle, &r, base, MwGetInteger(handle, MwNinverted), 0); } MwDrawRect(handle, &r, base); diff --git a/src/widget/combobox.c b/src/widget/combobox.c index 6b5437335..0672ff3ad 100644 --- a/src/widget/combobox.c +++ b/src/widget/combobox.c @@ -72,7 +72,7 @@ static void draw(MwWidget handle) { r.y += r.height; r.height = MwDefaultBorderWidth(handle) * 2; - MwDrawFrame(handle, &r, base, 0); + MwDrawFrame(handle, &r, base, 0, 0); MwLLFreeColor(text); MwLLFreeColor(base); diff --git a/src/widget/frame.c b/src/widget/frame.c index 117b0f8b9..3c2ffe99f 100644 --- a/src/widget/frame.c +++ b/src/widget/frame.c @@ -22,7 +22,7 @@ static void draw(MwWidget handle) { fr.y = 0; fr.width = MwGetInteger(handle, MwNwidth); fr.height = MwGetInteger(handle, MwNheight); - MwDrawFrame(handle, &fr, base, inverted); + MwDrawFrame(handle, &fr, base, inverted, 0); rr.x = MwDefaultBorderWidth(handle); rr.y = MwDefaultBorderWidth(handle); diff --git a/src/widget/image.c b/src/widget/image.c index 74ee0bfd6..cadddb323 100644 --- a/src/widget/image.c +++ b/src/widget/image.c @@ -20,7 +20,7 @@ static void draw(MwWidget handle) { r.width = MwGetInteger(handle, MwNwidth); r.height = MwGetInteger(handle, MwNheight); - if(MwGetInteger(handle, MwNhasBorder)) MwDrawFrame(handle, &r, base, MwGetInteger(handle, MwNinverted)); + if(MwGetInteger(handle, MwNhasBorder)) MwDrawFrame(handle, &r, base, MwGetInteger(handle, MwNinverted), 0); MwDrawRect(handle, &r, base); if(px != NULL) { diff --git a/src/widget/listbox.c b/src/widget/listbox.c index cb84e44c4..be467084a 100644 --- a/src/widget/listbox.c +++ b/src/widget/listbox.c @@ -208,7 +208,7 @@ static void frame_draw(MwWidget handle) { p.x = MwDefaultBorderWidth(handle); p.y = MwDefaultBorderWidth(handle); - MwDrawFrame(handle, &r, base, 1); + MwDrawFrame(handle, &r, base, 1, 0); MwDrawRect(handle, &r, base2); r = r2; @@ -282,7 +282,7 @@ static void frame_draw(MwWidget handle) { handle->bgcolor = NULL; } - MwDrawFrame(handle, &r, base, 1); + MwDrawFrame(handle, &r, base, 1, 0); MwLLFreeColor(text2); MwLLFreeColor(text); @@ -401,7 +401,7 @@ static void draw(MwWidget handle) { r.y = 0; r.width = get_col_width(lb, i); r.height = MwDefaultBorderWidth(handle) * 2 + MwTextHeight(handle, "M"); - MwDrawFrame(handle, &r, base, 0); + MwDrawFrame(handle, &r, base, 0, 0); x += MwDefaultBorderWidth(handle); diff --git a/src/widget/menu.c b/src/widget/menu.c index 44fc2fe57..e360f3d91 100644 --- a/src/widget/menu.c +++ b/src/widget/menu.c @@ -100,7 +100,7 @@ static void draw(MwWidget handle) { BEGIN_MENU_LOOP; if(m->sub[i]->wsub != NULL || (in_area && handle->pressed)) { - MwDrawFrame(handle, &r, base, MwFALSE); + MwDrawFrame(handle, &r, base, MwFALSE, 0); MwDrawWidgetBack(handle, &r, base, 0, MwFALSE); } diff --git a/src/widget/progressbar.c b/src/widget/progressbar.c index d85a8ddaf..7be7bffd7 100644 --- a/src/widget/progressbar.c +++ b/src/widget/progressbar.c @@ -23,7 +23,7 @@ static void draw(MwWidget handle) { r.width = MwGetInteger(handle, MwNwidth); r.height = MwGetInteger(handle, MwNheight); - MwDrawFrame(handle, &r, base, 1); + MwDrawFrame(handle, &r, base, 1, 0); MwDrawRect(handle, &r, base); w = MwGetInteger(handle, MwNvalue) - MwGetInteger(handle, MwNminValue); w = w / (MwGetInteger(handle, MwNmaxValue) - MwGetInteger(handle, MwNminValue)); diff --git a/src/widget/separator.c b/src/widget/separator.c index 8fcfc5b71..571c5dfa9 100644 --- a/src/widget/separator.c +++ b/src/widget/separator.c @@ -25,7 +25,7 @@ static void draw(MwWidget handle) { r.y = (r.height - 2) / 2; r.height = 2; } - MwDrawFrameEx(handle, &r, base, 1, 1, 0, 0); + MwDrawFrameEx(handle, &r, base, 1, 1, 0, 0, MwGetInteger(handle, MwNmodernLook)); MwLLFreeColor(base); } diff --git a/src/widget/submenu.c b/src/widget/submenu.c index 828155014..88607ffc0 100644 --- a/src/widget/submenu.c +++ b/src/widget/submenu.c @@ -59,7 +59,7 @@ static void draw(MwWidget handle) { rc.x += MwGetInteger(handle, MwNleftPadding); - MwDrawFrameEx(handle, &rc, base, 1, 1, 0, 0); + MwDrawFrameEx(handle, &rc, base, 1, 1, 0, 0, 0); p.y += 2 + 1; } else { diff --git a/src/widget/treeview.c b/src/widget/treeview.c index 76e1e0139..3a335be32 100644 --- a/src/widget/treeview.c +++ b/src/widget/treeview.c @@ -64,7 +64,7 @@ static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry** const int len = 4; MwDrawRect(handle, &r, col); - MwDrawFrame(handle, &r, base, tree->opened); + MwDrawFrame(handle, &r, base, tree->opened, 0); if(tree->opened) { l[0].x = r.x + (r.width - len) / 2; l[0].y = r.y + r.height / 2; @@ -91,7 +91,7 @@ static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry** MwLLLine(handle->lowlevel, &l[0], text); } r = r2; - MwDrawFrame(handle, &r, base, tree->opened); + MwDrawFrame(handle, &r, base, tree->opened, 0); if(col != base) MwLLFreeColor(col); } else { @@ -183,7 +183,7 @@ static void frame_draw(MwWidget handle) { p.x = MwDefaultBorderWidth(handle); p.y = MwDefaultBorderWidth(handle); - MwDrawFrame(handle, &r, base, 1); + MwDrawFrame(handle, &r, base, 1, 0); MwDrawRect(handle, &r, base2); r = r2; @@ -193,7 +193,7 @@ static void frame_draw(MwWidget handle) { recursion(handle, tv->tree[i], tv->tree, base, text, base2, text2, &p, 0, LineSpace, &skip, &shared, 1, NULL); } - MwDrawFrame(handle, &r, base, 1); + MwDrawFrame(handle, &r, base, 1, 0); MwLLFreeColor(text2); MwLLFreeColor(text); diff --git a/src/widget/window.c b/src/widget/window.c index 979e073c8..74a96e61e 100644 --- a/src/widget/window.c +++ b/src/widget/window.c @@ -18,7 +18,7 @@ static void draw(MwWidget handle) { r.width = MwGetInteger(handle, MwNwidth); r.height = MwGetInteger(handle, MwNheight); - if(MwGetInteger(handle, MwNhasBorder)) MwDrawFrame(handle, &r, c, MwGetInteger(handle, MwNinverted)); + if(MwGetInteger(handle, MwNhasBorder)) MwDrawFrame(handle, &r, c, MwGetInteger(handle, MwNinverted), 0); MwDrawRect(handle, &r, c); From 548d6c46fd2d7b9df2f75b7c9ab8c8df4169f17e Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 26 Mar 2026 15:17:01 -0700 Subject: [PATCH 039/195] r --- include/Mw/StringDefs.h | 1 + src/backend/wayland.c | 1 + src/draw.c | 152 +++++++++++++++++++++------------------- 3 files changed, 82 insertions(+), 72 deletions(-) diff --git a/include/Mw/StringDefs.h b/include/Mw/StringDefs.h index db597889f..832096338 100644 --- a/include/Mw/StringDefs.h +++ b/include/Mw/StringDefs.h @@ -39,6 +39,7 @@ #define MwNsevenSegment "IsevenSegment" #define MwNlength "Ilength" #define MwNforceInverted "IforceInverted" +#define MwNroundness "Iroundness" #define MwNtitle "Stitle" #define MwNtext "Stext" diff --git a/src/backend/wayland.c b/src/backend/wayland.c index f747955e2..d43a2c595 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1719,6 +1719,7 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r = malloc(sizeof(*r)); memset(r, 0, sizeof(*r)); MwLLCreateCommon(r); + r->common.supports_transparency = MwTRUE; widget_setup(r, parent, x, y, width, height, MWLL_WAYLAND_UNKNOWN); diff --git a/src/draw.c b/src/draw.c index 274623772..e367c2f78 100644 --- a/src/draw.c +++ b/src/draw.c @@ -11,7 +11,8 @@ #include "../external/stb_ds.h" -#define BORDER_ROUNDNESS 10 +#define DEFAULT_ROUNDNESS 10 +#define MAX_ROUNDNESS 30 #define BORDER_SMOOTHNESS 50 static int get_color_diff(MwWidget handle) { @@ -114,6 +115,11 @@ void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color, int rounde unsigned long sz = 1 * rect->height * 4; unsigned char* data = malloc(sz); MwRect r = *rect; + int roundness = MwGetInteger(handle, MwNroundness); + double h; + if(roundness == MwDEFAULT) roundness = DEFAULT_ROUNDNESS; + if(roundness >= MAX_ROUNDNESS) roundness = MAX_ROUNDNESS; + h = (roundness <= 10) ? 7. : 10.; memset(data, 0, sz); for(y = 0; y < rect->height; y++) { @@ -128,46 +134,46 @@ void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color, int rounde } pixmap = MwLLCreatePixmap(handle->lowlevel, data, 1, rect->height); - if(rounded && rect->height >= (BORDER_ROUNDNESS * 2) && rect->width >= (BORDER_ROUNDNESS * 2)) { + if(rounded && rect->height >= (roundness * 2) && rect->width >= (roundness * 2) && roundness > 0) { int xt; - int x = rect->x + (BORDER_ROUNDNESS + 1); - int y = rect->y + (BORDER_ROUNDNESS + 1); - for(i = 0; i < BORDER_ROUNDNESS; i++) { - double point = ((i + (M_PI * 4)) / 7.); - double point2 = (((i + 1) + (M_PI * 4)) / 7.); - int x2 = x - (sin(point2) * BORDER_ROUNDNESS); - r.x = x - (sin(point) * BORDER_ROUNDNESS); - r.y = y + (cos(point) * BORDER_ROUNDNESS); - r.width = (x - (sin(point + 1) * BORDER_ROUNDNESS)) - r.x; + int x = rect->x + (roundness + 1); + int y = rect->y + (roundness + 1); + for(i = 0; i < roundness; i++) { + double point = ((i + (M_PI * 4)) / h); + double point2 = (((i + 1) + (M_PI * 4)) / h); + int x2 = x - (sin(point2) * roundness); + r.x = x - (sin(point) * roundness); + r.y = y + (cos(point) * roundness); + r.width = (x - (sin(point + 1) * roundness)) - r.x; r.height = (rect->height - ((r.y - rect->y) * 2) - 1); MwLLDrawPixmap(handle->lowlevel, &r, pixmap); for(xt = x; xt < x2; xt++) { r.x = xt; - r.y = y + (cos(point2) * BORDER_ROUNDNESS); + r.y = y + (cos(point2) * roundness); r.height = (rect->height - ((r.y - rect->y)) - 1); MwLLDrawPixmap(handle->lowlevel, &r, pixmap); } } r = *rect; - r.x += BORDER_ROUNDNESS; - r.width -= (BORDER_ROUNDNESS * 2); + r.x += roundness; + r.width -= (roundness * 2); r.height -= 1; MwLLDrawPixmap(handle->lowlevel, &r, pixmap); r = *rect; - x = (rect->x + rect->width) - (BORDER_ROUNDNESS + 2); - y = rect->y + (BORDER_ROUNDNESS + 1); - for(i = 0; i < BORDER_ROUNDNESS; i++) { - double point = ((i + (M_PI * 4)) / 7.); - double point2 = (((i + 1) + (M_PI * 4)) / 7.); - int x2 = x + (sin(point2) * BORDER_ROUNDNESS); - r.x = x + (sin(point) * BORDER_ROUNDNESS); - r.y = y + (cos(point) * BORDER_ROUNDNESS); + x = (rect->x + rect->width) - (roundness + 2); + y = rect->y + (roundness + 1); + for(i = 0; i < roundness; i++) { + double point = ((i + (M_PI * 4)) / h); + double point2 = (((i + 1) + (M_PI * 4)) / h); + int x2 = x + (sin(point2) * roundness); + r.x = x + (sin(point) * roundness); + r.y = y + (cos(point) * roundness); r.width = 1; r.height = (rect->height - ((r.y - rect->y) * 2) - 1); MwLLDrawPixmap(handle->lowlevel, &r, pixmap); for(xt = x; xt < x2; xt++) { r.x = xt; - r.y = y + (cos(point2) * BORDER_ROUNDNESS); + r.y = y + (cos(point2) * roundness); r.height = (rect->height - ((r.y - rect->y) * 2) - 2); MwLLDrawPixmap(handle->lowlevel, &r, pixmap); } @@ -290,56 +296,58 @@ void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, i 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); int i; - MwLLColor middle = MwLLAllocColor(handle->lowlevel, - (lighter->common.red * darker->common.red) / 255, - (lighter->common.green * darker->common.green) / 255, - (lighter->common.blue * darker->common.blue) / 255); - - if(rounded) { + MwLLColor middle = MwLLAllocColor(handle->lowlevel, + (lighter->common.red * darker->common.red) / 255, + (lighter->common.green * darker->common.green) / 255, + (lighter->common.blue * darker->common.blue) / 255); + int roundness = MwGetInteger(handle, MwNroundness); + if(roundness == MwDEFAULT) roundness = DEFAULT_ROUNDNESS; + if(roundness >= MAX_ROUNDNESS) roundness = MAX_ROUNDNESS; + if(rounded && rect->height >= (roundness * 2) && rect->width >= (roundness * 2) && roundness > 0) { /* top left edge */ for(i = 0; i < BORDER_SMOOTHNESS; i += 2) { MwPoint line[2]; double point = ((i + (M_PI * (BORDER_SMOOTHNESS / 2.))) / (BORDER_SMOOTHNESS)); - int x = rect->x + (BORDER_ROUNDNESS + 2); - int y = rect->y + (BORDER_ROUNDNESS + 2); + int x = rect->x + (roundness + 2); + int y = rect->y + (roundness + 2); - line[0].x = x - (sin(point) * BORDER_ROUNDNESS); - line[0].y = y + (cos(point) * BORDER_ROUNDNESS); - line[1].x = x - (sin(point + 1) * BORDER_ROUNDNESS); - line[1].y = y + (cos(point + 1) * BORDER_ROUNDNESS); + line[0].x = x - (sin(point) * roundness); + line[0].y = y + (cos(point) * roundness); + line[1].x = x - (sin(point + 1) * roundness); + line[1].y = y + (cos(point + 1) * roundness); MwLLLine(handle->lowlevel, line, invert ? darker : lighter); } - p[0].x = rect->x + BORDER_ROUNDNESS; + p[0].x = rect->x + roundness; p[0].y = rect->y; - p[1].x = rect->x + rect->width - BORDER_ROUNDNESS; + p[1].x = rect->x + rect->width - roundness; p[1].y = rect->y; - p[2].x = rect->x + rect->width - border - BORDER_ROUNDNESS; + p[2].x = rect->x + rect->width - border - roundness; p[2].y = rect->y + border; - p[3].x = rect->x + border - BORDER_ROUNDNESS; - p[3].y = rect->y + border + BORDER_ROUNDNESS; + p[3].x = rect->x + border - roundness; + p[3].y = rect->y + border + roundness; - p[4].x = rect->x + border - BORDER_ROUNDNESS; - p[4].y = rect->y + rect->height - border - BORDER_ROUNDNESS; + p[4].x = rect->x + border - roundness; + p[4].y = rect->y + rect->height - border - roundness; - p[5].x = rect->x + BORDER_ROUNDNESS; - p[5].y = rect->y + rect->height - BORDER_ROUNDNESS; + p[5].x = rect->x + roundness; + p[5].y = rect->y + rect->height - roundness; MwLLPolygon(handle->lowlevel, p, 6, invert ? darker : lighter); /* top right edge */ for(i = 0; i < BORDER_SMOOTHNESS; i += 2) { MwPoint line[2]; double point = ((i + (M_PI * (BORDER_SMOOTHNESS / 2.))) / (BORDER_SMOOTHNESS)); - int x = (rect->x + rect->width) - (BORDER_ROUNDNESS + 2); - int y = rect->y + (BORDER_ROUNDNESS + 2); - double placeholder = (sin(point) * BORDER_ROUNDNESS); + int x = (rect->x + rect->width) - (roundness + 2); + int y = rect->y + (roundness + 2); + double placeholder = (sin(point) * roundness); line[0].x = x + placeholder; - line[0].y = y + (cos(point) * BORDER_ROUNDNESS); - line[1].x = x + (sin(point + 1) * BORDER_ROUNDNESS); - line[1].y = y + (cos(point + 1) * BORDER_ROUNDNESS); + line[0].y = y + (cos(point) * roundness); + line[1].x = x + (sin(point + 1) * roundness); + line[1].y = y + (cos(point + 1) * roundness); MwLLLine(handle->lowlevel, line, middle); } } else { @@ -362,40 +370,40 @@ void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, i } MwLLPolygon(handle->lowlevel, p, 6, invert ? darker : lighter); - if(rounded && rect->height >= (BORDER_ROUNDNESS * 2) && rect->width >= (BORDER_ROUNDNESS * 2)) { + if(rounded && rect->height >= (roundness * 2) && rect->width >= (roundness * 2) && roundness > 0) { /* bottom left edge */ for(i = 0; i < BORDER_SMOOTHNESS; i += 2) { MwPoint line[2]; double point = ((i + (M_PI * (BORDER_SMOOTHNESS / 2.))) / (BORDER_SMOOTHNESS)); - int x = rect->x + (BORDER_ROUNDNESS + 2); - int y = (rect->y + rect->height) - (BORDER_ROUNDNESS + 2); + int x = rect->x + (roundness + 2); + int y = (rect->y + rect->height) - (roundness + 2); - line[0].x = x - (sin(point) * BORDER_ROUNDNESS); - line[0].y = y - (cos(point) * BORDER_ROUNDNESS); - line[1].x = x - (sin(point + 1) * BORDER_ROUNDNESS); - line[1].y = y - (cos(point + 1) * BORDER_ROUNDNESS); + line[0].x = x - (sin(point) * roundness); + line[0].y = y - (cos(point) * roundness); + line[1].x = x - (sin(point + 1) * roundness); + line[1].y = y - (cos(point + 1) * roundness); MwLLLine(handle->lowlevel, line, middle); } - p[0].x = rect->x + BORDER_ROUNDNESS; + p[0].x = rect->x + roundness; p[0].y = rect->y + 1; p[1].x = rect->x + rect->width - border; - p[1].y = rect->y + border + BORDER_ROUNDNESS; + p[1].y = rect->y + border + roundness; p[2].x = rect->x + rect->width - border; - p[2].y = rect->y + rect->height - border - BORDER_ROUNDNESS; + p[2].y = rect->y + rect->height - border - roundness; - p[3].x = rect->x + rect->width - border - BORDER_ROUNDNESS; + p[3].x = rect->x + rect->width - border - roundness; p[3].y = rect->y + rect->height - border; - p[4].x = rect->x + border + BORDER_ROUNDNESS; + p[4].x = rect->x + border + roundness; p[4].y = rect->y + rect->height - border; - p[5].x = rect->x + BORDER_ROUNDNESS; - p[5].y = rect->y + rect->height - BORDER_ROUNDNESS; + p[5].x = rect->x + roundness; + p[5].y = rect->y + rect->height - roundness; - p[6].x = rect->x + rect->width - BORDER_ROUNDNESS; - p[6].y = rect->y + rect->height - BORDER_ROUNDNESS; + p[6].x = rect->x + rect->width - roundness; + p[6].y = rect->y + rect->height - roundness; MwLLPolygon(handle->lowlevel, p, 7, invert ? lighter : darker); @@ -403,13 +411,13 @@ void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, i for(i = 0; i < BORDER_SMOOTHNESS; i += 2) { MwPoint line[2]; double point = ((i + (M_PI * (BORDER_SMOOTHNESS / 2.))) / (BORDER_SMOOTHNESS)); - int x = (rect->x + rect->width) - (BORDER_ROUNDNESS + 2); - int y = (rect->y + rect->height) - (BORDER_ROUNDNESS + 2); + int x = (rect->x + rect->width) - (roundness + 2); + int y = (rect->y + rect->height) - (roundness + 2); - line[0].x = x + (sin(point) * BORDER_ROUNDNESS); - line[0].y = y - (cos(point) * BORDER_ROUNDNESS); - line[1].x = x + (sin(point + 1) * BORDER_ROUNDNESS); - line[1].y = y - (cos(point + 1) * BORDER_ROUNDNESS); + line[0].x = x + (sin(point) * roundness); + line[0].y = y - (cos(point) * roundness); + line[1].x = x + (sin(point + 1) * roundness); + line[1].y = y - (cos(point + 1) * roundness); MwLLLine(handle->lowlevel, line, middle); } } else { From 19cd6dc242f7a44ca6d480401d22dec0ef64acae Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 26 Mar 2026 15:56:27 -0700 Subject: [PATCH 040/195] increase smoothness --- src/draw.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/draw.c b/src/draw.c index e367c2f78..d5d466c68 100644 --- a/src/draw.c +++ b/src/draw.c @@ -13,7 +13,7 @@ #define DEFAULT_ROUNDNESS 10 #define MAX_ROUNDNESS 30 -#define BORDER_SMOOTHNESS 50 +#define BORDER_SMOOTHNESS 250 static int get_color_diff(MwWidget handle) { if(MwGetInteger(handle, MwNmodernLook)) { @@ -135,7 +135,6 @@ void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color, int rounde pixmap = MwLLCreatePixmap(handle->lowlevel, data, 1, rect->height); if(rounded && rect->height >= (roundness * 2) && rect->width >= (roundness * 2) && roundness > 0) { - int xt; int x = rect->x + (roundness + 1); int y = rect->y + (roundness + 1); for(i = 0; i < roundness; i++) { @@ -147,9 +146,8 @@ void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color, int rounde r.width = (x - (sin(point + 1) * roundness)) - r.x; r.height = (rect->height - ((r.y - rect->y) * 2) - 1); MwLLDrawPixmap(handle->lowlevel, &r, pixmap); - for(xt = x; xt < x2; xt++) { - r.x = xt; - r.y = y + (cos(point2) * roundness); + r.y = y + (cos(point2) * roundness); + for(r.x = x; r.x < x2; r.x++) { r.height = (rect->height - ((r.y - rect->y)) - 1); MwLLDrawPixmap(handle->lowlevel, &r, pixmap); } @@ -171,9 +169,8 @@ void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color, int rounde r.width = 1; r.height = (rect->height - ((r.y - rect->y) * 2) - 1); MwLLDrawPixmap(handle->lowlevel, &r, pixmap); - for(xt = x; xt < x2; xt++) { - r.x = xt; - r.y = y + (cos(point2) * roundness); + r.y = y + (cos(point2) * roundness); + for(r.x = x; r.x < x2; r.x++) { r.height = (rect->height - ((r.y - rect->y) * 2) - 2); MwLLDrawPixmap(handle->lowlevel, &r, pixmap); } @@ -321,7 +318,7 @@ void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, i p[0].x = rect->x + roundness; p[0].y = rect->y; - p[1].x = rect->x + rect->width - roundness; + p[1].x = rect->x + rect->width - border - roundness; p[1].y = rect->y; p[2].x = rect->x + rect->width - border - roundness; @@ -402,7 +399,7 @@ void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, i p[5].x = rect->x + roundness; p[5].y = rect->y + rect->height - roundness; - p[6].x = rect->x + rect->width - roundness; + p[6].x = rect->x + rect->width - border - roundness; p[6].y = rect->y + rect->height - roundness; MwLLPolygon(handle->lowlevel, p, 7, invert ? lighter : darker); From 2a2fdf55bcbbb51730aa81f3cb11108869685f5f Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 26 Mar 2026 16:54:40 -0700 Subject: [PATCH 041/195] wayland: double buffering --- include/Mw/LowLevel/Wayland.h | 4 ++ src/backend/wayland.c | 70 +++++++++++++++++++++++------------ src/draw.c | 6 +-- 3 files changed, 53 insertions(+), 27 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index de7828ad5..8d47b5103 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -346,12 +346,16 @@ struct _MwLLWaylandShmBuffer { struct wl_shm* shm; struct wl_shm_pool* shm_pool; struct wl_buffer* shm_buffer; + struct wl_shm_pool* shm_pool_back; + struct wl_buffer* shm_buffer_back; struct wl_surface* surface; struct wl_output* output; MwU8* buf; + MwU8* buf_back; MwU64 buf_size; int fd; + int fd_back; MwBool setup; }; diff --git a/src/backend/wayland.c b/src/backend/wayland.c index d43a2c595..1f27ed7f6 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1186,41 +1186,60 @@ static void wl_shm_interface_destroy(struct _MwLLWayland* wayland, wayland_proto static void update_buffer(MwLL self, struct _MwLLWaylandShmBuffer* buffer) { (void)self; // for later, just in case. + memcpy(buffer->buf, buffer->buf_back, buffer->buf_size); wl_surface_attach(buffer->surface, buffer->shm_buffer, 0, 0); wl_surface_commit(buffer->surface); } static void buffer_setup(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height) { - int stride = width * 4; - char temp_name[] = "/tmp/milsko-wl-shm-XXXXXX"; + int stride = width * 4; + 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->fd = mkstemp(temp_name); + buffer->fd = mkstemp(temp_name); + buffer->fd_back = mkstemp(temp_name_back); 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)); 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)); + close(buffer->fd_back); + return; + } 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; } + 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); fsync(buffer->fd); + fsync(buffer->fd_back); if(!(buffer->shm_pool = wl_shm_create_pool(buffer->shm, buffer->fd, buffer->buf_size))) { printf("failure setting up wl_shm: could not create pool.\n"); } - - buffer->shm_buffer = wl_shm_pool_create_buffer(buffer->shm_pool, 0, width, height, stride, WL_SHM_FORMAT_ARGB8888); - buffer->setup = MwTRUE; + if(!(buffer->shm_pool_back = wl_shm_create_pool(buffer->shm, buffer->fd_back, buffer->buf_size))) { + printf("failure setting up wl_shm: could not create pool.\n"); + } + 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) { @@ -1228,18 +1247,21 @@ static void buffer_destroy(struct _MwLLWaylandShmBuffer* buffer) { return; } wl_buffer_destroy(buffer->shm_buffer); + wl_buffer_destroy(buffer->shm_buffer_back); wl_shm_pool_destroy(buffer->shm_pool); + wl_shm_pool_destroy(buffer->shm_pool_back); close(buffer->fd); + close(buffer->fd_back); buffer->setup = MwFALSE; } static void framebuffer_setup(struct _MwLLWayland* wayland) { buffer_setup(&wayland->framebuffer, wayland->ww, wayland->wh); - wayland->front_cs = cairo_image_surface_create_for_data(wayland->framebuffer.buf, CAIRO_FORMAT_ARGB32, wayland->ww, wayland->wh, 4 * wayland->ww); + wayland->front_cs = cairo_image_surface_create_for_data(wayland->framebuffer.buf_back, CAIRO_FORMAT_ARGB32, wayland->ww, wayland->wh, 4 * wayland->ww); wayland->front_cairo = cairo_create(wayland->front_cs); - memset(wayland->framebuffer.buf, 0, wayland->framebuffer.buf_size); + memset(wayland->framebuffer.buf_back, 0, wayland->framebuffer.buf_size); hang_until_configured((MwLL)wayland); update_buffer((MwLL)wayland, &wayland->framebuffer); }; @@ -1261,10 +1283,10 @@ static void backbuffer_setup(struct _MwLLWayland* wayland) { } buffer_setup(&wayland->backbuffer, w, h); - wayland->back_cs = cairo_image_surface_create_for_data(wayland->backbuffer.buf, CAIRO_FORMAT_ARGB32, w, h, 4 * w); + wayland->back_cs = cairo_image_surface_create_for_data(wayland->backbuffer.buf_back, CAIRO_FORMAT_ARGB32, w, h, 4 * w); wayland->back_cairo = cairo_create(wayland->back_cs); - memset(wayland->backbuffer.buf, 255, wayland->backbuffer.buf_size); + memset(wayland->backbuffer.buf_back, 255, wayland->backbuffer.buf_size); hang_until_configured((MwLL)wayland); update_buffer((MwLL)wayland, &wayland->backbuffer); }; @@ -2156,7 +2178,7 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { cairo_surface_destroy(cs); MwLLForceRender(handle); - update_buffer(handle, &handle->wayland.framebuffer); + // update_buffer(handle, &handle->wayland.framebuffer); wl_surface_damage(handle->wayland.framebuffer.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); } static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { @@ -2182,15 +2204,15 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { buffer_setup(handle->wayland.icon, pixmap->common.width, pixmap->common.height); for(; i < size; i += 2) { - handle->wayland.icon->buf[i] = pixmap->common.raw[i + 2]; - handle->wayland.icon->buf[i + 1] = pixmap->common.raw[i + 1]; - handle->wayland.icon->buf[i + 2] = pixmap->common.raw[i + 0]; - handle->wayland.icon->buf[i + 3] = 255; + 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; } if(handle->wayland.configured) update_buffer(handle, handle->wayland.icon); - xdg_toplevel_icon_v1_add_buffer(icon, handle->wayland.icon->shm_buffer, 1); + 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); } @@ -2214,7 +2236,7 @@ static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { wl_surface_destroy(handle->wayland.cursor.surface); } buffer_setup(&handle->wayland.cursor, image->width, image->height); - memset(handle->wayland.cursor.buf, 0, handle->wayland.cursor.buf_size); + memset(handle->wayland.cursor.buf_back, 0, handle->wayland.cursor.buf_size); xs = -mask->x + image->x; ys = mask->height + mask->y; @@ -2226,7 +2248,7 @@ static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { int idx = ((y * image->width) + x) * 4; if(d & 1) { - handle->wayland.cursor.buf[idx + 3] = 255; + handle->wayland.cursor.buf_back[idx + 3] = 255; }; d = d >> 1; } @@ -2241,16 +2263,16 @@ static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { px = 255; }; - handle->wayland.cursor.buf[idx] = px; - handle->wayland.cursor.buf[idx + 1] = px; - handle->wayland.cursor.buf[idx + 2] = px; - d = d >> 1; + handle->wayland.cursor.buf_back[idx] = px; + handle->wayland.cursor.buf_back[idx + 1] = px; + handle->wayland.cursor.buf_back[idx + 2] = px; + d = d >> 1; } } handle->wayland.cursor.surface = wl_compositor_create_surface(handle->wayland.compositor); - wl_surface_attach(handle->wayland.cursor.surface, handle->wayland.cursor.shm_buffer, xs + image->x, ys + image->height + image->y); + wl_surface_attach(handle->wayland.cursor.surface, handle->wayland.cursor.shm_buffer_back, xs + image->x, ys + image->height + image->y); wl_surface_commit(handle->wayland.cursor.surface); /* If there's currently a pointer, set it up. (Otherwise, it'll be setup during the pointer enter event) */ diff --git a/src/draw.c b/src/draw.c index d5d466c68..7bf413e34 100644 --- a/src/draw.c +++ b/src/draw.c @@ -11,9 +11,9 @@ #include "../external/stb_ds.h" -#define DEFAULT_ROUNDNESS 10 +#define DEFAULT_ROUNDNESS 5 #define MAX_ROUNDNESS 30 -#define BORDER_SMOOTHNESS 250 +#define BORDER_SMOOTHNESS 50 static int get_color_diff(MwWidget handle) { if(MwGetInteger(handle, MwNmodernLook)) { @@ -171,7 +171,7 @@ void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color, int rounde MwLLDrawPixmap(handle->lowlevel, &r, pixmap); r.y = y + (cos(point2) * roundness); for(r.x = x; r.x < x2; r.x++) { - r.height = (rect->height - ((r.y - rect->y) * 2) - 2); + r.height = (rect->height - ((r.y - rect->y) * 2) - 1); MwLLDrawPixmap(handle->lowlevel, &r, pixmap); } } From 6538f8e836cbd79c1c9cebf00542381d5a6fd3c6 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 26 Mar 2026 17:48:22 -0700 Subject: [PATCH 042/195] fix wayland csd, more doublebuffering fixes --- src/backend/wayland.c | 30 ++++++++++++++++++------------ src/draw.c | 28 ++++++++++++++-------------- src/widget/button.c | 1 + src/widget/checkbox.c | 1 + src/widget/combobox.c | 1 + src/widget/entry.c | 1 + 6 files changed, 36 insertions(+), 26 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 1f27ed7f6..d3e8e0241 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -46,7 +46,7 @@ static void buffer_destroy(struct _MwLLWaylandShmBuffer* buffer); static void region_setup(MwLL handle); static void region_invalidate(MwLL handle); - +static void update_buffer(MwLL self, struct _MwLLWaylandShmBuffer* buffer); /* Get the registered interface from r, or NULL if it doesn't currently have it. */ #define WAYLAND_GET_INTERFACE(handle, inter) shget(handle.wl_protocol_map, inter##_interface.name) @@ -65,8 +65,11 @@ static void new_protocol(void* data, struct wl_registry* registry, char* inter = malloc(strlen(interface) + 1); 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 */ + } else if(strcmp(interface, "wp_alpha_modifier_v1") == 0) { + self->common.supports_transparency = MwTRUE; } else { - /* printf("unknown interface %s\n", interface); */ + // printf("unknown interface %s\n", interface); } WAYLAND_EVENT_OP_END(self); @@ -1075,9 +1078,9 @@ static int event_loop(MwLL handle) { if(!poll(&fd, 1, timeout.tv_nsec)) { wl_display_cancel_read(wayland->display); - wl_surface_commit(wayland->framebuffer.surface); + update_buffer(handle, &wayland->framebuffer); if(wayland->type == MWLL_WAYLAND_TOPLEVEL) - wl_surface_commit(wayland->backbuffer.surface); + update_buffer(handle, &wayland->backbuffer); return 0; } wl_display_read_events(wayland->display); @@ -1163,8 +1166,8 @@ static void xdg_surface_configure( xdg_surface_ack_configure(xdg_surface, serial); if(self->wayland.configured) { - wl_surface_commit(self->wayland.framebuffer.surface); - wl_surface_commit(self->wayland.backbuffer.surface); + update_buffer(self, &self->wayland.framebuffer); + update_buffer(self, &self->wayland.backbuffer); } self->wayland.configured = MwTRUE; @@ -1735,13 +1738,17 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh if(parent != NULL) { MwLLForceRender(parent); } + + if(!r->wayland.has_decorations) { + MwLLBeginDraw(r); + MwLLEndDraw(r); + } } static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { MwLL r; r = malloc(sizeof(*r)); memset(r, 0, sizeof(*r)); MwLLCreateCommon(r); - r->common.supports_transparency = MwTRUE; widget_setup(r, parent, x, y, width, height, MWLL_WAYLAND_UNKNOWN); @@ -1956,8 +1963,6 @@ static void MwLLBeginDrawImpl(MwLL handle) { free(px); } update_buffer(handle, &handle->wayland.backbuffer); - - wl_surface_commit(handle->wayland.backbuffer.surface); } handle->wayland.selected_cairo = handle->wayland.front_cairo; } @@ -1976,7 +1981,7 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL clip(handle); - cairo_set_source_rgb(handle->wayland.front_cairo, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); + cairo_set_source_rgba(handle->wayland.front_cairo, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0, 1.0); cairo_new_path(handle->wayland.front_cairo); for(i = 0; i < points_count; i++) { if(i == 0) { @@ -1999,7 +2004,7 @@ static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { cairo_set_antialias(handle->wayland.front_cairo, CAIRO_ANTIALIAS_NONE); cairo_set_line_cap(handle->wayland.front_cairo, CAIRO_LINE_CAP_SQUARE); - cairo_set_source_rgb(handle->wayland.front_cairo, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); + cairo_set_source_rgba(handle->wayland.front_cairo, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0, 1.0); cairo_new_path(handle->wayland.front_cairo); for(i = 0; i < 2; i++) { if(i == 0) { @@ -2109,6 +2114,8 @@ static void MwLLSetTitleImpl(MwLL handle, const char* title) { } if(!handle->wayland.has_decorations) { strncpy(handle->wayland.title, title, 255); + MwLLBeginDraw(handle); + MwLLEndDraw(handle); } } @@ -2178,7 +2185,6 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { cairo_surface_destroy(cs); MwLLForceRender(handle); - // update_buffer(handle, &handle->wayland.framebuffer); wl_surface_damage(handle->wayland.framebuffer.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); } static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { diff --git a/src/draw.c b/src/draw.c index 7bf413e34..ee9475e3c 100644 --- a/src/draw.c +++ b/src/draw.c @@ -116,10 +116,10 @@ void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color, int rounde unsigned char* data = malloc(sz); MwRect r = *rect; int roundness = MwGetInteger(handle, MwNroundness); - double h; + double div; if(roundness == MwDEFAULT) roundness = DEFAULT_ROUNDNESS; if(roundness >= MAX_ROUNDNESS) roundness = MAX_ROUNDNESS; - h = (roundness <= 10) ? 7. : 10.; + div = (roundness <= 10) ? 7. : 10.; memset(data, 0, sz); for(y = 0; y < rect->height; y++) { @@ -138,8 +138,8 @@ void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color, int rounde int x = rect->x + (roundness + 1); int y = rect->y + (roundness + 1); for(i = 0; i < roundness; i++) { - double point = ((i + (M_PI * 4)) / h); - double point2 = (((i + 1) + (M_PI * 4)) / h); + double point = ((i + (M_PI * 4)) / div); + double point2 = (((i + 1) + (M_PI * 4)) / div); int x2 = x - (sin(point2) * roundness); r.x = x - (sin(point) * roundness); r.y = y + (cos(point) * roundness); @@ -153,16 +153,16 @@ void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color, int rounde } } r = *rect; - r.x += roundness; - r.width -= (roundness * 2); - r.height -= 1; + r.x += roundness - 1; + r.width -= (roundness * 2) + 1; + r.height -= 2; MwLLDrawPixmap(handle->lowlevel, &r, pixmap); r = *rect; x = (rect->x + rect->width) - (roundness + 2); y = rect->y + (roundness + 1); for(i = 0; i < roundness; i++) { - double point = ((i + (M_PI * 4)) / h); - double point2 = (((i + 1) + (M_PI * 4)) / h); + double point = ((i + (M_PI * 4)) / div); + double point2 = (((i + 1) + (M_PI * 4)) / div); int x2 = x + (sin(point2) * roundness); r.x = x + (sin(point) * roundness); r.y = y + (cos(point) * roundness); @@ -207,13 +207,14 @@ void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int void MwDrawWidgetBack(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border) { MwLLColor col; + MwBool rounded = handle->lowlevel->common.supports_transparency && MwGetInteger(handle, MwNroundness) != MwDEFAULT; if(border) { - MwDrawFrame(handle, rect, color, invert, handle->lowlevel->common.supports_transparency); + MwDrawFrame(handle, rect, color, invert, rounded); } col = invert ? MwLightenColor(handle, color, -8, -8, -8) : color; if(MwGetInteger(handle, MwNmodernLook)) { - MwDrawRectFading(handle, rect, col, handle->lowlevel->common.supports_transparency); + MwDrawRectFading(handle, rect, col, rounded); } else { MwDrawRect(handle, rect, col); } @@ -318,10 +319,10 @@ void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, i p[0].x = rect->x + roundness; p[0].y = rect->y; - p[1].x = rect->x + rect->width - border - roundness; + p[1].x = rect->x + rect->width - border - roundness - 2; p[1].y = rect->y; - p[2].x = rect->x + rect->width - border - roundness; + p[2].x = rect->x + rect->width - border - roundness - 2; p[2].y = rect->y + border; p[3].x = rect->x + border - roundness; @@ -332,7 +333,6 @@ void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, i p[5].x = rect->x + roundness; p[5].y = rect->y + rect->height - roundness; - MwLLPolygon(handle->lowlevel, p, 6, invert ? darker : lighter); /* top right edge */ for(i = 0; i < BORDER_SMOOTHNESS; i += 2) { diff --git a/src/widget/button.c b/src/widget/button.c index dac7739c6..f3240b0a4 100644 --- a/src/widget/button.c +++ b/src/widget/button.c @@ -8,6 +8,7 @@ static int create(MwWidget handle) { MwSetInteger(handle, MwNflat, 0); MwSetInteger(handle, MwNpadding, 0); MwSetInteger(handle, MwNfillArea, 1); + MwSetInteger(handle, MwNroundness, 5); return 0; } diff --git a/src/widget/checkbox.c b/src/widget/checkbox.c index 1ccccd416..224cfec1d 100644 --- a/src/widget/checkbox.c +++ b/src/widget/checkbox.c @@ -4,6 +4,7 @@ static int create(MwWidget handle) { MwSetDefault(handle); MwSetInteger(handle, MwNchecked, 0); + MwSetInteger(handle, MwNroundness, 5); return 0; } diff --git a/src/widget/combobox.c b/src/widget/combobox.c index 0672ff3ad..998237263 100644 --- a/src/widget/combobox.c +++ b/src/widget/combobox.c @@ -14,6 +14,7 @@ static int create(MwWidget handle) { MwSetInteger(handle, MwNareaShown, 6); MwSetInteger(handle, MwNvalue, 0); + MwSetInteger(handle, MwNroundness, 5); return 0; } diff --git a/src/widget/entry.c b/src/widget/entry.c index 34a90a36b..998935b80 100644 --- a/src/widget/entry.c +++ b/src/widget/entry.c @@ -11,6 +11,7 @@ static int create(MwWidget handle) { MwSetDefault(handle); MwLLSetCursor(handle->lowlevel, &MwCursorText, &MwCursorTextMask); + MwSetInteger(handle, MwNroundness, 5); return 0; } From 00e44bec324a00011c55089a775eb0775a0733bc Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 26 Mar 2026 18:02:48 -0700 Subject: [PATCH 043/195] MwNisRounded --- include/Mw/StringDefs.h | 1 + src/core.c | 1 + src/draw.c | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/Mw/StringDefs.h b/include/Mw/StringDefs.h index 832096338..f30a21b31 100644 --- a/include/Mw/StringDefs.h +++ b/include/Mw/StringDefs.h @@ -40,6 +40,7 @@ #define MwNlength "Ilength" #define MwNforceInverted "IforceInverted" #define MwNroundness "Iroundness" +#define MwNisRounded "IisRounded" #define MwNtitle "Stitle" #define MwNtext "Stext" diff --git a/src/core.c b/src/core.c index 39cae9244..88cd84285 100644 --- a/src/core.c +++ b/src/core.c @@ -516,6 +516,7 @@ int MwGetInteger(MwWidget handle, const char* key) { #else if(strcmp(key, MwNmodernLook) == 0) return inherit_integer(handle, key, 1); #endif + if(strcmp(key, MwNisRounded) == 0) return inherit_integer(handle, key, 1); } return shget(handle->integer, key); } diff --git a/src/draw.c b/src/draw.c index ee9475e3c..944600f78 100644 --- a/src/draw.c +++ b/src/draw.c @@ -207,7 +207,7 @@ void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int void MwDrawWidgetBack(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border) { MwLLColor col; - MwBool rounded = handle->lowlevel->common.supports_transparency && MwGetInteger(handle, MwNroundness) != MwDEFAULT; + MwBool rounded = handle->lowlevel->common.supports_transparency && MwGetInteger(handle, MwNroundness) != MwDEFAULT && MwGetInteger(handle, MwNisRounded) != 0; if(border) { MwDrawFrame(handle, rect, color, invert, rounded); @@ -333,6 +333,7 @@ void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, i p[5].x = rect->x + roundness; p[5].y = rect->y + rect->height - roundness; + MwLLPolygon(handle->lowlevel, p, 6, invert ? darker : lighter); /* top right edge */ for(i = 0; i < BORDER_SMOOTHNESS; i += 2) { From 60e1f36a4125472040ee1b61b1dfc19fd943a73c Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 26 Mar 2026 18:12:45 -0700 Subject: [PATCH 044/195] slightly stronger gradient on modern theme --- src/draw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/draw.c b/src/draw.c index 944600f78..4926fe085 100644 --- a/src/draw.c +++ b/src/draw.c @@ -111,7 +111,7 @@ void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color, int rounde int y, i; double darken = 0.; int ColorDiff = get_color_diff(handle); - double darkenStep = (ColorDiff / 4.) / rect->height; + double darkenStep = (ColorDiff / 2.) / rect->height; unsigned long sz = 1 * rect->height * 4; unsigned char* data = malloc(sz); MwRect r = *rect; From 17e437075e7763d5c8a3872683a0034ec15957ea Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Fri, 27 Mar 2026 10:28:21 +0900 Subject: [PATCH 045/195] let ioixd do the job --- src/draw.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/draw.c b/src/draw.c index 4926fe085..2983e5635 100644 --- a/src/draw.c +++ b/src/draw.c @@ -299,6 +299,13 @@ void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, i (lighter->common.green * darker->common.green) / 255, (lighter->common.blue * darker->common.blue) / 255); int roundness = MwGetInteger(handle, MwNroundness); + MwLLColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground)); + + if(c != NULL){ + MwDrawRect(handle, rect, c); + MwLLFreeColor(c); + } + if(roundness == MwDEFAULT) roundness = DEFAULT_ROUNDNESS; if(roundness >= MAX_ROUNDNESS) roundness = MAX_ROUNDNESS; if(rounded && rect->height >= (roundness * 2) && rect->width >= (roundness * 2) && roundness > 0) { From 8dfa34e55553ffbe1642baa0d4500e710d22ed65 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 26 Mar 2026 18:34:08 -0700 Subject: [PATCH 046/195] only do backing box draw if backend doesn't do transparency --- src/draw.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/draw.c b/src/draw.c index 2983e5635..51e79ff9d 100644 --- a/src/draw.c +++ b/src/draw.c @@ -207,7 +207,7 @@ void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int void MwDrawWidgetBack(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border) { MwLLColor col; - MwBool rounded = handle->lowlevel->common.supports_transparency && MwGetInteger(handle, MwNroundness) != MwDEFAULT && MwGetInteger(handle, MwNisRounded) != 0; + MwBool rounded = MwGetInteger(handle, MwNroundness) != MwDEFAULT && MwGetInteger(handle, MwNisRounded) != 0; if(border) { MwDrawFrame(handle, rect, color, invert, rounded); @@ -299,11 +299,14 @@ void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, i (lighter->common.green * darker->common.green) / 255, (lighter->common.blue * darker->common.blue) / 255); int roundness = MwGetInteger(handle, MwNroundness); - MwLLColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground)); - if(c != NULL){ - MwDrawRect(handle, rect, c); - MwLLFreeColor(c); + if(!handle->lowlevel->common.supports_transparency) { + MwLLColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground)); + + if(c != NULL) { + MwDrawRect(handle, rect, c); + MwLLFreeColor(c); + } } if(roundness == MwDEFAULT) roundness = DEFAULT_ROUNDNESS; From e5acf07b38e494c03ad0870b1f941677c6122783 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 26 Mar 2026 18:36:35 -0700 Subject: [PATCH 047/195] disable rounding on combobox --- src/widget/combobox.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/widget/combobox.c b/src/widget/combobox.c index 998237263..0672ff3ad 100644 --- a/src/widget/combobox.c +++ b/src/widget/combobox.c @@ -14,7 +14,6 @@ static int create(MwWidget handle) { MwSetInteger(handle, MwNareaShown, 6); MwSetInteger(handle, MwNvalue, 0); - MwSetInteger(handle, MwNroundness, 5); return 0; } From fc18c86201386dfdff0421bd0fe3c93863017494 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 26 Mar 2026 18:37:47 -0700 Subject: [PATCH 048/195] disable rounding on checkbox --- src/widget/checkbox.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/widget/checkbox.c b/src/widget/checkbox.c index 224cfec1d..1ccccd416 100644 --- a/src/widget/checkbox.c +++ b/src/widget/checkbox.c @@ -4,7 +4,6 @@ static int create(MwWidget handle) { MwSetDefault(handle); MwSetInteger(handle, MwNchecked, 0); - MwSetInteger(handle, MwNroundness, 5); return 0; } From 8f7df275fba511c3f78e3523707e8895b2f0e6a2 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Fri, 27 Mar 2026 10:40:35 +0900 Subject: [PATCH 049/195] better --- src/draw.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/draw.c b/src/draw.c index 51e79ff9d..dfaf90c6e 100644 --- a/src/draw.c +++ b/src/draw.c @@ -210,6 +210,15 @@ void MwDrawWidgetBack(MwWidget handle, MwRect* rect, MwLLColor color, int invert MwBool rounded = MwGetInteger(handle, MwNroundness) != MwDEFAULT && MwGetInteger(handle, MwNisRounded) != 0; if(border) { + if(!handle->lowlevel->common.supports_transparency) { + MwLLColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground)); + + if(c != NULL) { + MwDrawRect(handle, rect, c); + MwLLFreeColor(c); + } + } + MwDrawFrame(handle, rect, color, invert, rounded); } col = invert ? MwLightenColor(handle, color, -8, -8, -8) : color; @@ -300,15 +309,6 @@ void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, i (lighter->common.blue * darker->common.blue) / 255); int roundness = MwGetInteger(handle, MwNroundness); - if(!handle->lowlevel->common.supports_transparency) { - MwLLColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground)); - - if(c != NULL) { - MwDrawRect(handle, rect, c); - MwLLFreeColor(c); - } - } - if(roundness == MwDEFAULT) roundness = DEFAULT_ROUNDNESS; if(roundness >= MAX_ROUNDNESS) roundness = MAX_ROUNDNESS; if(rounded && rect->height >= (roundness * 2) && rect->width >= (roundness * 2) && roundness > 0) { From a42482a4e44ddd346f393d29b69270cd8b7932d8 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Fri, 27 Mar 2026 10:46:27 +0900 Subject: [PATCH 050/195] epic --- src/draw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/draw.c b/src/draw.c index dfaf90c6e..84587b44f 100644 --- a/src/draw.c +++ b/src/draw.c @@ -233,7 +233,7 @@ void MwDrawWidgetBack(MwWidget handle, MwRect* rect, MwLLColor color, int invert void MwDrawDiamond(MwWidget handle, MwRect* rect, MwLLColor color, int invert) { MwPoint p[6]; int border = MwDefaultBorderWidth(handle); - int ColorDiff = get_color_diff(handle); + int ColorDiff = get_color_diff(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) : color; From 258d0d2cb21b71be73cbeaec31445165ee58bc5d Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Fri, 27 Mar 2026 10:58:17 +0900 Subject: [PATCH 051/195] update xml --- milsko.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/milsko.xml b/milsko.xml index bc73f0e2b..bc7f1531d 100644 --- a/milsko.xml +++ b/milsko.xml @@ -42,7 +42,9 @@ - - - - + + + + @@ -80,38 +66,39 @@ - - + + - - - + + + - + - + - - + + + - - - - + + + + - + diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 0bd23a649..801c03f68 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1264,7 +1264,7 @@ static void update_buffer(MwLL self, struct _MwLLWaylandShmBuffer* buffer) { memcpy(buffer->buf, buffer->buf_back, buffer->buf_size); // Yes this is needed every time, it's how we fix weston. wl_surface_attach(buffer->surface, buffer->shm_buffer, 0, 0); - wl_surface_commit(buffer->surface); + wl_surface_commit(buffer->surface); } static void buffer_setup(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height) { From 3852646ce30caf47b74a7be2ed388d2fd6d17ea1 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Sun, 12 Apr 2026 07:12:59 +0900 Subject: [PATCH 115/195] fix warning --- src/text/text.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/text/text.c b/src/text/text.c index f550195c4..fec0bb449 100644 --- a/src/text/text.c +++ b/src/text/text.c @@ -26,6 +26,7 @@ static int is_bold(MwWidget handle, MwFLFont ttf) { return s; } +#ifdef TTF static int is_monospace(MwWidget handle, MwFLFont ttf) { size_t u = (size_t)ttf; int s; @@ -36,6 +37,7 @@ static int is_monospace(MwWidget handle, MwFLFont ttf) { if(s == MwDEFAULT) return 0; return s; } +#endif #ifdef TTF From d1f351a7efb8a3b278e5684b801b07b11a92811f Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Sun, 12 Apr 2026 07:27:07 +0900 Subject: [PATCH 116/195] fix cmake --- examples/gldemos/CMakeLists.txt | 2 +- examples/vkdemos/CMakeLists.txt | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/examples/gldemos/CMakeLists.txt b/examples/gldemos/CMakeLists.txt index 9afda19fb..122f62c59 100644 --- a/examples/gldemos/CMakeLists.txt +++ b/examples/gldemos/CMakeLists.txt @@ -15,7 +15,7 @@ foreach(PATH IN LISTS EXAMPLES_GL_SOURCES) ${TARGET} PRIVATE Mw - OpenGL::GL + OpenGL::GL OpenGL::GLU ) if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") target_link_libraries( diff --git a/examples/vkdemos/CMakeLists.txt b/examples/vkdemos/CMakeLists.txt index 354bf3634..a315bf91b 100644 --- a/examples/vkdemos/CMakeLists.txt +++ b/examples/vkdemos/CMakeLists.txt @@ -3,10 +3,16 @@ file( EXAMPLES_VULKAN_SOURCES *.c ) +find_package(Vulkan) foreach(PATH IN LISTS EXAMPLES_VULKAN_SOURCES) get_filename_component(TARGET ${PATH} NAME_WE) add_executable(${TARGET} WIN32 MACOSX_BUNDLE ${PATH}) + target_include_directories( + ${TARGET} + PRIVATE + ${Vulkan_INCLUDE_DIR} + ) target_link_libraries( ${TARGET} PRIVATE From 2a7cf2de83d1fb5051013ccc988ec367564a932f Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Sat, 11 Apr 2026 18:26:15 -0500 Subject: [PATCH 117/195] x11: allow apple. --- src/backend/x11.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/backend/x11.c b/src/backend/x11.c index 72e54f336..755da7127 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -1292,7 +1292,11 @@ static int MwLLX11CallInitImpl(void) { return 1; } +#ifdef __APPLE__ + xsymtbl.lib_xlib = MwDynamicOpen("libX11.dylib"); +#else xsymtbl.lib_xlib = MwDynamicOpen("libX11.so"); +#endif if(!xsymtbl.lib_xlib) { return 1; } From c4f6d1eb14c94721fc4e18b76b4557c7def4b3e4 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Sat, 11 Apr 2026 18:30:00 -0500 Subject: [PATCH 118/195] Update src/core.c --- src/core.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/core.c b/src/core.c index c8a5c12d0..b4b6743ce 100644 --- a/src/core.c +++ b/src/core.c @@ -856,15 +856,16 @@ MwWidget MwGetParent(MwWidget handle) { typedef int (*call_t)(void); int MwLibraryInit(void) { call_t calls[] = { +/* x11 has higher priority then cocoa until it works */ +#ifdef USE_X11 + MwLLX11CallInit, +#endif #ifdef USE_COCOA MwLLCocoaCallInit, #endif #ifdef USE_WAYLAND MwLLWaylandCallInit, #endif -#ifdef USE_X11 - MwLLX11CallInit, -#endif #ifdef USE_GDI MwLLGDICallInit, #endif From 0ab497ca8869bcc968d3e48ff5e3ea4c15c3c766 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Mon, 13 Apr 2026 11:28:54 -0700 Subject: [PATCH 119/195] oops prioritize wayland --- src/backend/wayland.c | 7 +------ src/backend/x11.c | 3 --- src/core.c | 8 ++++---- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 801c03f68..148ca4420 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -2575,7 +2575,6 @@ static int MwLLWaylandCallInitImpl(void) { /* * Order of precedence: * - MILSKO_BACKEND - * - XDG_SESSION_TYPE * - manually checking environment variables */ #ifdef __linux__ @@ -2583,11 +2582,7 @@ static int MwLLWaylandCallInitImpl(void) { if(getenv("MILSKO_BACKEND")) { loadWayland |= (strcmp(getenv("MILSKO_BACKEND"), "wayland") == 0); - } - if(getenv("XDG_SESSION_TYPE")) { - loadWayland |= (strcmp(getenv("XDG_SESSION_TYPE"), "wayland") == 0); - } - if(getenv("WAYLAND_DISPLAY")) { + } else if(getenv("WAYLAND_DISPLAY")) { loadWayland |= (getenv("WAYLAND_DISPLAY") != NULL); } diff --git a/src/backend/x11.c b/src/backend/x11.c index 755da7127..4068186d4 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -1281,9 +1281,6 @@ static int MwLLX11CallInitImpl(void) { loadX11 |= (strcmp(getenv("MILSKO_BACKEND"), "x11") == 0); } - if(getenv("XDG_SESSION_TYPE")) { - loadX11 |= (strcmp(getenv("XDG_SESSION_TYPE"), "x11") == 0); - } if(getenv("DISPLAY")) { loadX11 |= (getenv("DISPLAY") != NULL); } diff --git a/src/core.c b/src/core.c index b4b6743ce..cdd0723b9 100644 --- a/src/core.c +++ b/src/core.c @@ -856,16 +856,16 @@ MwWidget MwGetParent(MwWidget handle) { typedef int (*call_t)(void); int MwLibraryInit(void) { call_t calls[] = { -/* x11 has higher priority then cocoa until it works */ +#ifdef USE_WAYLAND + MwLLWaylandCallInit, +#endif +/* x11 has higher priority then cocoa until it works */ #ifdef USE_X11 MwLLX11CallInit, #endif #ifdef USE_COCOA MwLLCocoaCallInit, #endif -#ifdef USE_WAYLAND - MwLLWaylandCallInit, -#endif #ifdef USE_GDI MwLLGDICallInit, #endif From 728983b92ccd4a79925b36f035b0cbdce003221c Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 13 Apr 2026 13:46:25 -0700 Subject: [PATCH 120/195] fix builds on osx 10.4 --- configure | 4 +++- include/Mw/LowLevel/Cocoa.h | 23 +++++++++++------------ include/Mw/MachDep.h | 9 +++++++++ pl/utils.pl | 1 + src/backend/cocoa.m | 8 ++++++-- 5 files changed, 30 insertions(+), 15 deletions(-) diff --git a/configure b/configure index 0371bcd05..0c1766315 100755 --- a/configure +++ b/configure @@ -38,7 +38,6 @@ require("./pl/utils.pl"); param_set("classic-theme", 0); param_set("stb-image", 1); -param_set("stb-truetype", 0); param_set("xrender", 1); param_set("opengl", 0); param_set("vulkan", 0); @@ -50,6 +49,9 @@ param_set("examples", 1); if($target ne "Darwin") { param_set("freetype2", 1); + param_set("stb-truetype", 0); +} else { + param_set("stb-truetype", 1); } my %features = ( diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index da104f018..6e51c3051 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -86,18 +86,17 @@ @end @interface MilskoCocoaView : NSView { - NSBitmapImageRep* rep; - NSGraphicsContext* context; - MwBool valid; - CGColorSpaceRef space; - CGDataProviderRef provider; - NSRect givenRect; - float x; - float y; - float width; - float height; - MwBool _child; - IBOutlet NSViewController* viewController; + NSBitmapImageRep* rep; + NSGraphicsContext* context; + MwBool valid; + CGColorSpaceRef space; + CGDataProviderRef provider; + NSRect givenRect; + float x; + float y; + float width; + float height; + MwBool _child; } - (void)initRepAndContextWithWidth:(float)w Height:(float)h; diff --git a/include/Mw/MachDep.h b/include/Mw/MachDep.h index 61a6f909b..50898f676 100644 --- a/include/Mw/MachDep.h +++ b/include/Mw/MachDep.h @@ -57,17 +57,26 @@ #define M_PI 3.14159265 #endif +/* Windows */ #if defined(_MILSKO) && defined(_WIN32) #define MWDECL extern __declspec(dllexport) #elif defined(_WIN32) #define MWDECL extern __declspec(dllimport) +/* GCC/Clang */ +/* First check if we have __has_attribute and can check for the existence of visibility */ #elif defined(__has_attribute) #if __has_attribute(visibility) #define MWDECL extern __attribute__((visibility("default"))) #else #define MWDECL extern #endif +/* It might be that we're on an old version of GCC (like the one Apple ships with older versions of Mac OS). + * If we're on gcc 3 or above, assume it's there + */ +#elif __GNUC__ >= 3 +#define MWDECL extern __attribute__((visibility("default"))) #else +/* all else fails */ #define MWDECL extern #endif diff --git a/pl/utils.pl b/pl/utils.pl index 70c0b517c..947212328 100644 --- a/pl/utils.pl +++ b/pl/utils.pl @@ -55,6 +55,7 @@ sub new_object { my @l = glob($_[0]); foreach my $e (@l) { $e =~ s/\.(c|m)$/$object_suffix/; + print($e."\n"); push(@library_targets, $e); } } diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 04ce17edf..195e33948 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -665,6 +665,9 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { NSSize sz = [self->rep size]; MwLL ll = [((MilskoFakePointer*)[[[[self window] contentView] subviews] objectAtIndex:0]) pointer]; + NSRect bounds; + NSArray* subviews = [self subviews]; + int i; [super drawRect:dirtyRect]; if(!self->rep) { @@ -683,8 +686,9 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { [self->rep drawInRect:dirtyRect]; - for(NSView* subview in [self subviews]) { - NSRect bounds = [subview bounds]; + for(i = 0; i < [subviews count]; i++) { + NSView* subview = [subviews objectAtIndex:i]; + bounds = [subview bounds]; [subview drawRect:bounds]; } From 14e908488c3f5ffa7e450e6380a318be97cb4d65 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 13 Apr 2026 16:09:28 -0700 Subject: [PATCH 121/195] mac --- include/Mw/LowLevel/Cocoa.h | 6 +++ src/backend/cocoa.m | 86 ++++++++++++++++++++++--------------- 2 files changed, 58 insertions(+), 34 deletions(-) diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index 6e51c3051..fc39b07e4 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -104,7 +104,11 @@ - (void)destroy; - (NSBitmapImageRep*)getRep; - (void)setChild; +- (void)drawRectSub:(NSRect)dirtyRect; +@end +@interface MilskoCocoaSubView : MilskoCocoaView { +} @end @interface MilskoCocoa : NSObject { @@ -125,6 +129,8 @@ MwBool pointerLocked; MwBool mouseMoved; + + MwBool rejectFirstTest; } + (MilskoCocoa*)newWithParent:(MwLL)parent diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 195e33948..dc3028738 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -116,8 +116,8 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { - (void)destroy { free(self->buf); [self->image removeRepresentation:self->rep]; - [self->image dealloc]; - [self->rep dealloc]; + [self->image release]; + [self->rep release]; self->image = NULL; self->rep = NULL; } @@ -134,7 +134,9 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { width:(int)width height:(int)height handle:(MwLL)r { - MilskoCocoa* c = [MilskoCocoa alloc]; + MilskoCocoa* c = [MilskoCocoa alloc]; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [c retain]; /* @@ -156,7 +158,6 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { c->window = [[MilskoCocoaWindow alloc] initWithContentRect:rectFlip(c->rect) styleMask:(NSTitledWindowMask | - NSTexturedBackgroundWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask) backing:NSBackingStoreBuffered @@ -190,15 +191,12 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { NSRect rect = localRectFlip(c->rect, p->view); c->view = [[MilskoCocoaView alloc] initWithFrame:rect]; [c->view setBounds:c->rect]; - [c->view retain]; - [c->view setNeedsDisplay:TRUE]; [c->view setChild]; [c->view addTrackingRect:c->rect owner:c->view userData:NULL assumeInside:MwFALSE]; [p->view addSubview:c->view]; - [p->window setContentView:p->view]; } [c->window setAcceptsMouseMovedEvents:MwTRUE]; @@ -219,6 +217,7 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { c->pointerLocked = MwFALSE; + [pool release]; return c; } @@ -331,7 +330,8 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { frame = localRectFlip(frame, parent->cocoa.real->view); [self->view setBounds:frame]; } - self->_eventsPending = MwTRUE; + // [self->view setNeedsDisplay:true]; + [self nudge]; }; - (void)setW:(int)w H:(int)h { NSRect frame = [self->window frame]; @@ -346,7 +346,7 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { } else { [self->window setFrame:frame display:YES animate:false]; } - self->_eventsPending = MwTRUE; + [self nudge]; }; - (int)pending { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; @@ -360,12 +360,12 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { MwLL h = [self->handle pointer]; if(_forceRender) { MwLLDispatch(h, draw, NULL); - [self->view setNeedsDisplay:true]; + // [self->view setNeedsDisplay:true]; _forceRender = MwFALSE; } if(_eventsPending) { MwLLDispatch(h, draw, NULL); - [self->view setNeedsDisplay:true]; + // [self->view setNeedsDisplay:true]; _eventsPending = MwFALSE; } [self sendClipboardEvent]; @@ -579,9 +579,7 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { }; - (void)destroy { [self->handle release]; - [self->handle dealloc]; [self->window release]; - [self->window dealloc]; } - (MwLL)getParent { @@ -596,7 +594,13 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { } - (void)nudge { + MwLL p = self->parent; self->_eventsPending = MwTRUE; + + if(p) { + [p->cocoa.real->view setNeedsDisplay:true]; + p = p->cocoa.real->parent; + } } - (void)pushCursor { @@ -661,15 +665,10 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { } - (void)drawRect:(NSRect)dirtyRect { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSSize sz = [self->rep size]; - MwLL ll = [((MilskoFakePointer*)[[[[self window] contentView] subviews] - objectAtIndex:0]) pointer]; - NSRect bounds; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSArray* subviews = [self subviews]; int i; - [super drawRect:dirtyRect]; if(!self->rep) { if(dirtyRect.size.width && dirtyRect.size.height) { [self initRepAndContextWithWidth:dirtyRect.size.width @@ -682,22 +681,41 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { } } - // MwLLDispatch(ll, draw, NULL); - - [self->rep drawInRect:dirtyRect]; + if(!_child) + [self->rep drawInRect:[self bounds]]; for(i = 0; i < [subviews count]; i++) { - NSView* subview = [subviews objectAtIndex:i]; - bounds = [subview bounds]; - [subview drawRect:bounds]; + MilskoCocoaView* subview = [subviews objectAtIndex:i]; + NSRect bounds = [subview bounds]; + if([subview respondsToSelector:@selector(drawRectSub:)]) { + [subview drawRectSub:bounds]; + } } - - [self->rep bitmapData]; - [pool release]; } +- (void)drawRectSub:(NSRect)dirtyRect { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + if(!self->rep) { + if(dirtyRect.size.width && dirtyRect.size.height) { + [self initRepAndContextWithWidth:dirtyRect.size.width + Height:dirtyRect.size.height]; + self->width = dirtyRect.size.width; + self->height = dirtyRect.size.height; + } else { + [pool release]; + return; + } + } + + [self->rep drawInRect:dirtyRect]; + + [pool release]; +}; + - (void)initRepAndContextWithWidth:(float)w Height:(float)h { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; self->rep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL pixelsWide:w @@ -712,10 +730,14 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { assert(self->rep); [self->rep retain]; + [self->rep setOpaque:MwFALSE]; + [self->rep setAlpha:MwTRUE]; + self->context = [NSGraphicsContext graphicsContextWithBitmapImageRep:self->rep]; assert(self->context); [self->context retain]; + [pool release]; } - (void)destroy { @@ -1142,11 +1164,7 @@ static void MwLLFreeColorImpl(MwLLColor color) { } static int MwLLPendingImpl(MwLL handle) { - int p = [handle->cocoa.real pending]; - if(p) { - MwLLDispatch(handle, draw, NULL); - } - return p; + return [handle->cocoa.real pending]; } static void MwLLNextEventImpl(MwLL handle) { @@ -1186,7 +1204,7 @@ static void MwLLPixmapUpdateImpl(MwLLPixmap pixmap) { static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { MilskoCocoaPixmap* p = pixmap->cocoa.real; [p destroy]; - [p dealloc]; + [p release]; free(pixmap); } From f44a70d4ecc621897eb723eb30c848cb6235fd9d Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Mon, 13 Apr 2026 16:21:30 -0700 Subject: [PATCH 122/195] mac: untested code but i'll fall asleep at night with this in the codebase compared to the other thing --- include/Mw/LowLevel/Cocoa.h | 1 - src/backend/cocoa.m | 51 +++++++++---------------------------- 2 files changed, 12 insertions(+), 40 deletions(-) diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index fc39b07e4..89e5f5887 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -104,7 +104,6 @@ - (void)destroy; - (NSBitmapImageRep*)getRep; - (void)setChild; -- (void)drawRectSub:(NSRect)dirtyRect; @end @interface MilskoCocoaSubView : MilskoCocoaView { diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index dc3028738..0f979b9dc 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -669,51 +669,24 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { NSArray* subviews = [self subviews]; int i; - if(!self->rep) { - if(dirtyRect.size.width && dirtyRect.size.height) { - [self initRepAndContextWithWidth:dirtyRect.size.width - Height:dirtyRect.size.height]; - self->width = dirtyRect.size.width; - self->height = dirtyRect.size.height; - } else { - [pool release]; - return; - } + if(self->rep) { + [self->rep release]; + } + if(dirtyRect.size.width && dirtyRect.size.height) { + [self initRepAndContextWithWidth:dirtyRect.size.width + Height:dirtyRect.size.height]; + self->width = dirtyRect.size.width; + self->height = dirtyRect.size.height; + } else { + [pool release]; + return; } - if(!_child) - [self->rep drawInRect:[self bounds]]; + [self->rep drawInRect:[self bounds]]; - for(i = 0; i < [subviews count]; i++) { - MilskoCocoaView* subview = [subviews objectAtIndex:i]; - NSRect bounds = [subview bounds]; - if([subview respondsToSelector:@selector(drawRectSub:)]) { - [subview drawRectSub:bounds]; - } - } [pool release]; } -- (void)drawRectSub:(NSRect)dirtyRect { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - - if(!self->rep) { - if(dirtyRect.size.width && dirtyRect.size.height) { - [self initRepAndContextWithWidth:dirtyRect.size.width - Height:dirtyRect.size.height]; - self->width = dirtyRect.size.width; - self->height = dirtyRect.size.height; - } else { - [pool release]; - return; - } - } - - [self->rep drawInRect:dirtyRect]; - - [pool release]; -}; - - (void)initRepAndContextWithWidth:(float)w Height:(float)h { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; self->rep = From b661face2647645499a5d475ce1e99e0561d3138 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Mon, 13 Apr 2026 16:43:31 -0700 Subject: [PATCH 123/195] mac: more untested changes but its just removing dead comments so i know this won't break anything --- src/backend/cocoa.m | 89 +++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 64 deletions(-) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 0f979b9dc..a66b31c36 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -330,7 +330,6 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { frame = localRectFlip(frame, parent->cocoa.real->view); [self->view setBounds:frame]; } - // [self->view setNeedsDisplay:true]; [self nudge]; }; - (void)setW:(int)w H:(int)h { @@ -360,12 +359,10 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { MwLL h = [self->handle pointer]; if(_forceRender) { MwLLDispatch(h, draw, NULL); - // [self->view setNeedsDisplay:true]; _forceRender = MwFALSE; } if(_eventsPending) { MwLLDispatch(h, draw, NULL); - // [self->view setNeedsDisplay:true]; _eventsPending = MwFALSE; } [self sendClipboardEvent]; @@ -443,18 +440,6 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { }; - (void)forceRender { self->_forceRender = MwTRUE; - // NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - // NSEvent *event = [NSEvent otherEventWithType:NSApplicationDefined - // location:NSMakePoint(0, 0) - // modifierFlags:0 - // timestamp:0 - // windowNumber:0 - // context:nil - // subtype:0 - // data1:0 - // data2:0]; - // [NSApp postEvent:event atStart:YES]; - // [pool release]; }; - (void)setCursor:(MwCursor*)image mask:(MwCursor*)mask { int y, x, ys, xs; @@ -670,8 +655,8 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { int i; if(self->rep) { - [self->rep release]; - } + [self->rep release]; + } if(dirtyRect.size.width && dirtyRect.size.height) { [self initRepAndContextWithWidth:dirtyRect.size.width Height:dirtyRect.size.height]; @@ -993,7 +978,6 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { if([ptr isKindOfClass:[MilskoFakePointer class]]) { MwLL h = [(MilskoFakePointer*)ptr pointer]; MwLLDispatch(h, resize, NULL); - // MwLLDispatch(h, draw, NULL); } } return frameSize; @@ -1118,18 +1102,15 @@ static void MwLLColorUpdateImpl(MwLL handle, MwLLColor c, int r, int g, int b) { static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* height) { - MilskoCocoa* h = handle->cocoa.real; - [h getX:x Y:y W:w H:height]; + [handle->cocoa.real getX:x Y:y W:w H:height]; } static void MwLLSetXYImpl(MwLL handle, int x, int y) { - MilskoCocoa* h = handle->cocoa.real; - [h setX:x Y:y]; + [handle->cocoa.real setX:x Y:y]; } static void MwLLSetWHImpl(MwLL handle, int w, int height) { - MilskoCocoa* h = handle->cocoa.real; - [h setW:w H:height]; + [handle->cocoa.real setW:w H:height]; } static void MwLLFreeColorImpl(MwLLColor color) { @@ -1141,13 +1122,11 @@ static int MwLLPendingImpl(MwLL handle) { } static void MwLLNextEventImpl(MwLL handle) { - MilskoCocoa* h = handle->cocoa.real; - [h getNextEvent]; + [handle->cocoa.real getNextEvent]; } static void MwLLSetTitleImpl(MwLL handle, const char* title) { - MilskoCocoa* h = handle->cocoa.real; - [h setTitle:title]; + [handle->cocoa.real setTitle:title]; } static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, @@ -1170,77 +1149,63 @@ static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, } static void MwLLPixmapUpdateImpl(MwLLPixmap pixmap) { - MilskoCocoaPixmap* p = pixmap->cocoa.real; - [p updateWithData:pixmap->common.raw]; + [pixmap->cocoa.real updateWithData:pixmap->common.raw]; } static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { - MilskoCocoaPixmap* p = pixmap->cocoa.real; - [p destroy]; - [p release]; + [pixmap->cocoa.real destroy]; + [pixmap->cocoa.real release]; free(pixmap); } static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { - MilskoCocoa* h = handle->cocoa.real; - [h drawPixmap:pixmap rect:rect]; + [handle->cocoa.real drawPixmap:pixmap rect:rect]; MwLLForceRender(handle); } static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { - MilskoCocoa* h = handle->cocoa.real; - [h setIcon:pixmap]; + [handle->cocoa.real setIcon:pixmap]; } static void MwLLForceRenderImpl(MwLL handle) { - MilskoCocoa* h = handle->cocoa.real; - [h forceRender]; + [handle->cocoa.real forceRender]; } static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { - MilskoCocoa* h = handle->cocoa.real; - [h setCursor:image mask:mask]; + [handle->cocoa.real setCursor:image mask:mask]; } static void MwLLDetachImpl(MwLL handle, MwPoint* point) { - MilskoCocoa* h = handle->cocoa.real; - [h detachWithPoint:point]; + [handle->cocoa.real detachWithPoint:point]; } static void MwLLShowImpl(MwLL handle, int show) { - MilskoCocoa* h = handle->cocoa.real; - [h show:show]; + [handle->cocoa.real show:show]; } static void MwLLMakePopupImpl(MwLL handle, MwLL parent) { - MilskoCocoa* h = handle->cocoa.real; - [h makePopupWithParent:parent]; + [handle->cocoa.real makePopupWithParent:parent]; } static void MwLLSetSizeHintsImpl(MwLL handle, int minx, int miny, int maxx, int maxy) { - MilskoCocoa* h = handle->cocoa.real; - [h setSizeHintsWithMinX:minx MinY:miny MaxX:maxx MaxY:maxy]; + [handle->cocoa.real setSizeHintsWithMinX:minx MinY:miny MaxX:maxx MaxY:maxy]; } static void MwLLMakeBorderlessImpl(MwLL handle, int toggle) { - MilskoCocoa* h = handle->cocoa.real; - [h makeBorderless:toggle]; + [handle->cocoa.real makeBorderless:toggle]; } static void MwLLFocusImpl(MwLL handle) { - MilskoCocoa* h = handle->cocoa.real; - [h focus]; + [handle->cocoa.real focus]; } static void MwLLGrabPointerImpl(MwLL handle, int toggle) { - MilskoCocoa* h = handle->cocoa.real; - [h grabPointer:toggle]; + [handle->cocoa.real grabPointer:toggle]; } static void MwLLSetClipboardImpl(MwLL handle, const char* text) { - MilskoCocoa* h = handle->cocoa.real; - [h setClipboard:text]; + [handle->cocoa.real setClipboard:text]; } static void MwLLGetClipboardImpl(MwLL handle) { @@ -1248,19 +1213,15 @@ static void MwLLGetClipboardImpl(MwLL handle) { } static void MwLLMakeToolWindowImpl(MwLL handle) { - - MilskoCocoa* h = handle->cocoa.real; - [h makeToolWindow]; + [handle->cocoa.real makeToolWindow]; } static void MwLLGetCursorCoordImpl(MwLL handle, MwPoint* point) { - MilskoCocoa* h = handle->cocoa.real; - [h getCursorCoord:point]; + [handle->cocoa.real getCursorCoord:point]; } static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) { - MilskoCocoa* h = handle->cocoa.real; - [h getScreenSize:rect]; + [handle->cocoa.real getScreenSize:rect]; } static void MwLLBeginStateChangeImpl(MwLL handle) { From bb876b96201a93c1fe6a55583ebcd79a9842b27f Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Mon, 13 Apr 2026 16:45:20 -0700 Subject: [PATCH 124/195] mac: only recreate rep if width/height is different. also untested but i'm confident in this --- src/backend/cocoa.m | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index a66b31c36..6961a9630 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -654,17 +654,19 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { NSArray* subviews = [self subviews]; int i; - if(self->rep) { - [self->rep release]; - } - if(dirtyRect.size.width && dirtyRect.size.height) { - [self initRepAndContextWithWidth:dirtyRect.size.width - Height:dirtyRect.size.height]; - self->width = dirtyRect.size.width; - self->height = dirtyRect.size.height; - } else { - [pool release]; - return; + if(self->width != dirtyRect.size.width || self->height != dirtyRect.size.height) { + if(self->rep) { + [self->rep release]; + } + if(dirtyRect.size.width && dirtyRect.size.height) { + [self initRepAndContextWithWidth:dirtyRect.size.width + Height:dirtyRect.size.height]; + self->width = dirtyRect.size.width; + self->height = dirtyRect.size.height; + } else { + [pool release]; + return; + } } [self->rep drawInRect:[self bounds]]; From a4c61b0e38c9737978e28014e38d5fc48fe02f06 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Mon, 13 Apr 2026 17:44:27 -0700 Subject: [PATCH 125/195] gnustep support? --- configure | 17 ++++++++++------- include/Mw/LowLevel/Cocoa.h | 34 +++++++++++++--------------------- pl/rules.pl | 6 +++++- pl/utils.pl | 1 - src/backend/cocoa.m | 18 +++++++++--------- src/backend/x11.c | 3 +-- 6 files changed, 38 insertions(+), 41 deletions(-) diff --git a/configure b/configure index 0c1766315..5551d4ced 100755 --- a/configure +++ b/configure @@ -66,6 +66,7 @@ my %features = ( "shared" => "build shared library", "static" => "build static library", "wayland" => "enable wayland backend", + "gnustep" => "use gnustep", ); my @features_keys = ( "1classic-theme", "1stb-image", @@ -73,9 +74,16 @@ my @features_keys = ( "1opengl", "2xrender", "1vulkan", "2vulkan-string-helper", "1shared", "1static", - "1wayland", + "1wayland", "1gnustep", ); +if($target eq "Linux") { + param_set("x11", 1); + if(!param_get("tiny")){ + param_set("wayland", 1); + } +} + foreach my $l (@ARGV) { if ($l =~ /^--with-([^=]+)=(.+)$/) { param_set($1, $2); @@ -138,12 +146,7 @@ foreach my $l (@ARGV) { } } -if($target eq "Linux") { - param_set("x11", 1); - if(!param_get("tiny")){ - param_set("wayland", 1); - } -} + if (-f "./pl/ostype/${target}.pl") { require("./pl/ostype/${target}.pl"); diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index 89e5f5887..d31e590b6 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -15,12 +15,6 @@ #import #import -#ifdef __APPLE__ -#import -#else -#import -#endif - @interface MilskoCocoaApplication : NSApplication { MwBool doPending; } @@ -29,9 +23,9 @@ // Note: implements NSApplicationDelegate @interface MilskoCocoaApplicationDelegate : NSObject { - MilskoCocoaApplication* appl; + NSApplication* appl; } -- (MilskoCocoaApplicationDelegate*)initWithAppl:(MilskoCocoaApplication*)appl; +- (MilskoCocoaApplicationDelegate*)initWithAppl:(NSApplication*)appl; @end @interface MilskoCocoaWindow : NSWindow { @@ -40,7 +34,7 @@ // Note: implements NSWindowDelegate @interface MilskoCocoaWindowDelegate : NSObject { - MilskoCocoaWindow* w; + NSWindow* w; } - (MilskoCocoaWindowDelegate*)initWithWin:(MilskoCocoaWindow*)win; @end @@ -89,8 +83,6 @@ NSBitmapImageRep* rep; NSGraphicsContext* context; MwBool valid; - CGColorSpaceRef space; - CGDataProviderRef provider; NSRect givenRect; float x; float y; @@ -111,16 +103,16 @@ @end @interface MilskoCocoa : NSObject { - MilskoCocoaApplication* application; - MwBool _forceRender; - MwBool _eventsPending; - MilskoCocoaWindow* window; - NSRect rect; - MilskoCocoaView* view; - MwLL parent; - MilskoFakePointer* handle; - unsigned int strHash; - NSEvent* lastEvent; + NSApplication* application; + MwBool _forceRender; + MwBool _eventsPending; + MilskoCocoaWindow* window; + NSRect rect; + MilskoCocoaView* view; + MwLL parent; + MilskoFakePointer* handle; + unsigned int strHash; + NSEvent* lastEvent; MilskoCocoaPixmap* cursorPixmap; NSCursor* cursor; diff --git a/pl/rules.pl b/pl/rules.pl index bf1857576..000a6fec0 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -52,10 +52,14 @@ if (grep(/^wayland$/, @backends)) { $gl_libs = "-lGL -lGLU"; } -if (grep(/^cocoa$/, @backends)) { +if (grep(/^cocoa$/, @backends) || param_get("gnustep")) { add_cflags("-DUSE_COCOA"); new_object("src/backend/cocoa.m"); + if(param_get("gnustep")){ + add_ldflags("-lobjc -lgnustep-base -lm -lgnustep-gui"); + } + if (param_get("opengl")) { new_object("src/widget/opengl_cocoa.m"); } diff --git a/pl/utils.pl b/pl/utils.pl index 947212328..70c0b517c 100644 --- a/pl/utils.pl +++ b/pl/utils.pl @@ -55,7 +55,6 @@ sub new_object { my @l = glob($_[0]); foreach my $e (@l) { $e =~ s/\.(c|m)$/$object_suffix/; - print($e."\n"); push(@library_targets, $e); } } diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 6961a9630..7b281722e 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -325,7 +325,7 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { if(!parent) { frame = rectFlip(frame); - [self->window setFrame:frame display:TRUE animate:TRUE]; + [self->window setFrame:frame display:MwTRUE animate:MwTRUE]; } else { frame = localRectFlip(frame, parent->cocoa.real->view); [self->view setBounds:frame]; @@ -367,6 +367,7 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { } [self sendClipboardEvent]; +#ifdef __APPLE__ if(self->pointerLocked && [self->window isMainWindow] && self->lastEvent) { struct CGPoint pos; pos.x = [window frame].origin.x + [window frame].size.width / 2; @@ -374,6 +375,7 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { CGWarpMouseCursorPosition(pos); } +#endif [self->application updateWindows]; }; @@ -617,13 +619,12 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { @implementation MilskoCocoaView - (id)initWithFrame:(NSRect)frame { - givenRect = frame; - x = frame.origin.x; - y = frame.origin.y; - width = frame.size.width; - height = frame.size.height; - self = [super initWithFrame:frame]; - self->space = CGColorSpaceCreateDeviceRGB(); + givenRect = frame; + x = frame.origin.x; + y = frame.origin.y; + width = frame.size.width; + height = frame.size.height; + self = [super initWithFrame:frame]; if(width == 0 || height == 0) { self->rep = NULL; @@ -701,7 +702,6 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { } - (void)destroy { - CGColorSpaceRelease(self->space); [self->rep release]; [self->context release]; } diff --git a/src/backend/x11.c b/src/backend/x11.c index 4068186d4..ad97d6885 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -1280,8 +1280,7 @@ static int MwLLX11CallInitImpl(void) { if(getenv("MILSKO_BACKEND")) { loadX11 |= (strcmp(getenv("MILSKO_BACKEND"), "x11") == 0); - } - if(getenv("DISPLAY")) { + } else if(getenv("DISPLAY")) { loadX11 |= (getenv("DISPLAY") != NULL); } From 7d85a784f589a79d14bd3158a3a258d6175cefff Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Mon, 13 Apr 2026 18:39:21 -0700 Subject: [PATCH 126/195] i think we're now linking to gnustep properly --- pl/rules.pl | 4 +++- src/backend/cocoa.m | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pl/rules.pl b/pl/rules.pl index 000a6fec0..3d1f2c0fc 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -57,7 +57,9 @@ if (grep(/^cocoa$/, @backends) || param_get("gnustep")) { new_object("src/backend/cocoa.m"); if(param_get("gnustep")){ - add_ldflags("-lobjc -lgnustep-base -lm -lgnustep-gui"); + add_incdir2("-I/usr/GNUstep/System/Library/Headers"); + add_libdir("-L/usr/GNUstep/System/Library/Libraries"); + add_ldflags("-fblocks -lobjc -lgnustep-base -lm -lgnustep-gui"); } if (param_get("opengl")) { diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 7b281722e..1048f82bf 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -151,7 +151,7 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { y = r ? ([[NSScreen mainScreen] frame].size.height / 2.) - (height / 2.) : 0; } - c->application = [MilskoCocoaApplication sharedApplication]; + c->application = NSApp; c->rect = NSMakeRect(x, y, width, height); if(parent == NULL) { @@ -1235,6 +1235,8 @@ static void MwLLEndStateChangeImpl(MwLL handle) { } static int MwLLCocoaCallInitImpl(void) { + [NSApplication sharedApplication]; + return 0; } From 9283455cb971857e14e62f0aa594b4b4091ace0b Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Mon, 13 Apr 2026 20:07:00 -0700 Subject: [PATCH 127/195] links to gnustep but doesn't run --- configure | 2 -- include/Mw/LowLevel/Cocoa.h | 29 ++++++++++++++--------------- pl/rules.pl | 7 ++++--- src/backend/cocoa.m | 29 ++++++++++++++++------------- 4 files changed, 34 insertions(+), 33 deletions(-) diff --git a/configure b/configure index 5551d4ced..5d9810863 100755 --- a/configure +++ b/configure @@ -146,8 +146,6 @@ foreach my $l (@ARGV) { } } - - if (-f "./pl/ostype/${target}.pl") { require("./pl/ostype/${target}.pl"); } diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index d31e590b6..ff7029580 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -23,9 +23,9 @@ // Note: implements NSApplicationDelegate @interface MilskoCocoaApplicationDelegate : NSObject { - NSApplication* appl; + MilskoCocoaApplication* appl; } -- (MilskoCocoaApplicationDelegate*)initWithAppl:(NSApplication*)appl; +- (MilskoCocoaApplicationDelegate*)initWithAppl:(MilskoCocoaApplication*)appl; @end @interface MilskoCocoaWindow : NSWindow { @@ -36,7 +36,7 @@ @interface MilskoCocoaWindowDelegate : NSObject { NSWindow* w; } -- (MilskoCocoaWindowDelegate*)initWithWin:(MilskoCocoaWindow*)win; +- (MilskoCocoaWindowDelegate*)initWithWin:(NSWindow*)win; @end /* @@ -103,16 +103,16 @@ @end @interface MilskoCocoa : NSObject { - NSApplication* application; - MwBool _forceRender; - MwBool _eventsPending; - MilskoCocoaWindow* window; - NSRect rect; - MilskoCocoaView* view; - MwLL parent; - MilskoFakePointer* handle; - unsigned int strHash; - NSEvent* lastEvent; + MilskoCocoaApplication* application; + MwBool _forceRender; + MwBool _eventsPending; + NSWindow* window; + NSRect rect; + MilskoCocoaView* view; + MwLL parent; + MilskoFakePointer* handle; + unsigned int strHash; + NSEvent* lastEvent; MilskoCocoaPixmap* cursorPixmap; NSCursor* cursor; @@ -163,14 +163,13 @@ - (MwLL)getParent; - (NSView*)getView; -- (MilskoCocoaWindow*)getWindow; +- (NSWindow*)getWindow; - (void)nudge; - (void)pushCursor; - (void)popCursor; - (MilskoFakePointer*)getHandle; -+ (void)eventCanceller:(MilskoCocoa*)this; @end #define OBJC(x) x diff --git a/pl/rules.pl b/pl/rules.pl index 3d1f2c0fc..6c23006bd 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -57,9 +57,10 @@ if (grep(/^cocoa$/, @backends) || param_get("gnustep")) { new_object("src/backend/cocoa.m"); if(param_get("gnustep")){ - add_incdir2("-I/usr/GNUstep/System/Library/Headers"); - add_libdir("-L/usr/GNUstep/System/Library/Libraries"); - add_ldflags("-fblocks -lobjc -lgnustep-base -lm -lgnustep-gui"); + add_incdir("-I".`gnustep-config --variable=GNUSTEP_SYSTEM_HEADERS`); + add_libdir("-L".`gnustep-config --variable=GNUSTEP_SYSTEM_LIBRARIES`); + add_cflags("-fobjc-runtime=gnustep-2.0 -fblocks"); + add_ldflags("-lobjc -lgnustep-base -lm -lgnustep-gui"); } if (param_get("opengl")) { diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 1048f82bf..adf8f740f 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -136,8 +136,9 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { handle:(MwLL)r { MilskoCocoa* c = [MilskoCocoa alloc]; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - [c retain]; + c->application = (MilskoCocoaApplication*)[MilskoCocoaApplication sharedApplication]; + [c->application retain]; /* * MacOS doesn't really have a "default" window position, you're actually @@ -151,11 +152,10 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { y = r ? ([[NSScreen mainScreen] frame].size.height / 2.) - (height / 2.) : 0; } - c->application = NSApp; - c->rect = NSMakeRect(x, y, width, height); + c->rect = NSMakeRect(x, y, width, height); if(parent == NULL) { - c->window = [[MilskoCocoaWindow alloc] + c->window = [[NSWindow alloc] initWithContentRect:rectFlip(c->rect) styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | @@ -183,6 +183,7 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { [c->application retain]; [c->view addTrackingRect:c->rect owner:c->view userData:NULL assumeInside:MwFALSE]; + c->modalSession = [c->application beginModalSessionForWindow:c->window]; } else { MilskoCocoa* p = parent->cocoa.real; @@ -197,6 +198,8 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { [c->view addTrackingRect:c->rect owner:c->view userData:NULL assumeInside:MwFALSE]; [p->view addSubview:c->view]; + + c->modalSession = p->modalSession; } [c->window setAcceptsMouseMovedEvents:MwTRUE]; @@ -205,8 +208,7 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { [c->handle setPointer:r]; [c->view addSubview:c->handle]; - c->modalSession = [c->application beginModalSessionForWindow:c->window]; - c->parent = parent; + c->parent = parent; c->_forceRender = MwTRUE; c->strHash = 0; @@ -350,7 +352,7 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { - (int)pending { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; MwBool isPending = [self->application pending]; - [NSApp runModalSession:self->modalSession]; + [self->application runModalSession:self->modalSession]; [pool release]; return _forceRender || _eventsPending || isPending; }; @@ -954,7 +956,7 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { @end @implementation MilskoCocoaApplicationDelegate -- (MilskoCocoaApplicationDelegate*)initWithAppl:(NSApplication*)_appl { +- (MilskoCocoaApplicationDelegate*)initWithAppl:(MilskoCocoaApplication*)_appl { self->appl = _appl; return self; } @@ -1001,10 +1003,9 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { // This will close/terminate the application when the main window is closed. - (void)windowWillClose:(NSNotification*)notification { (void)notification; - // MilskoCocoa *window = notification.object; - // MwLL handle = [window getHandle].pointer; - // MwLLDispatch(handle, close, NULL); - [NSApp terminate:nil]; + MilskoCocoa* window = notification.object; + MwLL handle = [window getHandle].pointer; + MwLLDispatch(handle, close, NULL); } - (MilskoCocoaWindowDelegate*)initWithWin:(NSWindow*)win { @@ -1235,7 +1236,9 @@ static void MwLLEndStateChangeImpl(MwLL handle) { } static int MwLLCocoaCallInitImpl(void) { - [NSApplication sharedApplication]; + printf("Using GNUStep Backend\n"); + + [MilskoCocoaApplication sharedApplication]; return 0; } From 522f32cfcdd1f0edc85ab429c447482058a201ec Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 13 Apr 2026 21:19:09 -0700 Subject: [PATCH 128/195] mac: revert back to what i had before with drawing, i still don't know how to fix this but it's better then nothing --- src/backend/cocoa.m | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index adf8f740f..c8fa2a9ca 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -657,10 +657,7 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { NSArray* subviews = [self subviews]; int i; - if(self->width != dirtyRect.size.width || self->height != dirtyRect.size.height) { - if(self->rep) { - [self->rep release]; - } + if(!self->rep) { if(dirtyRect.size.width && dirtyRect.size.height) { [self initRepAndContextWithWidth:dirtyRect.size.width Height:dirtyRect.size.height]; @@ -672,8 +669,13 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { } } - [self->rep drawInRect:[self bounds]]; + [self->rep drawInRect:NSMakeRect(dirtyRect.origin.x, dirtyRect.origin.y, [self->rep pixelsWide], [self->rep pixelsHigh])]; + for(i = 0; i < [subviews count]; i++) { + MilskoCocoaView* subview = [subviews objectAtIndex:i]; + NSRect bounds = [subview bounds]; + [subview drawRect:bounds]; + } [pool release]; } @@ -1003,9 +1005,9 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { // This will close/terminate the application when the main window is closed. - (void)windowWillClose:(NSNotification*)notification { (void)notification; - MilskoCocoa* window = notification.object; - MwLL handle = [window getHandle].pointer; - MwLLDispatch(handle, close, NULL); + // MilskoCocoa* window = notification.object; + // MwLL handle = [window getHandle].pointer; + // MwLLDispatch(handle, close, NULL); } - (MilskoCocoaWindowDelegate*)initWithWin:(NSWindow*)win { @@ -1236,7 +1238,9 @@ static void MwLLEndStateChangeImpl(MwLL handle) { } static int MwLLCocoaCallInitImpl(void) { +#ifndef __APPLE__ printf("Using GNUStep Backend\n"); +#endif [MilskoCocoaApplication sharedApplication]; From 554e5cd5ddf711ebb8d69f06768de73eeb6d3afc Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 13 Apr 2026 21:36:17 -0700 Subject: [PATCH 129/195] mac: merge all the MilskoCocoa* functions into the C Milsko functions that call them, cleaning up the codebase --- include/Mw/LowLevel/Cocoa.h | 37 +- src/backend/cocoa.m | 820 +++++++++++++++++------------------- 2 files changed, 377 insertions(+), 480 deletions(-) diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index ff7029580..3577ad03e 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -61,6 +61,7 @@ @end @interface MilskoCocoaPixmap : NSObject { + @public MwBool valid; int width; int height; @@ -103,6 +104,7 @@ @end @interface MilskoCocoa : NSObject { + @public MilskoCocoaApplication* application; MwBool _forceRender; MwBool _eventsPending; @@ -123,41 +125,6 @@ MwBool rejectFirstTest; } - -+ (MilskoCocoa*)newWithParent:(MwLL)parent - x:(int)x - y:(int)y - width:(int)width - height:(int)height - handle:(MwLL)handle; -- (void)polygonWithPoints:(MwPoint*)points - points_count:(int)points_count - color:(MwLLColor)color; -- (void)lineWithPoints:(MwPoint*)points color:(MwLLColor)color; -- (void)getX:(int*)x Y:(int*)y W:(unsigned int*)w H:(unsigned int*)h; -- (void)setX:(int)x Y:(int)y; -- (void)setW:(int)w H:(int)h; -- (int)pending; -- (void)getNextEvent; -- (void)setTitle:(const char*)title; -- (void)drawPixmap:(MwLLPixmap)pixmap rect:(MwRect*)rect; -- (void)setIcon:(MwLLPixmap)pixmap; -- (void)forceRender; -- (void)setCursor:(MwCursor*)image mask:(MwCursor*)mask; -- (void)detachWithPoint:(MwPoint*)point; -- (void)show:(int)show; -- (void)makePopupWithParent:(MwLL)parent; -- (void)setSizeHintsWithMinX:(int)minx - MinY:(int)miny - MaxX:(int)maxx - MaxY:(int)maxy; -- (void)makeBorderless:(int)toggle; -- (void)focus; -- (void)grabPointer:(int)toggle; -- (void)setClipboard:(const char*)text; -- (void)makeToolWindow; -- (void)getCursorCoord:(MwPoint*)point; -- (void)getScreenSize:(MwRect*)rect; - (void)destroy; - (void)sendClipboardEvent; diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index c8fa2a9ca..b43aef2b7 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -127,261 +127,6 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { @end @implementation MilskoCocoa - -+ (MilskoCocoa*)newWithParent:(MwLL)parent - x:(int)x - y:(int)y - width:(int)width - height:(int)height - handle:(MwLL)r { - MilskoCocoa* c = [MilskoCocoa alloc]; - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - [c retain]; - c->application = (MilskoCocoaApplication*)[MilskoCocoaApplication sharedApplication]; - [c->application retain]; - - /* - * MacOS doesn't really have a "default" window position, you're actually - * meant to center the window yourself, so if the user passes MwDEFAULT - * respond appropriately. Also for child windows just have it be 0. - */ - if(x == MwDEFAULT) { - x = r ? ([[NSScreen mainScreen] frame].size.width / 2.) - (width / 2.) : 0; - } - if(y == MwDEFAULT) { - y = r ? ([[NSScreen mainScreen] frame].size.height / 2.) - (height / 2.) - : 0; - } - c->rect = NSMakeRect(x, y, width, height); - - if(parent == NULL) { - c->window = [[NSWindow alloc] - initWithContentRect:rectFlip(c->rect) - styleMask:(NSTitledWindowMask | - NSClosableWindowMask | NSMiniaturizableWindowMask | - NSResizableWindowMask) - backing:NSBackingStoreBuffered - defer:NO]; - [c->window - setDelegate:[[MilskoCocoaWindowDelegate alloc] initWithWin:c->window]]; - [c->window retain]; - - [c->window makeKeyAndOrderFront:c->application]; - [c->window makeFirstResponder:c->view]; - - c->view = [[MilskoCocoaView alloc] initWithFrame:c->rect]; - [c->view retain]; - [c->window setContentView:c->view]; - - if([c->application respondsToSelector:@selector(setActivationPolicy:)]) { - [c->application - setActivationPolicy:0 /* NSApplicationActivationPolicyRegular */]; - } - [c->application activateIgnoringOtherApps:MwTRUE]; - [c->application setDelegate:[[MilskoCocoaApplicationDelegate alloc] - initWithAppl:c->application]]; - [c->application retain]; - - [c->view addTrackingRect:c->rect owner:c->view userData:NULL assumeInside:MwFALSE]; - c->modalSession = [c->application beginModalSessionForWindow:c->window]; - } else { - MilskoCocoa* p = parent->cocoa.real; - - c->window = p->window; - - NSRect rect = localRectFlip(c->rect, p->view); - c->view = [[MilskoCocoaView alloc] initWithFrame:rect]; - [c->view setBounds:c->rect]; - [c->view retain]; - [c->view setChild]; - - [c->view addTrackingRect:c->rect owner:c->view userData:NULL assumeInside:MwFALSE]; - - [p->view addSubview:c->view]; - - c->modalSession = p->modalSession; - } - [c->window setAcceptsMouseMovedEvents:MwTRUE]; - - c->handle = [[MilskoFakePointer alloc] initWithFrame:NSMakeRect(0, 0, 1, 1)]; - [c->handle retain]; - [c->handle setPointer:r]; - [c->view addSubview:c->handle]; - - c->parent = parent; - - c->_forceRender = MwTRUE; - c->strHash = 0; - - c->cursorPixmap = NULL; - - [c->application finishLaunching]; - - c->pointerLocked = MwFALSE; - - [pool release]; - return c; -} - -- (void)polygonWithPoints:(MwPoint*)points - points_count:(int)points_count - color:(MwLLColor)color { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSGraphicsContext* ctx = [self->view context]; - if(ctx) { - int i; - NSBezierPath* path = [NSBezierPath bezierPath]; - /* whatever rect we use for coordinate flipping */ - NSRect _rect = parent ? [self->view bounds] : [self->window frame]; - - NSColor* nscolor = - [NSColor colorWithCalibratedRed:color->common.red / 255. - green:color->common.green / 255. - blue:color->common.blue / 255. - alpha:1.0]; - - [NSGraphicsContext saveGraphicsState]; - [NSGraphicsContext setCurrentContext:ctx]; - - [nscolor setFill]; - for(i = 0; i < points_count; i++) { - NSPoint p = localPointFlip(NSMakePoint(points[i].x, points[i].y), self->view); - if(i == 0) { - [path moveToPoint:p]; - } else { - [path lineToPoint:p]; - } - } - - [path closePath]; - [path fill]; - - [NSGraphicsContext restoreGraphicsState]; - - [self->view setNeedsDisplay:YES]; - } - [pool release]; -}; -- (void)lineWithPoints:(MwPoint*)points color:(MwLLColor)color { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSGraphicsContext* ctx = [self->view context]; - if(ctx) { - int i; - NSBezierPath* path = [NSBezierPath bezierPath]; - /* whatever rect we use for coordinate flipping */ - NSRect _rect = parent ? [self->view bounds] : [self->window frame]; - - NSColor* nscolor = - [NSColor colorWithCalibratedRed:color->common.red / 255. - green:color->common.green / 255. - blue:color->common.blue / 255. - alpha:1.0]; - - [NSGraphicsContext saveGraphicsState]; - [NSGraphicsContext setCurrentContext:ctx]; - - [nscolor setFill]; - for(i = 0; i < 2; i++) { - NSPoint p = localPointFlip(NSMakePoint(points[i].x, points[i].y), self->view); - if(i == 0) { - [path moveToPoint:p]; - } else { - [path lineToPoint:p]; - } - } - - [path closePath]; - [path stroke]; - - [NSGraphicsContext restoreGraphicsState]; - - [self->view setNeedsDisplay:YES]; - } - [pool release]; -}; -- (void)getX:(int*)x Y:(int*)y W:(unsigned int*)w H:(unsigned int*)h { - NSRect frame; - if(parent) { - frame = [self->view frame]; - } else { - frame = [self->window frame]; - } - frame = rectFlip(frame); - - *x = frame.origin.x; - *y = frame.origin.y; - - *w = frame.size.width; - *h = frame.size.height; -}; -- (void)setX:(int)x Y:(int)y { - NSRect frame; - if(parent) { - frame = [self->view frame]; - } else { - frame = [self->window frame]; - } - - frame.origin.x = x; - frame.origin.y = y; - - if(!parent) { - frame = rectFlip(frame); - [self->window setFrame:frame display:MwTRUE animate:MwTRUE]; - } else { - frame = localRectFlip(frame, parent->cocoa.real->view); - [self->view setBounds:frame]; - } - [self nudge]; -}; -- (void)setW:(int)w H:(int)h { - NSRect frame = [self->window frame]; - frame.size.width = w; - frame.size.height = h; - - self->rect = frame; - - [self->view setFrameSize:frame.size]; - if(self->parent) { - [self->view setFrame:frame]; - } else { - [self->window setFrame:frame display:YES animate:false]; - } - [self nudge]; -}; -- (int)pending { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - MwBool isPending = [self->application pending]; - [self->application runModalSession:self->modalSession]; - [pool release]; - return _forceRender || _eventsPending || isPending; -}; - -- (void)getNextEvent { - MwLL h = [self->handle pointer]; - if(_forceRender) { - MwLLDispatch(h, draw, NULL); - _forceRender = MwFALSE; - } - if(_eventsPending) { - MwLLDispatch(h, draw, NULL); - _eventsPending = MwFALSE; - } - [self sendClipboardEvent]; - -#ifdef __APPLE__ - if(self->pointerLocked && [self->window isMainWindow] && self->lastEvent) { - struct CGPoint pos; - pos.x = [window frame].origin.x + [window frame].size.width / 2; - pos.y = [window frame].origin.y + [window frame].size.height / 2; - - CGWarpMouseCursorPosition(pos); - } -#endif - - [self->application updateWindows]; -}; - - (void)sendClipboardEvent { /*NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSPasteboard* pasteboard = [NSPasteboard generalPasteboard]; @@ -413,159 +158,6 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { [pool release];*/ } -- (void)setTitle:(const char*)title { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - [self->window - setTitleWithRepresentedFilename:[NSString stringWithUTF8String:title]]; - [pool release]; -}; -- (void)drawPixmap:(MwLLPixmap)pixmap rect:(MwRect*)_rect { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - MilskoCocoaPixmap* p = pixmap->cocoa.real; - NSGraphicsContext* ctx = [self->view context]; - if(ctx) { - [NSGraphicsContext saveGraphicsState]; - [NSGraphicsContext setCurrentContext:ctx]; - - [[p image] - drawInRect:localRectFlip(NSMakeRect(_rect->x, _rect->y, _rect->width, _rect->height), self->view) - fromRect:NSZeroRect - operation:NSCompositeSourceOver - fraction:1.0]; - - [NSGraphicsContext restoreGraphicsState]; - - [self->view setNeedsDisplay:YES]; - } - [pool release]; -}; -- (void)setIcon:(MwLLPixmap)pixmap { - [self->application setApplicationIconImage:[pixmap->cocoa.real image]]; -}; -- (void)forceRender { - self->_forceRender = MwTRUE; -}; -- (void)setCursor:(MwCursor*)image mask:(MwCursor*)mask { - int y, x, ys, xs; - unsigned char* di = malloc(image->width * image->height * 4); - memset(di, 0, image->width * image->height * 4); - - if(self->cursorPixmap) { - [self->cursorPixmap destroy]; - } - self->cursorPixmap = - [MilskoCocoaPixmap newWithWidth:image->width - height:image->height]; - - xs = -mask->x + image->x; - ys = MwCursorDataHeight + mask->y; - ys = MwCursorDataHeight + image->y - ys; - - for(y = 0; y < mask->height; y++) { - unsigned int d = mask->data[y]; - for(x = mask->width - 1; x >= 0; x--) { - int px = 0; - int idx = ((y * mask->width) + x) * 4; - - if(d & 1) { - di[idx + 3] = 255; - }; - d = d >> 1; - } - } - for(y = 0; y < image->height; y++) { - unsigned int d = image->data[y]; - for(x = image->width - 1; x >= 0; x--) { - int px = 0; - int idx = ((y * image->width) + x) * 4; - - if(d & 1) { - px = 255; - }; - - di[idx] = px; - di[idx + 1] = px; - di[idx + 2] = px; - d = d >> 1; - } - } - - [self->cursorPixmap updateWithData:di]; - - self->cursor = [[NSCursor alloc] - initWithImage:[self->cursorPixmap image] - hotSpot:NSMakePoint(image->x, image->y + image->height)]; - [self->cursor retain]; - - [self->cursor pop]; - [self->cursor push]; - - free(di); -}; -- (void)detachWithPoint:(MwPoint*)point { - [self->window setParentWindow:NULL]; -}; -- (void)show:(int)show { - (void)show; -}; -- (void)makePopupWithParent:(MwLL)_parent { - (void)_parent; -}; -- (void)setSizeHintsWithMinX:(int)minx - MinY:(int)miny - MaxX:(int)maxx - MaxY:(int)maxy { - [self->window setMinSize:NSMakeSize(minx, miny)]; - [self->window setMaxSize:NSMakeSize(maxx, maxy)]; -}; -- (void)makeBorderless:(int)toggle { - MwU32 mask = [self->window styleMask]; - if(toggle) { - mask ^= NSBorderlessWindowMask; - mask |= NSTitledWindowMask; - } else { - mask |= NSBorderlessWindowMask; - mask ^= NSTitledWindowMask; - } - [self->window initWithContentRect:self->rect - styleMask:mask - backing:NSBackingStoreBuffered - defer:NO]; -}; -- (void)focus { - [self->window makeMainWindow]; -}; -- (void)grabPointer:(int)toggle { - self->pointerLocked = toggle; -}; -- (void)setClipboard:(const char*)text { - (void)text; - // TODO: find out how to do this while supporting 10.4 - // NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - // NSPasteboard* pasteboard = [NSPasteboard generalPasteboard]; - // [pasteboard declareTypes:[NSArray arrayWithObjects:NSPasteboardTypeString] - // owner:nil]; [pasteboard setString:[NSString stringWithUTF8String:text] - // forType:NSPasteboardTypeString]; [pool release]; -}; -- (void)makeToolWindow { - /* If my understand of what a "tool window" usually is is correct then I - * highly doubt the Mac OS has this and if they did they probably outright - * removed it along time ago is this kind of conflicts with modern UX. So - * we'll just make it borderless idgaf */ - [self makeBorderless:MwTRUE]; -}; -- (void)getCursorCoord:(MwPoint*)point { - NSPoint p = [NSEvent mouseLocation]; - point->x = p.x; - point->y = p.y; -}; -- (void)getScreenSize:(MwRect*)_rect { - NSScreen* screen = [self->window screen]; - _rect->x = [screen frame].origin.x; - _rect->y = [screen frame].origin.y; - _rect->width = [screen frame].size.width; - _rect->height = [screen frame].size.height; -}; - (void)destroy { [self->handle release]; [self->window release]; @@ -1046,18 +638,98 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { @end static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { - MwLL r; - r = malloc(sizeof(*r)); + MwLL r; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + MilskoCocoa* c = [MilskoCocoa alloc]; + r = malloc(sizeof(*r)); MwLLCreateCommon(r); - MilskoCocoa* o = [MilskoCocoa newWithParent:parent - x:x - y:y - width:width - height:height - handle:r]; - r->cocoa.real = o; + [c retain]; + c->application = (MilskoCocoaApplication*)[MilskoCocoaApplication sharedApplication]; + [c->application retain]; + + /* + * MacOS doesn't really have a "default" window position, you're actually + * meant to center the window yourself, so if the user passes MwDEFAULT + * respond appropriately. Also for child windows just have it be 0. + */ + if(x == MwDEFAULT) { + x = r ? ([[NSScreen mainScreen] frame].size.width / 2.) - (width / 2.) : 0; + } + if(y == MwDEFAULT) { + y = r ? ([[NSScreen mainScreen] frame].size.height / 2.) - (height / 2.) + : 0; + } + c->rect = NSMakeRect(x, y, width, height); + + if(parent == NULL) { + c->window = [[NSWindow alloc] + initWithContentRect:rectFlip(c->rect) + styleMask:(NSTitledWindowMask | + NSClosableWindowMask | NSMiniaturizableWindowMask | + NSResizableWindowMask) + backing:NSBackingStoreBuffered + defer:NO]; + [c->window + setDelegate:[[MilskoCocoaWindowDelegate alloc] initWithWin:c->window]]; + [c->window retain]; + + [c->window makeKeyAndOrderFront:c->application]; + [c->window makeFirstResponder:c->view]; + + c->view = [[MilskoCocoaView alloc] initWithFrame:c->rect]; + [c->view retain]; + [c->window setContentView:c->view]; + + if([c->application respondsToSelector:@selector(setActivationPolicy:)]) { + [c->application + setActivationPolicy:0 /* NSApplicationActivationPolicyRegular */]; + } + [c->application activateIgnoringOtherApps:MwTRUE]; + [c->application setDelegate:[[MilskoCocoaApplicationDelegate alloc] + initWithAppl:c->application]]; + [c->application retain]; + + [c->view addTrackingRect:c->rect owner:c->view userData:NULL assumeInside:MwFALSE]; + c->modalSession = [c->application beginModalSessionForWindow:c->window]; + } else { + MilskoCocoa* p = parent->cocoa.real; + + c->window = p->window; + + NSRect rect = localRectFlip(c->rect, p->view); + c->view = [[MilskoCocoaView alloc] initWithFrame:rect]; + [c->view setBounds:c->rect]; + [c->view retain]; + [c->view setChild]; + + [c->view addTrackingRect:c->rect owner:c->view userData:NULL assumeInside:MwFALSE]; + + [p->view addSubview:c->view]; + + c->modalSession = p->modalSession; + } + [c->window setAcceptsMouseMovedEvents:MwTRUE]; + + c->handle = [[MilskoFakePointer alloc] initWithFrame:NSMakeRect(0, 0, 1, 1)]; + [c->handle retain]; + [c->handle setPointer:r]; + [c->view addSubview:c->handle]; + + c->parent = parent; + + c->_forceRender = MwTRUE; + c->strHash = 0; + + c->cursorPixmap = NULL; + + [c->application finishLaunching]; + + c->pointerLocked = MwFALSE; + + [pool release]; + r->cocoa.real = c; return r; } @@ -1082,13 +754,81 @@ static void MwLLEndDrawImpl(MwLL handle) { static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { - MilskoCocoa* h = handle->cocoa.real; - [h polygonWithPoints:points points_count:points_count color:color]; + MilskoCocoa* self = handle->cocoa.real; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSGraphicsContext* ctx = [self->view context]; + if(ctx) { + int i; + NSBezierPath* path = [NSBezierPath bezierPath]; + /* whatever rect we use for coordinate flipping */ + NSRect _rect = self->parent ? [self->view bounds] : [self->window frame]; + + NSColor* nscolor = + [NSColor colorWithCalibratedRed:color->common.red / 255. + green:color->common.green / 255. + blue:color->common.blue / 255. + alpha:1.0]; + + [NSGraphicsContext saveGraphicsState]; + [NSGraphicsContext setCurrentContext:ctx]; + + [nscolor setFill]; + for(i = 0; i < points_count; i++) { + NSPoint p = localPointFlip(NSMakePoint(points[i].x, points[i].y), self->view); + if(i == 0) { + [path moveToPoint:p]; + } else { + [path lineToPoint:p]; + } + } + + [path closePath]; + [path fill]; + + [NSGraphicsContext restoreGraphicsState]; + + [self->view setNeedsDisplay:YES]; + } + [pool release]; } static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { - MilskoCocoa* h = handle->cocoa.real; - [h lineWithPoints:points color:color]; + MilskoCocoa* self = handle->cocoa.real; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSGraphicsContext* ctx = [self->view context]; + if(ctx) { + int i; + NSBezierPath* path = [NSBezierPath bezierPath]; + /* whatever rect we use for coordinate flipping */ + NSRect _rect = self->parent ? [self->view bounds] : [self->window frame]; + + NSColor* nscolor = + [NSColor colorWithCalibratedRed:color->common.red / 255. + green:color->common.green / 255. + blue:color->common.blue / 255. + alpha:1.0]; + + [NSGraphicsContext saveGraphicsState]; + [NSGraphicsContext setCurrentContext:ctx]; + + [nscolor setFill]; + for(i = 0; i < 2; i++) { + NSPoint p = localPointFlip(NSMakePoint(points[i].x, points[i].y), self->view); + if(i == 0) { + [path moveToPoint:p]; + } else { + [path lineToPoint:p]; + } + } + + [path closePath]; + [path stroke]; + + [NSGraphicsContext restoreGraphicsState]; + + [self->view setNeedsDisplay:YES]; + } + [pool release]; } static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { @@ -1106,16 +846,60 @@ static void MwLLColorUpdateImpl(MwLL handle, MwLLColor c, int r, int g, int b) { } static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, - unsigned int* height) { - [handle->cocoa.real getX:x Y:y W:w H:height]; + unsigned int* h) { + MilskoCocoa* self = handle->cocoa.real; + NSRect frame; + if(self->parent) { + frame = [self->view frame]; + } else { + frame = [self->window frame]; + } + frame = rectFlip(frame); + + *x = frame.origin.x; + *y = frame.origin.y; + + *w = frame.size.width; + *h = frame.size.height; } static void MwLLSetXYImpl(MwLL handle, int x, int y) { - [handle->cocoa.real setX:x Y:y]; + MilskoCocoa* self = handle->cocoa.real; + NSRect frame; + if(self->parent) { + frame = [self->view frame]; + } else { + frame = [self->window frame]; + } + + frame.origin.x = x; + frame.origin.y = y; + + if(!self->parent) { + frame = rectFlip(frame); + [self->window setFrame:frame display:MwTRUE animate:MwTRUE]; + } else { + frame = localRectFlip(frame, self->parent->cocoa.real->view); + [self->view setBounds:frame]; + } + [self nudge]; } -static void MwLLSetWHImpl(MwLL handle, int w, int height) { - [handle->cocoa.real setW:w H:height]; +static void MwLLSetWHImpl(MwLL handle, int w, int h) { + MilskoCocoa* self = handle->cocoa.real; + NSRect frame = [self->window frame]; + frame.size.width = w; + frame.size.height = h; + + self->rect = frame; + + [self->view setFrameSize:frame.size]; + if(self->parent) { + [self->view setFrame:frame]; + } else { + [self->window setFrame:frame display:YES animate:false]; + } + [self nudge]; } static void MwLLFreeColorImpl(MwLLColor color) { @@ -1123,15 +907,45 @@ static void MwLLFreeColorImpl(MwLLColor color) { } static int MwLLPendingImpl(MwLL handle) { - return [handle->cocoa.real pending]; + MilskoCocoa* self = handle->cocoa.real; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + MwBool isPending = [self->application pending]; + [self->application runModalSession:self->modalSession]; + [pool release]; + return self->_forceRender || self->_eventsPending || isPending; } static void MwLLNextEventImpl(MwLL handle) { - [handle->cocoa.real getNextEvent]; + MilskoCocoa* self = handle->cocoa.real; + MwLL h = [self->handle pointer]; + if(self->_forceRender) { + MwLLDispatch(h, draw, NULL); + self->_forceRender = MwFALSE; + } + if(self->_eventsPending) { + MwLLDispatch(h, draw, NULL); + self->_eventsPending = MwFALSE; + } + [self sendClipboardEvent]; + +#ifdef __APPLE__ + if(self->pointerLocked && [self->window isMainWindow] && self->lastEvent) { + struct CGPoint pos; + pos.x = [self->window frame].origin.x + [self->window frame].size.width / 2; + pos.y = [self->window frame].origin.y + [self->window frame].size.height / 2; + + CGWarpMouseCursorPosition(pos); + } +#endif + + [self->application updateWindows]; } static void MwLLSetTitleImpl(MwLL handle, const char* title) { - [handle->cocoa.real setTitle:title]; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [handle->cocoa.real->window + setTitleWithRepresentedFilename:[NSString stringWithUTF8String:title]]; + [pool release]; } static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, @@ -1154,7 +968,24 @@ static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, } static void MwLLPixmapUpdateImpl(MwLLPixmap pixmap) { - [pixmap->cocoa.real updateWithData:pixmap->common.raw]; + MilskoCocoaPixmap* self = pixmap->cocoa.real; + memcpy(self->buf, pixmap->common.raw, pixmap->common.width * pixmap->common.height * 4); + if(self->rep) { + [self->image removeRepresentation:self->rep]; + [self->rep release]; + } + self->rep = + [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:&self->buf + pixelsWide:(int)pixmap->common.width + pixelsHigh:(int)pixmap->common.height + bitsPerSample:8 + samplesPerPixel:4 + hasAlpha:YES + isPlanar:NO + colorSpaceName:NSDeviceRGBColorSpace + bytesPerRow:(int)pixmap->common.width * 4 + bitsPerPixel:32]; + [self->image addRepresentation:self->rep]; } static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { @@ -1164,53 +995,141 @@ static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { } static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { - [handle->cocoa.real drawPixmap:pixmap rect:rect]; + MilskoCocoa* self = handle->cocoa.real; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + MilskoCocoaPixmap* p = pixmap->cocoa.real; + NSGraphicsContext* ctx = [self->view context]; + if(ctx) { + [NSGraphicsContext saveGraphicsState]; + [NSGraphicsContext setCurrentContext:ctx]; + + [[p image] + drawInRect:localRectFlip(NSMakeRect(rect->x, rect->y, rect->width, rect->height), self->view) + fromRect:NSZeroRect + operation:NSCompositeSourceOver + fraction:1.0]; + + [NSGraphicsContext restoreGraphicsState]; + + [self->view setNeedsDisplay:YES]; + } + [pool release]; MwLLForceRender(handle); } static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { - [handle->cocoa.real setIcon:pixmap]; + [handle->cocoa.real->application setApplicationIconImage:[pixmap->cocoa.real image]]; } static void MwLLForceRenderImpl(MwLL handle) { - [handle->cocoa.real forceRender]; + handle->cocoa.real->_forceRender = MwTRUE; } static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { - [handle->cocoa.real setCursor:image mask:mask]; + MilskoCocoa* self = handle->cocoa.real; + int y, x, ys, xs; + unsigned char* di = malloc(image->width * image->height * 4); + memset(di, 0, image->width * image->height * 4); + + if(self->cursorPixmap) { + [self->cursorPixmap destroy]; + } + self->cursorPixmap = + [MilskoCocoaPixmap newWithWidth:image->width + height:image->height]; + + xs = -mask->x + image->x; + ys = MwCursorDataHeight + mask->y; + ys = MwCursorDataHeight + image->y - ys; + + for(y = 0; y < mask->height; y++) { + unsigned int d = mask->data[y]; + for(x = mask->width - 1; x >= 0; x--) { + int px = 0; + int idx = ((y * mask->width) + x) * 4; + + if(d & 1) { + di[idx + 3] = 255; + }; + d = d >> 1; + } + } + for(y = 0; y < image->height; y++) { + unsigned int d = image->data[y]; + for(x = image->width - 1; x >= 0; x--) { + int px = 0; + int idx = ((y * image->width) + x) * 4; + + if(d & 1) { + px = 255; + }; + + di[idx] = px; + di[idx + 1] = px; + di[idx + 2] = px; + d = d >> 1; + } + } + + [self->cursorPixmap updateWithData:di]; + + self->cursor = [[NSCursor alloc] + initWithImage:[self->cursorPixmap image] + hotSpot:NSMakePoint(image->x, image->y + image->height)]; + [self->cursor retain]; + + [self->cursor pop]; + [self->cursor push]; + + free(di); } static void MwLLDetachImpl(MwLL handle, MwPoint* point) { - [handle->cocoa.real detachWithPoint:point]; + [handle->cocoa.real->window setParentWindow:NULL]; } static void MwLLShowImpl(MwLL handle, int show) { - [handle->cocoa.real show:show]; + (void)show; } static void MwLLMakePopupImpl(MwLL handle, MwLL parent) { - [handle->cocoa.real makePopupWithParent:parent]; + (void)parent; } static void MwLLSetSizeHintsImpl(MwLL handle, int minx, int miny, int maxx, int maxy) { - [handle->cocoa.real setSizeHintsWithMinX:minx MinY:miny MaxX:maxx MaxY:maxy]; + MilskoCocoa* self = handle->cocoa.real; + [self->window setMinSize:NSMakeSize(minx, miny)]; + [self->window setMaxSize:NSMakeSize(maxx, maxy)]; } static void MwLLMakeBorderlessImpl(MwLL handle, int toggle) { - [handle->cocoa.real makeBorderless:toggle]; + MilskoCocoa* self = handle->cocoa.real; + MwU32 mask = [self->window styleMask]; + if(toggle) { + mask ^= NSBorderlessWindowMask; + mask |= NSTitledWindowMask; + } else { + mask |= NSBorderlessWindowMask; + mask ^= NSTitledWindowMask; + } + [self->window initWithContentRect:self->rect + styleMask:mask + backing:NSBackingStoreBuffered + defer:NO]; } static void MwLLFocusImpl(MwLL handle) { - [handle->cocoa.real focus]; + [handle->cocoa.real->application activateIgnoringOtherApps:MwTRUE]; } static void MwLLGrabPointerImpl(MwLL handle, int toggle) { - [handle->cocoa.real grabPointer:toggle]; + handle->cocoa.real->pointerLocked = toggle; } static void MwLLSetClipboardImpl(MwLL handle, const char* text) { - [handle->cocoa.real setClipboard:text]; + (void)handle; + (void)text; } static void MwLLGetClipboardImpl(MwLL handle) { @@ -1218,15 +1137,26 @@ static void MwLLGetClipboardImpl(MwLL handle) { } static void MwLLMakeToolWindowImpl(MwLL handle) { - [handle->cocoa.real makeToolWindow]; + /* If my understand of what a "tool window" usually is is correct then I + * highly doubt the Mac OS has this and if they did they probably outright + * removed it along time ago is this kind of conflicts with modern UX. So + * we'll just make it borderless idgaf */ + MwLLMakeBorderlessImpl(handle, 1); } static void MwLLGetCursorCoordImpl(MwLL handle, MwPoint* point) { - [handle->cocoa.real getCursorCoord:point]; + NSPoint p = [NSEvent mouseLocation]; + point->x = p.x; + point->y = p.y; } static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) { - [handle->cocoa.real getScreenSize:rect]; + MilskoCocoa* self = handle->cocoa.real; + NSScreen* screen = [self->window screen]; + rect->x = [screen frame].origin.x; + rect->y = [screen frame].origin.y; + rect->width = [screen frame].size.width; + rect->height = [screen frame].size.height; } static void MwLLBeginStateChangeImpl(MwLL handle) { From c0d7cb3fbc71811cf4bd6346b58d579567ac890c Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 13 Apr 2026 21:50:10 -0700 Subject: [PATCH 130/195] mac: add a few comments --- src/backend/cocoa.m | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index b43aef2b7..ec20af1c9 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -327,6 +327,7 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { - (void)handleKeyEvent:(NSEvent*)ev ll:(MwLL)ll down:(MwBool)isDown { int ch; + /* todo: consolidate these values into the below switch case. */ enum { kVK_ANSI_A = 0x00, kVK_ANSI_S = 0x01, @@ -682,10 +683,12 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { [c->view retain]; [c->window setContentView:c->view]; + /* In order for our application to be front and center when launched, we need to use this function introduced in 10.5. There's no function that works on 10.4 or below as far as I know because what you're actually supposed to do is use a feature of XCode project files to modify the settings of the compiled app to set the activation policy. */ if([c->application respondsToSelector:@selector(setActivationPolicy:)]) { [c->application setActivationPolicy:0 /* NSApplicationActivationPolicyRegular */]; } + [c->application activateIgnoringOtherApps:MwTRUE]; [c->application setDelegate:[[MilskoCocoaApplicationDelegate alloc] initWithAppl:c->application]]; @@ -694,12 +697,11 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { [c->view addTrackingRect:c->rect owner:c->view userData:NULL assumeInside:MwFALSE]; c->modalSession = [c->application beginModalSessionForWindow:c->window]; } else { - MilskoCocoa* p = parent->cocoa.real; + MilskoCocoa* p = parent->cocoa.real; + NSRect rect = localRectFlip(c->rect, p->view); c->window = p->window; - - NSRect rect = localRectFlip(c->rect, p->view); - c->view = [[MilskoCocoaView alloc] initWithFrame:rect]; + c->view = [[MilskoCocoaView alloc] initWithFrame:rect]; [c->view setBounds:c->rect]; [c->view retain]; [c->view setChild]; @@ -729,6 +731,7 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { c->pointerLocked = MwFALSE; [pool release]; + r->cocoa.real = c; return r; From fe72bc92bfd3781b723c7c65ccbc36d8cc04cefb Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 13 Apr 2026 22:30:25 -0700 Subject: [PATCH 131/195] mac: actually dispatch close event. reorganize code slightly more now that less is in objective-c methods --- src/backend/cocoa.m | 317 ++++++++++++++++++++------------------------ 1 file changed, 143 insertions(+), 174 deletions(-) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index ec20af1c9..b88bd423b 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -64,139 +64,6 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { } }; -@implementation MilskoCocoaPixmap - -+ (MilskoCocoaPixmap*)newWithWidth:(int)width height:(int)height { - MilskoCocoaPixmap* p = [MilskoCocoaPixmap alloc]; - - p->width = width; - p->height = height; - p->image = NULL; - - p->buf = malloc(width * height * 4); - - p->rep = - [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:&p->buf - pixelsWide:(int)width - pixelsHigh:(int)height - bitsPerSample:8 - samplesPerPixel:4 - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSDeviceRGBColorSpace - bytesPerRow:(int)width * 4 - bitsPerPixel:32]; - assert(p->rep); - - p->image = [[NSImage alloc] initWithSize:NSMakeSize(width, height)]; - assert(p->image); - [p->image addRepresentation:p->rep]; - - return p; -} -- (void)updateWithData:(unsigned char*)_data { - memcpy(self->buf, _data, width * height * 4); - if(self->rep) { - [self->image removeRepresentation:self->rep]; - [self->rep release]; - } - self->rep = - [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:&self->buf - pixelsWide:(int)width - pixelsHigh:(int)height - bitsPerSample:8 - samplesPerPixel:4 - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSDeviceRGBColorSpace - bytesPerRow:(int)width * 4 - bitsPerPixel:32]; - [self->image addRepresentation:self->rep]; -} -- (void)destroy { - free(self->buf); - [self->image removeRepresentation:self->rep]; - [self->image release]; - [self->rep release]; - self->image = NULL; - self->rep = NULL; -} -- (NSImage*)image { - return self->image; -} -@end - -@implementation MilskoCocoa -- (void)sendClipboardEvent { - /*NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSPasteboard* pasteboard = [NSPasteboard generalPasteboard]; - NSArray* items = @[ - @"public.utf8-plain-text", - @"public.utf16-external-plain-text", - @"com.apple.traditional-mac-plain-text", - ]; - MwLL this = self->handle.pointer; - - if([pasteboard canReadItemWithDataConformingToTypes:items]) { - char* data = NULL; - size_t size = 0; - for(NSPasteboardItem* item in [pasteboard pasteboardItems]) { - for(NSString* it in items) { - NSString* itemData = [item - stringForType:(NSString*)it]; if(itemData != NULL) { if(strHash != 0 && - strHash != [itemData hash]) { char* text = malloc([itemData length]); - strncpy(text, [itemData UTF8String], - [itemData length]); MwLLDispatch(this, clipboard, text); printf("%s -> %p\n", - text, this); free(text); - } - strHash = [itemData hash]; - } - } - } - } - - [pool release];*/ -} - -- (void)destroy { - [self->handle release]; - [self->window release]; -} - -- (MwLL)getParent { - return self->parent; -} - -- (NSView*)getView { - return view; -} -- (NSWindow*)getWindow { - return window; -} - -- (void)nudge { - MwLL p = self->parent; - self->_eventsPending = MwTRUE; - - if(p) { - [p->cocoa.real->view setNeedsDisplay:true]; - p = p->cocoa.real->parent; - } -} - -- (void)pushCursor { - [self->cursor push]; -} -- (void)popCursor { - [self->cursor pop]; -} - -- (MilskoFakePointer*)getHandle { - return handle; -} - -@end - @implementation MilskoCocoaApplication - (void)sendEvent:(NSEvent*)event { self->doPending = MwTRUE; @@ -555,17 +422,6 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { self->appl = _appl; return self; } -- (void)applicationDidBecomeActive:(NSNotification*)notification { - [self->appl activateIgnoringOtherApps:true]; - // printf("test\n"); -} -- (void)applicationWillFinishLaunching:(NSNotification*)notification { - // printf("test\n"); - // [self->appl activateIgnoringOtherApps:MwTRUE]; -} -- (void)applicationDidFinishLaunching:(NSNotification*)notification { - // [self->appl activateIgnoringOtherApps:MwTRUE]; -} @end @implementation MilskoCocoaWindowDelegate @@ -591,23 +447,19 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { [self->w makeKeyAndOrderFront:nil]; } -- (void)windowDidResize:(NSNotification*)notification { - (void)notification; -} - -// This will close/terminate the application when the main window is closed. -- (void)windowWillClose:(NSNotification*)notification { - (void)notification; - // MilskoCocoa* window = notification.object; - // MwLL handle = [window getHandle].pointer; - // MwLLDispatch(handle, close, NULL); -} - - (MilskoCocoaWindowDelegate*)initWithWin:(NSWindow*)win { self->w = win; return self; } +- (void)windowWillClose:(NSNotification*)notification { + if([[[w contentView] subviews] count] != 0) { + MwLL h = [((MilskoFakePointer*)[[[w contentView] subviews] + objectAtIndex:0]) pointer]; + MwLLDispatch(h, close, NULL); + } +} + @end @implementation MilskoFakePointer @@ -638,6 +490,138 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { @end +@implementation MilskoCocoaPixmap ++ (MilskoCocoaPixmap*)newWithWidth:(int)width height:(int)height { + MilskoCocoaPixmap* p = [MilskoCocoaPixmap alloc]; + + p->width = width; + p->height = height; + p->image = NULL; + + p->buf = malloc(width * height * 4); + + p->rep = + [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:&p->buf + pixelsWide:(int)width + pixelsHigh:(int)height + bitsPerSample:8 + samplesPerPixel:4 + hasAlpha:YES + isPlanar:NO + colorSpaceName:NSDeviceRGBColorSpace + bytesPerRow:(int)width * 4 + bitsPerPixel:32]; + assert(p->rep); + + p->image = [[NSImage alloc] initWithSize:NSMakeSize(width, height)]; + assert(p->image); + [p->image addRepresentation:p->rep]; + + return p; +} +- (void)updateWithData:(unsigned char*)_data { + memcpy(self->buf, _data, width * height * 4); + if(self->rep) { + [self->image removeRepresentation:self->rep]; + [self->rep release]; + } + self->rep = + [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:&self->buf + pixelsWide:(int)width + pixelsHigh:(int)height + bitsPerSample:8 + samplesPerPixel:4 + hasAlpha:YES + isPlanar:NO + colorSpaceName:NSDeviceRGBColorSpace + bytesPerRow:(int)width * 4 + bitsPerPixel:32]; + [self->image addRepresentation:self->rep]; +} +- (void)destroy { + free(self->buf); + [self->image removeRepresentation:self->rep]; + [self->image release]; + [self->rep release]; + self->image = NULL; + self->rep = NULL; +} +- (NSImage*)image { + return self->image; +} +@end + +@implementation MilskoCocoa +- (void)sendClipboardEvent { + /*NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSPasteboard* pasteboard = [NSPasteboard generalPasteboard]; + NSArray* items = @[ + @"public.utf8-plain-text", + @"public.utf16-external-plain-text", + @"com.apple.traditional-mac-plain-text", + ]; + MwLL this = self->handle.pointer; + + if([pasteboard canReadItemWithDataConformingToTypes:items]) { + char* data = NULL; + size_t size = 0; + for(NSPasteboardItem* item in [pasteboard pasteboardItems]) { + for(NSString* it in items) { + NSString* itemData = [item + stringForType:(NSString*)it]; if(itemData != NULL) { if(strHash != 0 && + strHash != [itemData hash]) { char* text = malloc([itemData length]); + strncpy(text, [itemData UTF8String], + [itemData length]); MwLLDispatch(this, clipboard, text); printf("%s -> %p\n", + text, this); free(text); + } + strHash = [itemData hash]; + } + } + } + } + + [pool release];*/ +} + +- (void)destroy { + [self->handle release]; + [self->window release]; +} + +- (MwLL)getParent { + return self->parent; +} + +- (NSView*)getView { + return view; +} +- (NSWindow*)getWindow { + return window; +} + +- (void)nudge { + MwLL p = self->parent; + self->_eventsPending = MwTRUE; + + if(p) { + [p->cocoa.real->view setNeedsDisplay:true]; + p = p->cocoa.real->parent; + } +} + +- (void)pushCursor { + [self->cursor push]; +} +- (void)popCursor { + [self->cursor pop]; +} + +- (MilskoFakePointer*)getHandle { + return handle; +} + +@end + static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { MwLL r; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; @@ -953,9 +937,9 @@ static void MwLLSetTitleImpl(MwLL handle, const char* title) { static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, int width, int height) { - (void)handle; - MwLLPixmap r = malloc(sizeof(*r)); + + (void)handle; memset(r, 0, sizeof(*r)); r->common.raw = malloc(4 * width * height); @@ -973,22 +957,7 @@ static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, static void MwLLPixmapUpdateImpl(MwLLPixmap pixmap) { MilskoCocoaPixmap* self = pixmap->cocoa.real; memcpy(self->buf, pixmap->common.raw, pixmap->common.width * pixmap->common.height * 4); - if(self->rep) { - [self->image removeRepresentation:self->rep]; - [self->rep release]; - } - self->rep = - [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:&self->buf - pixelsWide:(int)pixmap->common.width - pixelsHigh:(int)pixmap->common.height - bitsPerSample:8 - samplesPerPixel:4 - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSDeviceRGBColorSpace - bytesPerRow:(int)pixmap->common.width * 4 - bitsPerPixel:32]; - [self->image addRepresentation:self->rep]; + [pixmap->cocoa.real updateWithData:pixmap->common.raw]; } static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { From 0e2e3a190157cc5f29fdbb1a54a2301383e9f97d Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 14 Apr 2026 13:13:17 -0700 Subject: [PATCH 132/195] some gnustep fixes, probably close to giving up on this ngl --- include/Mw/LowLevel/Cocoa.h | 2 ++ src/backend/cocoa.m | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index 3577ad03e..2a8c7ec7c 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -81,6 +81,8 @@ @end @interface MilskoCocoaView : NSView { + @public + unsigned char* buf; NSBitmapImageRep* rep; NSGraphicsContext* context; MwBool valid; diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index b88bd423b..c336f7fb8 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -140,8 +140,11 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { - (void)initRepAndContextWithWidth:(float)w Height:(float)h { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + self->buf = malloc(w * h * 4); + memset(self->buf, 255, w * h * 4); + self->rep = - [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL + [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:&self->buf pixelsWide:w pixelsHigh:h bitsPerSample:8 @@ -536,6 +539,7 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { colorSpaceName:NSDeviceRGBColorSpace bytesPerRow:(int)width * 4 bitsPerPixel:32]; + assert(self->rep); [self->image addRepresentation:self->rep]; } - (void)destroy { @@ -975,7 +979,7 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { [NSGraphicsContext saveGraphicsState]; [NSGraphicsContext setCurrentContext:ctx]; - [[p image] + [p->image drawInRect:localRectFlip(NSMakeRect(rect->x, rect->y, rect->width, rect->height), self->view) fromRect:NSZeroRect operation:NSCompositeSourceOver From f22f45d5bf61f1b2fb9dd819bfe6b3f73acfb303 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 14 Apr 2026 13:34:49 -0700 Subject: [PATCH 133/195] give up on rounded borders --- include/Mw/Draw.h | 6 +- src/core.c | 1 - src/draw.c | 284 ++++++++++----------------------------- src/widget/box.c | 2 +- src/widget/combobox.c | 2 +- src/widget/entry.c | 2 +- src/widget/frame.c | 2 +- src/widget/image.c | 2 +- src/widget/listbox.c | 6 +- src/widget/menu.c | 2 +- src/widget/progressbar.c | 2 +- src/widget/separator.c | 2 +- src/widget/submenu.c | 2 +- src/widget/treeview.c | 8 +- src/widget/window.c | 2 +- 15 files changed, 92 insertions(+), 233 deletions(-) diff --git a/include/Mw/Draw.h b/include/Mw/Draw.h index c6c361275..9208d725d 100644 --- a/include/Mw/Draw.h +++ b/include/Mw/Draw.h @@ -53,7 +53,7 @@ MWDECL void MwDrawRect(MwWidget handle, MwRect* rect, MwLLColor color); * @param rect Rectangle area * @param color Color */ -MWDECL void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color, int rounded); +MWDECL void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color); /*! * @brief Draws a frame @@ -63,7 +63,7 @@ MWDECL void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color, int * @param invert Invert the 3D border color or not * @warning `rect` gets changed to the area of rectangle inside */ -MWDECL void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int rounded); +MWDECL void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert); /*! * @brief Does the DrawFrame/DrawRect combo used for drawing widget. @@ -96,7 +96,7 @@ MWDECL void MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int i * @param rounded Rounded or not * @warning `rect` gets changed to the area of rectangle inside */ -MWDECL void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border, int diff, int same, int rounded); +MWDECL void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border, int diff, int same); /*! * @brief Creates a pixmap from image diff --git a/src/core.c b/src/core.c index cdd0723b9..2b98ec5fc 100644 --- a/src/core.c +++ b/src/core.c @@ -606,7 +606,6 @@ int MwGetInteger(MwWidget handle, const char* key) { #else if(strcmp(key, MwNmodernLook) == 0) return inherit_integer(handle, key, 1); #endif - if(strcmp(key, MwNisRounded) == 0) return inherit_integer(handle, key, 1); if(strcmp(key, MwNdarkTheme) == 0) return inherit_integer(handle, key, 0); if(strcmp(key, MwNuseMonospace) == 0) return inherit_integer(handle, key, 0); } diff --git a/src/draw.c b/src/draw.c index 12ccb5127..f5e1368dd 100644 --- a/src/draw.c +++ b/src/draw.c @@ -11,10 +11,6 @@ #include "../external/stb_ds.h" -#define DEFAULT_ROUNDNESS 5 -#define MAX_ROUNDNESS 30 -#define BORDER_SMOOTHNESS 50 - static int get_color_diff(MwWidget handle) { if(MwGetInteger(handle, MwNmodernLook)) { return 40; @@ -106,7 +102,7 @@ void MwDrawRect(MwWidget handle, MwRect* rect, MwLLColor color) { MwLLPolygon(handle->lowlevel, p, 4, color); } -void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color, int rounded) { +void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color) { MwLLPixmap pixmap; int y, i; double darken = 0.; @@ -115,17 +111,18 @@ void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color, int rounde unsigned long sz = 1 * rect->height * 4; unsigned char* data = malloc(sz); MwRect r = *rect; - int roundness = MwGetInteger(handle, MwNroundness); double div; if(rect->width <= 0 || rect->height <= 0) { free(data); return; } - if(roundness == MwDEFAULT) roundness = DEFAULT_ROUNDNESS; - if(roundness >= MAX_ROUNDNESS) roundness = MAX_ROUNDNESS; - div = (roundness <= 10) ? 7. : 10.; memset(data, 0, sz); + r.x += 1; + r.y += 1; + r.width -= 2; + r.height -= 2; + for(y = 0; y < rect->height; y++) { MwLLColor col = MwLightenColor(handle, color, -darken, -darken, -darken); int idx = y * 4; @@ -138,42 +135,18 @@ void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color, int rounde } pixmap = MwLLCreatePixmap(handle->lowlevel, data, 1, rect->height); - if(rounded && rect->height >= (roundness * 2) && rect->width >= (roundness * 2) && roundness > 0) { - for(i = 0; i < roundness; i++) { - int x = (roundness + 2); - int y = rect->y + (roundness + 2); - double point = ((i + (M_PI * 4)) / div); - r.x = (roundness + 4) - (sin(point) * roundness); - r.y = y + (cos(point) * roundness) + 1; - r.width = roundness; - r.height = (rect->height - ((r.y - rect->y) * 2) - 1); - MwLLDrawPixmap(handle->lowlevel, &r, pixmap); - r.width = x + (sin(point + 1) * roundness); - r.x = ((rect->width - (roundness + 1)) + (sin(point) * roundness)) - r.width; - MwLLDrawPixmap(handle->lowlevel, &r, pixmap); - } - - r = *rect; - r.x += roundness; - r.y += 3; - r.width -= (roundness * 2) + 1; - r.height -= 6; - MwLLDrawPixmap(handle->lowlevel, &r, pixmap); - - } else { - MwLLDrawPixmap(handle->lowlevel, &r, pixmap); - } + MwLLDrawPixmap(handle->lowlevel, &r, pixmap); MwLLDestroyPixmap(pixmap); free(data); } -void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int rounded) { +void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert) { int inv; if((inv = MwGetInteger(handle, MwNforceInverted)) != MwDEFAULT && inv) invert = 1; if(MwGetInteger(handle, MwNmodernLook)) { - MwDrawFrameEx(handle, rect, color, invert, MwDefaultBorderWidth(handle), 0, 0, rounded); + MwDrawFrameEx(handle, rect, color, invert, MwDefaultBorderWidth(handle), 0, 0); } else { int diff = get_color_diff(handle) / 3 * 2; @@ -181,18 +154,17 @@ void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int int i; int st = invert ? 1 : 0; for(i = st; i < st + 2; i++) { - if((i % 2) == 0) MwDrawFrameEx(handle, rect, color, invert, MwDefaultBorderWidth(handle) - 1, -diff, (handle->parent == NULL || handle->parent->lowlevel == NULL) ? 1 : 0, 0); - if((i % 2) == 1) MwDrawFrameEx(handle, rect, color, invert, 1, diff, 0, 0); + if((i % 2) == 0) MwDrawFrameEx(handle, rect, color, invert, MwDefaultBorderWidth(handle) - 1, -diff, (handle->parent == NULL || handle->parent->lowlevel == NULL) ? 1 : 0); + if((i % 2) == 1) MwDrawFrameEx(handle, rect, color, invert, 1, diff, 0); } } else { - MwDrawFrameEx(handle, rect, color, invert, 1, 0, 0, 0); + MwDrawFrameEx(handle, rect, color, invert, 1, 0, 0); } } } void MwDrawWidgetBack(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border) { MwLLColor col; - MwBool rounded = MwGetInteger(handle, MwNroundness) != MwDEFAULT && MwGetInteger(handle, MwNisRounded) != 0; if(rect->width <= 0 || rect->height <= 0) return; @@ -206,11 +178,11 @@ void MwDrawWidgetBack(MwWidget handle, MwRect* rect, MwLLColor color, int invert } } - MwDrawFrame(handle, rect, color, invert, rounded); + MwDrawFrame(handle, rect, color, invert); } col = invert ? MwLightenColor(handle, color, -8, -8, -8) : color; if(MwGetInteger(handle, MwNmodernLook)) { - MwDrawRectFading(handle, rect, col, rounded); + MwDrawRectFading(handle, rect, col); } else { MwDrawRect(handle, rect, col); } @@ -284,55 +256,47 @@ void MwDrawDiamond(MwWidget handle, MwRect* rect, MwLLColor color, int invert) { MwLLFreeColor(darker); } -static void MwDrawFrameEx_simple(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border, int diff, int same, int rounded) { +static void MwDrawFrameEx_simple(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border, int diff, int same) { MwPoint p[7]; int ColorDiff = get_color_diff(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); - int roundness = MwGetInteger(handle, MwNroundness); + p[0].x = rect->x; + p[0].y = rect->y; - if(roundness == MwDEFAULT) roundness = DEFAULT_ROUNDNESS; - if(roundness >= MAX_ROUNDNESS) roundness = MAX_ROUNDNESS; - if(!(rounded && rect->height >= (roundness * 2) && rect->width >= (roundness * 2) && roundness > 0)) { - p[0].x = rect->x; - p[0].y = rect->y; + p[1].x = rect->x + rect->width; + p[1].y = rect->y; - p[1].x = rect->x + rect->width; - p[1].y = rect->y; + p[2].x = rect->x + rect->width - border; + p[2].y = rect->y + border; + p[3].x = rect->x + border; + p[3].y = rect->y + border; - p[2].x = rect->x + rect->width - border; - p[2].y = rect->y + border; - p[3].x = rect->x + border; - p[3].y = rect->y + border; + p[4].x = rect->x + border; + p[4].y = rect->y + rect->height - border; - p[4].x = rect->x + border; - p[4].y = rect->y + rect->height - border; - - p[5].x = rect->x; - p[5].y = rect->y + rect->height; - } + p[5].x = rect->x; + p[5].y = rect->y + rect->height; MwLLPolygon(handle->lowlevel, p, 6, invert ? darker : lighter); - if(!(rounded && rect->height >= (roundness * 2) && rect->width >= (roundness * 2) && roundness > 0)) { - p[0].x = rect->x + rect->width; - p[0].y = rect->y; + p[0].x = rect->x + rect->width; + p[0].y = rect->y; - p[1].x = rect->x + rect->width - border; - p[1].y = rect->y + border; + p[1].x = rect->x + rect->width - border; + p[1].y = rect->y + border; - p[2].x = rect->x + rect->width - border; - p[2].y = rect->y + rect->height - border; + p[2].x = rect->x + rect->width - border; + p[2].y = rect->y + rect->height - border; - p[3].x = rect->x + border; - p[3].y = rect->y + rect->height - border; + p[3].x = rect->x + border; + p[3].y = rect->y + rect->height - border; - p[4].x = rect->x; - p[4].y = rect->y + rect->height; + p[4].x = rect->x; + p[4].y = rect->y + rect->height; - p[5].x = rect->x + rect->width; - p[5].y = rect->y + rect->height; - MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker); - } + p[5].x = rect->x + rect->width; + p[5].y = rect->y + rect->height; + MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker); MwLLFreeColor(lighter); MwLLFreeColor(darker); @@ -343,168 +307,64 @@ 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, int rounded) { +static void frame_border_complex(MwWidget handle, MwRect* rect, MwLLColor lighter, MwLLColor darker, int invert, int border, int diff, int same) { MwPoint p[7]; - int roundness = MwGetInteger(handle, MwNroundness); int i; (void)diff; (void)same; - if(roundness == MwDEFAULT) roundness = DEFAULT_ROUNDNESS; - if(roundness >= MAX_ROUNDNESS) roundness = MAX_ROUNDNESS; - if(rounded && rect->height >= (roundness * 4) && rect->width >= (roundness * 4) && roundness > 0) { - /* top left edge */ - for(i = 0; i < BORDER_SMOOTHNESS; i += 2) { - MwPoint line[2]; - double point = ((i + (M_PI * (BORDER_SMOOTHNESS / 2.))) / (BORDER_SMOOTHNESS)); - int x = rect->x + (roundness + 2); - int y = rect->y + (roundness + 2); + p[0].x = rect->x; + p[0].y = rect->y; - line[0].x = x - (sin(point) * roundness); - line[0].y = y + (cos(point) * roundness); - line[1].x = x - (sin(point + 1) * roundness); - line[1].y = y + (cos(point + 1) * roundness); - MwLLLine(handle->lowlevel, line, invert ? lighter : darker); - } + p[1].x = rect->x + rect->width; + p[1].y = rect->y; - p[0].x = rect->x + roundness; - p[0].y = rect->y + border; + p[2].x = rect->x + rect->width - border; + p[2].y = rect->y + border; + p[3].x = rect->x + border; + p[3].y = rect->y + border; - p[1].x = rect->x + rect->width - border - roundness; - p[1].y = rect->y + border; + p[4].x = rect->x + border; + p[4].y = rect->y + rect->height - border; - p[2].x = rect->x + rect->width - border - roundness; - p[2].y = rect->y + border + roundness; - - p[3].x = rect->x + border; - p[3].y = rect->y + border + roundness; - - p[4].x = rect->x + border; - p[4].y = (rect->y + border) + rect->height - roundness; - - p[5].x = rect->x + roundness; - p[5].y = (rect->y + border) + rect->height - roundness; - MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker); - - /* top right edge */ - for(i = 0; i < BORDER_SMOOTHNESS; i += 2) { - MwPoint line[2]; - double point = ((i + (M_PI * (BORDER_SMOOTHNESS / 2.))) / (BORDER_SMOOTHNESS)); - int x = (rect->x + rect->width) - (roundness + 2); - int y = rect->y + (roundness + 2); - double placeholder = (sin(point) * roundness); - line[0].x = x + placeholder; - line[0].y = y + (cos(point) * roundness); - line[1].x = x + (sin(point + 1) * roundness); - line[1].y = y + (cos(point + 1) * roundness); - MwLLLine(handle->lowlevel, line, invert ? lighter : darker); - } - } else { - p[0].x = rect->x; - p[0].y = rect->y; - - p[1].x = rect->x + rect->width; - p[1].y = rect->y; - - p[2].x = rect->x + rect->width - border; - p[2].y = rect->y + border; - p[3].x = rect->x + border; - p[3].y = rect->y + border; - - p[4].x = rect->x + border; - p[4].y = rect->y + rect->height - border; - - p[5].x = rect->x; - p[5].y = rect->y + rect->height; - } + p[5].x = rect->x; + p[5].y = rect->y + rect->height; MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker); - if(rounded && rect->height >= (roundness * 4) && rect->width >= (roundness * 4) && roundness > 0) { - /* bottom left edge */ - for(i = 0; i < BORDER_SMOOTHNESS; i += 2) { - MwPoint line[2]; - double point = ((i + (M_PI * (BORDER_SMOOTHNESS / 2.))) / (BORDER_SMOOTHNESS)); - int x = rect->x + (roundness + 2); - int y = (rect->y + rect->height) - (roundness + 2); + p[0].x = rect->x + rect->width; + p[0].y = rect->y; - line[0].x = x - (sin(point) * roundness); - line[0].y = y - (cos(point) * roundness); - line[1].x = x - (sin(point + 1) * roundness); - line[1].y = y - (cos(point + 1) * roundness); - MwLLLine(handle->lowlevel, line, invert ? lighter : darker); - } - p[0].x = rect->x + roundness; - p[0].y = rect->y + border + roundness; + p[1].x = rect->x + rect->width - border; + p[1].y = rect->y + border; - p[1].x = rect->x + rect->width - border; - p[1].y = rect->y + border + roundness; + p[2].x = rect->x + rect->width - border; + p[2].y = rect->y + rect->height - border; - p[2].x = rect->x + rect->width - border; - p[2].y = rect->y + rect->height - border - roundness; + p[3].x = rect->x + border; + p[3].y = rect->y + rect->height - border; - p[3].x = rect->x + rect->width - border - roundness; - p[3].y = rect->y + rect->height - border; + p[4].x = rect->x; + p[4].y = rect->y + rect->height; - p[4].x = rect->x + border + roundness; - p[4].y = rect->y + rect->height - border; - - p[5].x = rect->x + roundness; - p[5].y = rect->y + rect->height - roundness; - - p[6].x = rect->x + rect->width - border - roundness; - p[6].y = rect->y + rect->height - roundness; - - MwLLPolygon(handle->lowlevel, p, 7, invert ? lighter : darker); - - /* bottom right edge */ - for(i = 0; i < BORDER_SMOOTHNESS; i += 2) { - MwPoint line[2]; - double point = ((i + (M_PI * (BORDER_SMOOTHNESS / 2.))) / (BORDER_SMOOTHNESS)); - int x = (rect->x + rect->width) - (roundness + 2); - int y = (rect->y + rect->height) - (roundness + 2); - - line[0].x = x + (sin(point) * roundness); - line[0].y = y - (cos(point) * roundness); - line[1].x = x + (sin(point + 1) * roundness); - line[1].y = y - (cos(point + 1) * roundness); - MwLLLine(handle->lowlevel, line, invert ? lighter : darker); - } - } else { - p[0].x = rect->x + rect->width; - p[0].y = rect->y; - - p[1].x = rect->x + rect->width - border; - p[1].y = rect->y + border; - - p[2].x = rect->x + rect->width - border; - p[2].y = rect->y + rect->height - border; - - p[3].x = rect->x + border; - p[3].y = rect->y + rect->height - border; - - p[4].x = rect->x; - p[4].y = rect->y + rect->height; - - p[5].x = rect->x + rect->width; - p[5].y = rect->y + rect->height; - MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker); - } + p[5].x = rect->x + rect->width; + p[5].y = rect->y + rect->height; + MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker); } -static void MwDrawFrameEx_complex(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border, int diff, int same, int rounded) { +static void MwDrawFrameEx_complex(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border, int diff, int same) { int ColorDiff = get_color_diff(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; - frame_border_complex(handle, rect, lighter, darker, invert, border, diff, same, rounded); + frame_border_complex(handle, rect, lighter, darker, invert, border, diff, same); r.x += 1; r.y += 1; r.width -= 2; r.height -= 2; - frame_border_complex(handle, &r, lighter, darker, !invert, border, diff, same, rounded); + frame_border_complex(handle, &r, lighter, darker, !invert, border, diff, same); MwLLFreeColor(lighter); MwLLFreeColor(darker); @@ -515,11 +375,11 @@ 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, int rounded) { +void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border, int diff, int same) { if(MwGetInteger(handle, MwNmodernLook)) { - MwDrawFrameEx_complex(handle, rect, color, invert, border, diff, same, rounded); + MwDrawFrameEx_complex(handle, rect, color, invert, border, diff, same); } else { - MwDrawFrameEx_simple(handle, rect, color, invert, border, diff, same, rounded); + MwDrawFrameEx_simple(handle, rect, color, invert, border, diff, same); } } diff --git a/src/widget/box.c b/src/widget/box.c index 0cc8df1f7..a87000f0e 100644 --- a/src/widget/box.c +++ b/src/widget/box.c @@ -86,7 +86,7 @@ static void draw(MwWidget handle) { r.height = MwGetInteger(handle, MwNheight); if(MwGetInteger(handle, MwNhasBorder)) { - MwDrawFrame(handle, &r, base, MwGetInteger(handle, MwNinverted), 0); + MwDrawFrame(handle, &r, base, MwGetInteger(handle, MwNinverted)); } MwDrawRect(handle, &r, base); diff --git a/src/widget/combobox.c b/src/widget/combobox.c index d52cc2503..22a90060f 100644 --- a/src/widget/combobox.c +++ b/src/widget/combobox.c @@ -72,7 +72,7 @@ static void draw(MwWidget handle) { r.y += r.height; r.height = MwDefaultBorderWidth(handle) * 2; - MwDrawFrame(handle, &r, base, 0, 0); + MwDrawFrame(handle, &r, base, 0); MwLLFreeColor(text); MwLLFreeColor(base); diff --git a/src/widget/entry.c b/src/widget/entry.c index 3a7aa764d..bd7dbe1b5 100644 --- a/src/widget/entry.c +++ b/src/widget/entry.c @@ -49,7 +49,7 @@ static void draw(MwWidget handle) { int attr; MwRect currc; - p.x = (r.width - (r.width / w * w)) / 2 + (MwGetInteger(handle, MwNisRounded) ? MwGetInteger(handle, MwNroundness) : 0); + p.x = (r.width - (r.width / w * w)) / 2; p.y = r.height / 2; len = (r.width - p.x * 2) / w; diff --git a/src/widget/frame.c b/src/widget/frame.c index 3c2ffe99f..117b0f8b9 100644 --- a/src/widget/frame.c +++ b/src/widget/frame.c @@ -22,7 +22,7 @@ static void draw(MwWidget handle) { fr.y = 0; fr.width = MwGetInteger(handle, MwNwidth); fr.height = MwGetInteger(handle, MwNheight); - MwDrawFrame(handle, &fr, base, inverted, 0); + MwDrawFrame(handle, &fr, base, inverted); rr.x = MwDefaultBorderWidth(handle); rr.y = MwDefaultBorderWidth(handle); diff --git a/src/widget/image.c b/src/widget/image.c index cadddb323..74ee0bfd6 100644 --- a/src/widget/image.c +++ b/src/widget/image.c @@ -20,7 +20,7 @@ static void draw(MwWidget handle) { r.width = MwGetInteger(handle, MwNwidth); r.height = MwGetInteger(handle, MwNheight); - if(MwGetInteger(handle, MwNhasBorder)) MwDrawFrame(handle, &r, base, MwGetInteger(handle, MwNinverted), 0); + if(MwGetInteger(handle, MwNhasBorder)) MwDrawFrame(handle, &r, base, MwGetInteger(handle, MwNinverted)); MwDrawRect(handle, &r, base); if(px != NULL) { diff --git a/src/widget/listbox.c b/src/widget/listbox.c index b25528fb7..9960e1d67 100644 --- a/src/widget/listbox.c +++ b/src/widget/listbox.c @@ -210,7 +210,7 @@ static void frame_draw(MwWidget handle) { p.x = MwDefaultBorderWidth(handle); p.y = MwDefaultBorderWidth(handle); - MwDrawFrame(handle, &r, base, 1, 0); + MwDrawFrame(handle, &r, base, 1); MwDrawRect(handle, &r, base2); r = r2; @@ -284,7 +284,7 @@ static void frame_draw(MwWidget handle) { handle->bgcolor = NULL; } - MwDrawFrame(handle, &r, base, 1, 0); + MwDrawFrame(handle, &r, base, 1); MwLLFreeColor(text2); MwLLFreeColor(text); @@ -403,7 +403,7 @@ static void draw(MwWidget handle) { r.y = 0; r.width = get_col_width(lb, i); r.height = MwDefaultBorderWidth(handle) * 2 + MwTextHeight(handle, NULL, "M"); - MwDrawFrame(handle, &r, base, 0, 0); + MwDrawFrame(handle, &r, base, 0); x += MwDefaultBorderWidth(handle); diff --git a/src/widget/menu.c b/src/widget/menu.c index 85753f9b3..0808f691d 100644 --- a/src/widget/menu.c +++ b/src/widget/menu.c @@ -100,7 +100,7 @@ static void draw(MwWidget handle) { BEGIN_MENU_LOOP; if(m->sub[i]->wsub != NULL || (in_area && handle->pressed)) { - MwDrawFrame(handle, &r, base, MwFALSE, 0); + MwDrawFrame(handle, &r, base, MwFALSE); MwDrawWidgetBack(handle, &r, base, 0, MwFALSE); } diff --git a/src/widget/progressbar.c b/src/widget/progressbar.c index 7be7bffd7..d85a8ddaf 100644 --- a/src/widget/progressbar.c +++ b/src/widget/progressbar.c @@ -23,7 +23,7 @@ static void draw(MwWidget handle) { r.width = MwGetInteger(handle, MwNwidth); r.height = MwGetInteger(handle, MwNheight); - MwDrawFrame(handle, &r, base, 1, 0); + MwDrawFrame(handle, &r, base, 1); MwDrawRect(handle, &r, base); w = MwGetInteger(handle, MwNvalue) - MwGetInteger(handle, MwNminValue); w = w / (MwGetInteger(handle, MwNmaxValue) - MwGetInteger(handle, MwNminValue)); diff --git a/src/widget/separator.c b/src/widget/separator.c index 571c5dfa9..8fcfc5b71 100644 --- a/src/widget/separator.c +++ b/src/widget/separator.c @@ -25,7 +25,7 @@ static void draw(MwWidget handle) { r.y = (r.height - 2) / 2; r.height = 2; } - MwDrawFrameEx(handle, &r, base, 1, 1, 0, 0, MwGetInteger(handle, MwNmodernLook)); + MwDrawFrameEx(handle, &r, base, 1, 1, 0, 0); MwLLFreeColor(base); } diff --git a/src/widget/submenu.c b/src/widget/submenu.c index 3b6460555..4990fd211 100644 --- a/src/widget/submenu.c +++ b/src/widget/submenu.c @@ -59,7 +59,7 @@ static void draw(MwWidget handle) { rc.x += MwGetInteger(handle, MwNleftPadding); - MwDrawFrameEx(handle, &rc, base, 1, 1, 0, 0, 0); + MwDrawFrameEx(handle, &rc, base, 1, 1, 0, 0); p.y += 2 + 1; } else { diff --git a/src/widget/treeview.c b/src/widget/treeview.c index 16898ef90..acc35bf69 100644 --- a/src/widget/treeview.c +++ b/src/widget/treeview.c @@ -64,7 +64,7 @@ static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry** const int len = 4; MwDrawRect(handle, &r, col); - MwDrawFrame(handle, &r, base, tree->opened, 0); + MwDrawFrame(handle, &r, base, tree->opened); if(tree->opened) { l[0].x = r.x + (r.width - len) / 2; l[0].y = r.y + r.height / 2; @@ -91,7 +91,7 @@ static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry** MwLLLine(handle->lowlevel, &l[0], text); } r = r2; - MwDrawFrame(handle, &r, base, tree->opened, 0); + MwDrawFrame(handle, &r, base, tree->opened); if(col != base) MwLLFreeColor(col); } else { @@ -183,7 +183,7 @@ static void frame_draw(MwWidget handle) { p.x = MwDefaultBorderWidth(handle); p.y = MwDefaultBorderWidth(handle); - MwDrawFrame(handle, &r, base, 1, 0); + MwDrawFrame(handle, &r, base, 1); MwDrawRect(handle, &r, base2); r = r2; @@ -193,7 +193,7 @@ static void frame_draw(MwWidget handle) { recursion(handle, tv->tree[i], tv->tree, base, text, base2, text2, &p, 0, LineSpace, &skip, &shared, 1, NULL); } - MwDrawFrame(handle, &r, base, 1, 0); + MwDrawFrame(handle, &r, base, 1); MwLLFreeColor(text2); MwLLFreeColor(text); diff --git a/src/widget/window.c b/src/widget/window.c index 74a96e61e..979e073c8 100644 --- a/src/widget/window.c +++ b/src/widget/window.c @@ -18,7 +18,7 @@ static void draw(MwWidget handle) { r.width = MwGetInteger(handle, MwNwidth); r.height = MwGetInteger(handle, MwNheight); - if(MwGetInteger(handle, MwNhasBorder)) MwDrawFrame(handle, &r, c, MwGetInteger(handle, MwNinverted), 0); + if(MwGetInteger(handle, MwNhasBorder)) MwDrawFrame(handle, &r, c, MwGetInteger(handle, MwNinverted)); MwDrawRect(handle, &r, c); From 1d59488927a823eabcd08b98b20b7820ab5eaafd Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 14 Apr 2026 13:45:47 -0700 Subject: [PATCH 134/195] wayland: fix several places where we don't attach buffer if not configured --- src/backend/wayland.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 148ca4420..220f3901f 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1260,10 +1260,10 @@ static void wl_shm_interface_destroy(struct _MwLLWayland* wayland, wayland_proto } static void update_buffer(MwLL self, struct _MwLLWaylandShmBuffer* buffer) { - (void)self; memcpy(buffer->buf, buffer->buf_back, buffer->buf_size); // Yes this is needed every time, it's how we fix weston. - wl_surface_attach(buffer->surface, buffer->shm_buffer, 0, 0); + if(self->wayland.configured) + wl_surface_attach(buffer->surface, buffer->shm_buffer, 0, 0); wl_surface_commit(buffer->surface); } @@ -1338,7 +1338,8 @@ static void framebuffer_setup(struct _MwLLWayland* wayland) { wayland->front_cairo = cairo_create(wayland->front_cs); memset(wayland->framebuffer.buf_back, 0, wayland->framebuffer.buf_size); - wl_surface_attach(wayland->framebuffer.surface, wayland->framebuffer.shm_buffer, 0, 0); + if(wayland->configured) + wl_surface_attach(wayland->framebuffer.surface, wayland->framebuffer.shm_buffer, 0, 0); wl_surface_commit(wayland->framebuffer.surface); hang_until_configured((MwLL)wayland); @@ -1366,7 +1367,8 @@ static void backbuffer_setup(struct _MwLLWayland* wayland) { wayland->back_cairo = cairo_create(wayland->back_cs); memset(wayland->backbuffer.buf_back, 255, wayland->backbuffer.buf_size); - wl_surface_attach(wayland->backbuffer.surface, wayland->backbuffer.shm_buffer, 0, 0); + if(wayland->configured) + wl_surface_attach(wayland->backbuffer.surface, wayland->backbuffer.shm_buffer, 0, 0); wl_surface_commit(wayland->backbuffer.surface); hang_until_configured((MwLL)wayland); update_buffer((MwLL)wayland, &wayland->backbuffer); @@ -2293,11 +2295,11 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { } handle->wayland.icon->surface = wl_compositor_create_surface(handle->wayland.compositor); + buffer_setup(handle->wayland.icon, pixmap->common.width, pixmap->common.height); + wl_surface_attach(handle->wayland.icon->surface, handle->wayland.icon->shm_buffer, 0, 0); wl_surface_commit(handle->wayland.icon->surface); - buffer_setup(handle->wayland.icon, pixmap->common.width, pixmap->common.height); - 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]; @@ -2392,6 +2394,9 @@ static void MwLLDetachImpl(MwLL handle, MwPoint* point) { } static void MwLLShowImpl(MwLL handle, int show) { + if(!handle->wayland.configured) { + return; + } /* Some guy on a mailing list said that "abusing" wl_surface_attach for this purpose is bad? This is documented behavior so please I beg of you let me know if there's a compositor that actually has a problem with this. */ if(handle->wayland.framebuffer.surface) { wl_surface_attach(handle->wayland.framebuffer.surface, show ? handle->wayland.framebuffer.shm_buffer : NULL, 0, 0); From bfc6d8e9aff636a9143ac55592fab57cb25d3cd0 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 14 Apr 2026 15:52:11 -0700 Subject: [PATCH 135/195] mac: ditch the image rep shit and try switching to a draw commands system --- include/Mw/LowLevel/Cocoa.h | 39 ++++-- src/backend/cocoa.m | 262 ++++++++++++++---------------------- 2 files changed, 124 insertions(+), 177 deletions(-) diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index 2a8c7ec7c..f553af5f5 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -10,6 +10,29 @@ #include #include +typedef struct { + enum { + COCOA_DRAW_COMMAND_POLY = 0, + COCOA_DRAW_COMMAND_LINES, + COCOA_DRAW_COMMAND_PIXMAP, + } type; + union { + struct { + MwPoint* points; + int points_count; + MwLLColor color; + } poly; + struct { + MwPoint* points; + MwLLColor color; + } lines; + struct { + MwRect rect; + MwLLPixmap pixmap; + } pixmap; + }; +} draw_command; + #ifdef __OBJC__ #import #import @@ -81,23 +104,13 @@ @end @interface MilskoCocoaView : NSView { + MwBool _child; + @public - unsigned char* buf; - NSBitmapImageRep* rep; - NSGraphicsContext* context; - MwBool valid; - NSRect givenRect; - float x; - float y; - float width; - float height; - MwBool _child; + draw_command** commands; } -- (void)initRepAndContextWithWidth:(float)w Height:(float)h; -- (NSGraphicsContext*)context; - (void)destroy; -- (NSBitmapImageRep*)getRep; - (void)setChild; @end diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index c336f7fb8..e3f899e46 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -80,106 +80,101 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { @implementation MilskoCocoaView - (id)initWithFrame:(NSRect)frame { - givenRect = frame; - x = frame.origin.x; - y = frame.origin.y; - width = frame.size.width; - height = frame.size.height; - self = [super initWithFrame:frame]; - - if(width == 0 || height == 0) { - self->rep = NULL; - self->context = NULL; - } else { - [self initRepAndContextWithWidth:width Height:height]; - } - - self->_child = MwFALSE; - + [super initWithFrame:frame]; + self->commands = NULL; return self; } - (void)setChild { self->_child = MwTRUE; } - -- (NSGraphicsContext*)context { - return self->context; -} - -- (NSBitmapImageRep*)getRep { - return self->rep; -} +- (void)destroy { + arrfree(self->commands); +}; - (void)drawRect:(NSRect)dirtyRect { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSArray* subviews = [self subviews]; int i; + [super drawRect:dirtyRect]; - if(!self->rep) { - if(dirtyRect.size.width && dirtyRect.size.height) { - [self initRepAndContextWithWidth:dirtyRect.size.width - Height:dirtyRect.size.height]; - self->width = dirtyRect.size.width; - self->height = dirtyRect.size.height; - } else { - [pool release]; - return; + for(i = 0; i < arrlen(self->commands); i++) { + draw_command* cmd = self->commands[i]; + switch(cmd->type) { + case COCOA_DRAW_COMMAND_POLY: { + int i; + NSBezierPath* path = [NSBezierPath bezierPath]; + + NSColor* nscolor = + [NSColor colorWithCalibratedRed:cmd->poly.color->common.red / 255. + green:cmd->poly.color->common.green / 255. + blue:cmd->poly.color->common.blue / 255. + alpha:1.0]; + + [nscolor setFill]; + for(i = 0; i < cmd->poly.points_count; i++) { + NSPoint p = localPointFlip(NSMakePoint(cmd->poly.points[i].x, cmd->poly.points[i].y), self); + if(i == 0) { + [path moveToPoint:p]; + } else { + [path lineToPoint:p]; + } + } + + [path closePath]; + [path fill]; + + free(cmd->poly.points); + MwLLFreeColor(cmd->poly.color); + free(cmd); + + } break; + + case COCOA_DRAW_COMMAND_LINES: { + int n; + NSBezierPath* path = [NSBezierPath bezierPath]; + + NSColor* nscolor = + [NSColor colorWithCalibratedRed:cmd->lines.color->common.red / 255. + green:cmd->lines.color->common.green / 255. + blue:cmd->lines.color->common.blue / 255. + alpha:1.0]; + + [nscolor setFill]; + for(n = 0; n < 2; n++) { + NSPoint p = localPointFlip(NSMakePoint(cmd->lines.points[n].x, cmd->lines.points[n].y), self); + if(n == 0) { + [path moveToPoint:p]; + } else { + [path lineToPoint:p]; + } + } + + [path closePath]; + [path stroke]; + + free(cmd->lines.points); + MwLLFreeColor(cmd->lines.color); + free(cmd); + } break; + + case COCOA_DRAW_COMMAND_PIXMAP: { + [cmd->pixmap.pixmap->cocoa.real.image + drawInRect:localRectFlip(NSMakeRect(cmd->pixmap.rect.x, cmd->pixmap.rect.y, cmd->pixmap.rect.width, cmd->pixmap.rect.height), self) + fromRect:NSZeroRect + operation:NSCompositeSourceOver + fraction:1.0]; + MwLLDestroyPixmap(cmd->pixmap.pixmap); + free(cmd); + } break; } } - [self->rep drawInRect:NSMakeRect(dirtyRect.origin.x, dirtyRect.origin.y, [self->rep pixelsWide], [self->rep pixelsHigh])]; + arrfree(self->commands); - for(i = 0; i < [subviews count]; i++) { - MilskoCocoaView* subview = [subviews objectAtIndex:i]; - NSRect bounds = [subview bounds]; - [subview drawRect:bounds]; - } [pool release]; } -- (void)initRepAndContextWithWidth:(float)w Height:(float)h { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - self->buf = malloc(w * h * 4); - memset(self->buf, 255, w * h * 4); - - self->rep = - [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:&self->buf - pixelsWide:w - pixelsHigh:h - bitsPerSample:8 - samplesPerPixel:4 - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSDeviceRGBColorSpace - bytesPerRow:w * 4 - bitsPerPixel:32]; - assert(self->rep); - [self->rep retain]; - - [self->rep setOpaque:MwFALSE]; - [self->rep setAlpha:MwTRUE]; - - self->context = - [NSGraphicsContext graphicsContextWithBitmapImageRep:self->rep]; - assert(self->context); - [self->context retain]; - [pool release]; -} - -- (void)destroy { - [self->rep release]; - [self->context release]; -} - -- (void)setFrameSize:(NSSize)newSize { - [super setFrameSize:newSize]; - [self->rep setSize:newSize]; - - self->width = newSize.width; - self->height = newSize.height; -} - - (BOOL)canBecomeKeyView { return YES; } @@ -745,81 +740,31 @@ static void MwLLEndDrawImpl(MwLL handle) { static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { - MilskoCocoa* self = handle->cocoa.real; - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSGraphicsContext* ctx = [self->view context]; - if(ctx) { - int i; - NSBezierPath* path = [NSBezierPath bezierPath]; - /* whatever rect we use for coordinate flipping */ - NSRect _rect = self->parent ? [self->view bounds] : [self->window frame]; + draw_command* poly = malloc(sizeof(draw_command)); + poly->type = COCOA_DRAW_COMMAND_POLY; - NSColor* nscolor = - [NSColor colorWithCalibratedRed:color->common.red / 255. - green:color->common.green / 255. - blue:color->common.blue / 255. - alpha:1.0]; + poly->poly.color = MwLLAllocColor(handle, color->common.red, color->common.blue, color->common.green); + poly->poly.points_count = points_count; - [NSGraphicsContext saveGraphicsState]; - [NSGraphicsContext setCurrentContext:ctx]; + poly->poly.points = malloc(sizeof(MwPoint) * points_count); + memcpy(poly->poly.points, points, sizeof(MwPoint) * points_count); - [nscolor setFill]; - for(i = 0; i < points_count; i++) { - NSPoint p = localPointFlip(NSMakePoint(points[i].x, points[i].y), self->view); - if(i == 0) { - [path moveToPoint:p]; - } else { - [path lineToPoint:p]; - } - } + arrpush(handle->cocoa.real->view->commands, poly); - [path closePath]; - [path fill]; - - [NSGraphicsContext restoreGraphicsState]; - - [self->view setNeedsDisplay:YES]; - } - [pool release]; + [handle->cocoa.real->view setNeedsDisplay:MwTRUE]; } static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { - MilskoCocoa* self = handle->cocoa.real; - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSGraphicsContext* ctx = [self->view context]; - if(ctx) { - int i; - NSBezierPath* path = [NSBezierPath bezierPath]; - /* whatever rect we use for coordinate flipping */ - NSRect _rect = self->parent ? [self->view bounds] : [self->window frame]; + draw_command* lines = malloc(sizeof(draw_command)); + lines->type = COCOA_DRAW_COMMAND_LINES; - NSColor* nscolor = - [NSColor colorWithCalibratedRed:color->common.red / 255. - green:color->common.green / 255. - blue:color->common.blue / 255. - alpha:1.0]; + lines->lines.color = MwLLAllocColor(handle, color->common.red, color->common.blue, color->common.green); - [NSGraphicsContext saveGraphicsState]; - [NSGraphicsContext setCurrentContext:ctx]; + lines->lines.points = malloc(sizeof(MwPoint) * 2); + memcpy(lines->lines.points, points, sizeof(MwPoint) * 2); - [nscolor setFill]; - for(i = 0; i < 2; i++) { - NSPoint p = localPointFlip(NSMakePoint(points[i].x, points[i].y), self->view); - if(i == 0) { - [path moveToPoint:p]; - } else { - [path lineToPoint:p]; - } - } - - [path closePath]; - [path stroke]; - - [NSGraphicsContext restoreGraphicsState]; - - [self->view setNeedsDisplay:YES]; - } - [pool release]; + arrpush(handle->cocoa.real->view->commands, lines); + [handle->cocoa.real->view setNeedsDisplay:MwTRUE]; } static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { @@ -971,26 +916,15 @@ static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { } static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { - MilskoCocoa* self = handle->cocoa.real; - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - MilskoCocoaPixmap* p = pixmap->cocoa.real; - NSGraphicsContext* ctx = [self->view context]; - if(ctx) { - [NSGraphicsContext saveGraphicsState]; - [NSGraphicsContext setCurrentContext:ctx]; + draw_command* pix = malloc(sizeof(draw_command)); + pix->type = COCOA_DRAW_COMMAND_PIXMAP; - [p->image - drawInRect:localRectFlip(NSMakeRect(rect->x, rect->y, rect->width, rect->height), self->view) - fromRect:NSZeroRect - operation:NSCompositeSourceOver - fraction:1.0]; + pix->pixmap.rect = *rect; + /* copy the pixmap into a new object that we'll free later */ + pix->pixmap.pixmap = MwLLCreatePixmap(handle, pixmap->common.raw, pixmap->common.width, pixmap->common.height); - [NSGraphicsContext restoreGraphicsState]; - - [self->view setNeedsDisplay:YES]; - } - [pool release]; - MwLLForceRender(handle); + arrpush(handle->cocoa.real->view->commands, pix); + [handle->cocoa.real->view setNeedsDisplay:MwTRUE]; } static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { From d597dc941157a90ce0db86195f68874ad060395d Mon Sep 17 00:00:00 2001 From: IoIxD Date: Tue, 14 Apr 2026 16:58:28 -0700 Subject: [PATCH 136/195] new drawing system now works properly-ish --- src/backend/cocoa.m | 22 ++++++++++++---------- src/core.c | 4 +++- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index e3f899e46..5e9fa8bdb 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -93,16 +93,16 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { }; - (void)drawRect:(NSRect)dirtyRect { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSArray* subviews = [self subviews]; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; int i; + [super drawRect:dirtyRect]; for(i = 0; i < arrlen(self->commands); i++) { draw_command* cmd = self->commands[i]; switch(cmd->type) { case COCOA_DRAW_COMMAND_POLY: { - int i; + int n; NSBezierPath* path = [NSBezierPath bezierPath]; NSColor* nscolor = @@ -112,9 +112,9 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { alpha:1.0]; [nscolor setFill]; - for(i = 0; i < cmd->poly.points_count; i++) { - NSPoint p = localPointFlip(NSMakePoint(cmd->poly.points[i].x, cmd->poly.points[i].y), self); - if(i == 0) { + for(n = 0; n < cmd->poly.points_count; n++) { + NSPoint p = localPointFlip(NSMakePoint(cmd->poly.points[n].x, cmd->poly.points[n].y), self); + if(n == 0) { [path moveToPoint:p]; } else { [path lineToPoint:p]; @@ -159,7 +159,7 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { } break; case COCOA_DRAW_COMMAND_PIXMAP: { - [cmd->pixmap.pixmap->cocoa.real.image + [cmd->pixmap.pixmap->cocoa.real->image drawInRect:localRectFlip(NSMakeRect(cmd->pixmap.rect.x, cmd->pixmap.rect.y, cmd->pixmap.rect.width, cmd->pixmap.rect.height), self) fromRect:NSZeroRect operation:NSCompositeSourceOver @@ -736,6 +736,7 @@ static void MwLLBeginDrawImpl(MwLL handle) { static void MwLLEndDrawImpl(MwLL handle) { (void)handle; + [handle->cocoa.real->view displayRect:[handle->cocoa.real->window frame]]; } static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, @@ -743,7 +744,7 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, draw_command* poly = malloc(sizeof(draw_command)); poly->type = COCOA_DRAW_COMMAND_POLY; - poly->poly.color = MwLLAllocColor(handle, color->common.red, color->common.blue, color->common.green); + poly->poly.color = MwLLAllocColor(handle, color->common.red, color->common.green, color->common.blue); poly->poly.points_count = points_count; poly->poly.points = malloc(sizeof(MwPoint) * points_count); @@ -752,13 +753,14 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, arrpush(handle->cocoa.real->view->commands, poly); [handle->cocoa.real->view setNeedsDisplay:MwTRUE]; + // [handle->cocoa.real->view displayRect:[handle->cocoa.real->window frame]]; } static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { draw_command* lines = malloc(sizeof(draw_command)); lines->type = COCOA_DRAW_COMMAND_LINES; - lines->lines.color = MwLLAllocColor(handle, color->common.red, color->common.blue, color->common.green); + lines->lines.color = MwLLAllocColor(handle, color->common.red, color->common.green, color->common.blue); lines->lines.points = malloc(sizeof(MwPoint) * 2); memcpy(lines->lines.points, points, sizeof(MwPoint) * 2); @@ -816,7 +818,7 @@ static void MwLLSetXYImpl(MwLL handle, int x, int y) { [self->window setFrame:frame display:MwTRUE animate:MwTRUE]; } else { frame = localRectFlip(frame, self->parent->cocoa.real->view); - [self->view setBounds:frame]; + [self->view setFrame:frame]; } [self nudge]; } diff --git a/src/core.c b/src/core.c index 2b98ec5fc..51018630b 100644 --- a/src/core.c +++ b/src/core.c @@ -2,7 +2,9 @@ #include "../external/stb_ds.h" -// #define PERIODIC +#ifdef __APPLE__ +#define PERIODIC +#endif #define DRAW(handle) \ { \ From 6e5057f8c62f903efecff3a81630710d35733396 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 14 Apr 2026 18:04:00 -0700 Subject: [PATCH 137/195] cocoa: no more flickering --- src/backend/cocoa.m | 9 +++++---- src/core.c | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 5e9fa8bdb..ac694c836 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -602,7 +602,8 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { MwLL p = self->parent; self->_eventsPending = MwTRUE; - if(p) { + while(p) { + MwLLDispatch(p, draw, NULL); [p->cocoa.real->view setNeedsDisplay:true]; p = p->cocoa.real->parent; } @@ -752,7 +753,7 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, arrpush(handle->cocoa.real->view->commands, poly); - [handle->cocoa.real->view setNeedsDisplay:MwTRUE]; + // [handle->cocoa.real->view setNeedsDisplay:MwTRUE]; // [handle->cocoa.real->view displayRect:[handle->cocoa.real->window frame]]; } @@ -766,7 +767,7 @@ static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { memcpy(lines->lines.points, points, sizeof(MwPoint) * 2); arrpush(handle->cocoa.real->view->commands, lines); - [handle->cocoa.real->view setNeedsDisplay:MwTRUE]; + // [handle->cocoa.real->view setNeedsDisplay:MwTRUE]; } static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { @@ -926,7 +927,7 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { pix->pixmap.pixmap = MwLLCreatePixmap(handle, pixmap->common.raw, pixmap->common.width, pixmap->common.height); arrpush(handle->cocoa.real->view->commands, pix); - [handle->cocoa.real->view setNeedsDisplay:MwTRUE]; + // [handle->cocoa.real->view setNeedsDisplay:MwTRUE]; } static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { diff --git a/src/core.c b/src/core.c index 51018630b..cf45dddc2 100644 --- a/src/core.c +++ b/src/core.c @@ -2,7 +2,7 @@ #include "../external/stb_ds.h" -#ifdef __APPLE__ +#ifdef USE_COCOA #define PERIODIC #endif From a7d790698f75950f35634a944ede1ba29ef6d64a Mon Sep 17 00:00:00 2001 From: IoIxD Date: Tue, 14 Apr 2026 18:28:33 -0700 Subject: [PATCH 138/195] mac: getXYImpl should also flip whatever is given to it --- src/backend/cocoa.m | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index ac694c836..8e3ba2b66 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -793,7 +793,12 @@ static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, } else { frame = [self->window frame]; } - frame = rectFlip(frame); + + if(!self->parent) { + frame = rectFlip(frame); + } else { + frame = localRectFlip(frame, self->parent->cocoa.real->view); + } *x = frame.origin.x; *y = frame.origin.y; From a01e1a951480f34836dae2c7409ed354a0cfb738 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 14 Apr 2026 20:54:05 -0500 Subject: [PATCH 139/195] milsko.xml: remove roundness --- milsko.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/milsko.xml b/milsko.xml index 18caed3c0..9fb45a608 100644 --- a/milsko.xml +++ b/milsko.xml @@ -81,7 +81,6 @@ - From 4d7b33741f5cacabf7c85a0030e44dd31903b9f6 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 14 Apr 2026 19:38:52 -0700 Subject: [PATCH 140/195] fix mac os memleak, maybe fix stringisutf8 idk --- include/Mw/LowLevel/Cocoa.h | 12 +++--- src/backend/cocoa.m | 74 +++++++++++++++++-------------------- src/string.c | 2 +- 3 files changed, 40 insertions(+), 48 deletions(-) diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index f553af5f5..6c5f12b43 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -18,13 +18,13 @@ typedef struct { } type; union { struct { - MwPoint* points; - int points_count; - MwLLColor color; + MwPoint* points; + int points_count; + struct _MwLLCommonColor color; } poly; struct { - MwPoint* points; - MwLLColor color; + MwPoint* points; + struct _MwLLCommonColor color; } lines; struct { MwRect rect; @@ -107,7 +107,7 @@ typedef struct { MwBool _child; @public - draw_command** commands; + draw_command* commands; } - (void)destroy; diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 8e3ba2b66..705136721 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -99,21 +99,21 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { [super drawRect:dirtyRect]; for(i = 0; i < arrlen(self->commands); i++) { - draw_command* cmd = self->commands[i]; - switch(cmd->type) { + draw_command cmd = self->commands[i]; + switch(cmd.type) { case COCOA_DRAW_COMMAND_POLY: { int n; NSBezierPath* path = [NSBezierPath bezierPath]; NSColor* nscolor = - [NSColor colorWithCalibratedRed:cmd->poly.color->common.red / 255. - green:cmd->poly.color->common.green / 255. - blue:cmd->poly.color->common.blue / 255. + [NSColor colorWithCalibratedRed:cmd.poly.color.red / 255. + green:cmd.poly.color.green / 255. + blue:cmd.poly.color.blue / 255. alpha:1.0]; [nscolor setFill]; - for(n = 0; n < cmd->poly.points_count; n++) { - NSPoint p = localPointFlip(NSMakePoint(cmd->poly.points[n].x, cmd->poly.points[n].y), self); + for(n = 0; n < cmd.poly.points_count; n++) { + NSPoint p = localPointFlip(NSMakePoint(cmd.poly.points[n].x, cmd.poly.points[n].y), self); if(n == 0) { [path moveToPoint:p]; } else { @@ -124,10 +124,7 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { [path closePath]; [path fill]; - free(cmd->poly.points); - MwLLFreeColor(cmd->poly.color); - free(cmd); - + free(cmd.poly.points); } break; case COCOA_DRAW_COMMAND_LINES: { @@ -135,14 +132,14 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { NSBezierPath* path = [NSBezierPath bezierPath]; NSColor* nscolor = - [NSColor colorWithCalibratedRed:cmd->lines.color->common.red / 255. - green:cmd->lines.color->common.green / 255. - blue:cmd->lines.color->common.blue / 255. + [NSColor colorWithCalibratedRed:cmd.lines.color.red / 255. + green:cmd.lines.color.green / 255. + blue:cmd.lines.color.blue / 255. alpha:1.0]; [nscolor setFill]; for(n = 0; n < 2; n++) { - NSPoint p = localPointFlip(NSMakePoint(cmd->lines.points[n].x, cmd->lines.points[n].y), self); + NSPoint p = localPointFlip(NSMakePoint(cmd.lines.points[n].x, cmd.lines.points[n].y), self); if(n == 0) { [path moveToPoint:p]; } else { @@ -153,19 +150,16 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { [path closePath]; [path stroke]; - free(cmd->lines.points); - MwLLFreeColor(cmd->lines.color); - free(cmd); + free(cmd.lines.points); } break; case COCOA_DRAW_COMMAND_PIXMAP: { - [cmd->pixmap.pixmap->cocoa.real->image - drawInRect:localRectFlip(NSMakeRect(cmd->pixmap.rect.x, cmd->pixmap.rect.y, cmd->pixmap.rect.width, cmd->pixmap.rect.height), self) + [cmd.pixmap.pixmap->cocoa.real->image + drawInRect:localRectFlip(NSMakeRect(cmd.pixmap.rect.x, cmd.pixmap.rect.y, cmd.pixmap.rect.width, cmd.pixmap.rect.height), self) fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0]; - MwLLDestroyPixmap(cmd->pixmap.pixmap); - free(cmd); + MwLLDestroyPixmap(cmd.pixmap.pixmap); } break; } } @@ -742,32 +736,28 @@ static void MwLLEndDrawImpl(MwLL handle) { static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { - draw_command* poly = malloc(sizeof(draw_command)); - poly->type = COCOA_DRAW_COMMAND_POLY; + draw_command poly; + poly.type = COCOA_DRAW_COMMAND_POLY; - poly->poly.color = MwLLAllocColor(handle, color->common.red, color->common.green, color->common.blue); - poly->poly.points_count = points_count; + poly.poly.color = color->common; + poly.poly.points_count = points_count; - poly->poly.points = malloc(sizeof(MwPoint) * points_count); - memcpy(poly->poly.points, points, sizeof(MwPoint) * points_count); + poly.poly.points = malloc(sizeof(MwPoint) * points_count); + memcpy(poly.poly.points, points, sizeof(MwPoint) * points_count); arrpush(handle->cocoa.real->view->commands, poly); - - // [handle->cocoa.real->view setNeedsDisplay:MwTRUE]; - // [handle->cocoa.real->view displayRect:[handle->cocoa.real->window frame]]; } static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { - draw_command* lines = malloc(sizeof(draw_command)); - lines->type = COCOA_DRAW_COMMAND_LINES; + draw_command lines; + lines.type = COCOA_DRAW_COMMAND_LINES; - lines->lines.color = MwLLAllocColor(handle, color->common.red, color->common.green, color->common.blue); + lines.lines.color = color->common; - lines->lines.points = malloc(sizeof(MwPoint) * 2); - memcpy(lines->lines.points, points, sizeof(MwPoint) * 2); + lines.lines.points = malloc(sizeof(MwPoint) * 2); + memcpy(lines.lines.points, points, sizeof(MwPoint) * 2); arrpush(handle->cocoa.real->view->commands, lines); - // [handle->cocoa.real->view setNeedsDisplay:MwTRUE]; } static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { @@ -918,18 +908,20 @@ static void MwLLPixmapUpdateImpl(MwLLPixmap pixmap) { } static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { + free(pixmap->common.raw); [pixmap->cocoa.real destroy]; [pixmap->cocoa.real release]; free(pixmap); } static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { - draw_command* pix = malloc(sizeof(draw_command)); - pix->type = COCOA_DRAW_COMMAND_PIXMAP; + draw_command pix; + pix.type = COCOA_DRAW_COMMAND_PIXMAP; + + pix.pixmap.rect = *rect; - pix->pixmap.rect = *rect; /* copy the pixmap into a new object that we'll free later */ - pix->pixmap.pixmap = MwLLCreatePixmap(handle, pixmap->common.raw, pixmap->common.width, pixmap->common.height); + pix.pixmap.pixmap = MwLLCreatePixmap(handle, pixmap->common.raw, pixmap->common.width, pixmap->common.height); arrpush(handle->cocoa.real->view->commands, pix); // [handle->cocoa.real->view setNeedsDisplay:MwTRUE]; diff --git a/src/string.c b/src/string.c index f48169599..943867aec 100644 --- a/src/string.c +++ b/src/string.c @@ -51,7 +51,7 @@ void MwStringPrintIntoBuffer(char* out, MwU32 size, const char* fmt, ...) { }; MWDECL MwBool MwStringIsKeyUTF8(MwU32 key) { - unsigned char bytes[sizeof(MwU32)]; + unsigned char bytes[sizeof(MwU32) * 16]; int i; memcpy(bytes, &key, sizeof(MwU32)); From 32f99b62b6931a2a6c081cddcb040eabb863dd21 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 14 Apr 2026 19:51:52 -0700 Subject: [PATCH 141/195] have MwStringIsKeyUTF8 not use ub --- src/string.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/string.c b/src/string.c index 943867aec..2a1504639 100644 --- a/src/string.c +++ b/src/string.c @@ -51,9 +51,18 @@ void MwStringPrintIntoBuffer(char* out, MwU32 size, const char* fmt, ...) { }; MWDECL MwBool MwStringIsKeyUTF8(MwU32 key) { - unsigned char bytes[sizeof(MwU32) * 16]; - int i; - memcpy(bytes, &key, sizeof(MwU32)); + /* little endian */ +#if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86) || defined(__aarch64__) || defined(_M_ARM64) + unsigned char bytes[4] = { + (key & 0x000000FF), + (key & 0x0000FF00) >> 8, + (key & 0x00FF0000) >> 16, + (key & 0xFF000000) >> 24, + }; +#else +#error Unspecified architecture! This error exists here because above it is endian-specific code. Add your architecture above. +#endif + int i; for(i = 0; i < sizeof(MwU32); i++) { if(( // ASCII From 065b0d824cf29926b74e7c91ba549176435aa506 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 14 Apr 2026 20:03:59 -0700 Subject: [PATCH 142/195] cocoa: untested vulkan code --- CMakeLists.txt | 5 +++++ pl/rules.pl | 1 + src/backend/cocoa.m | 17 +++++++++++++++++ src/widget/vulkan.c | 20 ++++++++++++++++++++ 4 files changed, 43 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 585fb4ddd..0cc795308 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,6 +70,11 @@ if(MW_TRY_VULKAN) if(HAVE_VULKAN_VULKAN_H) set(MW_BUILD_VULKAN ON) list(APPEND SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/vulkan.c") + target_compile_definitions( + Mw + PRIVATE + MW_VULKAN + ) message(STATUS "Vulkan widget has been enabled") else() message(WARNING "Vulkan widget has been disabled") diff --git a/pl/rules.pl b/pl/rules.pl index 6c23006bd..3da19289e 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -131,6 +131,7 @@ if (param_get("opengl")) { new_object("src/widget/opengl.c"); } if (param_get("vulkan")) { + add_cflags("-DMW_VULKAN"); new_object("src/widget/vulkan.c"); } diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 705136721..4cdc5b2b6 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -2,6 +2,11 @@ #include "../../external/stb_ds.h" #include "Mw/LowLevel/Cocoa.h" +#ifdef MW_VULKAN +#include +#include +#endif + #ifdef __clang__ #pragma clang push #pragma clang diagnostic ignored "-Wdeprecated-declarations" @@ -1087,5 +1092,17 @@ static int MwLLCocoaCallInitImpl(void) { return 0; } +#ifdef MW_VULKAN +VkMetalSurfaceCreateInfoEXT MwCocoaGetMetalSurfaceCreateInfo(MwWidget handle) { + VkMetalSurfaceCreateInfoEXT createInfo = { + .sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT, + .pNext = NULL, + .flags = 0, + .pLayer = (CAMetalLayer*)[handle->lowlevel->cocoa.real->view layer], + }; + return createInfo; +}; +#endif + #include "call.c" CALL(Cocoa); diff --git a/src/widget/vulkan.c b/src/widget/vulkan.c index 1a9ea1234..195384c61 100644 --- a/src/widget/vulkan.c +++ b/src/widget/vulkan.c @@ -26,6 +26,9 @@ #ifdef USE_WAYLAND #include #endif +#ifdef USE_COCOA +#include +#endif #ifdef HAS_VK_ENUM_STRING_HELPER #include @@ -167,6 +170,8 @@ static void destroy(MwWidget handle) { static void* vulkan_lib_load() { #ifdef _WIN32 return MwDynamicOpen("vulkan-1.dll"); +#elif defined(__APPLE__) + return MwDynamicOpen("libvulkan.dylib"); #else return MwDynamicOpen("libvulkan.so"); #endif @@ -230,6 +235,11 @@ static int vulkan_instance_setup(MwWidget handle, vulkan_t* o) { MwWaylandAlwaysRender = MwTRUE; } #endif +#ifdef USE_WAYLAND + if(handle->lowlevel->common.type == MwLLBackendCocoa) { + arrput(enabledExtensions, VK_EXT_METAL_SURFACE_EXTENSION_NAME); + } +#endif /* passing null gives us all the extensions provided by the current vulkan implementation */ VK_CMD(_vkEnumerateInstanceExtensionProperties(NULL, &extension_count, NULL)); @@ -338,6 +348,16 @@ static int vulkan_surface_setup(MwWidget handle, vulkan_t* o) { }; VK_CMD(_vkCreateWaylandSurfaceKHR(o->vkInstance, &createInfo, NULL, &o->vkSurface)); } +#endif +#ifdef USE_COCOA + if(handle->lowlevel->common.type == MwLLBackendCocoa) { + VkMetalSurfaceCreateInfoEXT MwCocoaGetMetalSurfaceCreateInfo(MwWidget handle); + VkMetalSurfaceCreateInfoEXT inf = MwCocoaGetMetalSurfaceCreateInfo(handle); + + LOAD_VK_FUNCTION(vkCreateMetalSurfaceEXT); + + VK_CMD(_vkCreateMetalSurfaceEXT(o->vkInstance, &inf, NULL, &o->vkSurface)); + } #endif return 0; } From 28f6d6ac56acfbf4a0f7ef63a0909ff634fff8ca Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 14 Apr 2026 20:08:45 -0700 Subject: [PATCH 143/195] cocoa: untested vulkan code --- src/widget/vulkan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widget/vulkan.c b/src/widget/vulkan.c index 195384c61..8d4aa3daa 100644 --- a/src/widget/vulkan.c +++ b/src/widget/vulkan.c @@ -235,7 +235,7 @@ static int vulkan_instance_setup(MwWidget handle, vulkan_t* o) { MwWaylandAlwaysRender = MwTRUE; } #endif -#ifdef USE_WAYLAND +#ifdef USE_COCOA if(handle->lowlevel->common.type == MwLLBackendCocoa) { arrput(enabledExtensions, VK_EXT_METAL_SURFACE_EXTENSION_NAME); } From 391f5a69245e3e1182d6110713ce151135f0209d Mon Sep 17 00:00:00 2001 From: Nishi Date: Wed, 15 Apr 2026 12:23:54 +0900 Subject: [PATCH 144/195] remove endian related error --- WatMakefile | 2 +- src/string.c | 16 +++++----------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/WatMakefile b/WatMakefile index 231820788..633a259a3 100644 --- a/WatMakefile +++ b/WatMakefile @@ -1,4 +1,4 @@ -CC = wcc386 -bt=nt -q -bd +CC = wcc386 -bt=nt -q -bd -d3 LD = wlink option quiet CFLAGS = -i=include -i=external/libz/include -d_MILSKO -dUSE_GDI -dUSE_STB_TRUETYPE -dUSE_STB_IMAGE -dSTBI_NO_SIMD diff --git a/src/string.c b/src/string.c index 2a1504639..a7c23381c 100644 --- a/src/string.c +++ b/src/string.c @@ -51,18 +51,12 @@ void MwStringPrintIntoBuffer(char* out, MwU32 size, const char* fmt, ...) { }; MWDECL MwBool MwStringIsKeyUTF8(MwU32 key) { - /* little endian */ -#if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86) || defined(__aarch64__) || defined(_M_ARM64) - unsigned char bytes[4] = { - (key & 0x000000FF), - (key & 0x0000FF00) >> 8, - (key & 0x00FF0000) >> 16, - (key & 0xFF000000) >> 24, - }; -#else -#error Unspecified architecture! This error exists here because above it is endian-specific code. Add your architecture above. -#endif + unsigned char bytes[4]; int i; + bytes[0] = (key & 0x000000FF); + bytes[1] = (key & 0x0000FF00) >> 8; + bytes[2] = (key & 0x00FF0000) >> 16; + bytes[3] = (key & 0xFF000000) >> 24; for(i = 0; i < sizeof(MwU32); i++) { if(( // ASCII From 83f5f7a8200fad133462421d053a676248f870b9 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 14 Apr 2026 23:04:13 -0500 Subject: [PATCH 145/195] examples cmake doesnt need win32 --- examples/basic/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/basic/CMakeLists.txt b/examples/basic/CMakeLists.txt index acda320d2..ab58a5c1a 100644 --- a/examples/basic/CMakeLists.txt +++ b/examples/basic/CMakeLists.txt @@ -6,7 +6,7 @@ file( foreach(PATH IN LISTS EXAMPLES_BASIC_SOURCES) get_filename_component(TARGET ${PATH} NAME_WE) - add_executable(${TARGET} WIN32 MACOSX_BUNDLE ${PATH}) + add_executable(${TARGET} MACOSX_BUNDLE ${PATH}) target_link_libraries( ${TARGET} PRIVATE From aac2b410c08f6b0157cddf8542e0d113047711a3 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 14 Apr 2026 23:04:39 -0500 Subject: [PATCH 146/195] gl cmake doesnt need win32 --- examples/gldemos/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/gldemos/CMakeLists.txt b/examples/gldemos/CMakeLists.txt index 122f62c59..0a8fa78e6 100644 --- a/examples/gldemos/CMakeLists.txt +++ b/examples/gldemos/CMakeLists.txt @@ -10,7 +10,7 @@ foreach(PATH IN LISTS EXAMPLES_GL_SOURCES) if(${TARGET} STREQUAL "glutlayer") continue() endif() - add_executable(${TARGET} WIN32 MACOSX_BUNDLE ${PATH}) + add_executable(${TARGET} MACOSX_BUNDLE ${PATH}) target_link_libraries( ${TARGET} PRIVATE From 714842461cffc43a906ac2b04b8741c15cbce8b4 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 14 Apr 2026 23:04:59 -0500 Subject: [PATCH 147/195] Update examples/vkdemos/CMakeLists.txt --- examples/vkdemos/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/vkdemos/CMakeLists.txt b/examples/vkdemos/CMakeLists.txt index a315bf91b..41f832c2d 100644 --- a/examples/vkdemos/CMakeLists.txt +++ b/examples/vkdemos/CMakeLists.txt @@ -7,7 +7,7 @@ find_package(Vulkan) foreach(PATH IN LISTS EXAMPLES_VULKAN_SOURCES) get_filename_component(TARGET ${PATH} NAME_WE) - add_executable(${TARGET} WIN32 MACOSX_BUNDLE ${PATH}) + add_executable(${TARGET} MACOSX_BUNDLE ${PATH}) target_include_directories( ${TARGET} PRIVATE From fc8330f4772b2d9564bdf958b89aff7cf62a866a Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 15 Apr 2026 00:29:16 -0500 Subject: [PATCH 148/195] uninitialized --- src/backend/wayland.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 220f3901f..bbc1220e6 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -2583,7 +2583,7 @@ static int MwLLWaylandCallInitImpl(void) { * - manually checking environment variables */ #ifdef __linux__ - MwBool loadWayland; + MwBool loadWayland = MwFALSE; if(getenv("MILSKO_BACKEND")) { loadWayland |= (strcmp(getenv("MILSKO_BACKEND"), "wayland") == 0); From 4ab846ad51d701842afbddaf2af41879418056d3 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Tue, 14 Apr 2026 22:53:20 -0700 Subject: [PATCH 149/195] fix fpe in text drawing code --- src/text/ft2.c | 15 ++++++--------- src/text/stbtt.c | 15 ++++++--------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/text/ft2.c b/src/text/ft2.c index 17381f98a..32e658775 100644 --- a/src/text/ft2.c +++ b/src/text/ft2.c @@ -69,16 +69,13 @@ static int ft2_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const c int ox = x + (ttf->face->glyph->metrics.horiBearingX / 64) + 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]; - - if(opx[3] == 0) { - opx[0] = color->common.red; - opx[1] = color->common.green; - opx[2] = color->common.blue; - opx[3] = bmp->buffer[cy * bmp->pitch + cx]; + 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; } else { - opx[0] = (opx[0] / color->common.red) / 255; - opx[1] = (opx[1] / color->common.green) / 255; - opx[2] = (opx[2] / color->common.blue) / 255; opx[3] = bmp->buffer[cy * bmp->pitch + cx]; } } diff --git a/src/text/stbtt.c b/src/text/stbtt.c index 5e23f6cb5..a84190769 100644 --- a/src/text/stbtt.c +++ b/src/text/stbtt.c @@ -52,16 +52,13 @@ 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]; - - if(opx[3] == 0) { - opx[0] = color->common.red; - opx[1] = color->common.green; - opx[2] = color->common.blue; - opx[3] = out[cy * ow + cx]; + 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; } else { - opx[0] = (opx[0] / color->common.red) / 255; - opx[1] = (opx[1] / color->common.green) / 255; - opx[2] = (opx[2] / color->common.blue) / 255; opx[3] = out[cy * ow + cx]; } } From 0c822d5bfafdff603eed4dd44960ed87066412c0 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 14 Apr 2026 23:49:04 -0700 Subject: [PATCH 150/195] some wayland fixes curtosey of valgrind --- include/Mw/LowLevel/Wayland.h | 3 +++ src/backend/wayland.c | 9 ++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 7b31bd7e3..ce1630c5b 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -123,6 +123,7 @@ typedef struct wayland_call_table { void (*cairo_pattern_set_filter)(cairo_pattern_t* pattern, cairo_filter_t filter); void (*cairo_set_antialias)(cairo_t*, cairo_antialias_t); + void (*cairo_set_operator)(cairo_t* cr, cairo_operator_t op); } wayland_call_table_t; @@ -220,6 +221,7 @@ MwInline int wayland_load_funcs() { CAIRO_FUNC(cairo_stroke); CAIRO_FUNC(cairo_set_source_surface); CAIRO_FUNC(cairo_fill); + CAIRO_FUNC(cairo_set_operator); CAIRO_FUNC(cairo_pattern_set_filter); #undef CAIRO_FUNC @@ -277,6 +279,7 @@ MwInline int wayland_load_funcs() { #define cairo_stroke wl_call_tbl.cairo_stroke #define cairo_set_source_surface wl_call_tbl.cairo_set_source_surface #define cairo_fill wl_call_tbl.cairo_fill +#define cairo_set_operator wl_call_tbl.cairo_set_operator #define cairo_pattern_set_filter wl_call_tbl.cairo_pattern_set_filter #ifndef WL_PROTOCOLS_DEFINED diff --git a/src/backend/wayland.c b/src/backend/wayland.c index bbc1220e6..8bb6f3eed 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -2082,7 +2082,9 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL } cairo_close_path(handle->wayland.front_cairo); + cairo_set_operator(handle->wayland.front_cairo, CAIRO_OPERATOR_SOURCE); cairo_fill(handle->wayland.front_cairo); + cairo_set_operator(handle->wayland.front_cairo, CAIRO_OPERATOR_OVER); handle->wayland.events_pending = 1; } @@ -2264,6 +2266,8 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { cairo_set_source_surface(c, pixmap->wayland.cs, 0, 0); cairo_pattern_set_filter(cairo_get_source(c), CAIRO_FILTER_NEAREST); + cairo_set_operator(handle->wayland.front_cairo, CAIRO_OPERATOR_OVER); + cairo_paint(c); cairo_set_source_surface(selected_cairo, cs, rect->x, rect->y); @@ -2577,11 +2581,6 @@ static void MwLLEndStateChangeImpl(MwLL handle) { } static int MwLLWaylandCallInitImpl(void) { - /* - * Order of precedence: - * - MILSKO_BACKEND - * - manually checking environment variables - */ #ifdef __linux__ MwBool loadWayland = MwFALSE; if(getenv("MILSKO_BACKEND")) { From 5cb9b5cab93d9a215012eb7d83c92cb11193a52c Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 15 Apr 2026 00:54:47 -0700 Subject: [PATCH 151/195] have color picker check for dark theme --- examples/basic/colorpicker.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/basic/colorpicker.c b/examples/basic/colorpicker.c index 0096ae64a..4c246f763 100644 --- a/examples/basic/colorpicker.c +++ b/examples/basic/colorpicker.c @@ -28,7 +28,7 @@ void color_picker(MwWidget handle, void* user_data, void* call_data) { MwAddUserHandler(cpicker, MwNcolorChosenHandler, color_callback, NULL); - MwSetText(cpicker, MwNbackground, MwDefaultBackground); + MwSetText(cpicker, MwNbackground, MwGetInteger(cpicker, MwNdarkTheme) ? MwDefaultForeground : MwDefaultBackground); } int main() { @@ -41,7 +41,7 @@ int main() { button = MwVaCreateWidget(MwButtonClass, "button", window, 160, 180, 320, 120, MwNtext, "change window background", NULL); - MwSetText(button, MwNbackground, MwDefaultBackground); + MwSetText(button, MwNbackground, MwGetInteger(button, MwNdarkTheme) ? MwDefaultForeground : MwDefaultBackground); MwAddUserHandler(button, MwNactivateHandler, color_picker, NULL); From 6ff6b22644b03d70452f4c2675ff3ab60da9aa9b Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 15 Apr 2026 01:05:51 -0700 Subject: [PATCH 152/195] border around color picker wheel --- src/dialog/colorpicker.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/dialog/colorpicker.c b/src/dialog/colorpicker.c index 2be8df2ec..3b7d33188 100644 --- a/src/dialog/colorpicker.c +++ b/src/dialog/colorpicker.c @@ -1,7 +1,7 @@ #include #define WIN_SIZE 464 -#define PICKER_SIZE 360 +#define PICKER_SIZE 364 #define IMG_POS_X(w) ((w - PICKER_SIZE) / 2) #define IMG_POS_Y(h) ((h - PICKER_SIZE) / 2) #define SCROLL_BAR_WIDTH 16 @@ -104,11 +104,16 @@ static void color_picker_image_update(color_picker_t* picker) { int _y = y - (PICKER_SIZE / 2); double dist = sqrt(_x * _x + _y * _y); - if(dist >= 180.) { + if(dist >= 182.) { picker->color_picker_image_data[i] = 0; picker->color_picker_image_data[i + 1] = 0; picker->color_picker_image_data[i + 2] = 0; picker->color_picker_image_data[i + 3] = 0; + } else if(dist >= 180.) { + picker->color_picker_image_data[i] = dist; + picker->color_picker_image_data[i + 1] = dist; + picker->color_picker_image_data[i + 2] = dist; + picker->color_picker_image_data[i + 3] = 255; } else { MwHSV hsv_v; MwRGB color; From 5c386e766504014d942ff2762bef1a3aec274940 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 15 Apr 2026 03:08:55 -0500 Subject: [PATCH 153/195] Update examples/basic/colorpicker.c --- examples/basic/colorpicker.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/basic/colorpicker.c b/examples/basic/colorpicker.c index 4c246f763..22e647cc8 100644 --- a/examples/basic/colorpicker.c +++ b/examples/basic/colorpicker.c @@ -1,4 +1,3 @@ - #include MwWidget cpicker; @@ -28,7 +27,7 @@ void color_picker(MwWidget handle, void* user_data, void* call_data) { MwAddUserHandler(cpicker, MwNcolorChosenHandler, color_callback, NULL); - MwSetText(cpicker, MwNbackground, MwGetInteger(cpicker, MwNdarkTheme) ? MwDefaultForeground : MwDefaultBackground); + MwSetText(cpicker, MwNbackground, MwGetInteger(cpicker, MwNdarkTheme) ? MwDefaultDarkBackground : MwDefaultBackground); } int main() { @@ -41,7 +40,7 @@ int main() { button = MwVaCreateWidget(MwButtonClass, "button", window, 160, 180, 320, 120, MwNtext, "change window background", NULL); - MwSetText(button, MwNbackground, MwGetInteger(button, MwNdarkTheme) ? MwDefaultForeground : MwDefaultBackground); + MwSetText(button, MwNbackground, MwGetInteger(button, MwNdarkTheme) ? MwDefaultDarkBackground : MwDefaultBackground); MwAddUserHandler(button, MwNactivateHandler, color_picker, NULL); From b641a03bae430feb77c180777107db6fcd12ed0f Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 15 Apr 2026 10:58:46 -0700 Subject: [PATCH 154/195] clipboard refactoring --- examples/basic/clipboard.c | 33 +++++++++---- include/Mw/Core.h | 5 +- include/Mw/LowLevel.h | 4 +- include/Mw/LowLevel/Wayland.h | 5 +- include/Mw/TypeDefs.h | 8 +++ src/backend/cocoa.m | 6 ++- src/backend/gdi.c | 6 ++- src/backend/wayland.c | 92 ++++++++++++++++++----------------- src/backend/x11.c | 4 +- src/core.c | 4 +- src/lowlevel.c | 4 +- src/widget/entry.c | 18 ++++++- 12 files changed, 116 insertions(+), 73 deletions(-) diff --git a/examples/basic/clipboard.c b/examples/basic/clipboard.c index e6a75023f..38084a184 100644 --- a/examples/basic/clipboard.c +++ b/examples/basic/clipboard.c @@ -1,6 +1,6 @@ #include -MwWidget window, instructions, text; +MwWidget window, instructions, text1, text2, cur_text; static void resize(MwWidget handle, void* user_data, void* call_data) { unsigned int w, h; @@ -17,9 +17,14 @@ static void resize(MwWidget handle, void* user_data, void* call_data) { MwNheight, h - 125 - 50 * 3, NULL); - MwVaApply(text, - MwNy, 200, - MwNwidth, w - 50 * 2, + MwVaApply(text1, + MwNy, 150, + MwNwidth, w - 25 * 2, + MwNheight, h - 125 - 50 * 3, + NULL); + MwVaApply(text2, + MwNy, 250, + MwNwidth, w - 25 * 2, MwNheight, h - 125 - 50 * 3, NULL); } @@ -30,14 +35,17 @@ static void clipboard(MwWidget handle, void* user_data, void* call_data) { (void)user_data; if(clipboard != NULL) { - MwVaApply(text, MwNtext, clipboard, NULL); - MwForceRender(text); + MwVaApply(cur_text, MwNtext, clipboard, NULL); + MwForceRender(cur_text); } - MwForceRender(window); } static void tick(MwWidget handle, void* user_data, void* call_data) { - MwGetClipboard(handle); + cur_text = text1; + MwGetClipboard(handle, MwClipboardMain); + cur_text = text2; + MwGetClipboard(handle, MwClipboardPrimary); + MwForceRender(window); } int main() { @@ -49,14 +57,19 @@ int main() { instructions = MwVaCreateWidget(MwLabelClass, "button", window, 50, 50, 300, 125, MwNtext, "clipboard contents will show up below.", NULL); - text = MwVaCreateWidget(MwLabelClass, "label", window, 50, 200, 300, 125, + text1 = MwVaCreateWidget(MwLabelClass, "label", window, 25, 150, 300, 75, MwNtext, "", NULL); + text2 = MwVaCreateWidget(MwLabelClass, "label2", window, 25, 250, 300, 75, + MwNtext, "", + NULL); + + cur_text = text1; MwAddUserHandler(window, MwNresizeHandler, resize, NULL); MwAddUserHandler(window, MwNclipboardHandler, clipboard, NULL); MwAddUserHandler(instructions, MwNclipboardHandler, clipboard, NULL); - MwAddUserHandler(text, MwNclipboardHandler, clipboard, NULL); + MwAddUserHandler(cur_text, MwNclipboardHandler, clipboard, NULL); MwAddUserHandler(window, MwNtickHandler, tick, NULL); resize(window, NULL, NULL); diff --git a/include/Mw/Core.h b/include/Mw/Core.h index 4d3e4b99e..ad4cd19de 100644 --- a/include/Mw/Core.h +++ b/include/Mw/Core.h @@ -362,10 +362,11 @@ MWDECL void MwGetScreenSize(MwWidget handle, MwRect* rect); MWDECL int MwGetCoordinateType(MwWidget handle); /*! - * @brief Queue to get clipboard content + * @brief Queue to get clipboard content. * @param handle Widget + * @param clipboard_type The Clipboard Type to get. See MwClipboardType. This is ignored on backends that aren't X11/Wayland, so if you're unsure, just use MwClipboardMain */ -MWDECL void MwGetClipboard(MwWidget handle); +MWDECL void MwGetClipboard(MwWidget handle, int clipboard_type); #ifdef __cplusplus } diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index d5a0b1b5b..abe81b669 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -234,8 +234,8 @@ MWDECL void (*MwLLEndStateChange)(MwLL handle); MWDECL void (*MwLLFocus)(MwLL handle); MWDECL void (*MwLLGrabPointer)(MwLL handle, int toggle); -MWDECL void (*MwLLSetClipboard)(MwLL handle, const char* text); -MWDECL void (*MwLLGetClipboard)(MwLL handle); +MWDECL void (*MwLLSetClipboard)(MwLL handle, const char* text, int clipboard_type); +MWDECL void (*MwLLGetClipboard)(MwLL handle, int clipboard_type); MWDECL void (*MwLLGetCursorCoord)(MwLL handle, MwPoint* point); MWDECL void (*MwLLGetScreenSize)(MwLL handle, MwRect* rect); diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index ce1630c5b..a94d1c812 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -439,7 +439,7 @@ struct _MwLLWayland { /* 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.*/ - union { + struct { struct wl_data_device_manager* wl; struct zwp_primary_selection_device_manager_v1* zwp; } clipboard_manager; @@ -451,7 +451,8 @@ struct _MwLLWayland { MwBool supports_zwp; uint32_t clipboard_serial; - wl_clipboard_device_context_t** clipboard_devices; + wl_clipboard_device_context_t** clipboard_devices_wl; + wl_clipboard_device_context_t** clipboard_devices_zwp; struct wl_pointer* pointer; MwU32 pointer_serial; diff --git a/include/Mw/TypeDefs.h b/include/Mw/TypeDefs.h index 62380f008..bd0af3d78 100644 --- a/include/Mw/TypeDefs.h +++ b/include/Mw/TypeDefs.h @@ -239,4 +239,12 @@ enum MwCoordinateType { MwCoordinatesLocal, }; +/* The clipboard type that MwGetClipboard should return */ +enum MwClipboardType { + /* the clipboard that is present on every platform that supports it */ + MwClipboardMain = 0, + /* the "primary" clipboard that Wayland stores to emulate X11's behavior. */ + MwClipboardPrimary, +}; + #endif diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 4cdc5b2b6..240e5b87e 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -1042,13 +1042,15 @@ static void MwLLGrabPointerImpl(MwLL handle, int toggle) { handle->cocoa.real->pointerLocked = toggle; } -static void MwLLSetClipboardImpl(MwLL handle, const char* text) { +static void MwLLSetClipboardImpl(MwLL handle, const char* text, int clipboard_type) { (void)handle; (void)text; + (void)clipboard_type; } -static void MwLLGetClipboardImpl(MwLL handle) { +static void MwLLGetClipboardImpl(MwLL handle, int clipboard_type) { (void)handle; + (void)clipboard_type; } static void MwLLMakeToolWindowImpl(MwLL handle) { diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 5d89419d0..2941e5cab 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -735,8 +735,9 @@ 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) { HGLOBAL hg; + (void)clipboard_type; if(OpenClipboard(handle->gdi.hWnd) != 0) { char* lock; @@ -753,7 +754,8 @@ static void MwLLSetClipboardImpl(MwLL handle, const char* text) { } } -static void MwLLGetClipboardImpl(MwLL handle) { +static void MwLLGetClipboardImpl(MwLL handle, int clipboard_type) { + (void)clipboard_type; handle->gdi.get_clipboard = 1; /* nishi: we do this to make clipboard api work similar to other backends */ } diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 8bb6f3eed..7f6247fb6 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -266,7 +266,7 @@ struct zwp_primary_selection_device_v1_listener zwp_primary_selection_device_v1_ .selection = zwp_primary_selection_device_v1_selection, }; -static void wl_clipboard_read(wl_clipboard_device_context_t* ctx) { +static void wl_clipboard_read(wl_clipboard_device_context_t* ctx, int clipboard_type) { int fds[2]; fd_set set; char* buf = NULL; @@ -282,7 +282,7 @@ static void wl_clipboard_read(wl_clipboard_device_context_t* ctx) { timeout.tv_sec = 0; timeout.tv_usec = 100; - if(ctx->ll->wayland.supports_zwp) { + if(clipboard_type == MwClipboardPrimary) { zwp_primary_selection_offer_v1_receive(ctx->offer.zwp, "text/plain", fds[1]); } else if(ctx->offer.wl) { wl_data_offer_receive(ctx->offer.wl, "text/plain", fds[1]); @@ -427,7 +427,7 @@ 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; - if(wayland->clipboard_manager.wl != NULL && !wayland->supports_zwp) { + if(wayland->clipboard_manager.wl != NULL) { wl_data_device_manager_destroy(wayland->clipboard_manager.wl); wl_data_source_destroy(wayland->clipboard_source.wl); wayland->clipboard_manager.wl = NULL; @@ -436,10 +436,6 @@ static void wl_data_device_manager_interface_destroy(struct _MwLLWayland* waylan /* zwp_primary_selection_device_manager_v1 setup function */ static wayland_protocol_t* zwp_primary_selection_device_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland) { - if(wayland->clipboard_manager.wl != NULL) { - wl_data_device_manager_interface_destroy(wayland, NULL); - } - wayland->clipboard_manager.zwp = wl_registry_bind(wayland->registry, name, &zwp_primary_selection_device_manager_v1_interface, 1); wayland->clipboard_source.zwp = zwp_primary_selection_device_manager_v1_create_source(wayland->clipboard_manager.zwp); @@ -621,10 +617,6 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri break; case BTN_MIDDLE: p.button = MwLLMouseMiddle; - for(i = 0; i < arrlen(self->wayland.clipboard_devices); i++) { - wl_clipboard_read( - self->wayland.clipboard_devices[i]); - } break; case BTN_RIGHT: p.button = MwLLMouseRight; @@ -840,14 +832,6 @@ static void keyboard_key(void* data, } if((self->wayland.mod_state & 4) == 4) { - /* clipboard paste */ - if(key == 'V') { - int i; - for(i = 0; i < arrlen(self->wayland.clipboard_devices); i++) { - wl_clipboard_read( - self->wayland.clipboard_devices[i]); - } - } key |= MwLLControlMask; } if((self->wayland.mod_state & 8) == 8) { @@ -913,8 +897,9 @@ wl_seat_name(void* data, struct wl_seat* wl_seat, const char* name) { /* `wl_seat.capabilities` callback */ static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat, MwU32 capabilities) { - MwLL self = data; - wl_clipboard_device_context_t* device_ctx = malloc(sizeof(wl_clipboard_device_context_t)); + MwLL self = data; + wl_clipboard_device_context_t* device_ctx_zwp = NULL; + wl_clipboard_device_context_t* device_ctx_wl = malloc(sizeof(wl_clipboard_device_context_t)); WAYLAND_EVENT_OP_START(self); @@ -930,21 +915,23 @@ static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat, if(self->wayland.clipboard_manager.wl != NULL) { if(self->wayland.supports_zwp) { - device_ctx->device.zwp = zwp_primary_selection_device_manager_v1_get_device(self->wayland.clipboard_manager.zwp, wl_seat); - } else { - device_ctx->device.wl = wl_data_device_manager_get_data_device(self->wayland.clipboard_manager.wl, wl_seat); + device_ctx_zwp = malloc(sizeof(wl_clipboard_device_context_t)); + device_ctx_zwp->device.zwp = zwp_primary_selection_device_manager_v1_get_device(self->wayland.clipboard_manager.zwp, wl_seat); + device_ctx_zwp->ll = self; + device_ctx_zwp->seat = wl_seat; + device_ctx_zwp->capabilities = capabilities; } - device_ctx->ll = self; - device_ctx->seat = wl_seat; - device_ctx->capabilities = capabilities; + device_ctx_wl->device.wl = wl_data_device_manager_get_data_device(self->wayland.clipboard_manager.wl, wl_seat); + device_ctx_wl->ll = self; + device_ctx_wl->seat = wl_seat; + device_ctx_wl->capabilities = capabilities; if(self->wayland.supports_zwp) { - zwp_primary_selection_device_v1_add_listener(device_ctx->device.zwp, &zwp_primary_selection_device_v1_listener, device_ctx); - } else { - wl_data_device_add_listener(device_ctx->device.wl, &wl_data_device_listener, device_ctx); + zwp_primary_selection_device_v1_add_listener(device_ctx_zwp->device.zwp, &zwp_primary_selection_device_v1_listener, device_ctx_zwp); + arrpush(self->wayland.clipboard_devices_zwp, device_ctx_zwp); } - - arrpush(self->wayland.clipboard_devices, device_ctx); + wl_data_device_add_listener(device_ctx_wl->device.wl, &wl_data_device_listener, device_ctx_wl); + arrpush(self->wayland.clipboard_devices_wl, device_ctx_wl); } WAYLAND_EVENT_OP_END(self); @@ -2471,33 +2458,48 @@ 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) { + int i; + if(handle->wayland.clipboard_buffer != NULL) { free(handle->wayland.clipboard_buffer); } handle->wayland.clipboard_buffer = malloc(strlen(text)); strcpy(handle->wayland.clipboard_buffer, text); - if(handle->wayland.supports_zwp) { - int i; - for(i = 0; i < arrlen(handle->wayland.clipboard_devices); i++) { - wl_clipboard_device_context_t* device = handle->wayland.clipboard_devices[i]; - zwp_primary_selection_device_v1_set_selection(device->device.zwp, handle->wayland.clipboard_source.zwp, handle->wayland.keyboard_serial); + if(clipboard_type == MwClipboardPrimary) { + if(handle->wayland.supports_zwp) { + for(i = 0; i < arrlen(handle->wayland.clipboard_devices_zwp); i++) { + wl_clipboard_device_context_t* device = handle->wayland.clipboard_devices_zwp[i]; + zwp_primary_selection_device_v1_set_selection(device->device.zwp, handle->wayland.clipboard_source.zwp, handle->wayland.keyboard_serial); + } + } else { + printf("[WARNING] Primary clipboard requested for MwLLSetClipboard, but this Wayland compositor doesn't support it.\n"); } } else { - int i; - for(i = 0; i < arrlen(handle->wayland.clipboard_devices); i++) { - wl_clipboard_device_context_t* device = handle->wayland.clipboard_devices[i]; + for(i = 0; i < arrlen(handle->wayland.clipboard_devices_wl); i++) { + wl_clipboard_device_context_t* device = handle->wayland.clipboard_devices_wl[i]; wl_data_device_set_selection(device->device.wl, handle->wayland.clipboard_source.wl, handle->wayland.keyboard_serial); } } } -static void MwLLGetClipboardImpl(MwLL handle) { +static void MwLLGetClipboardImpl(MwLL handle, int clipboard_type) { int i; - for(i = 0; i < arrlen(handle->wayland.clipboard_devices); i++) { - wl_clipboard_read( - handle->wayland.clipboard_devices[i]); + if(clipboard_type == MwClipboardPrimary) { + if(handle->wayland.supports_zwp) { + for(i = 0; i < arrlen(handle->wayland.clipboard_devices_zwp); i++) { + wl_clipboard_read( + handle->wayland.clipboard_devices_zwp[i], clipboard_type); + } + } else { + printf("[WARNING] Primary clipboard requested for MwLLSetClipboard, but this Wayland compositor doesn't support it.\n"); + } + } else { + for(i = 0; i < arrlen(handle->wayland.clipboard_devices_wl); i++) { + wl_clipboard_read( + handle->wayland.clipboard_devices_wl[i], clipboard_type); + } } return; } diff --git a/src/backend/x11.c b/src/backend/x11.c index ad97d6885..4393317c4 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -1220,14 +1220,14 @@ 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 */ (void)handle; (void)text; } -static void MwLLGetClipboardImpl(MwLL handle) { +static void MwLLGetClipboardImpl(MwLL handle, int clipboard_type) { if(handle->x11.clipboard_pending) return; XConvertSelection(handle->x11.display, handle->x11.clipboard, handle->x11.utf8_string, handle->x11.selection, handle->x11.window, CurrentTime); diff --git a/src/core.c b/src/core.c index cf45dddc2..de2774d85 100644 --- a/src/core.c +++ b/src/core.c @@ -958,6 +958,6 @@ int MwGetCoordinateType(MwWidget handle) { } } -void MwGetClipboard(MwWidget handle) { - MwLLGetClipboard(handle->lowlevel); +void MwGetClipboard(MwWidget handle, int clipboard_type) { + MwLLGetClipboard(handle->lowlevel, clipboard_type); } diff --git a/src/lowlevel.c b/src/lowlevel.c index 597a23a82..534ecd28d 100644 --- a/src/lowlevel.c +++ b/src/lowlevel.c @@ -45,8 +45,8 @@ void (*MwLLEndStateChange)(MwLL handle) = NULL; void (*MwLLFocus)(MwLL handle) = NULL; void (*MwLLGrabPointer)(MwLL handle, int toggle) = NULL; -void (*MwLLSetClipboard)(MwLL handle, const char* text) = NULL; -void (*MwLLGetClipboard)(MwLL handle) = NULL; +void (*MwLLSetClipboard)(MwLL handle, const char* text, int clipboard_type) = NULL; +void (*MwLLGetClipboard)(MwLL, int clipboard_type) = NULL; void (*MwLLGetCursorCoord)(MwLL handle, MwPoint* point) = NULL; void (*MwLLGetScreenSize)(MwLL handle, MwRect* rect) = NULL; diff --git a/src/widget/entry.c b/src/widget/entry.c index bd7dbe1b5..a8d094130 100644 --- a/src/widget/entry.c +++ b/src/widget/entry.c @@ -113,7 +113,7 @@ static void key(MwWidget handle, int code) { } else if(code == MwLLKeyEnter) { MwDispatchUserHandler(handle, MwNactivateHandler, NULL); } else if(code == (MwLLControlMask | 'v')) { - MwLLGetClipboard(handle->lowlevel); + MwLLGetClipboard(handle->lowlevel, MwClipboardMain); } else if(!(code & MwLLKeyMask)) { int incr = 0; out = malloc(strlen(str) + 5 + 1); @@ -133,6 +133,20 @@ static void key(MwWidget handle, int code) { MwForceRender(handle); } +#if defined(USE_X11) || defined(USE_WAYLAND) +static void mouse_up(MwWidget handle, void* ptr) { + if(handle->lowlevel->common.type == MwLLBackendWayland || handle->lowlevel->common.type == MwLLBackendX11) { + MwLLMouse* mouse = ptr; + if(mouse->button == MwLLMouseMiddle) { + MwLLGetClipboard(handle->lowlevel, MwClipboardPrimary); + } + } + MwForceRender2(handle, NULL); +} +#else +#define mouse_up MwForceRender2 +#endif + static void prop_change(MwWidget handle, const char* prop) { if(strcmp(prop, MwNtext) == 0 || strcmp(prop, MwNhideInput) == 0) MwForceRender(handle); @@ -179,7 +193,7 @@ MwClassRec MwEntryClassRec = { NULL, /* parent_resize */ prop_change, /* prop_change */ NULL, /* mouse_move */ - MwForceRender2, /* mouse_up */ + mouse_up, /* mouse_up */ MwForceRender2, /* mouse_down */ key, /* key */ NULL, /* execute */ From e77eb5e08a48d6df3d9d4066e245d29baaa9f4fd Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 15 Apr 2026 11:14:13 -0700 Subject: [PATCH 155/195] add clipboard stuff to milsko.xml --- milsko.xml | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/milsko.xml b/milsko.xml index 9fb45a608..70503a1d8 100644 --- a/milsko.xml +++ b/milsko.xml @@ -1,4 +1,4 @@ - + + @@ -146,6 +149,10 @@ + + 0 + + 0x0fffffff @@ -399,6 +406,19 @@ + + + + + + + + + + + + +
From f7eb9840def45894a416521cb5f0b555dad29ca6 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 15 Apr 2026 11:19:10 -0700 Subject: [PATCH 156/195] milsko.xml: MwClipboardType should be marked as an enum for MwGetClipboard --- milsko.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/milsko.xml b/milsko.xml index 70503a1d8..d42f7e961 100644 --- a/milsko.xml +++ b/milsko.xml @@ -409,7 +409,7 @@ - + From a3bbcf30b2b94c88a3b59f86260a59cee3d6715d Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 15 Apr 2026 12:25:51 -0700 Subject: [PATCH 157/195] wayland: dark theme detection --- include/Mw/LowLevel/Wayland.h | 53 ++++++++++++++++- pl/rules.pl | 2 + src/backend/wayland.c | 105 ++++++++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+), 2 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index ce1630c5b..9377bc837 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -14,6 +14,7 @@ #include #include #include +#include MWDECL int MwLLWaylandCallInit(void); @@ -35,8 +36,7 @@ typedef struct wayland_call_table { void* lib; void* xkb_lib; void* cairo_lib; -#if WAYLAND_LOAD_OPENGL -#endif + void* dbus_lib; int (*wl_display_dispatch_pending)(struct wl_display* display); void (*wl_display_disconnect)(struct wl_display* display); @@ -125,6 +125,21 @@ typedef struct wayland_call_table { void (*cairo_set_antialias)(cairo_t*, cairo_antialias_t); void (*cairo_set_operator)(cairo_t* cr, cairo_operator_t op); + void (*dbus_error_init)(DBusError* error); + DBusConnection* (*dbus_bus_get)(DBusBusType type, DBusError* error); + dbus_bool_t (*dbus_error_is_set)(const DBusError* error); + void (*dbus_error_free)(DBusError* error); + DBusMessage* (*dbus_message_new_method_call)(const char* bus_name, const char* path, const char* iface, const char* method); + void (*dbus_message_iter_init_append)(DBusMessage* message, DBusMessageIter* iter); + dbus_bool_t (*dbus_message_iter_append_basic)(DBusMessageIter* iter, int type, const void* value); + DBusMessage* (*dbus_connection_send_with_reply_and_block)(DBusConnection* connection, DBusMessage* message, int timeout_milliseconds, DBusError* error); + void (*dbus_message_unref)(DBusMessage* message); + dbus_bool_t (*dbus_message_iter_init)(DBusMessage* message, DBusMessageIter* iter); + int (*dbus_message_iter_get_arg_type)(DBusMessageIter* iter); + void (*dbus_message_iter_recurse)(DBusMessageIter* iter, DBusMessageIter* sub); + void (*dbus_connection_unref)(DBusConnection* connection); + void (*dbus_message_iter_get_basic)(DBusMessageIter* iter, void* value); + } wayland_call_table_t; extern wayland_call_table_t wl_call_tbl; @@ -225,6 +240,34 @@ MwInline int wayland_load_funcs() { CAIRO_FUNC(cairo_pattern_set_filter); #undef CAIRO_FUNC + wl_call_tbl.dbus_lib = MwDynamicOpen("libdbus-1.so"); + if(!wl_call_tbl.dbus_lib) { + fprintf(stderr, "[WARNING] Will not be able to detect dark theme: dbus library (libdbus-1.so) not found.\n"); + return 0; + } + +#define DBUS_FUNC(x) \ + wl_call_tbl.x = MwDynamicSymbol(wl_call_tbl.dbus_lib, #x); \ + if(!x) { \ + fprintf(stderr, "[WARNING] Will not be able to detect dark theme: dbus function %s (libdbus-1.so) not found.\n", #x); \ + return 0; \ + } + + DBUS_FUNC(dbus_error_init); + DBUS_FUNC(dbus_bus_get); + DBUS_FUNC(dbus_error_is_set); + DBUS_FUNC(dbus_error_free); + DBUS_FUNC(dbus_message_new_method_call); + DBUS_FUNC(dbus_message_iter_init_append); + DBUS_FUNC(dbus_message_iter_append_basic); + DBUS_FUNC(dbus_connection_send_with_reply_and_block); + DBUS_FUNC(dbus_message_unref); + DBUS_FUNC(dbus_message_iter_init); + DBUS_FUNC(dbus_message_iter_get_arg_type); + DBUS_FUNC(dbus_message_iter_recurse); + DBUS_FUNC(dbus_connection_unref); + DBUS_FUNC(dbus_message_iter_get_basic); + return 0; } @@ -436,6 +479,12 @@ struct _MwLLWayland { struct zwp_locked_pointer_v1* locked_pointer; MwBool pointer_constrained; + DBusConnection* dbus_conn; + DBusError dbus_err; + DBusMessage* dbus_msg; + DBusMessage* dbus_reply; + DBusMessageIter dbus_args, dbus_variant, dbus_inner_variant; + /* 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.*/ diff --git a/pl/rules.pl b/pl/rules.pl index 3da19289e..d6f72fb6e 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -49,6 +49,8 @@ if (grep(/^wayland$/, @backends)) { scan_wayland_protocol("unstable", "pointer-constraints", "-unstable-v1"); scan_wayland_protocol("unstable", "relative-pointer", "-unstable-v1"); + add_cflags("-I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include"); + $gl_libs = "-lGL -lGLU"; } diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 8bb6f3eed..e1e8ee4d0 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1829,6 +1829,99 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh MwLLEndDraw(r); } } + +static void dark_theme_detection_setup(MwLL handle) { + + if(!wl_call_tbl.dbus_lib) { + return; + } + + wl_call_tbl.dbus_error_init(&handle->wayland.dbus_err); + + handle->wayland.dbus_conn = wl_call_tbl.dbus_bus_get(0 /* DBUS_BUS_SESSION */, &handle->wayland.dbus_err); + if(wl_call_tbl.dbus_error_is_set(&handle->wayland.dbus_err)) { + fprintf(stderr, "[WARNING] Could not detect dark theme: Connection error: %s\n", handle->wayland.dbus_err.message); + wl_call_tbl.dbus_error_free(&handle->wayland.dbus_err); + return; + } + if(!handle->wayland.dbus_conn) { + fprintf(stderr, "[WARNING] Could not detect dark theme: Failed to connect to session bus\n"); + return; + } +} + +static void detect_dark_theme(MwLL handle) { + const char* namespace = "org.freedesktop.appearance"; + const char* key = "color-scheme"; /* 0=no preference, 1=dark, 2=light */ + MwU32 value = 0; + int translated_value = 0; + + if(!handle->wayland.dbus_conn) { + return; + } + + handle->wayland.dbus_msg = wl_call_tbl.dbus_message_new_method_call( + "org.freedesktop.portal.Desktop", + "/org/freedesktop/portal/desktop", + "org.freedesktop.portal.Settings", + "Read"); + if(!handle->wayland.dbus_msg) { + fprintf(stderr, "[WARNING] Could not detect dark theme: Failed to create message\n"); + return; + } + + wl_call_tbl.dbus_message_iter_init_append(handle->wayland.dbus_msg, &handle->wayland.dbus_args); + wl_call_tbl.dbus_message_iter_append_basic(&handle->wayland.dbus_args, 's', &namespace); + wl_call_tbl.dbus_message_iter_append_basic(&handle->wayland.dbus_args, 's', &key); + + handle->wayland.dbus_reply = wl_call_tbl.dbus_connection_send_with_reply_and_block(handle->wayland.dbus_conn, handle->wayland.dbus_msg, 100, &handle->wayland.dbus_err); + wl_call_tbl.dbus_message_unref(handle->wayland.dbus_msg); + + if(wl_call_tbl.dbus_error_is_set(&handle->wayland.dbus_err)) { + fprintf(stderr, "[WARNING] Could not detect dark theme: Send error: %s\n", handle->wayland.dbus_err.message); + wl_call_tbl.dbus_error_free(&handle->wayland.dbus_err); + return; + } + if(!handle->wayland.dbus_reply) { + fprintf(stderr, "[WARNING] Could not detect dark theme: No reply received\n"); + return; + } + + if(!wl_call_tbl.dbus_message_iter_init(handle->wayland.dbus_reply, &handle->wayland.dbus_args)) { + fprintf(stderr, "[WARNING] Could not detect dark theme: Reply has no arguments\n"); + wl_call_tbl.dbus_message_unref(handle->wayland.dbus_reply); + return; + } + + if(wl_call_tbl.dbus_message_iter_get_arg_type(&handle->wayland.dbus_args) != 'v') { + fprintf(stderr, "[WARNING] Could not detect dark theme: Expected outer variant\n"); + wl_call_tbl.dbus_message_unref(handle->wayland.dbus_reply); + return; + } + wl_call_tbl.dbus_message_iter_recurse(&handle->wayland.dbus_args, &handle->wayland.dbus_variant); + + /* Some portals wrap the value in a second variant */ + if(wl_call_tbl.dbus_message_iter_get_arg_type(&handle->wayland.dbus_variant) == 'v') { + wl_call_tbl.dbus_message_iter_recurse(&handle->wayland.dbus_variant, &handle->wayland.dbus_inner_variant); + wl_call_tbl.dbus_message_iter_get_basic(&handle->wayland.dbus_inner_variant, &value); + } else { + wl_call_tbl.dbus_message_iter_get_basic(&handle->wayland.dbus_variant, &value); + } + + translated_value = (value == 1) ? 1 : 0; + + MwLLDispatch(handle, dark_theme, &translated_value); +} + +static void dark_theme_detection_destroy(MwLL handle) { + if(!wl_call_tbl.dbus_lib) { + return; + } + + wl_call_tbl.dbus_message_unref(handle->wayland.dbus_reply); + wl_call_tbl.dbus_connection_unref(handle->wayland.dbus_conn); +} + static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { MwLL r; r = malloc(sizeof(*r)); @@ -1837,6 +1930,10 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { widget_setup(r, parent, x, y, width, height, MWLL_WAYLAND_UNKNOWN); + if(!parent) { + dark_theme_detection_setup(r); + } + return r; } @@ -1856,6 +1953,10 @@ static void MwLLDestroyImpl(MwLL handle) { MwLLDestroyCommon(handle); + if(!handle->wayland.dbus_conn) { + dark_theme_detection_destroy(handle); + } + event_loop(handle); /* sleep long enough that any active attempts to wait for the mutex will have given up and we can safely unlock/destroy it */ @@ -2144,6 +2245,10 @@ static int MwLLPendingImpl(MwLL handle) { }; int pending = 0; + if(handle->wayland.dbus_conn) { + detect_dark_theme(handle); + } + if(!handle->wayland.did_initial_resize) { recursive_dispatch_resize(handle); handle->wayland.did_initial_resize = 1; From d05e31b154baea11d14f76c99deb00b682e56f8f Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 15 Apr 2026 13:00:59 -0700 Subject: [PATCH 158/195] wayland: don't poll for dark theme, that doesn't work --- include/Mw/LowLevel/Wayland.h | 2 ++ src/backend/wayland.c | 49 +++++++++++++++++++++-------------- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 9377bc837..d4ebdef93 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -479,6 +479,8 @@ struct _MwLLWayland { struct zwp_locked_pointer_v1* locked_pointer; MwBool pointer_constrained; + MwBool dark_theme_detection; + time_t dbus_timer; DBusConnection* dbus_conn; DBusError dbus_err; DBusMessage* dbus_msg; diff --git a/src/backend/wayland.c b/src/backend/wayland.c index e1e8ee4d0..68207b871 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1831,11 +1831,17 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh } static void dark_theme_detection_setup(MwLL handle) { + const char* namespace = "org.freedesktop.appearance"; + const char* key = "color-scheme"; /* 0=no preference, 1=dark, 2=light */ + MwU32 value = 0; + int translated_value = 0; if(!wl_call_tbl.dbus_lib) { return; } + time(&handle->wayland.dbus_timer); + wl_call_tbl.dbus_error_init(&handle->wayland.dbus_err); handle->wayland.dbus_conn = wl_call_tbl.dbus_bus_get(0 /* DBUS_BUS_SESSION */, &handle->wayland.dbus_err); @@ -1848,17 +1854,6 @@ static void dark_theme_detection_setup(MwLL handle) { fprintf(stderr, "[WARNING] Could not detect dark theme: Failed to connect to session bus\n"); return; } -} - -static void detect_dark_theme(MwLL handle) { - const char* namespace = "org.freedesktop.appearance"; - const char* key = "color-scheme"; /* 0=no preference, 1=dark, 2=light */ - MwU32 value = 0; - int translated_value = 0; - - if(!handle->wayland.dbus_conn) { - return; - } handle->wayland.dbus_msg = wl_call_tbl.dbus_message_new_method_call( "org.freedesktop.portal.Desktop", @@ -1873,9 +1868,18 @@ static void detect_dark_theme(MwLL handle) { wl_call_tbl.dbus_message_iter_init_append(handle->wayland.dbus_msg, &handle->wayland.dbus_args); wl_call_tbl.dbus_message_iter_append_basic(&handle->wayland.dbus_args, 's', &namespace); wl_call_tbl.dbus_message_iter_append_basic(&handle->wayland.dbus_args, 's', &key); +} + +static void detect_dark_theme(MwLL handle) { + const char* namespace = "org.freedesktop.appearance"; + const char* key = "color-scheme"; /* 0=no preference, 1=dark, 2=light */ + MwU32 value = 0; + + if(!handle->wayland.dbus_conn) { + return; + } handle->wayland.dbus_reply = wl_call_tbl.dbus_connection_send_with_reply_and_block(handle->wayland.dbus_conn, handle->wayland.dbus_msg, 100, &handle->wayland.dbus_err); - wl_call_tbl.dbus_message_unref(handle->wayland.dbus_msg); if(wl_call_tbl.dbus_error_is_set(&handle->wayland.dbus_err)) { fprintf(stderr, "[WARNING] Could not detect dark theme: Send error: %s\n", handle->wayland.dbus_err.message); @@ -1908,18 +1912,16 @@ static void detect_dark_theme(MwLL handle) { wl_call_tbl.dbus_message_iter_get_basic(&handle->wayland.dbus_variant, &value); } - translated_value = (value == 1) ? 1 : 0; - - MwLLDispatch(handle, dark_theme, &translated_value); + MwLLDispatch(handle, dark_theme, &value); } static void dark_theme_detection_destroy(MwLL handle) { if(!wl_call_tbl.dbus_lib) { return; } - - wl_call_tbl.dbus_message_unref(handle->wayland.dbus_reply); - wl_call_tbl.dbus_connection_unref(handle->wayland.dbus_conn); + if(handle->wayland.dbus_msg) wl_call_tbl.dbus_message_unref(handle->wayland.dbus_msg); + if(handle->wayland.dbus_reply) wl_call_tbl.dbus_message_unref(handle->wayland.dbus_reply); + if(handle->wayland.dbus_conn) wl_call_tbl.dbus_connection_unref(handle->wayland.dbus_conn); } static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { @@ -1932,6 +1934,7 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { if(!parent) { dark_theme_detection_setup(r); + r->wayland.dark_theme_detection = MwTRUE; } return r; @@ -2245,8 +2248,11 @@ static int MwLLPendingImpl(MwLL handle) { }; int pending = 0; - if(handle->wayland.dbus_conn) { - detect_dark_theme(handle); + if(handle->wayland.dark_theme_detection) { + if(handle->wayland.dbus_conn) { + detect_dark_theme(handle); + handle->wayland.dark_theme_detection = MwFALSE; + } } if(!handle->wayland.did_initial_resize) { @@ -2652,6 +2658,9 @@ static void MwLLEndStateChangeImpl(MwLL handle) { widget_setup(handle, handle->wayland.parent, handle->wayland.detach_point.x, handle->wayland.detach_point.y, handle->wayland.ww, handle->wayland.wh, handle->wayland.type_to_be); + if(!handle->wayland.parent) + handle->wayland.dark_theme_detection = MwTRUE; + if(handle->common.user) { MwWidget w = handle->common.user; int i; From 64930db2fc89f2b08bc5e8d9cdcfa1ce565f0079 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 15 Apr 2026 13:03:24 -0700 Subject: [PATCH 159/195] color picker example: have button match the background --- examples/basic/colorpicker.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/basic/colorpicker.c b/examples/basic/colorpicker.c index 22e647cc8..8d0c0f369 100644 --- a/examples/basic/colorpicker.c +++ b/examples/basic/colorpicker.c @@ -35,12 +35,11 @@ int main() { window = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, MwDEFAULT, 640, 480, MwNtitle, "color picker", NULL); - MwSetText(window, MwNbackground, "#000000"); + MwSetText(window, MwNbackground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultBackground : MwDefaultDarkBackground); button = MwVaCreateWidget(MwButtonClass, "button", window, 160, 180, 320, 120, MwNtext, "change window background", NULL); - MwSetText(button, MwNbackground, MwGetInteger(button, MwNdarkTheme) ? MwDefaultDarkBackground : MwDefaultBackground); MwAddUserHandler(button, MwNactivateHandler, color_picker, NULL); From a0c864d85b2bf782e78ef15068b0a293910fc017 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 15 Apr 2026 13:58:50 -0700 Subject: [PATCH 160/195] fix wayland crash by having MwLLDestroy flush before actually destroying handle --- src/backend/wayland.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 68207b871..435033643 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1949,6 +1949,11 @@ static void MwLLDestroyImpl(MwLL handle) { }; int select_ret; + event_loop(handle); + // wl_display_cancel_read(handle->wayland.display); + + wl_flush(handle); + if(pthread_mutex_timedlock(&handle->wayland.eventsMutex, &t) != 0) { printf("WARNING: Couldn't call MwLLDestroyImpl due to deadlock.\n"); return; @@ -1956,12 +1961,6 @@ static void MwLLDestroyImpl(MwLL handle) { MwLLDestroyCommon(handle); - if(!handle->wayland.dbus_conn) { - dark_theme_detection_destroy(handle); - } - - event_loop(handle); - /* sleep long enough that any active attempts to wait for the mutex will have given up and we can safely unlock/destroy it */ tv.tv_sec = 0; tv.tv_usec = 1000; @@ -1972,7 +1971,10 @@ static void MwLLDestroyImpl(MwLL handle) { pthread_mutex_unlock(&handle->wayland.eventsMutex); pthread_mutex_destroy(&handle->wayland.eventsMutex); - // framebuffer_destroy(&handle->wayland); + if(!handle->wayland.dbus_conn) { + dark_theme_detection_destroy(handle); + } + buffer_destroy(&handle->wayland.cursor); wl_region_destroy(handle->wayland.region); @@ -2005,7 +2007,12 @@ static void MwLLDestroyImpl(MwLL handle) { shfree(handle->wayland.wl_protocol_map); shfree(handle->wayland.wl_protocol_setup_map); - free(handle); + wl_keyboard_destroy(handle->wayland.keyboard); + wl_pointer_destroy(handle->wayland.pointer); + + wl_flush(handle); + + // free(handle); if(currentlyHeldWidget == handle) { currentlyHeldWidget = NULL; @@ -2252,6 +2259,7 @@ static int MwLLPendingImpl(MwLL handle) { if(handle->wayland.dbus_conn) { detect_dark_theme(handle); handle->wayland.dark_theme_detection = MwFALSE; + MwLLDispatch(handle, draw, NULL); } } From 12703d451e63bbf5d505ba0c33f00deab5d3989c Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 15 Apr 2026 14:02:22 -0700 Subject: [PATCH 161/195] use pkg-config for dbus includes --- pl/rules.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pl/rules.pl b/pl/rules.pl index d6f72fb6e..af1bb21cc 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -49,7 +49,7 @@ if (grep(/^wayland$/, @backends)) { scan_wayland_protocol("unstable", "pointer-constraints", "-unstable-v1"); scan_wayland_protocol("unstable", "relative-pointer", "-unstable-v1"); - add_cflags("-I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include"); + add_cflags(`pkg-config --cflags dbus-1.0`); $gl_libs = "-lGL -lGLU"; } From 43c66417c7f15a07b8207d432f27531bc1bbd6d5 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 15 Apr 2026 14:03:48 -0700 Subject: [PATCH 162/195] use pkg-config for dbus includes --- pl/rules.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pl/rules.pl b/pl/rules.pl index af1bb21cc..2b222249b 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -49,7 +49,7 @@ if (grep(/^wayland$/, @backends)) { scan_wayland_protocol("unstable", "pointer-constraints", "-unstable-v1"); scan_wayland_protocol("unstable", "relative-pointer", "-unstable-v1"); - add_cflags(`pkg-config --cflags dbus-1.0`); + add_cflags(`pkg-config --cflags dbus-1`); $gl_libs = "-lGL -lGLU"; } From dc97522bb075527f428d8c3e44a8fdc50a29f0ac Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 15 Apr 2026 15:21:16 -0700 Subject: [PATCH 163/195] wayland: abstract the dbus stuff a bit in case we need it later --- src/backend/wayland.c | 60 ++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 435033643..3c8c9cd20 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1830,11 +1830,9 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh } } -static void dark_theme_detection_setup(MwLL handle) { - const char* namespace = "org.freedesktop.appearance"; - const char* key = "color-scheme"; /* 0=no preference, 1=dark, 2=light */ - MwU32 value = 0; - int translated_value = 0; +static void dbus_setup(MwLL handle) { + MwU32 value = 0; + int translated_value = 0; if(!wl_call_tbl.dbus_lib) { return; @@ -1854,51 +1852,47 @@ static void dark_theme_detection_setup(MwLL handle) { fprintf(stderr, "[WARNING] Could not detect dark theme: Failed to connect to session bus\n"); return; } +} + +static void dbus_get(MwLL handle, const char* portal, const char* namespace, const char* key, void* out) { + if(!handle->wayland.dbus_conn) { + return; + } handle->wayland.dbus_msg = wl_call_tbl.dbus_message_new_method_call( "org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop", - "org.freedesktop.portal.Settings", + portal, "Read"); if(!handle->wayland.dbus_msg) { - fprintf(stderr, "[WARNING] Could not detect dark theme: Failed to create message\n"); + fprintf(stderr, "[WARNING] Couldn't get %s::%s: Failed to create message\n", namespace, key); return; } wl_call_tbl.dbus_message_iter_init_append(handle->wayland.dbus_msg, &handle->wayland.dbus_args); wl_call_tbl.dbus_message_iter_append_basic(&handle->wayland.dbus_args, 's', &namespace); wl_call_tbl.dbus_message_iter_append_basic(&handle->wayland.dbus_args, 's', &key); -} - -static void detect_dark_theme(MwLL handle) { - const char* namespace = "org.freedesktop.appearance"; - const char* key = "color-scheme"; /* 0=no preference, 1=dark, 2=light */ - MwU32 value = 0; - - if(!handle->wayland.dbus_conn) { - return; - } handle->wayland.dbus_reply = wl_call_tbl.dbus_connection_send_with_reply_and_block(handle->wayland.dbus_conn, handle->wayland.dbus_msg, 100, &handle->wayland.dbus_err); if(wl_call_tbl.dbus_error_is_set(&handle->wayland.dbus_err)) { - fprintf(stderr, "[WARNING] Could not detect dark theme: Send error: %s\n", handle->wayland.dbus_err.message); + fprintf(stderr, "[WARNING] Couldn't get %s::%s: Send error: %s\n", namespace, key, handle->wayland.dbus_err.message); wl_call_tbl.dbus_error_free(&handle->wayland.dbus_err); return; } if(!handle->wayland.dbus_reply) { - fprintf(stderr, "[WARNING] Could not detect dark theme: No reply received\n"); + fprintf(stderr, "[WARNING] Couldn't get %s::%s: No reply received\n", namespace, key); return; } if(!wl_call_tbl.dbus_message_iter_init(handle->wayland.dbus_reply, &handle->wayland.dbus_args)) { - fprintf(stderr, "[WARNING] Could not detect dark theme: Reply has no arguments\n"); + fprintf(stderr, "[WARNING] Couldn't get %s::%s: Reply has no arguments\n", namespace, key); wl_call_tbl.dbus_message_unref(handle->wayland.dbus_reply); return; } if(wl_call_tbl.dbus_message_iter_get_arg_type(&handle->wayland.dbus_args) != 'v') { - fprintf(stderr, "[WARNING] Could not detect dark theme: Expected outer variant\n"); + fprintf(stderr, "[WARNING] Couldn't get %s::%s: Expected outer variant\n", namespace, key); wl_call_tbl.dbus_message_unref(handle->wayland.dbus_reply); return; } @@ -1907,19 +1901,27 @@ static void detect_dark_theme(MwLL handle) { /* Some portals wrap the value in a second variant */ if(wl_call_tbl.dbus_message_iter_get_arg_type(&handle->wayland.dbus_variant) == 'v') { wl_call_tbl.dbus_message_iter_recurse(&handle->wayland.dbus_variant, &handle->wayland.dbus_inner_variant); - wl_call_tbl.dbus_message_iter_get_basic(&handle->wayland.dbus_inner_variant, &value); + wl_call_tbl.dbus_message_iter_get_basic(&handle->wayland.dbus_inner_variant, out); } else { - wl_call_tbl.dbus_message_iter_get_basic(&handle->wayland.dbus_variant, &value); + wl_call_tbl.dbus_message_iter_get_basic(&handle->wayland.dbus_variant, out); } - - MwLLDispatch(handle, dark_theme, &value); + wl_call_tbl.dbus_message_unref(handle->wayland.dbus_msg); } -static void dark_theme_detection_destroy(MwLL handle) { +static void detect_dark_theme(MwLL handle) { + MwU32 value = 0; + MwU32 dark_theme = 0; + dbus_get(handle, "org.freedesktop.portal.Settings", "org.freedesktop.appearance", "color-scheme", &value); + + dark_theme = (value == 1) ? 1 : 0; + + MwLLDispatch(handle, dark_theme, &dark_theme); +} + +static void dbus_destroy(MwLL handle) { if(!wl_call_tbl.dbus_lib) { return; } - if(handle->wayland.dbus_msg) wl_call_tbl.dbus_message_unref(handle->wayland.dbus_msg); if(handle->wayland.dbus_reply) wl_call_tbl.dbus_message_unref(handle->wayland.dbus_reply); if(handle->wayland.dbus_conn) wl_call_tbl.dbus_connection_unref(handle->wayland.dbus_conn); } @@ -1933,7 +1935,7 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { widget_setup(r, parent, x, y, width, height, MWLL_WAYLAND_UNKNOWN); if(!parent) { - dark_theme_detection_setup(r); + dbus_setup(r); r->wayland.dark_theme_detection = MwTRUE; } @@ -1972,7 +1974,7 @@ static void MwLLDestroyImpl(MwLL handle) { pthread_mutex_destroy(&handle->wayland.eventsMutex); if(!handle->wayland.dbus_conn) { - dark_theme_detection_destroy(handle); + dbus_destroy(handle); } buffer_destroy(&handle->wayland.cursor); From 9087782960496a271c184e9e2c913a38611139cd Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 15 Apr 2026 15:23:55 -0700 Subject: [PATCH 164/195] wayland: fix DBUS_FUNC --- include/Mw/LowLevel/Wayland.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index d4ebdef93..6b2c08ff9 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -248,8 +248,9 @@ MwInline int wayland_load_funcs() { #define DBUS_FUNC(x) \ wl_call_tbl.x = MwDynamicSymbol(wl_call_tbl.dbus_lib, #x); \ - if(!x) { \ - fprintf(stderr, "[WARNING] Will not be able to detect dark theme: dbus function %s (libdbus-1.so) not found.\n", #x); \ + if(!wl_call_tbl.x) { \ + fprintf(stderr, "[WARNING] Will not be able to detect dark theme: dbus function %s not found.\n", #x); \ + dlclose(wl_call_tbl.dbus_lib); \ return 0; \ } From 54fed150e8be93fc89df79c430e528c28907fc98 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 15 Apr 2026 16:12:38 -0700 Subject: [PATCH 165/195] dbus --- include/Mw/LowLevel.h | 37 +++++++++++ include/Mw/LowLevel/Wayland.h | 63 ++++-------------- include/Mw/LowLevel/X11.h | 6 ++ include/Mw/MachDep.h | 4 ++ pl/ostype/Linux.pl | 2 + src/backend/wayland.c | 100 +++------------------------- src/backend/x11.c | 35 ++++++++++ src/lowlevel.c | 119 ++++++++++++++++++++++++++++++++++ 8 files changed, 223 insertions(+), 143 deletions(-) diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index d5a0b1b5b..c958e00d7 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -56,6 +56,43 @@ struct _MwLLCommonPixmap { void* user; }; +#ifdef USE_DBUS +typedef struct _MwLLDBusFuncTable { + void* lib; + + void (*dbus_error_init)(DBusError* error); + DBusConnection* (*dbus_bus_get)(DBusBusType type, DBusError* error); + dbus_bool_t (*dbus_error_is_set)(const DBusError* error); + void (*dbus_error_free)(DBusError* error); + DBusMessage* (*dbus_message_new_method_call)(const char* bus_name, const char* path, const char* iface, const char* method); + void (*dbus_message_iter_init_append)(DBusMessage* message, DBusMessageIter* iter); + dbus_bool_t (*dbus_message_iter_append_basic)(DBusMessageIter* iter, int type, const void* value); + DBusMessage* (*dbus_connection_send_with_reply_and_block)(DBusConnection* connection, DBusMessage* message, int timeout_milliseconds, DBusError* error); + void (*dbus_message_unref)(DBusMessage* message); + dbus_bool_t (*dbus_message_iter_init)(DBusMessage* message, DBusMessageIter* iter); + int (*dbus_message_iter_get_arg_type)(DBusMessageIter* iter); + void (*dbus_message_iter_recurse)(DBusMessageIter* iter, DBusMessageIter* sub); + void (*dbus_connection_unref)(DBusConnection* connection); + void (*dbus_message_iter_get_basic)(DBusMessageIter* iter, void* value); +} MwLLDBusFuncTable; + +typedef struct _MwLLDBusContext { + DBusConnection* dbus_conn; + DBusError dbus_err; + DBusMessage* dbus_msg; + DBusMessage* dbus_reply; + DBusMessageIter dbus_args, dbus_variant, dbus_inner_variant; +} MwLLDBusContext; + +/* setup the dbus func table. Returns false and prints a warning if dbus couldn't be found. */ +MWDECL MwBool MwLLDBusFuncSetup(MwLLDBusFuncTable* tbl); + +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 void MwLLDBusFreeContext(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx); + +#endif + #ifdef _MILSKO #ifdef USE_X11 #include diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 6b2c08ff9..77e43b3be 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -36,7 +36,10 @@ typedef struct wayland_call_table { void* lib; void* xkb_lib; void* cairo_lib; - void* dbus_lib; +#ifdef USE_DBUS + MwLLDBusFuncTable dbus; + MwBool has_dbus; +#endif int (*wl_display_dispatch_pending)(struct wl_display* display); void (*wl_display_disconnect)(struct wl_display* display); @@ -125,21 +128,6 @@ typedef struct wayland_call_table { void (*cairo_set_antialias)(cairo_t*, cairo_antialias_t); void (*cairo_set_operator)(cairo_t* cr, cairo_operator_t op); - void (*dbus_error_init)(DBusError* error); - DBusConnection* (*dbus_bus_get)(DBusBusType type, DBusError* error); - dbus_bool_t (*dbus_error_is_set)(const DBusError* error); - void (*dbus_error_free)(DBusError* error); - DBusMessage* (*dbus_message_new_method_call)(const char* bus_name, const char* path, const char* iface, const char* method); - void (*dbus_message_iter_init_append)(DBusMessage* message, DBusMessageIter* iter); - dbus_bool_t (*dbus_message_iter_append_basic)(DBusMessageIter* iter, int type, const void* value); - DBusMessage* (*dbus_connection_send_with_reply_and_block)(DBusConnection* connection, DBusMessage* message, int timeout_milliseconds, DBusError* error); - void (*dbus_message_unref)(DBusMessage* message); - dbus_bool_t (*dbus_message_iter_init)(DBusMessage* message, DBusMessageIter* iter); - int (*dbus_message_iter_get_arg_type)(DBusMessageIter* iter); - void (*dbus_message_iter_recurse)(DBusMessageIter* iter, DBusMessageIter* sub); - void (*dbus_connection_unref)(DBusConnection* connection); - void (*dbus_message_iter_get_basic)(DBusMessageIter* iter, void* value); - } wayland_call_table_t; extern wayland_call_table_t wl_call_tbl; @@ -240,34 +228,9 @@ MwInline int wayland_load_funcs() { CAIRO_FUNC(cairo_pattern_set_filter); #undef CAIRO_FUNC - wl_call_tbl.dbus_lib = MwDynamicOpen("libdbus-1.so"); - if(!wl_call_tbl.dbus_lib) { - fprintf(stderr, "[WARNING] Will not be able to detect dark theme: dbus library (libdbus-1.so) not found.\n"); - return 0; - } - -#define DBUS_FUNC(x) \ - wl_call_tbl.x = MwDynamicSymbol(wl_call_tbl.dbus_lib, #x); \ - if(!wl_call_tbl.x) { \ - fprintf(stderr, "[WARNING] Will not be able to detect dark theme: dbus function %s not found.\n", #x); \ - dlclose(wl_call_tbl.dbus_lib); \ - return 0; \ - } - - DBUS_FUNC(dbus_error_init); - DBUS_FUNC(dbus_bus_get); - DBUS_FUNC(dbus_error_is_set); - DBUS_FUNC(dbus_error_free); - DBUS_FUNC(dbus_message_new_method_call); - DBUS_FUNC(dbus_message_iter_init_append); - DBUS_FUNC(dbus_message_iter_append_basic); - DBUS_FUNC(dbus_connection_send_with_reply_and_block); - DBUS_FUNC(dbus_message_unref); - DBUS_FUNC(dbus_message_iter_init); - DBUS_FUNC(dbus_message_iter_get_arg_type); - DBUS_FUNC(dbus_message_iter_recurse); - DBUS_FUNC(dbus_connection_unref); - DBUS_FUNC(dbus_message_iter_get_basic); +#ifdef USE_DBUS + wl_call_tbl.has_dbus = MwLLDBusFuncSetup(&wl_call_tbl.dbus); +#endif return 0; } @@ -480,13 +443,11 @@ struct _MwLLWayland { struct zwp_locked_pointer_v1* locked_pointer; MwBool pointer_constrained; - MwBool dark_theme_detection; - time_t dbus_timer; - DBusConnection* dbus_conn; - DBusError dbus_err; - DBusMessage* dbus_msg; - DBusMessage* dbus_reply; - DBusMessageIter dbus_args, dbus_variant, dbus_inner_variant; +#ifdef USE_DBUS + MwLLDBusContext dbus; +#endif + + MwBool dark_theme_detection; /* 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.*/ diff --git a/include/Mw/LowLevel/X11.h b/include/Mw/LowLevel/X11.h index 529a570c8..3d0e1252e 100644 --- a/include/Mw/LowLevel/X11.h +++ b/include/Mw/LowLevel/X11.h @@ -57,6 +57,12 @@ struct _MwLLX11 { unsigned long blue_mask; unsigned long blue_max; unsigned long blue_shift; + +#ifdef USE_DBUS + MwLLDBusContext dbus; +#endif + + MwBool dark_theme_detection; }; struct _MwLLX11Color { diff --git a/include/Mw/MachDep.h b/include/Mw/MachDep.h index 50898f676..025fc29b4 100644 --- a/include/Mw/MachDep.h +++ b/include/Mw/MachDep.h @@ -53,6 +53,10 @@ #include #endif +#ifdef USE_DBUS +#include +#endif + #ifndef M_PI #define M_PI 3.14159265 #endif diff --git a/pl/ostype/Linux.pl b/pl/ostype/Linux.pl index 73905d60b..278cbfe0c 100644 --- a/pl/ostype/Linux.pl +++ b/pl/ostype/Linux.pl @@ -7,6 +7,8 @@ if (param_get("x11")) { push(@enabled_backends, "x11"); } +add_cflags("-DUSE_DBUS"); + use_backend(@enabled_backends); 1; diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 3c8c9cd20..1fc68cb4c 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1830,102 +1830,16 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh } } -static void dbus_setup(MwLL handle) { - MwU32 value = 0; - int translated_value = 0; - - if(!wl_call_tbl.dbus_lib) { - return; - } - - time(&handle->wayland.dbus_timer); - - wl_call_tbl.dbus_error_init(&handle->wayland.dbus_err); - - handle->wayland.dbus_conn = wl_call_tbl.dbus_bus_get(0 /* DBUS_BUS_SESSION */, &handle->wayland.dbus_err); - if(wl_call_tbl.dbus_error_is_set(&handle->wayland.dbus_err)) { - fprintf(stderr, "[WARNING] Could not detect dark theme: Connection error: %s\n", handle->wayland.dbus_err.message); - wl_call_tbl.dbus_error_free(&handle->wayland.dbus_err); - return; - } - if(!handle->wayland.dbus_conn) { - fprintf(stderr, "[WARNING] Could not detect dark theme: Failed to connect to session bus\n"); - return; - } -} - -static void dbus_get(MwLL handle, const char* portal, const char* namespace, const char* key, void* out) { - if(!handle->wayland.dbus_conn) { - return; - } - - handle->wayland.dbus_msg = wl_call_tbl.dbus_message_new_method_call( - "org.freedesktop.portal.Desktop", - "/org/freedesktop/portal/desktop", - portal, - "Read"); - if(!handle->wayland.dbus_msg) { - fprintf(stderr, "[WARNING] Couldn't get %s::%s: Failed to create message\n", namespace, key); - return; - } - - wl_call_tbl.dbus_message_iter_init_append(handle->wayland.dbus_msg, &handle->wayland.dbus_args); - wl_call_tbl.dbus_message_iter_append_basic(&handle->wayland.dbus_args, 's', &namespace); - wl_call_tbl.dbus_message_iter_append_basic(&handle->wayland.dbus_args, 's', &key); - - handle->wayland.dbus_reply = wl_call_tbl.dbus_connection_send_with_reply_and_block(handle->wayland.dbus_conn, handle->wayland.dbus_msg, 100, &handle->wayland.dbus_err); - - if(wl_call_tbl.dbus_error_is_set(&handle->wayland.dbus_err)) { - fprintf(stderr, "[WARNING] Couldn't get %s::%s: Send error: %s\n", namespace, key, handle->wayland.dbus_err.message); - wl_call_tbl.dbus_error_free(&handle->wayland.dbus_err); - return; - } - if(!handle->wayland.dbus_reply) { - fprintf(stderr, "[WARNING] Couldn't get %s::%s: No reply received\n", namespace, key); - return; - } - - if(!wl_call_tbl.dbus_message_iter_init(handle->wayland.dbus_reply, &handle->wayland.dbus_args)) { - fprintf(stderr, "[WARNING] Couldn't get %s::%s: Reply has no arguments\n", namespace, key); - wl_call_tbl.dbus_message_unref(handle->wayland.dbus_reply); - return; - } - - if(wl_call_tbl.dbus_message_iter_get_arg_type(&handle->wayland.dbus_args) != 'v') { - fprintf(stderr, "[WARNING] Couldn't get %s::%s: Expected outer variant\n", namespace, key); - wl_call_tbl.dbus_message_unref(handle->wayland.dbus_reply); - return; - } - wl_call_tbl.dbus_message_iter_recurse(&handle->wayland.dbus_args, &handle->wayland.dbus_variant); - - /* Some portals wrap the value in a second variant */ - if(wl_call_tbl.dbus_message_iter_get_arg_type(&handle->wayland.dbus_variant) == 'v') { - wl_call_tbl.dbus_message_iter_recurse(&handle->wayland.dbus_variant, &handle->wayland.dbus_inner_variant); - wl_call_tbl.dbus_message_iter_get_basic(&handle->wayland.dbus_inner_variant, out); - } else { - wl_call_tbl.dbus_message_iter_get_basic(&handle->wayland.dbus_variant, out); - } - wl_call_tbl.dbus_message_unref(handle->wayland.dbus_msg); -} - static void detect_dark_theme(MwLL handle) { MwU32 value = 0; MwU32 dark_theme = 0; - dbus_get(handle, "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); dark_theme = (value == 1) ? 1 : 0; MwLLDispatch(handle, dark_theme, &dark_theme); } -static void dbus_destroy(MwLL handle) { - if(!wl_call_tbl.dbus_lib) { - return; - } - if(handle->wayland.dbus_reply) wl_call_tbl.dbus_message_unref(handle->wayland.dbus_reply); - if(handle->wayland.dbus_conn) wl_call_tbl.dbus_connection_unref(handle->wayland.dbus_conn); -} - static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { MwLL r; r = malloc(sizeof(*r)); @@ -1934,10 +1848,12 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { widget_setup(r, parent, x, y, width, height, MWLL_WAYLAND_UNKNOWN); - if(!parent) { - dbus_setup(r); +#ifdef USE_DBUS + if(!parent && wl_call_tbl.has_dbus) { + wl_call_tbl.has_dbus = MwLLDBusNewContext(&wl_call_tbl.dbus, &r->wayland.dbus); r->wayland.dark_theme_detection = MwTRUE; } +#endif return r; } @@ -1973,8 +1889,8 @@ static void MwLLDestroyImpl(MwLL handle) { pthread_mutex_unlock(&handle->wayland.eventsMutex); pthread_mutex_destroy(&handle->wayland.eventsMutex); - if(!handle->wayland.dbus_conn) { - dbus_destroy(handle); + if(!wl_call_tbl.has_dbus) { + MwLLDBusFreeContext(&wl_call_tbl.dbus, &handle->wayland.dbus); } buffer_destroy(&handle->wayland.cursor); @@ -2258,7 +2174,7 @@ static int MwLLPendingImpl(MwLL handle) { int pending = 0; if(handle->wayland.dark_theme_detection) { - if(handle->wayland.dbus_conn) { + if(wl_call_tbl.has_dbus) { detect_dark_theme(handle); handle->wayland.dark_theme_detection = MwFALSE; MwLLDispatch(handle, draw, NULL); diff --git a/src/backend/x11.c b/src/backend/x11.c index ad97d6885..d8f028b32 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -9,6 +9,9 @@ static struct { void* lib_xrender; MwBool has_xrender; + MwLLDBusFuncTable dbus; + MwBool has_dbus; + int (*XClearWindow)(Display* display, Window w); XImage* (*XCreateImage)(Display*, Visual*, unsigned int, int, int, char*, unsigned int, unsigned int, int, int); Display* (*XOpenDisplay)(_Xconst char*); @@ -308,6 +311,16 @@ static XVisualInfo* get_visual_info(Display* display) { return XGetVisualInfo(display, VisualIDMask, &xvi, &n); } +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; + + MwLLDispatch(handle, dark_theme, &dark_theme); +} + static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { MwLL r; Window p; @@ -429,6 +442,14 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { } } +#ifdef USE_DBUS + memset(&r->x11.dbus, 0, sizeof(r->x11.dbus)); + if(!parent && xsymtbl.has_dbus) { + xsymtbl.has_dbus = MwLLDBusNewContext(&xsymtbl.dbus, &r->x11.dbus); + r->x11.dark_theme_detection = MwTRUE; + } +#endif + return r; } @@ -449,6 +470,10 @@ static void MwLLDestroyImpl(MwLL handle) { if(handle->x11.toplevel) XCloseDisplay(handle->x11.display); + if(!xsymtbl.has_dbus) { + MwLLDBusFreeContext(&xsymtbl.dbus, &handle->x11.dbus); + } + free(handle); } @@ -607,6 +632,14 @@ static void MwLLFreeColorImpl(MwLLColor color) { static int MwLLPendingImpl(MwLL handle) { XEvent ev; + if(handle->x11.dark_theme_detection) { + if(xsymtbl.has_dbus) { + detect_dark_theme(handle); + handle->x11.dark_theme_detection = MwFALSE; + MwLLDispatch(handle, draw, NULL); + } + } + if(handle->x11.clipboard_pending && (MwTimeGetTick() - handle->x11.clipboard_time) >= ClipboardTimeout) { return 1; } @@ -1388,6 +1421,8 @@ static int MwLLX11CallInitImpl(void) { XRENDER_FUNC_LOAD(XRenderSetPictureTransform) XRENDER_FUNC_LOAD(XRenderComposite) #endif + + xsymtbl.has_dbus = MwLLDBusFuncSetup(&xsymtbl.dbus); return 0; } diff --git a/src/lowlevel.c b/src/lowlevel.c index 597a23a82..32188aa99 100644 --- a/src/lowlevel.c +++ b/src/lowlevel.c @@ -61,3 +61,122 @@ void MwLLCreateCommon(MwLL handle) { void MwLLDestroyCommon(MwLL handle) { free(handle->common.handler); } + +#ifdef USE_DBUS +MwBool MwLLDBusFuncSetup(MwLLDBusFuncTable* tbl) { + tbl->lib = MwDynamicOpen("libdbus-1.so"); + if(!tbl->lib) { + fprintf(stderr, "[WARNING] dbus library (libdbus-1.so) not found, will not be able to check for any XDG settings.\n"); + return MwFALSE; + } + +#define DBUS_FUNC(x) \ + tbl->x = MwDynamicSymbol(tbl->lib, #x); \ + if(!tbl->x) { \ + fprintf(stderr, "[WARNING] dbus function %s not found, will not be able to check for any XDG settings.\n", #x); \ + dlclose(tbl->lib); \ + return MwFALSE; \ + } + + DBUS_FUNC(dbus_error_init); + DBUS_FUNC(dbus_bus_get); + DBUS_FUNC(dbus_error_is_set); + DBUS_FUNC(dbus_error_free); + DBUS_FUNC(dbus_message_new_method_call); + DBUS_FUNC(dbus_message_iter_init_append); + DBUS_FUNC(dbus_message_iter_append_basic); + DBUS_FUNC(dbus_connection_send_with_reply_and_block); + DBUS_FUNC(dbus_message_unref); + DBUS_FUNC(dbus_message_iter_init); + DBUS_FUNC(dbus_message_iter_get_arg_type); + DBUS_FUNC(dbus_message_iter_recurse); + DBUS_FUNC(dbus_connection_unref); + DBUS_FUNC(dbus_message_iter_get_basic); + + return MwTRUE; +} +#endif + +MwBool MwLLDBusNewContext(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx) { + if(!tbl->lib) { + return MwFALSE; + } + + tbl->dbus_error_init(&ctx->dbus_err); + + ctx->dbus_conn = tbl->dbus_bus_get(DBUS_BUS_SESSION, &ctx->dbus_err); + if(tbl->dbus_error_is_set(&ctx->dbus_err)) { + fprintf(stderr, "[WARNING] Could not initialize dbus: Connection error: %s\n", ctx->dbus_err.message); + tbl->dbus_error_free(&ctx->dbus_err); + return MwFALSE; + } + if(!ctx->dbus_conn) { + fprintf(stderr, "[WARNING] Could not initialize dbus: Failed to connect to session bus\n"); + return MwFALSE; + } + return MwTRUE; +}; + +MWDECL MwBool MwLLDBusPortalGet(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx, const char* portal, const char* namespace, const char* key, void* out) { + if(!ctx->dbus_conn) { + return MwFALSE; + } + + ctx->dbus_msg = tbl->dbus_message_new_method_call( + "org.freedesktop.portal.Desktop", + "/org/freedesktop/portal/desktop", + portal, + "Read"); + if(!ctx->dbus_msg) { + fprintf(stderr, "[WARNING] Couldn't get %s::%s: Failed to create message\n", namespace, key); + return MwFALSE; + } + + tbl->dbus_message_iter_init_append(ctx->dbus_msg, &ctx->dbus_args); + tbl->dbus_message_iter_append_basic(&ctx->dbus_args, 's', &namespace); + tbl->dbus_message_iter_append_basic(&ctx->dbus_args, 's', &key); + + ctx->dbus_reply = tbl->dbus_connection_send_with_reply_and_block(ctx->dbus_conn, ctx->dbus_msg, 100, &ctx->dbus_err); + + if(tbl->dbus_error_is_set(&ctx->dbus_err)) { + fprintf(stderr, "[WARNING] Couldn't get %s::%s: Send error: %s\n", namespace, key, ctx->dbus_err.message); + tbl->dbus_error_free(&ctx->dbus_err); + return MwFALSE; + } + if(!ctx->dbus_reply) { + fprintf(stderr, "[WARNING] Couldn't get %s::%s: No reply received\n", namespace, key); + return MwFALSE; + } + + if(!tbl->dbus_message_iter_init(ctx->dbus_reply, &ctx->dbus_args)) { + fprintf(stderr, "[WARNING] Couldn't get %s::%s: Reply has no arguments\n", namespace, key); + tbl->dbus_message_unref(ctx->dbus_reply); + return MwFALSE; + } + + if(tbl->dbus_message_iter_get_arg_type(&ctx->dbus_args) != 'v') { + fprintf(stderr, "[WARNING] Couldn't get %s::%s: Expected outer variant\n", namespace, key); + tbl->dbus_message_unref(ctx->dbus_reply); + return MwFALSE; + } + tbl->dbus_message_iter_recurse(&ctx->dbus_args, &ctx->dbus_variant); + + /* Some portals wrap the value in a second variant */ + if(tbl->dbus_message_iter_get_arg_type(&ctx->dbus_variant) == 'v') { + tbl->dbus_message_iter_recurse(&ctx->dbus_variant, &ctx->dbus_inner_variant); + tbl->dbus_message_iter_get_basic(&ctx->dbus_inner_variant, out); + } else { + tbl->dbus_message_iter_get_basic(&ctx->dbus_variant, out); + } + tbl->dbus_message_unref(ctx->dbus_msg); + + return MwTRUE; +} + +void MwLLDBusFreeContext(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx) { + if(!tbl->lib) { + return; + } + if(ctx->dbus_reply) tbl->dbus_message_unref(ctx->dbus_reply); + if(ctx->dbus_conn) tbl->dbus_connection_unref(ctx->dbus_conn); +}; From 677d8c8046d620fbc901a4e2b15000088bc7fe2f Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 15 Apr 2026 18:26:32 -0500 Subject: [PATCH 166/195] guard dbus function impls with ifdef --- src/lowlevel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lowlevel.c b/src/lowlevel.c index 32188aa99..13a7d4999 100644 --- a/src/lowlevel.c +++ b/src/lowlevel.c @@ -97,6 +97,7 @@ MwBool MwLLDBusFuncSetup(MwLLDBusFuncTable* tbl) { } #endif +#ifdef USE_DBUS MwBool MwLLDBusNewContext(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx) { if(!tbl->lib) { return MwFALSE; @@ -180,3 +181,4 @@ void MwLLDBusFreeContext(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx) { if(ctx->dbus_reply) tbl->dbus_message_unref(ctx->dbus_reply); if(ctx->dbus_conn) tbl->dbus_connection_unref(ctx->dbus_conn); }; +#endif From 0fb9c45ea4cb39475fa7e97c8b6a4b8c26e35b5f Mon Sep 17 00:00:00 2001 From: Nishi Date: Thu, 16 Apr 2026 08:42:01 +0900 Subject: [PATCH 167/195] improve --- examples/basic/colorpicker.c | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/basic/colorpicker.c b/examples/basic/colorpicker.c index 8d0c0f369..6471b7822 100644 --- a/examples/basic/colorpicker.c +++ b/examples/basic/colorpicker.c @@ -40,6 +40,7 @@ int main() { button = MwVaCreateWidget(MwButtonClass, "button", window, 160, 180, 320, 120, MwNtext, "change window background", NULL); + MwSetText(button, MwNbackground, MwGetInteger(window, MwNdarkTheme) ? MwDefaultBackground : MwDefaultDarkBackground); MwAddUserHandler(button, MwNactivateHandler, color_picker, NULL); From a2c1489ffb0d70a13ad3c60032a08da8b6107486 Mon Sep 17 00:00:00 2001 From: Nishi Date: Thu, 16 Apr 2026 09:35:53 +0900 Subject: [PATCH 168/195] add MwLLSetDarkTheme --- include/Mw/LowLevel.h | 2 ++ src/backend/call.c | 2 ++ src/backend/cocoa.m | 5 +++++ src/backend/gdi.c | 27 +++++++++++++++++++++++++++ src/backend/wayland.c | 5 +++++ src/backend/x11.c | 7 ++++++- src/core.c | 8 ++++++++ src/lowlevel.c | 2 ++ 8 files changed, 57 insertions(+), 1 deletion(-) diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index c958e00d7..a1a469188 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -277,6 +277,8 @@ MWDECL void (*MwLLGetClipboard)(MwLL handle); MWDECL void (*MwLLGetCursorCoord)(MwLL handle, MwPoint* point); MWDECL void (*MwLLGetScreenSize)(MwLL handle, MwRect* rect); +MWDECL void (*MwLLSetDarkTheme)(MwLL handle, int toggle); + /* font renderer */ MWDECL void MwFLSetup(void); diff --git a/src/backend/call.c b/src/backend/call.c index e2ce934c9..07cf1e08f 100644 --- a/src/backend/call.c +++ b/src/backend/call.c @@ -54,6 +54,8 @@ \ MwLLGetCursorCoord = MwLLGetCursorCoordImpl; \ MwLLGetScreenSize = MwLLGetScreenSizeImpl; \ +\ + MwLLSetDarkTheme = MwLLSetDarkThemeImpl; \ \ return 0; \ } diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 4cdc5b2b6..95fd56db8 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -1082,6 +1082,11 @@ static void MwLLEndStateChangeImpl(MwLL handle) { MwLLShow(handle, 1); } +static void MwLLSetDarkThemeImpl(MwLL handle, int toggle){ + (void)handle; + (void)toggle; +} + static int MwLLCocoaCallInitImpl(void) { #ifndef __APPLE__ printf("Using GNUStep Backend\n"); diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 5d89419d0..9fe139826 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -8,6 +8,14 @@ typedef struct userdata { int max_set; } userdata_t; +static struct symtbl { + void* lib_dwmapi; + + HRESULT (WINAPI *DwmSetWindowAttribute)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute); +} wsymtbl; + +#define DwmSetWindowAttribute wsymtbl.DwmSetWindowAttribute + static void detect_darktheme(MwLL handle) { DWORD dw; DWORD sz = sizeof(dw); @@ -26,6 +34,12 @@ static void detect_darktheme(MwLL handle) { t = dw ? 0 : 1; + if(t && DwmSetWindowAttribute != NULL){ + LPARAM style = GetWindowLongPtr(handle->gdi.hWnd, GWL_STYLE); + BOOL v = TRUE; + if(!(style & WS_CHILD)) DwmSetWindowAttribute(handle->gdi.hWnd, 20, &v, sizeof(v)); + } + MwLLDispatch(handle, dark_theme, &t); } @@ -804,7 +818,20 @@ static void MwLLEndStateChangeImpl(MwLL handle) { (void)handle; } +static void MwLLSetDarkThemeImpl(MwLL handle, int toggle){ + BOOL v = toggle ? TRUE : FALSE; + + DwmSetWindowAttribute(handle->gdi.hWnd, 20, &v, sizeof(v)); + +} + static int MwLLGDICallInitImpl(void) { + memset(&wsymtbl, 0, sizeof(wsymtbl)); + + wsymtbl.lib_dwmapi = MwDynamicOpen("dwmapi.dll"); + + if(wsymtbl.lib_dwmapi != NULL) DwmSetWindowAttribute = MwDynamicSymbol(wsymtbl.lib_dwmapi, "DwmSetWindowAttribute"); + /* TODO: check properly */ return 0; } diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 1fc68cb4c..bd4686081 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -2620,6 +2620,11 @@ static void MwLLEndStateChangeImpl(MwLL handle) { } } +static void MwLLSetDarkThemeImpl(MwLL handle, int toggle){ + (void)handle; + (void)toggle; +} + static int MwLLWaylandCallInitImpl(void) { #ifdef __linux__ MwBool loadWayland = MwFALSE; diff --git a/src/backend/x11.c b/src/backend/x11.c index d8f028b32..dcc41d7ad 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -4,7 +4,7 @@ #define ClipboardTimeout 100 -static struct { +static struct symtbl { void* lib_xlib; void* lib_xrender; MwBool has_xrender; @@ -1308,6 +1308,11 @@ static void MwLLEndStateChangeImpl(MwLL handle) { MwLLShow(handle, 1); } +static void MwLLSetDarkThemeImpl(MwLL handle, int toggle){ + (void)handle; + (void)toggle; +} + static int MwLLX11CallInitImpl(void) { MwBool loadX11 = MwFALSE; if(getenv("MILSKO_BACKEND")) { diff --git a/src/core.c b/src/core.c index cf45dddc2..1b00615c2 100644 --- a/src/core.c +++ b/src/core.c @@ -532,6 +532,14 @@ void MwSetInteger(MwWidget handle, const char* key, int n) { if(strcmp(key, MwNmodernLook) == 0 || strcmp(key, MwNdarkTheme) == 0 || strcmp(key, MwNbitmapFont) == 0) { force_render_all(handle); } + + if(strcmp(key, MwNdarkTheme) == 0){ + MwWidget h = handle; + + while(h->parent != NULL && h->parent->widget_class != NULL) h = h->parent; + + MwLLSetDarkTheme(h->lowlevel, n); + } } void MwSetText(MwWidget handle, const char* key, const char* value) { diff --git a/src/lowlevel.c b/src/lowlevel.c index 13a7d4999..e80b95b9c 100644 --- a/src/lowlevel.c +++ b/src/lowlevel.c @@ -51,6 +51,8 @@ void (*MwLLGetClipboard)(MwLL handle) = NULL; void (*MwLLGetCursorCoord)(MwLL handle, MwPoint* point) = NULL; void (*MwLLGetScreenSize)(MwLL handle, MwRect* rect) = NULL; +void (*MwLLSetDarkTheme)(MwLL handle, int toggle) = NULL; + void MwLLCreateCommon(MwLL handle) { handle->common.handler = malloc(sizeof(*handle->common.handler)); memset(handle->common.handler, 0, sizeof(*handle->common.handler)); From 48b847093beb5cd383ecff86aadaa0a96e20da29 Mon Sep 17 00:00:00 2001 From: Nishi Date: Thu, 16 Apr 2026 09:50:08 +0900 Subject: [PATCH 169/195] oops --- src/backend/gdi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 9fe139826..385c477fc 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -279,7 +279,7 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r->common.copy_buffer = 1; r->common.type = MwLLBackendGDI; - r->gdi.get_clipboard = 1; + r->gdi.get_clipboard = 0; if(parent == NULL) r->gdi.get_darktheme = 1; r->gdi.force_render = 0; r->gdi.grabbed = 0; From 6f9b3c12a7a11d6c7a6c1aff20dd346770e38b7c Mon Sep 17 00:00:00 2001 From: Nishi Date: Thu, 16 Apr 2026 09:55:18 +0900 Subject: [PATCH 170/195] fix --- src/backend/gdi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 385c477fc..51e33df1d 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -36,8 +36,7 @@ static void detect_darktheme(MwLL handle) { if(t && DwmSetWindowAttribute != NULL){ LPARAM style = GetWindowLongPtr(handle->gdi.hWnd, GWL_STYLE); - BOOL v = TRUE; - if(!(style & WS_CHILD)) DwmSetWindowAttribute(handle->gdi.hWnd, 20, &v, sizeof(v)); + if(!(style & WS_CHILD)) MwLLSetDarkTheme(handle, 1); } MwLLDispatch(handle, dark_theme, &t); From 4e4da8659e1d2bcfdb4a564956fa1581cf400fd6 Mon Sep 17 00:00:00 2001 From: Nishi Date: Thu, 16 Apr 2026 10:45:53 +0900 Subject: [PATCH 171/195] fix gdi opengl --- src/widget/opengl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widget/opengl.c b/src/widget/opengl.c index d75b358f7..50fb7479f 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -381,7 +381,7 @@ static void mwOpenGLMakeCurrentImpl(MwWidget handle) { #ifdef USE_GDI if(handle->lowlevel->common.type == MwLLBackendGDI) { gdiopengl_t* o = handle->internal; - void (*swap_interval_ext)(int) = NULL; + int (__stdcall *swap_interval_ext)(int) = NULL; o->wglMakeCurrent(o->dc, o->gl); From 712a640f9df1b19f33bde1a608954acdd6aaceff Mon Sep 17 00:00:00 2001 From: Nishi Date: Thu, 16 Apr 2026 10:47:24 +0900 Subject: [PATCH 172/195] probably it is better to do this way --- src/widget/opengl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widget/opengl.c b/src/widget/opengl.c index 50fb7479f..6ffef725b 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -381,7 +381,7 @@ static void mwOpenGLMakeCurrentImpl(MwWidget handle) { #ifdef USE_GDI if(handle->lowlevel->common.type == MwLLBackendGDI) { gdiopengl_t* o = handle->internal; - int (__stdcall *swap_interval_ext)(int) = NULL; + BOOL (APIENTRY *swap_interval_ext)(int) = NULL; o->wglMakeCurrent(o->dc, o->gl); From 5315f4ec4df13f09b73fcd49ff3244385b211ee7 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 15 Apr 2026 20:21:20 -0700 Subject: [PATCH 173/195] classic mac os --- .gitignore | 6 ++ configure | 63 +++++++---- include/Mw/LowLevel/ClassicMacOS.h | 27 +++++ include/Mw/MachDep.h | 17 ++- pl/ostype/ClassicMacOS68k.pl | 7 ++ pl/ostype/ClassicMacOSPPC.pl | 7 ++ pl/rules.pl | 7 ++ src/abstract/directory.c | 12 +++ src/abstract/dynamic.c | 30 ++++++ src/abstract/time.c | 21 ++++ src/backend/classicmacos.c | 167 +++++++++++++++++++++++++++++ src/dialog/filechooser.c | 4 +- src/widget/box.c | 2 +- src/widget/button.c | 2 +- src/widget/checkbox.c | 2 +- src/widget/combobox.c | 2 +- src/widget/entry.c | 2 +- src/widget/frame.c | 2 +- src/widget/image.c | 2 +- src/widget/label.c | 2 +- src/widget/listbox.c | 2 +- src/widget/menu.c | 2 +- src/widget/numberentry.c | 2 +- src/widget/opengl.c | 2 +- src/widget/opengl_cocoa.m | 4 +- src/widget/progressbar.c | 2 +- src/widget/radiobox.c | 2 +- src/widget/scrollbar.c | 8 +- src/widget/separator.c | 2 +- src/widget/submenu.c | 2 +- src/widget/treeview.c | 2 +- src/widget/viewport.c | 2 +- src/widget/vulkan.c | 2 +- src/widget/window.c | 2 +- 34 files changed, 369 insertions(+), 51 deletions(-) create mode 100644 include/Mw/LowLevel/ClassicMacOS.h create mode 100644 pl/ostype/ClassicMacOS68k.pl create mode 100644 pl/ostype/ClassicMacOSPPC.pl create mode 100644 src/backend/classicmacos.c diff --git a/.gitignore b/.gitignore index 881607097..21058b8b1 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,9 @@ examples/*/*.exe compile_flags.txt .cache .DS_Store + +*.pef +*.dsk +*.bin +*.rsrc +*.finf diff --git a/configure b/configure index 5d9810863..5751b3d18 100755 --- a/configure +++ b/configure @@ -46,14 +46,6 @@ param_set("shared", 1); param_set("static", 1); param_set("examples", 1); - -if($target ne "Darwin") { - param_set("freetype2", 1); - param_set("stb-truetype", 0); -} else { - param_set("stb-truetype", 1); -} - my %features = ( "classic-theme" => "use classic theme", "stb-image" => "use stb_image, instead use libjpeg/libpng", @@ -77,13 +69,6 @@ my @features_keys = ( "1wayland", "1gnustep", ); -if($target eq "Linux") { - param_set("x11", 1); - if(!param_get("tiny")){ - param_set("wayland", 1); - } -} - foreach my $l (@ARGV) { if ($l =~ /^--with-([^=]+)=(.+)$/) { param_set($1, $2); @@ -146,6 +131,25 @@ foreach my $l (@ARGV) { } } +if($target ne "Darwin" and $target ne "ClassicMacOS68k" and $target ne "ClassicMacOSPPC") { + param_set("freetype2", 1); + param_set("stb-truetype", 0); +} else { + if($target ne "ClassicMacOS68k" and $target ne "ClassicMacOSPPC"){ + param_set("freetype2", 0); + param_set("stb-truetype", 1); + } else { + param_set("stb-truetype", 0); + } +} + +if($target eq "Linux") { + param_set("x11", 1); + if(!param_get("tiny")){ + param_set("wayland", 1); + } +} + if (-f "./pl/ostype/${target}.pl") { require("./pl/ostype/${target}.pl"); } @@ -256,7 +260,7 @@ foreach my $l (@library_targets) { } print(OUT "${l}: ${s}\n"); - print(OUT " \$(CC) $warn \$\(INCDIR) \$(CFLAGS\) -c -o ${l} ${s}\n"); + print(OUT " \$(CC) $warn \$\(INCDIR\) \$(CFLAGS\) -c -o ${l} ${s}\n"); } print(OUT "\n"); print(OUT "\n"); @@ -274,12 +278,18 @@ if (param_get("examples")) { $libs = $examples_libs{$l}; } - print(OUT -"${l}: ${s}${object_suffix} src/${library_prefix}Mw${library_suffix}\n" - ); + 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" + ); + } if (grep(/^cocoa$/, @backends)) { print(OUT -" \$(CC) -L./src \$\(LIBDIR) -o ${l} ${s}${object_suffix} -lMw ${math} ${libs}\n" +" \$(CC) -L./src -I\$\(INCDIR\) \$\(LIBDIR) -o ${l} ${s}${object_suffix} -lMw ${math} ${libs}\n" ); } else { @@ -287,10 +297,23 @@ if (param_get("examples")) { " \$(CC) -L src -Wl,-R./src \$\(LIBDIR) -o ${l} ${s}${object_suffix} -lMw ${math} ${libs}\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" + ); + print(OUT "${s}${object_suffix}: ${s}.c\n"); print(OUT " \$(CC) -c \$\(INCDIR) -o ${s}${object_suffix} ${s}.c -lMw ${math}\n" ); + + + #print(OUT "Rez -I /path/to/Universal/RIncludes /path/to/libretro/RIncludes/Retro68APPL.r -DCFRAG_NAME="\"MyProgram\"" --data program.pef -o program.bin -t APPL"); + } + } } print(OUT "\n"); diff --git a/include/Mw/LowLevel/ClassicMacOS.h b/include/Mw/LowLevel/ClassicMacOS.h new file mode 100644 index 000000000..01654387f --- /dev/null +++ b/include/Mw/LowLevel/ClassicMacOS.h @@ -0,0 +1,27 @@ +/*! + * @file Mw/LowLevel/ClassicMacOS.h + * @brief ClassicMacOS Backend + * @warning This is used internally + */ +#ifndef __MW_LOWLEVEL_ClassicMacOS_H__ +#define __MW_LOWLEVEL_ClassicMacOS_H__ + +#include +#include +#include + +struct _MwLLClassicMacOS { + struct _MwLLCommon common; +}; + +struct _MwLLClassicMacOSColor { + struct _MwLLCommonColor common; +}; + +struct _MwLLClassicMacOSPixmap { + struct _MwLLCommonPixmap common; +}; + +MWDECL int MwLLClassicMacOSCallInit(void); + +#endif diff --git a/include/Mw/MachDep.h b/include/Mw/MachDep.h index 025fc29b4..10a1a04b6 100644 --- a/include/Mw/MachDep.h +++ b/include/Mw/MachDep.h @@ -37,17 +37,28 @@ #define GET_WHEEL_DELTA_WPARAM(x) ((short)HIWORD(x)) #endif #endif - +#elif defined(CLASSIC_MAC_OS) +#include +#include +#include +#include +#include +#include +#include +#include #else #include #include -#include #include -#include #include #include #endif +#ifdef __unix__ +#include +#include +#endif + #ifdef __APPLE__ #include #include diff --git a/pl/ostype/ClassicMacOS68k.pl b/pl/ostype/ClassicMacOS68k.pl new file mode 100644 index 000000000..c9ceba8c6 --- /dev/null +++ b/pl/ostype/ClassicMacOS68k.pl @@ -0,0 +1,7 @@ +use_backend("classicmacos"); + +$cc = $ENV{RETRO68_TOOLCHAIN_PATH}."/bin/m68k-apple-macos-gcc"; +$ar = $ENV{RETRO68_TOOLCHAIN_PATH}."/bin/m68k-apple-macos-ar"; +add_cflags("-DCLASSIC_MAC_OS"); + +1; diff --git a/pl/ostype/ClassicMacOSPPC.pl b/pl/ostype/ClassicMacOSPPC.pl new file mode 100644 index 000000000..b2626d968 --- /dev/null +++ b/pl/ostype/ClassicMacOSPPC.pl @@ -0,0 +1,7 @@ +use_backend("classicmacos"); + +$cc = $ENV{RETRO68_TOOLCHAIN_PATH}."/bin/powerpc-apple-macos-gcc"; +$ar = $ENV{RETRO68_TOOLCHAIN_PATH}."/bin/powerpc-apple-macos-ar"; +add_cflags("-DCLASSIC_MAC_OS"); + +1; diff --git a/pl/rules.pl b/pl/rules.pl index 2b222249b..4d68cb94d 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -30,6 +30,13 @@ if (grep(/^gdi$/, @backends)) { $gl_libs = "-lopengl32 -lglu32"; } +if (grep(/^classicmacos$/, @backends)) { + #add_cflags("-DCLASSIC_MAC_OS"); + new_object("src/backend/classicmacos.c"); + + $gl_libs = ""; +} + if (grep(/^wayland$/, @backends)) { add_cflags("-DUSE_WAYLAND"); new_object("src/backend/wayland.c"); diff --git a/src/abstract/directory.c b/src/abstract/directory.c index aa516cf44..ac5a382d1 100644 --- a/src/abstract/directory.c +++ b/src/abstract/directory.c @@ -6,6 +6,10 @@ typedef struct dir { WIN32_FIND_DATA ffd; int next; } dir_t; +#elif defined(CLASSIC_MAC_OS) +typedef struct dir { + int dummy; +} dir_t; #else typedef struct dir { DIR* dir; @@ -31,6 +35,8 @@ void* MwDirectoryOpen(const char* path) { } free(p); dir->next = 1; +#elif defined(CLASSIC_MAC_OS) +/* todo */ #else if((dir->dir = opendir(path)) == NULL) { free(dir); @@ -47,6 +53,8 @@ void MwDirectoryClose(void* handle) { dir_t* dir = handle; #ifdef _WIN32 FindClose(dir->hFind); +#elif defined(CLASSIC_MAC_OS) +/* todo */ #else closedir(dir->dir); free(dir->base); @@ -80,6 +88,8 @@ MwDirectoryEntry* MwDirectoryRead(void* handle) { entry->mtime = l->QuadPart / 10000000 - 11644473600; dir->next = FindNextFile(dir->hFind, &dir->ffd); +#elif defined(CLASSIC_MAC_OS) +/* todo */ #else struct dirent* d; struct stat s; @@ -123,6 +133,8 @@ char* MwDirectoryCurrent(void) { GetCurrentDirectory(len, out); return out; +#elif CLASSIC_MAC_OS + return ""; #else return getcwd(NULL, 0); #endif diff --git a/src/abstract/dynamic.c b/src/abstract/dynamic.c index 79cad83fc..d9558af6d 100644 --- a/src/abstract/dynamic.c +++ b/src/abstract/dynamic.c @@ -12,6 +12,36 @@ void* MwDynamicSymbol(void* handle, const char* symbol) { void MwDynamicClose(void* handle) { FreeLibrary(handle); } +#elif defined(CLASSIC_MAC_OS) +void* MwDynamicOpen(const char* path) { + CFragConnectionID connID; + Ptr* addr; + unsigned char err[255]; + + if(GetSharedLibrary((ConstStr63Param)path, kPowerPCCFragArch, kPrivateCFragCopy, + &connID, addr, err)) { + printf("Error getting %s: %s\n", path, err); + return NULL; + }; + return connID; +} + +void* MwDynamicSymbol(void* handle, const char* symbol) { + CFragConnectionID connID = (CFragConnectionID)handle; + Ptr* symAddr; + CFragSymbolClass* symClass; + OSErr err; + if((err = FindSymbol(connID, (ConstStr63Param)symbol, symAddr, symClass))) { + printf("Error getting %s: %d\n", symbol, err); + return NULL; + }; + return symAddr; +} + +void MwDynamicClose(void* handle) { + CFragConnectionID connID = (CFragConnectionID)handle; + CloseConnection(&connID); +} #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 1050c46d3..52d998689 100644 --- a/src/abstract/time.c +++ b/src/abstract/time.c @@ -32,6 +32,27 @@ void MwTimeSleep(int ms) { nanosleep(&ts, NULL); } +#elif defined(CLASSIC_MAC_OS) +static TMTask tm; +static int timer; +void timerUpdateFunc(void) { + timer += 1; + PrimeTime((QElemPtr)&tm, 1); +}; + +long MwTimeGetTick(void) { + UnsignedWide h; + Microseconds(&h); + return *(long*)&h; +} +void MwTimeSleep(int ms) { + tm.tmAddr = NewTimerProc(timerUpdateFunc); + tm.tmWakeUp = 0; + tm.tmReserved = 0; + + InsTime((QElemPtr)&tm); + PrimeTime((QElemPtr)&tm, 1); +} #elif defined(__unix__) long MwTimeGetTick(void) { struct timespec ts; diff --git a/src/backend/classicmacos.c b/src/backend/classicmacos.c new file mode 100644 index 000000000..01a9d9735 --- /dev/null +++ b/src/backend/classicmacos.c @@ -0,0 +1,167 @@ +#include + +#include "../../external/stb_ds.h" + +static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { + MwLL 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) { + int i; +} + +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); + return c; +} + +static void MwLLColorUpdateImpl(MwLL handle, MwLLColor c, int r, int g, int b) { + 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) { +} + +static void MwLLSetWHImpl(MwLL handle, int w, int h) { +} + +static void MwLLFreeColorImpl(MwLLColor color) { + free(color); +} + +static int MwLLPendingImpl(MwLL handle) { + + return 0; +} + +static void MwLLNextEventImpl(MwLL handle) { +} + +static void MwLLSetTitleImpl(MwLL handle, const char* title) { +} + +static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, int width, int height) { + MwLLPixmap r = malloc(sizeof(*r)); + + r->common.raw = malloc(4 * width * height); + memcpy(r->common.raw, data, 4 * width * height); + + MwLLPixmapUpdate(r); + return r; +} + +static void MwLLPixmapUpdateImpl(MwLLPixmap r) { +} + +static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { +} + +static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { +} + +static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { +} + +static void MwLLForceRenderImpl(MwLL handle) { +} + +static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { +} + +static void MwLLDetachImpl(MwLL handle, MwPoint* point) { +} + +static void MwLLShowImpl(MwLL handle, int show) { +} + +static void MwLLMakePopupImpl(MwLL handle, MwLL parent) { +} + +static void MwLLSetSizeHintsImpl(MwLL handle, int minx, int miny, int maxx, int maxy) { +} + +static void MwLLMakeBorderlessImpl(MwLL handle, int toggle) { +} + +static void MwLLFocusImpl(MwLL handle) { +} + +static void MwLLGrabPointerImpl(MwLL handle, int toggle) { +} + +static void MwLLSetClipboardImpl(MwLL handle, const char* text) { + /* TODO */ + + (void)handle; + (void)text; +} + +static void MwLLGetClipboardImpl(MwLL handle) { +} + +static void MwLLMakeToolWindowImpl(MwLL handle) { +} + +static void MwLLGetCursorCoordImpl(MwLL handle, MwPoint* point) { +} + +static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) { +} + +static void MwLLBeginStateChangeImpl(MwLL handle) { + MwLLShow(handle, 0); +} + +static void MwLLEndStateChangeImpl(MwLL handle) { + MwLLShow(handle, 1); +} + +static void MwLLSetDarkThemeImpl(MwLL handle, int toggle) { + (void)handle; + (void)toggle; +} + +static int MwLLClassicMacOSCallInitImpl(void) { + InitGraf(&qd.thePort); + InitFonts(); + FlushEvents(everyEvent, 0); + InitWindows(); + InitMenus(); + TEInit(); + InitDialogs(0L); + InitCursor(); + + return 0; +} + +#include "call.c" +CALL(ClassicMacOS); diff --git a/src/dialog/filechooser.c b/src/dialog/filechooser.c index cd23faaa4..d5faa4bad 100644 --- a/src/dialog/filechooser.c +++ b/src/dialog/filechooser.c @@ -53,7 +53,7 @@ static void destroy(MwWidget handle) { MwDestroyWidget(handle); } -static void cancel(MwWidget handle, void* user, void* call) { +static void filecancel(MwWidget handle, void* user, void* call) { (void)user; (void)call; @@ -147,7 +147,7 @@ static void nav_activate(MwWidget handle, void* user, void* call) { (void)user; if(strcmp(e, "Home") == 0) { -#ifdef _WIN32 +#if defined(_WIN32) || defined(CLASSIC_MAC_OS) #else struct passwd* p = getpwuid(getuid()); diff --git a/src/widget/box.c b/src/widget/box.c index a87000f0e..e96c00874 100644 --- a/src/widget/box.c +++ b/src/widget/box.c @@ -2,7 +2,7 @@ #include "../../external/stb_ds.h" -static int create(MwWidget handle) { +static int wcreate(MwWidget handle) { MwBox b = malloc(sizeof(*b)); memset(b, 0, sizeof(*b)); diff --git a/src/widget/button.c b/src/widget/button.c index c5f3a4b9f..6653b54ed 100644 --- a/src/widget/button.c +++ b/src/widget/button.c @@ -2,7 +2,7 @@ #include "../../external/stb_ds.h" -static int create(MwWidget handle) { +static int wcreate(MwWidget handle) { MwSetDefault(handle); MwSetInteger(handle, MwNflat, 0); diff --git a/src/widget/checkbox.c b/src/widget/checkbox.c index 1ccccd416..56b8f11ae 100644 --- a/src/widget/checkbox.c +++ b/src/widget/checkbox.c @@ -1,6 +1,6 @@ #include -static int create(MwWidget handle) { +static int wcreate(MwWidget handle) { MwSetDefault(handle); MwSetInteger(handle, MwNchecked, 0); diff --git a/src/widget/combobox.c b/src/widget/combobox.c index 22a90060f..988bb24aa 100644 --- a/src/widget/combobox.c +++ b/src/widget/combobox.c @@ -2,7 +2,7 @@ #include "../../external/stb_ds.h" -static int create(MwWidget handle) { +static int wcreate(MwWidget handle) { MwComboBox cb = malloc(sizeof(*cb)); cb->list = NULL; diff --git a/src/widget/entry.c b/src/widget/entry.c index bd7dbe1b5..eca5e5ce4 100644 --- a/src/widget/entry.c +++ b/src/widget/entry.c @@ -1,6 +1,6 @@ #include -static int create(MwWidget handle) { +static int wcreate(MwWidget handle) { MwEntry t = malloc(sizeof(*t)); t->cursor = 0; diff --git a/src/widget/frame.c b/src/widget/frame.c index 117b0f8b9..6f9d88129 100644 --- a/src/widget/frame.c +++ b/src/widget/frame.c @@ -1,6 +1,6 @@ #include -static int create(MwWidget handle) { +static int wcreate(MwWidget handle) { MwSetDefault(handle); MwSetInteger(handle, MwNhasBorder, 0); diff --git a/src/widget/image.c b/src/widget/image.c index 74ee0bfd6..90f3cbe7a 100644 --- a/src/widget/image.c +++ b/src/widget/image.c @@ -1,6 +1,6 @@ #include -static int create(MwWidget handle) { +static int wcreate(MwWidget handle) { MwSetDefault(handle); MwSetInteger(handle, MwNhasBorder, 0); diff --git a/src/widget/label.c b/src/widget/label.c index d29977caf..3c88eb921 100644 --- a/src/widget/label.c +++ b/src/widget/label.c @@ -4,7 +4,7 @@ #define Spacing 1 -static int create(MwWidget handle) { +static int wcreate(MwWidget handle) { MwLabel lab = malloc(sizeof(*lab)); lab->segment = NULL; diff --git a/src/widget/listbox.c b/src/widget/listbox.c index 9960e1d67..7f4ef0b7d 100644 --- a/src/widget/listbox.c +++ b/src/widget/listbox.c @@ -347,7 +347,7 @@ static void resize(MwWidget handle) { NULL); } -static int create(MwWidget handle) { +static int wcreate(MwWidget handle) { MwListBox lb = malloc(sizeof(*lb)); memset(lb, 0, sizeof(*lb)); diff --git a/src/widget/menu.c b/src/widget/menu.c index 0808f691d..b36527885 100644 --- a/src/widget/menu.c +++ b/src/widget/menu.c @@ -18,7 +18,7 @@ static void set_xywh(MwWidget handle) { NULL); } -static int create(MwWidget handle) { +static int wcreate(MwWidget handle) { MwMenu m = malloc(sizeof(*m)); m->name = NULL; diff --git a/src/widget/numberentry.c b/src/widget/numberentry.c index 7c317d36b..96860f84e 100644 --- a/src/widget/numberentry.c +++ b/src/widget/numberentry.c @@ -1,6 +1,6 @@ #include -static int create(MwWidget handle) { +static int wcreate(MwWidget handle) { int st; MwEntry e; diff --git a/src/widget/opengl.c b/src/widget/opengl.c index d75b358f7..582db0cbd 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -101,7 +101,7 @@ typedef struct waylandopengl { } waylandopengl_t; #endif -static int create(MwWidget handle) { +static int wcreate(MwWidget handle) { void* r = NULL; MwWidget w = handle; diff --git a/src/widget/opengl_cocoa.m b/src/widget/opengl_cocoa.m index 2397a8473..27c21588a 100644 --- a/src/widget/opengl_cocoa.m +++ b/src/widget/opengl_cocoa.m @@ -20,7 +20,7 @@ @end -static int create(MwWidget handle) { +static int wcreate(MwWidget handle) { void* r = NULL; MwWidget w = handle; @@ -128,4 +128,4 @@ MwClassRec MwOpenGLClassRec = {create, /* create */ NULL, /* children_prop_change */ NULL, /* clipboard */ NULL, NULL, NULL, NULL}; -MwClass MwOpenGLClass = &MwOpenGLClassRec; \ No newline at end of file +MwClass MwOpenGLClass = &MwOpenGLClassRec; diff --git a/src/widget/progressbar.c b/src/widget/progressbar.c index d85a8ddaf..2a032b09d 100644 --- a/src/widget/progressbar.c +++ b/src/widget/progressbar.c @@ -1,6 +1,6 @@ #include -static int create(MwWidget handle) { +static int wcreate(MwWidget handle) { MwSetDefault(handle); MwVaApply(handle, MwNminValue, 0, diff --git a/src/widget/radiobox.c b/src/widget/radiobox.c index 3229faad3..2416b71d9 100644 --- a/src/widget/radiobox.c +++ b/src/widget/radiobox.c @@ -2,7 +2,7 @@ #include "../../external/stb_ds.h" -static int create(MwWidget handle) { +static int wcreate(MwWidget handle) { MwSetDefault(handle); MwSetInteger(handle, MwNchecked, 0); diff --git a/src/widget/scrollbar.c b/src/widget/scrollbar.c index bb75939c1..e11ba6ac4 100644 --- a/src/widget/scrollbar.c +++ b/src/widget/scrollbar.c @@ -1,6 +1,6 @@ #include -static int create(MwWidget handle) { +static int wcreate(MwWidget handle) { MwScrollBar scr = malloc(sizeof(*scr)); handle->internal = scr; @@ -58,9 +58,9 @@ static void draw(MwWidget handle) { MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); MwLLColor dark = MwLightenColor(handle, base, -64, -64, -64); MwScrollBar scr = handle->internal; - int or ; - int uy, dy, ux, dx; - MwLLPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); + int or; + int uy, dy, ux, dx; + MwLLPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); r.x = 0; r.y = 0; diff --git a/src/widget/separator.c b/src/widget/separator.c index 8fcfc5b71..d7d6aae20 100644 --- a/src/widget/separator.c +++ b/src/widget/separator.c @@ -1,6 +1,6 @@ #include -static int create(MwWidget handle) { +static int wcreate(MwWidget handle) { MwSetDefault(handle); MwSetInteger(handle, MwNorientation, MwHORIZONTAL); diff --git a/src/widget/submenu.c b/src/widget/submenu.c index 4990fd211..a71d65b08 100644 --- a/src/widget/submenu.c +++ b/src/widget/submenu.c @@ -2,7 +2,7 @@ #include "../../external/stb_ds.h" -static int create(MwWidget handle) { +static int wcreate(MwWidget handle) { MwLLBeginStateChange(handle->lowlevel); MwSetDefault(handle); diff --git a/src/widget/treeview.c b/src/widget/treeview.c index acc35bf69..bd3067c4c 100644 --- a/src/widget/treeview.c +++ b/src/widget/treeview.c @@ -297,7 +297,7 @@ static void resize(MwWidget handle) { NULL); } -static int create(MwWidget handle) { +static int wcreate(MwWidget handle) { MwTreeView tv = malloc(sizeof(*tv)); memset(tv, 0, sizeof(*tv)); diff --git a/src/widget/viewport.c b/src/widget/viewport.c index de71af790..38ef89948 100644 --- a/src/widget/viewport.c +++ b/src/widget/viewport.c @@ -74,7 +74,7 @@ static void resize(MwWidget handle) { NULL); } -static int create(MwWidget handle) { +static int wcreate(MwWidget handle) { MwViewport vp = malloc(sizeof(*vp)); memset(vp, 0, sizeof(*vp)); diff --git a/src/widget/vulkan.c b/src/widget/vulkan.c index 8d4aa3daa..ab73fcafc 100644 --- a/src/widget/vulkan.c +++ b/src/widget/vulkan.c @@ -116,7 +116,7 @@ static int vulkan_instance_setup(MwWidget handle, vulkan_t* o); static int vulkan_surface_setup(MwWidget handle, vulkan_t* o); static int vulkan_devices_setup(MwWidget handle, vulkan_t* o); -static int create(MwWidget handle) { +static int wcreate(MwWidget handle) { vulkan_t* o = malloc(sizeof(*o)); int err; diff --git a/src/widget/window.c b/src/widget/window.c index 979e073c8..b4aaa8d22 100644 --- a/src/widget/window.c +++ b/src/widget/window.c @@ -1,6 +1,6 @@ #include -static int create(MwWidget handle) { +static int wcreate(MwWidget handle) { MwSetDefault(handle); MwSetInteger(handle, MwNhasBorder, 0); From 47fe57b31ccb2629c28e7b04ac673cef17520435 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 15 Apr 2026 20:25:08 -0700 Subject: [PATCH 174/195] ok --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 5751b3d18..1f3ee9e53 100755 --- a/configure +++ b/configure @@ -260,7 +260,7 @@ foreach my $l (@library_targets) { } print(OUT "${l}: ${s}\n"); - print(OUT " \$(CC) $warn \$\(INCDIR\) \$(CFLAGS\) -c -o ${l} ${s}\n"); + print(OUT " \$(CC) $warn \$\(INCDIR) \$(CFLAGS\) -c -o ${l} ${s}\n"); } print(OUT "\n"); print(OUT "\n"); @@ -289,7 +289,7 @@ if (param_get("examples")) { } if (grep(/^cocoa$/, @backends)) { print(OUT -" \$(CC) -L./src -I\$\(INCDIR\) \$\(LIBDIR) -o ${l} ${s}${object_suffix} -lMw ${math} ${libs}\n" +" \$(CC) -L./src -I\$\(INCDIR) \$\(LIBDIR) -o ${l} ${s}${object_suffix} -lMw ${math} ${libs}\n" ); } else { From f8a94b73805c6a93aab7d1f8e9a6ad2f47de805b Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 15 Apr 2026 21:41:16 -0700 Subject: [PATCH 175/195] cmake --- .gitignore | 1 + CMakeLists.txt | 252 ++++++++++++++++------------- configure | 19 +-- examples/basic/CMakeLists.txt | 38 +++-- include/Mw/LowLevel.h | 6 + include/Mw/LowLevel/ClassicMacOS.h | 4 + pl/ostype/ClassicMacOS.pl | 10 ++ pl/ostype/ClassicMacOS68k.pl | 7 - pl/ostype/ClassicMacOSPPC.pl | 7 - src/backend/classicmacos.c | 12 +- src/dialog/filechooser.c | 2 +- src/widget/box.c | 2 +- src/widget/button.c | 2 +- src/widget/checkbox.c | 2 +- src/widget/combobox.c | 2 +- src/widget/entry.c | 2 +- src/widget/frame.c | 2 +- src/widget/image.c | 2 +- src/widget/label.c | 2 +- src/widget/listbox.c | 2 +- src/widget/menu.c | 2 +- src/widget/numberentry.c | 2 +- src/widget/progressbar.c | 2 +- src/widget/radiobox.c | 2 +- src/widget/scrollbar.c | 2 +- src/widget/separator.c | 2 +- src/widget/submenu.c | 2 +- src/widget/treeview.c | 2 +- src/widget/viewport.c | 2 +- src/widget/vulkan.c | 2 +- src/widget/window.c | 2 +- 31 files changed, 219 insertions(+), 179 deletions(-) create mode 100644 pl/ostype/ClassicMacOS.pl delete mode 100644 pl/ostype/ClassicMacOS68k.pl delete mode 100644 pl/ostype/ClassicMacOSPPC.pl diff --git a/.gitignore b/.gitignore index 21058b8b1..8535b6514 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ compile_flags.txt *.bin *.rsrc *.finf +*.gdb diff --git a/CMakeLists.txt b/CMakeLists.txt index 0cc795308..835ecdd26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,24 +9,34 @@ include(GNUInstallDirs) set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_FULL_LIBDIR}") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) -option(MW_TRY_OPENGL "Try to compile OpenGL widget or not" ON) -option(MW_TRY_VULKAN "Try to compile Vulkan widget or not" ON) + option(MW_CLASSIC_THEME "Use classic theme" OFF) option(MW_BUILD_EXAMPLES "Build examples" OFF) option(MW_USE_STB_IMAGE "Use stb_image" ON) option(MW_USE_STB_TRUETYPE "Use stb_truetype" OFF) -option(MW_BUILD_SHARED "Build a shared library" ON) -option(MW_BUILD_STATIC "Build a static library" OFF) + +if(${CMAKE_SYSTEM_NAME} MATCHES Retro) + option(MW_BUILD_SHARED "Build a shared library" OFF) + option(MW_BUILD_STATIC "Build a static library" ON) + option(MW_TRY_OPENGL "Try to compile OpenGL widget or not" OFF) + option(MW_TRY_VULKAN "Try to compile Vulkan widget or not" OFF) +else() + option(MW_BUILD_SHARED "Build a shared library" ON) + option(MW_BUILD_STATIC "Build a static library" OFF) + 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() + option(MW_INSTALL_HEADERS "Install headers" ON) -if(${CMAKE_SYSTEM_NAME} STREQUAL Darwin) - option(MW_USE_FREETYPE2 "Use FreeType 2" OFF) +if(${CMAKE_SYSTEM_NAME} STREQUAL Darwin OR ${CMAKE_SYSTEM_NAME} MATCHES Retro) + option(MW_USE_FREETYPE2 "Use FreeType 2" OFF) else() - option(MW_USE_FREETYPE2 "Use FreeType 2" ON) + option(MW_USE_FREETYPE2 "Use FreeType 2" ON) endif() if(${CMAKE_SYSTEM_NAME} STREQUAL Linux) - option(MW_USE_WAYLAND "Enable Wayland backend" ON) + option(MW_USE_WAYLAND "Enable Wayland backend" ON) endif() file( @@ -39,83 +49,83 @@ list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/opengl.c") list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/vulkan.c") if(NOT MW_USE_STB_IMAGE) - list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/external/stb_image.c") + list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/external/stb_image.c") endif() if(NOT MW_USE_STB_TRUETYPE) - list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/external/stb_truetype.c") + list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/external/stb_truetype.c") endif() if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD") - list(APPEND CMAKE_REQUIRED_INCLUDES "/usr/X11R7/include") - list(APPEND CMAKE_REQUIRED_INCLUDES "/usr/pkg/include") + list(APPEND CMAKE_REQUIRED_INCLUDES "/usr/X11R7/include") + list(APPEND CMAKE_REQUIRED_INCLUDES "/usr/pkg/include") endif() if(MW_TRY_OPENGL) - find_package(OpenGL) - if(OpenGL_FOUND) - set(MW_BUILD_OPENGL ON) - list(APPEND SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/opengl.c") - if(APPLE) - list(APPEND SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/opengl_cocoa.m") - endif() - message(STATUS "OpenGL widget has been enabled") - else() - message(WARNING "OpenGL widget has been disabled") + find_package(OpenGL) + if(OpenGL_FOUND) + set(MW_BUILD_OPENGL ON) + list(APPEND SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/opengl.c") + if(APPLE) + list(APPEND SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/opengl_cocoa.m") endif() + message(STATUS "OpenGL widget has been enabled") + else() + message(WARNING "OpenGL widget has been disabled") + endif() endif() if(MW_TRY_VULKAN) - check_include_files(vulkan/vulkan.h HAVE_VULKAN_VULKAN_H) - if(HAVE_VULKAN_VULKAN_H) - set(MW_BUILD_VULKAN ON) - list(APPEND SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/vulkan.c") - target_compile_definitions( + check_include_files(vulkan/vulkan.h HAVE_VULKAN_VULKAN_H) + if(HAVE_VULKAN_VULKAN_H) + set(MW_BUILD_VULKAN ON) + list(APPEND SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/vulkan.c") + target_compile_definitions( Mw PRIVATE MW_VULKAN ) - message(STATUS "Vulkan widget has been enabled") - else() - message(WARNING "Vulkan widget has been disabled") - endif() + message(STATUS "Vulkan widget has been enabled") + else() + message(WARNING "Vulkan widget has been disabled") + endif() endif() if(MW_BUILD_STATIC) - message(STATUS "Building Milsko as a static library") - add_library( + message(STATUS "Building Milsko as a static library") + add_library( Mw ${SOURCES} ) elseif(MW_BUILD_SHARED) - message(STATUS "Building Milsko as a shared library") - add_library( + message(STATUS "Building Milsko as a shared library") + add_library( Mw SHARED ${SOURCES} ) else() - message(ERROR "Must either build a shared library or a static library") + message(ERROR "Must either build a shared library or a static library") endif() if(MW_USE_STB_IMAGE) - target_compile_definitions( + target_compile_definitions( Mw PRIVATE USE_STB_IMAGE ) else() - file( + file( GLOB IMAGE_SOURCES external/libjpeg/src/*.c external/libpng/src/*.c ) - target_sources( + target_sources( Mw PRIVATE ${MW_IMAGE_SOURCES} ) - target_include_directories( + target_include_directories( Mw PRIVATE external/libjpeg/include external/libpng/include @@ -123,7 +133,7 @@ else() endif() if(MW_USE_STB_TRUETYPE) - target_compile_definitions( + target_compile_definitions( Mw PRIVATE USE_STB_TRUETYPE @@ -131,22 +141,22 @@ if(MW_USE_STB_TRUETYPE) endif() if(MW_USE_FREETYPE2) - target_compile_definitions( + target_compile_definitions( Mw PRIVATE USE_FREETYPE2 ) - find_package(PkgConfig) - pkg_check_modules(FT2 REQUIRED freetype2) - list(APPEND INCLUDE_DIRS ${FT2_INCLUDE_DIRS}) - list(APPEND LIBRARY_DIRS ${FT2_LIBRARY_DIRS}) - list(APPEND LIBRARIES ${FT2_LIBRARIES}) + find_package(PkgConfig) + pkg_check_modules(FT2 REQUIRED freetype2) + list(APPEND INCLUDE_DIRS ${FT2_INCLUDE_DIRS}) + list(APPEND LIBRARY_DIRS ${FT2_LIBRARY_DIRS}) + list(APPEND LIBRARIES ${FT2_LIBRARIES}) endif() if(MW_USE_WAYLAND) - function(scan_wayland_protocol_core) - execute_process( + function(scan_wayland_protocol_core) + execute_process( COMMAND wayland-scanner private-code /usr/share/wayland/wayland.xml ${CMAKE_CURRENT_SOURCE_DIR}/src/backend/wayland-core-protocol.c OUTPUT_VARIABLE WAYLAND_SCANNER_OUTPUT ERROR_VARIABLE WAYLAND_SCANNER_ERROR @@ -154,12 +164,12 @@ if(MW_USE_WAYLAND) ECHO_ERROR_VARIABLE COMMAND_ECHO STDOUT ) - target_sources( + target_sources( Mw PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/backend/wayland-core-protocol.c ) - execute_process( + execute_process( COMMAND wayland-scanner client-header /usr/share/wayland/wayland.xml ${CMAKE_CURRENT_SOURCE_DIR}/include/Mw/LowLevel/Wayland/wayland-core-protocol.h WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE WAYLAND_SCANNER_OUTPUT @@ -168,11 +178,11 @@ if(MW_USE_WAYLAND) ECHO_ERROR_VARIABLE COMMAND_ECHO STDOUT ) - endfunction() + endfunction() - function(scan_wayland_protocol tier proto ver) - SET(proto_c ${CMAKE_CURRENT_SOURCE_DIR}/src/backend/wayland-${proto}-protocol.c) - execute_process( + function(scan_wayland_protocol tier proto ver) + SET(proto_c ${CMAKE_CURRENT_SOURCE_DIR}/src/backend/wayland-${proto}-protocol.c) + execute_process( COMMAND wayland-scanner private-code /usr/share/wayland-protocols/${tier}/${proto}/${proto}${ver}.xml ${proto_c} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE WAYLAND_SCANNER_OUTPUT @@ -181,12 +191,12 @@ if(MW_USE_WAYLAND) ECHO_ERROR_VARIABLE COMMAND_ECHO STDOUT ) - target_sources( + target_sources( Mw PRIVATE ${proto_c} ) - execute_process( + execute_process( COMMAND wayland-scanner client-header /usr/share/wayland-protocols/${tier}/${proto}/${proto}${ver}.xml ${CMAKE_CURRENT_SOURCE_DIR}/include/Mw/LowLevel/Wayland/${proto}-client-protocol.h WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE WAYLAND_SCANNER_OUTPUT @@ -195,49 +205,49 @@ if(MW_USE_WAYLAND) ECHO_ERROR_VARIABLE COMMAND_ECHO STDOUT ) - endfunction() + endfunction() - check_include_files(wayland-client.h HAVE_WL_H) - check_include_files(xkbcommon/xkbcommon.h HAVE_XKBCOMMON_H) - check_include_files(cairo/cairo.h HAVE_CAIRO_H) - if(HAVE_WL_H) - if(HAVE_XKBCOMMON_H) - if(HAVE_CAIRO_H) - scan_wayland_protocol_core() - scan_wayland_protocol("stable" "xdg-shell" "") - scan_wayland_protocol("stable" "viewporter" "") - scan_wayland_protocol("stable" "tablet" "-v2") - scan_wayland_protocol("staging" "xdg-toplevel-icon" "-v1") - scan_wayland_protocol("staging" "cursor-shape" "-v1") - scan_wayland_protocol("unstable" "xdg-decoration" "-unstable-v1") - scan_wayland_protocol("unstable" "primary-selection" "-unstable-v1") - scan_wayland_protocol("unstable" "pointer-constraints" "-unstable-v1") - scan_wayland_protocol("unstable" "relative-pointer" "-unstable-v1") + check_include_files(wayland-client.h HAVE_WL_H) + check_include_files(xkbcommon/xkbcommon.h HAVE_XKBCOMMON_H) + check_include_files(cairo/cairo.h HAVE_CAIRO_H) + if(HAVE_WL_H) + if(HAVE_XKBCOMMON_H) + if(HAVE_CAIRO_H) + scan_wayland_protocol_core() + scan_wayland_protocol("stable" "xdg-shell" "") + scan_wayland_protocol("stable" "viewporter" "") + scan_wayland_protocol("stable" "tablet" "-v2") + scan_wayland_protocol("staging" "xdg-toplevel-icon" "-v1") + scan_wayland_protocol("staging" "cursor-shape" "-v1") + scan_wayland_protocol("unstable" "xdg-decoration" "-unstable-v1") + scan_wayland_protocol("unstable" "primary-selection" "-unstable-v1") + scan_wayland_protocol("unstable" "pointer-constraints" "-unstable-v1") + scan_wayland_protocol("unstable" "relative-pointer" "-unstable-v1") - target_sources( + target_sources( Mw PRIVATE src/backend/wayland.c ) - target_compile_definitions( + target_compile_definitions( Mw PRIVATE USE_WAYLAND ) - message(STATUS "Wayland backend has been enabled") - else() - message(WARNING "Wayland backend has been disabled") - endif() - else() - message(WARNING "Wayland backend has been disabled") - endif() - else() + message(STATUS "Wayland backend has been enabled") + else() message(WARNING "Wayland backend has been disabled") + endif() + else() + message(WARNING "Wayland backend has been disabled") endif() + else() + message(WARNING "Wayland backend has been disabled") + endif() endif() if(APPLE AND MW_BUILD_OPENGL) - target_compile_definitions( + target_compile_definitions( Mw PRIVATE GL_SILENCE_DEPRECATION @@ -257,7 +267,7 @@ target_include_directories( ) if(MW_CLASSIC_THEME) - target_compile_definitions( + target_compile_definitions( Mw PRIVATE USE_CLASSIC_THEME @@ -265,60 +275,78 @@ if(MW_CLASSIC_THEME) endif() if(CMAKE_SYSTEM_NAME STREQUAL "Windows") - target_sources( + target_sources( Mw PRIVATE src/backend/gdi.c ) - target_compile_definitions( + target_compile_definitions( Mw PRIVATE USE_GDI ) - list(APPEND LIBRARIES gdi32) - target_link_options( + list(APPEND LIBRARIES gdi32) + target_link_options( Mw PRIVATE -static-libgcc ) elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") - target_sources( + target_sources( Mw PRIVATE src/backend/cocoa.m ) - target_compile_definitions( + target_compile_definitions( Mw PRIVATE USE_COCOA ) - list(APPEND LIBRARIES objc) - target_link_options( + list(APPEND LIBRARIES objc) + target_link_options( Mw PRIVATE -framework Cocoa ) -else() - find_package(PkgConfig) - pkg_check_modules(X11 REQUIRED x11) - pkg_check_modules(XRENDER REQUIRED xrender) +elseif(CMAKE_SYSTEM_NAME MATCHES "Retro") + target_sources( + Mw + PRIVATE + src/backend/classicmacos.c + ) + if(PLATFORM MATCHES retroppc) + endif() + if(PLATFORM MATCHES retroppc) + set_target_properties(Mw PROPERTIES COMPILE_FLAGS "-ffunction-sections -mcpu=601 -Os -Wall -Wextra -Wno-unused-parameter") + set_target_properties(Mw PROPERTIES LINK_FLAGS "-Wl,-gc-sections") + endif() - target_sources( + target_compile_definitions( + Mw + PRIVATE + CLASSIC_MAC_OS + ) +else() + find_package(PkgConfig) + pkg_check_modules(X11 REQUIRED x11) + pkg_check_modules(XRENDER REQUIRED xrender) + + target_sources( Mw PRIVATE src/backend/x11.c ) - target_compile_definitions( + target_compile_definitions( Mw PRIVATE USE_X11 ) - list(APPEND INCLUDE_DIRS ${X11_INCLUDE_DIRS} ${XRENDER_INCLUDE_DIRS}) - list(APPEND LIBRARY_DIRS ${X11_LIBRARY_DIRS} ${XRENDER_LIBRARY_DIRS}) - list(APPEND LIBRARIES ${X11_LIBRARIES} ${XRENDER_LIBRARIES} m) - if(CMAKE_SYSTEM_NAME STREQUAL "Linux") - list(APPEND LIBRARIES dl) - endif() + list(APPEND INCLUDE_DIRS ${X11_INCLUDE_DIRS} ${XRENDER_INCLUDE_DIRS}) + list(APPEND LIBRARY_DIRS ${X11_LIBRARY_DIRS} ${XRENDER_LIBRARY_DIRS}) + list(APPEND LIBRARIES ${X11_LIBRARIES} ${XRENDER_LIBRARIES} m) + if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + list(APPEND LIBRARIES dl) + endif() endif() target_include_directories( @@ -338,14 +366,14 @@ target_link_libraries( ) if(MW_BUILD_VULKAN) - check_include_files(vulkan/vk_enum_string_helper.h HAS_VK_ENUM_STRING_HELPER) - if(HAS_VK_ENUM_STRING_HELPER) - target_compile_definitions( + check_include_files(vulkan/vk_enum_string_helper.h HAS_VK_ENUM_STRING_HELPER) + if(HAS_VK_ENUM_STRING_HELPER) + target_compile_definitions( Mw PRIVATE HAS_VK_ENUM_STRING_HELPER ) - endif() + endif() endif() target_compile_definitions( @@ -362,7 +390,7 @@ install( ) if(MW_INSTALL_HEADERS) - install( + install( DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} FILES_MATCHING PATTERN "*.h" @@ -370,5 +398,5 @@ if(MW_INSTALL_HEADERS) endif() if(MW_BUILD_EXAMPLES) - add_subdirectory(examples) + add_subdirectory(examples) endif() diff --git a/configure b/configure index 1f3ee9e53..a6e5941cf 100755 --- a/configure +++ b/configure @@ -46,6 +46,7 @@ param_set("shared", 1); param_set("static", 1); param_set("examples", 1); + my %features = ( "classic-theme" => "use classic theme", "stb-image" => "use stb_image, instead use libjpeg/libpng", @@ -131,16 +132,12 @@ foreach my $l (@ARGV) { } } -if($target ne "Darwin" and $target ne "ClassicMacOS68k" and $target ne "ClassicMacOSPPC") { +if($target ne "Darwin" and $target ne "ClassicMacOS") { param_set("freetype2", 1); param_set("stb-truetype", 0); } else { - if($target ne "ClassicMacOS68k" and $target ne "ClassicMacOSPPC"){ - param_set("freetype2", 0); - param_set("stb-truetype", 1); - } else { - param_set("stb-truetype", 0); - } + param_set("freetype2", 0); + param_set("stb-truetype", 0); } if($target eq "Linux") { @@ -289,7 +286,7 @@ if (param_get("examples")) { } if (grep(/^cocoa$/, @backends)) { print(OUT -" \$(CC) -L./src -I\$\(INCDIR) \$\(LIBDIR) -o ${l} ${s}${object_suffix} -lMw ${math} ${libs}\n" +" \$(CC) -L./src \$\(LIBDIR) -o ${l} ${s}${object_suffix} -lMw ${math} ${libs}\n" ); } else { @@ -304,16 +301,12 @@ if (param_get("examples")) { 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" ); + } print(OUT "${s}${object_suffix}: ${s}.c\n"); print(OUT " \$(CC) -c \$\(INCDIR) -o ${s}${object_suffix} ${s}.c -lMw ${math}\n" ); - - - #print(OUT "Rez -I /path/to/Universal/RIncludes /path/to/libretro/RIncludes/Retro68APPL.r -DCFRAG_NAME="\"MyProgram\"" --data program.pef -o program.bin -t APPL"); - } - } } print(OUT "\n"); diff --git a/examples/basic/CMakeLists.txt b/examples/basic/CMakeLists.txt index ab58a5c1a..e69c4ae55 100644 --- a/examples/basic/CMakeLists.txt +++ b/examples/basic/CMakeLists.txt @@ -1,22 +1,26 @@ file( - GLOB - EXAMPLES_BASIC_SOURCES - *.c + GLOB + EXAMPLES_BASIC_SOURCES + *.c ) foreach(PATH IN LISTS EXAMPLES_BASIC_SOURCES) - get_filename_component(TARGET ${PATH} NAME_WE) - add_executable(${TARGET} MACOSX_BUNDLE ${PATH}) - target_link_libraries( - ${TARGET} - PRIVATE - Mw - ) - if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") - target_link_libraries( - ${TARGET} - PRIVATE - m - ) - endif() + get_filename_component(TARGET ${PATH} NAME_WE) + if(CMAKE_SYSTEM_NAME MATCHES Retro) + add_application(${TARGET} ${PATH}) + else() + add_executable(${TARGET} MACOSX_BUNDLE ${PATH}) + endif() + target_link_libraries( + ${TARGET} + PRIVATE + Mw + ) + if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") + target_link_libraries( + ${TARGET} + PRIVATE + m + ) + endif() endforeach() diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index a1a469188..2a293b02a 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -106,6 +106,9 @@ MWDECL void MwLLDBusFreeContext(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx); #ifdef USE_COCOA #include #endif +#ifdef CLASSIC_MAC_OS +#include +#endif union _MwLL { struct _MwLLCommon common; @@ -121,6 +124,9 @@ union _MwLL { #ifdef USE_COCOA struct _MwLLCocoa cocoa; #endif +#ifdef CLASSIC_MAC_OS + struct _MwLLClassicMacOS cmacos; +#endif }; union _MwLLColor { diff --git a/include/Mw/LowLevel/ClassicMacOS.h b/include/Mw/LowLevel/ClassicMacOS.h index 01654387f..f377e4f91 100644 --- a/include/Mw/LowLevel/ClassicMacOS.h +++ b/include/Mw/LowLevel/ClassicMacOS.h @@ -12,6 +12,10 @@ struct _MwLLClassicMacOS { struct _MwLLCommon common; + + WindowRef window; + EventRecord event; + Rect winRect; }; struct _MwLLClassicMacOSColor { diff --git a/pl/ostype/ClassicMacOS.pl b/pl/ostype/ClassicMacOS.pl new file mode 100644 index 000000000..751525f7a --- /dev/null +++ b/pl/ostype/ClassicMacOS.pl @@ -0,0 +1,10 @@ +use_backend("classicmacos"); + +print("Compiling for Classic Mac OS via ./configure currently outputs a broken executable and it only supports PowerPC. Help is wanted. In the mean time, use CMake.") + +$cc = $ENV{RETRO68_TOOLCHAIN_PATH}."/bin/powerpc-apple-macos-gcc"; +$ar = $ENV{RETRO68_TOOLCHAIN_PATH}."/bin/powerpc-apple-macos-ar"; +add_cflags("-DCLASSIC_MAC_OS"); +add_cflags("-DSTBI_NO_THREAD_LOCALS"); + +1; diff --git a/pl/ostype/ClassicMacOS68k.pl b/pl/ostype/ClassicMacOS68k.pl deleted file mode 100644 index c9ceba8c6..000000000 --- a/pl/ostype/ClassicMacOS68k.pl +++ /dev/null @@ -1,7 +0,0 @@ -use_backend("classicmacos"); - -$cc = $ENV{RETRO68_TOOLCHAIN_PATH}."/bin/m68k-apple-macos-gcc"; -$ar = $ENV{RETRO68_TOOLCHAIN_PATH}."/bin/m68k-apple-macos-ar"; -add_cflags("-DCLASSIC_MAC_OS"); - -1; diff --git a/pl/ostype/ClassicMacOSPPC.pl b/pl/ostype/ClassicMacOSPPC.pl deleted file mode 100644 index b2626d968..000000000 --- a/pl/ostype/ClassicMacOSPPC.pl +++ /dev/null @@ -1,7 +0,0 @@ -use_backend("classicmacos"); - -$cc = $ENV{RETRO68_TOOLCHAIN_PATH}."/bin/powerpc-apple-macos-gcc"; -$ar = $ENV{RETRO68_TOOLCHAIN_PATH}."/bin/powerpc-apple-macos-ar"; -add_cflags("-DCLASSIC_MAC_OS"); - -1; diff --git a/src/backend/classicmacos.c b/src/backend/classicmacos.c index 01a9d9735..929c4930f 100644 --- a/src/backend/classicmacos.c +++ b/src/backend/classicmacos.c @@ -5,6 +5,15 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { MwLL r; + MwLLCreateCommon(r); + + SetRect(&r->cmacos.winRect, 100, 100, width, height); + + r->cmacos.window = NewCWindow(nil, &r->cmacos.winRect, (ConstStr255Param) "\p", true, + documentProc, (WindowPtr)(-1), true, 0); + + SetPort(r->cmacos.window); + return r; } @@ -59,8 +68,7 @@ static void MwLLFreeColorImpl(MwLLColor color) { } static int MwLLPendingImpl(MwLL handle) { - - return 0; + return GetNextEvent(everyEvent, &handle->cmacos.event); } static void MwLLNextEventImpl(MwLL handle) { diff --git a/src/dialog/filechooser.c b/src/dialog/filechooser.c index d5faa4bad..c18027677 100644 --- a/src/dialog/filechooser.c +++ b/src/dialog/filechooser.c @@ -383,7 +383,7 @@ static void layout(MwWidget handle) { MwNtext, "Cancel", NULL); - MwAddUserHandler(fc->cancel, MwNactivateHandler, cancel, NULL); + MwAddUserHandler(fc->cancel, MwNactivateHandler, filecancel, NULL); } else { MwVaApply(fc->cancel, MwNx, wx, diff --git a/src/widget/box.c b/src/widget/box.c index e96c00874..6fb893550 100644 --- a/src/widget/box.c +++ b/src/widget/box.c @@ -135,7 +135,7 @@ static void children_update(MwWidget handle) { } MwClassRec MwBoxClassRec = { - create, /* create */ + wcreate, /* create */ destroy, /* destroy */ draw, /* draw */ NULL, /* click */ diff --git a/src/widget/button.c b/src/widget/button.c index 6653b54ed..7287f2a4e 100644 --- a/src/widget/button.c +++ b/src/widget/button.c @@ -93,7 +93,7 @@ static void prop_change(MwWidget handle, const char* key) { } MwClassRec MwButtonClassRec = { - create, /* create */ + wcreate, /* create */ NULL, /* destroy */ draw, /* draw */ click, /* click */ diff --git a/src/widget/checkbox.c b/src/widget/checkbox.c index 56b8f11ae..2301aa0ff 100644 --- a/src/widget/checkbox.c +++ b/src/widget/checkbox.c @@ -38,7 +38,7 @@ static void prop_change(MwWidget handle, const char* key) { } MwClassRec MwCheckBoxClassRec = { - create, /* create */ + wcreate, /* create */ NULL, /* destroy */ draw, /* draw */ click, /* click */ diff --git a/src/widget/combobox.c b/src/widget/combobox.c index 988bb24aa..c061512d7 100644 --- a/src/widget/combobox.c +++ b/src/widget/combobox.c @@ -189,7 +189,7 @@ static void func_handler(MwWidget handle, const char* name, void* out, va_list v } MwClassRec MwComboBoxClassRec = { - create, /* create */ + wcreate, /* create */ destroy, /* destroy */ draw, /* draw */ click, /* click */ diff --git a/src/widget/entry.c b/src/widget/entry.c index eca5e5ce4..4d1cc7364 100644 --- a/src/widget/entry.c +++ b/src/widget/entry.c @@ -172,7 +172,7 @@ static void clipboard(MwWidget handle, const char* data) { } MwClassRec MwEntryClassRec = { - create, /* create */ + wcreate, /* create */ destroy, /* destroy */ draw, /* draw */ NULL, /* click */ diff --git a/src/widget/frame.c b/src/widget/frame.c index 6f9d88129..0cc0c4163 100644 --- a/src/widget/frame.c +++ b/src/widget/frame.c @@ -46,7 +46,7 @@ static void prop_change(MwWidget handle, const char* key) { } MwClassRec MwFrameClassRec = { - create, /* create */ + wcreate, /* create */ NULL, /* destroy */ draw, /* draw */ NULL, /* click */ diff --git a/src/widget/image.c b/src/widget/image.c index 90f3cbe7a..791570ecb 100644 --- a/src/widget/image.c +++ b/src/widget/image.c @@ -42,7 +42,7 @@ static void prop_change(MwWidget handle, const char* key) { } MwClassRec MwImageClassRec = { - create, /* create */ + wcreate, /* create */ NULL, /* destroy */ draw, /* draw */ NULL, /* click */ diff --git a/src/widget/label.c b/src/widget/label.c index 3c88eb921..98a0d5fef 100644 --- a/src/widget/label.c +++ b/src/widget/label.c @@ -360,7 +360,7 @@ static void func_handler(MwWidget handle, const char* name, void* out, va_list v } MwClassRec MwLabelClassRec = { - create, /* create */ + wcreate, /* create */ destroy, /* destroy */ draw, /* draw */ NULL, /* click */ diff --git a/src/widget/listbox.c b/src/widget/listbox.c index 7f4ef0b7d..98c86cf97 100644 --- a/src/widget/listbox.c +++ b/src/widget/listbox.c @@ -595,7 +595,7 @@ static void tick(MwWidget handle) { } MwClassRec MwListBoxClassRec = { - create, /* create */ + wcreate, /* create */ destroy, /* destroy */ draw, /* draw */ NULL, /* click */ diff --git a/src/widget/menu.c b/src/widget/menu.c index b36527885..b66108652 100644 --- a/src/widget/menu.c +++ b/src/widget/menu.c @@ -189,7 +189,7 @@ static void func_handler(MwWidget handle, const char* name, void* out, va_list v } MwClassRec MwMenuClassRec = { - create, /* create */ + wcreate, /* create */ destroy, /* destroy */ draw, /* draw */ NULL, /* click */ diff --git a/src/widget/numberentry.c b/src/widget/numberentry.c index 96860f84e..05d590f5c 100644 --- a/src/widget/numberentry.c +++ b/src/widget/numberentry.c @@ -128,7 +128,7 @@ static void prop_change(MwWidget handle, const char* prop) { } MwClassRec MwNumberEntryClassRec = { - create, /* create */ + wcreate, /* create */ destroy, /* destroy */ draw, /* draw */ NULL, /* click */ diff --git a/src/widget/progressbar.c b/src/widget/progressbar.c index 2a032b09d..dedd7a911 100644 --- a/src/widget/progressbar.c +++ b/src/widget/progressbar.c @@ -46,7 +46,7 @@ static void prop_change(MwWidget handle, const char* key) { } MwClassRec MwProgressBarClassRec = { - create, /* create */ + wcreate, /* create */ NULL, /* destroy */ draw, /* draw */ NULL, /* click */ diff --git a/src/widget/radiobox.c b/src/widget/radiobox.c index 2416b71d9..1342232e5 100644 --- a/src/widget/radiobox.c +++ b/src/widget/radiobox.c @@ -47,7 +47,7 @@ static void prop_change(MwWidget handle, const char* key) { } MwClassRec MwRadioBoxClassRec = { - create, /* create */ + wcreate, /* create */ NULL, /* destroy */ draw, /* draw */ click, /* click */ diff --git a/src/widget/scrollbar.c b/src/widget/scrollbar.c index e11ba6ac4..a1df9b2db 100644 --- a/src/widget/scrollbar.c +++ b/src/widget/scrollbar.c @@ -257,7 +257,7 @@ static void func_handler(MwWidget handle, const char* name, void* out, va_list v } MwClassRec MwScrollBarClassRec = { - create, /* create */ + wcreate, /* create */ destroy, /* destroy */ draw, /* draw */ NULL, /* click */ diff --git a/src/widget/separator.c b/src/widget/separator.c index d7d6aae20..15919d0ed 100644 --- a/src/widget/separator.c +++ b/src/widget/separator.c @@ -35,7 +35,7 @@ static void prop_change(MwWidget handle, const char* key) { } MwClassRec MwSeparatorClassRec = { - create, /* create */ + wcreate, /* create */ NULL, /* destroy */ draw, /* draw */ NULL, /* click */ diff --git a/src/widget/submenu.c b/src/widget/submenu.c index a71d65b08..f14d6d5f4 100644 --- a/src/widget/submenu.c +++ b/src/widget/submenu.c @@ -241,7 +241,7 @@ static void func_handler(MwWidget handle, const char* name, void* out, va_list v } MwClassRec MwSubMenuClassRec = { - create, /* create */ + wcreate, /* create */ destroy, /* destroy */ draw, /* draw */ click, /* click */ diff --git a/src/widget/treeview.c b/src/widget/treeview.c index bd3067c4c..9d3320699 100644 --- a/src/widget/treeview.c +++ b/src/widget/treeview.c @@ -481,7 +481,7 @@ static void tick(MwWidget handle) { } MwClassRec MwTreeViewClassRec = { - create, /* create */ + wcreate, /* create */ destroy, /* destroy */ draw, /* draw */ NULL, /* click */ diff --git a/src/widget/viewport.c b/src/widget/viewport.c index 38ef89948..f05b18d5b 100644 --- a/src/widget/viewport.c +++ b/src/widget/viewport.c @@ -176,7 +176,7 @@ static void tick(MwWidget handle) { } MwClassRec MwViewportClassRec = { - create, /* create */ + wcreate, /* create */ destroy, /* destroy */ draw, /* draw */ NULL, /* click */ diff --git a/src/widget/vulkan.c b/src/widget/vulkan.c index ab73fcafc..7cb33122a 100644 --- a/src/widget/vulkan.c +++ b/src/widget/vulkan.c @@ -556,7 +556,7 @@ static void func_handler(MwWidget handle, const char* name, void* out, va_list v } MwClassRec MwVulkanClassRec = { - create, /* create */ + wcreate, /* create */ destroy, /* destroy */ NULL, /* draw */ NULL, /* click */ diff --git a/src/widget/window.c b/src/widget/window.c index b4aaa8d22..2b596b50d 100644 --- a/src/widget/window.c +++ b/src/widget/window.c @@ -44,7 +44,7 @@ static void func_handler(MwWidget handle, const char* name, void* out, va_list v } } MwClassRec MwWindowClassRec = { - create, /* create */ + wcreate, /* create */ NULL, /* destroy */ draw, /* draw */ NULL, /* click */ From 2228fa1a467ab724002a6c82a9405987338896ac Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 15 Apr 2026 21:46:37 -0700 Subject: [PATCH 176/195] fix build --- src/widget/opengl.c | 6 +++--- src/widget/opengl_cocoa.m | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/widget/opengl.c b/src/widget/opengl.c index 2cb612eaa..39b5510c8 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -380,8 +380,8 @@ static void mwOpenGLMakeCurrentImpl(MwWidget handle) { #ifdef USE_GDI if(handle->lowlevel->common.type == MwLLBackendGDI) { - gdiopengl_t* o = handle->internal; - BOOL (APIENTRY *swap_interval_ext)(int) = NULL; + gdiopengl_t* o = handle->internal; + BOOL(APIENTRY * swap_interval_ext)(int) = NULL; o->wglMakeCurrent(o->dc, o->gl); @@ -498,7 +498,7 @@ static void func_handler(MwWidget handle, const char* name, void* out, } } -MwClassRec MwOpenGLClassRec = {create, /* create */ +MwClassRec MwOpenGLClassRec = {wcreate, /* create */ destroy, /* destroy */ NULL, /* draw */ NULL, /* click */ diff --git a/src/widget/opengl_cocoa.m b/src/widget/opengl_cocoa.m index 27c21588a..a4d2bfa2f 100644 --- a/src/widget/opengl_cocoa.m +++ b/src/widget/opengl_cocoa.m @@ -111,7 +111,7 @@ static void func_handler(MwWidget handle, const char* name, void* out, @end -MwClassRec MwOpenGLClassRec = {create, /* create */ +MwClassRec MwOpenGLClassRec = {wcreate, /* create */ destroy, /* destroy */ NULL, /* draw */ NULL, /* click */ From 15c39a2405a62c47f91b7a683ac367bc67332af7 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 15 Apr 2026 21:48:52 -0700 Subject: [PATCH 177/195] windows shouldn't default to ft2 anyways --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index a6e5941cf..98a6b3a6e 100755 --- a/configure +++ b/configure @@ -132,7 +132,7 @@ foreach my $l (@ARGV) { } } -if($target ne "Darwin" and $target ne "ClassicMacOS") { +if($target ne "Darwin" and $target ne "ClassicMacOS" and $target ne "Windows") { param_set("freetype2", 1); param_set("stb-truetype", 0); } else { From b2ce5597b0ac205330bb0dceb33fd78c09fcf9b4 Mon Sep 17 00:00:00 2001 From: Nishi Date: Thu, 16 Apr 2026 14:07:20 +0900 Subject: [PATCH 178/195] fix warning --- src/draw.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/draw.c b/src/draw.c index f5e1368dd..68f6862e6 100644 --- a/src/draw.c +++ b/src/draw.c @@ -104,14 +104,13 @@ void MwDrawRect(MwWidget handle, MwRect* rect, MwLLColor color) { void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color) { MwLLPixmap pixmap; - int y, i; + int y; double darken = 0.; int ColorDiff = get_color_diff(handle); double darkenStep = (ColorDiff / 2.) / rect->height; unsigned long sz = 1 * rect->height * 4; unsigned char* data = malloc(sz); MwRect r = *rect; - double div; if(rect->width <= 0 || rect->height <= 0) { free(data); return; @@ -309,8 +308,7 @@ static void MwDrawFrameEx_simple(MwWidget handle, MwRect* rect, MwLLColor color, static void frame_border_complex(MwWidget handle, MwRect* rect, MwLLColor lighter, MwLLColor darker, int invert, int border, int diff, int same) { MwPoint p[7]; - int i; - + (void)diff; (void)same; From 5ca241ad0af271f98fb6c3d780242d2046d76eca Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 15 Apr 2026 22:20:13 -0700 Subject: [PATCH 179/195] update time.c to not do a cast --- CMakeLists.txt | 2 -- src/abstract/time.c | 4 +++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 835ecdd26..c0c7f0b9d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -314,8 +314,6 @@ elseif(CMAKE_SYSTEM_NAME MATCHES "Retro") PRIVATE src/backend/classicmacos.c ) - if(PLATFORM MATCHES retroppc) - endif() if(PLATFORM MATCHES retroppc) set_target_properties(Mw PROPERTIES COMPILE_FLAGS "-ffunction-sections -mcpu=601 -Os -Wall -Wextra -Wno-unused-parameter") set_target_properties(Mw PROPERTIES LINK_FLAGS "-Wl,-gc-sections") diff --git a/src/abstract/time.c b/src/abstract/time.c index 52d998689..cdebc4b93 100644 --- a/src/abstract/time.c +++ b/src/abstract/time.c @@ -43,7 +43,7 @@ void timerUpdateFunc(void) { long MwTimeGetTick(void) { UnsignedWide h; Microseconds(&h); - return *(long*)&h; + return h.lo; } void MwTimeSleep(int ms) { tm.tmAddr = NewTimerProc(timerUpdateFunc); @@ -52,6 +52,8 @@ void MwTimeSleep(int ms) { InsTime((QElemPtr)&tm); PrimeTime((QElemPtr)&tm, 1); + + DisposeTimerUPP(tm.tmAddr); } #elif defined(__unix__) long MwTimeGetTick(void) { From 0e96b715b00c388f785940a1b86663f57d196edd Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 15 Apr 2026 22:25:26 -0700 Subject: [PATCH 180/195] classic mac os: comment out MwTimeSleep because I realize that wouldn't work either way --- src/abstract/time.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/abstract/time.c b/src/abstract/time.c index cdebc4b93..cd09b94d9 100644 --- a/src/abstract/time.c +++ b/src/abstract/time.c @@ -33,12 +33,12 @@ void MwTimeSleep(int ms) { nanosleep(&ts, NULL); } #elif defined(CLASSIC_MAC_OS) -static TMTask tm; -static int timer; -void timerUpdateFunc(void) { - timer += 1; - PrimeTime((QElemPtr)&tm, 1); -}; +// static TMTask tm; +// static int timer; +// void timerUpdateFunc(void) { +// timer += 1; +// PrimeTime((QElemPtr)&tm, 1); +// }; long MwTimeGetTick(void) { UnsignedWide h; @@ -46,14 +46,14 @@ long MwTimeGetTick(void) { return h.lo; } void MwTimeSleep(int ms) { - tm.tmAddr = NewTimerProc(timerUpdateFunc); - tm.tmWakeUp = 0; - tm.tmReserved = 0; + // tm.tmAddr = NewTimerProc(timerUpdateFunc); + // tm.tmWakeUp = 0; + // tm.tmReserved = 0; - InsTime((QElemPtr)&tm); - PrimeTime((QElemPtr)&tm, 1); + // InsTime((QElemPtr)&tm); + // PrimeTime((QElemPtr)&tm, 1); - DisposeTimerUPP(tm.tmAddr); + // DisposeTimerUPP(tm.tmAddr); } #elif defined(__unix__) long MwTimeGetTick(void) { From 9b138c458ec518121955abc77c0c9a239092c0a6 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 16 Apr 2026 00:45:59 -0700 Subject: [PATCH 181/195] cmacos: very untested code but it's all so basic that it should work --- include/Mw/LowLevel.h | 5 ++- include/Mw/LowLevel/ClassicMacOS.h | 1 + src/backend/classicmacos.c | 65 +++++++++++++++++++++++++----- 3 files changed, 59 insertions(+), 12 deletions(-) diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index 5ba698e9c..e025cb293 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -125,7 +125,7 @@ union _MwLL { struct _MwLLCocoa cocoa; #endif #ifdef CLASSIC_MAC_OS - struct _MwLLClassicMacOS cmacos; + struct _MwLLClassicMacOS cmacos; #endif }; @@ -159,6 +159,9 @@ union _MwLLPixmap { #ifdef USE_COCOA struct _MwLLCocoaPixmap cocoa; #endif +#ifdef CLASSIC_MAC_OS + struct _MwLLClassicMacOSPixmap cmacos; +#endif }; #endif #include diff --git a/include/Mw/LowLevel/ClassicMacOS.h b/include/Mw/LowLevel/ClassicMacOS.h index f377e4f91..4b32f6cd4 100644 --- a/include/Mw/LowLevel/ClassicMacOS.h +++ b/include/Mw/LowLevel/ClassicMacOS.h @@ -24,6 +24,7 @@ struct _MwLLClassicMacOSColor { struct _MwLLClassicMacOSPixmap { struct _MwLLCommonPixmap common; + BitMap bmp; }; MWDECL int MwLLClassicMacOSCallInit(void); diff --git a/src/backend/classicmacos.c b/src/backend/classicmacos.c index 929c4930f..168541559 100644 --- a/src/backend/classicmacos.c +++ b/src/backend/classicmacos.c @@ -7,12 +7,13 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { MwLLCreateCommon(r); - SetRect(&r->cmacos.winRect, 100, 100, width, height); - - r->cmacos.window = NewCWindow(nil, &r->cmacos.winRect, (ConstStr255Param) "\p", true, - documentProc, (WindowPtr)(-1), true, 0); - - SetPort(r->cmacos.window); + if(!parent) { + SetRect(&r->cmacos.winRect, 100, 100, width, height); + r->cmacos.window = NewCWindow(nil, &r->cmacos.winRect, (ConstStr255Param) "\p", true, + documentProc, (WindowPtr)(-1), true, 0); + SetPort(r->cmacos.window); + // + } return r; } @@ -32,10 +33,42 @@ static void MwLLEndDrawImpl(MwLL handle) { } static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { - int i; + int i; + PolyHandle p = OpenPoly(); + RGBColor col; + + col.red = color->common.red; + col.green = color->common.green; + col.blue = color->common.blue; + + RGBBackColor(&col); + RGBForeColor(&col); + + for(i = 0; i < points_count; i++) { + if(i == 0) { + MoveTo(points[i].x, points[i].y); + } else { + LineTo(points[i].x, points[i].y); + } + } + + ClosePoly(); + PaintPoly(p); + KillPoly(p); } static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { + RGBColor col; + + col.red = color->common.red; + col.green = color->common.green; + col.blue = color->common.blue; + + RGBBackColor(&col); + RGBForeColor(&col); + + MoveTo(points[0].x, points[0].y); + LineTo(points[1].x, points[1].y); } static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { @@ -51,16 +84,20 @@ static void MwLLColorUpdateImpl(MwLL handle, MwLLColor c, int r, int g, int b) { } static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h) { - *x = 0; - *y = 0; - *w = 0; - *h = 0; + Rect bounds; + GetWindowBounds(handle->cmacos.window, kWindowContentRgn, &bounds); + *x = bounds.left; + *y = bounds.top; + *w = bounds.right; + *h = bounds.bottom; } static void MwLLSetXYImpl(MwLL handle, int x, int y) { + MoveWindow(handle->cmacos.window, x, y, MwTRUE); } static void MwLLSetWHImpl(MwLL handle, int w, int h) { + SizeWindow(handle->cmacos.window, w, h, MwTRUE); } static void MwLLFreeColorImpl(MwLLColor color) { @@ -75,6 +112,7 @@ static void MwLLNextEventImpl(MwLL handle) { } static void MwLLSetTitleImpl(MwLL handle, const char* title) { + setwtitle(handle->cmacos.window, title); } static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, int width, int height) { @@ -109,6 +147,10 @@ static void MwLLDetachImpl(MwLL handle, MwPoint* point) { } static void MwLLShowImpl(MwLL handle, int show) { + if(show) + ShowWindow(handle->cmacos.window); + else + HideWindow(handle->cmacos.window); } static void MwLLMakePopupImpl(MwLL handle, MwLL parent) { @@ -121,6 +163,7 @@ static void MwLLMakeBorderlessImpl(MwLL handle, int toggle) { } static void MwLLFocusImpl(MwLL handle) { + HiliteWindow(handle->cmacos.window, MwTRUE); } static void MwLLGrabPointerImpl(MwLL handle, int toggle) { From 8b176d3a008e796ebaa036375256411ba15a3f03 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 16 Apr 2026 00:53:37 -0700 Subject: [PATCH 182/195] cmacos: remove parent check oops --- src/backend/classicmacos.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/backend/classicmacos.c b/src/backend/classicmacos.c index 168541559..8745c0ce5 100644 --- a/src/backend/classicmacos.c +++ b/src/backend/classicmacos.c @@ -7,13 +7,11 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { MwLLCreateCommon(r); - if(!parent) { - SetRect(&r->cmacos.winRect, 100, 100, width, height); - r->cmacos.window = NewCWindow(nil, &r->cmacos.winRect, (ConstStr255Param) "\p", true, - documentProc, (WindowPtr)(-1), true, 0); - SetPort(r->cmacos.window); - // - } + /* 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); + r->cmacos.window = NewCWindow(nil, &r->cmacos.winRect, (ConstStr255Param) "\p", true, + documentProc, (WindowPtr)(-1), true, 0); + SetPort(r->cmacos.window); return r; } From c88dc48817d92d9103a4852a56c494d95e1dc214 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 16 Apr 2026 00:55:18 -0700 Subject: [PATCH 183/195] cmacos: Right we can just use the lowercase newcwindow instead of worrying about pascal conversions --- src/backend/classicmacos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/classicmacos.c b/src/backend/classicmacos.c index 8745c0ce5..4fa7ab373 100644 --- a/src/backend/classicmacos.c +++ b/src/backend/classicmacos.c @@ -9,7 +9,7 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { /* 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); - r->cmacos.window = NewCWindow(nil, &r->cmacos.winRect, (ConstStr255Param) "\p", true, + r->cmacos.window = newcwindow(nil, &r->cmacos.winRect, "", true, documentProc, (WindowPtr)(-1), true, 0); SetPort(r->cmacos.window); From 79efc31c55093b3c6b1cfdd900e6e7af0ac16f07 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Thu, 16 Apr 2026 23:40:29 +0900 Subject: [PATCH 184/195] dbus should work on netbsd now --- include/Mw/LowLevel.h | 2 +- pl/ostype/ClassicMacOS.pl | 8 +++++--- pl/ostype/NetBSD.pl | 2 ++ pl/rules.pl | 13 ++++++++----- src/backend/call.c | 2 +- src/backend/cocoa.m | 2 +- src/backend/gdi.c | 7 +++---- src/backend/wayland.c | 10 ++++++++-- src/backend/x11.c | 17 +++++++++++++++-- src/core.c | 2 +- src/draw.c | 2 +- src/string.c | 2 +- src/widget/scrollbar.c | 6 +++--- 13 files changed, 50 insertions(+), 25 deletions(-) diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index e025cb293..ea31aefea 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -6,7 +6,7 @@ #ifndef __MW_LOWLEVEL_H__ #define __MW_LOWLEVEL_H__ -#include "Mw/BaseTypes.h" +#include #include typedef struct _MwLLHandler* MwLLHandler; diff --git a/pl/ostype/ClassicMacOS.pl b/pl/ostype/ClassicMacOS.pl index 751525f7a..1f2e532d6 100644 --- a/pl/ostype/ClassicMacOS.pl +++ b/pl/ostype/ClassicMacOS.pl @@ -1,9 +1,11 @@ use_backend("classicmacos"); -print("Compiling for Classic Mac OS via ./configure currently outputs a broken executable and it only supports PowerPC. Help is wanted. In the mean time, use CMake.") +print( +"Compiling for Classic Mac OS via ./configure currently outputs a broken executable and it only supports PowerPC. Help is wanted. In the mean time, use CMake." +); -$cc = $ENV{RETRO68_TOOLCHAIN_PATH}."/bin/powerpc-apple-macos-gcc"; -$ar = $ENV{RETRO68_TOOLCHAIN_PATH}."/bin/powerpc-apple-macos-ar"; +$cc = $ENV{RETRO68_TOOLCHAIN_PATH} . "/bin/powerpc-apple-macos-gcc"; +$ar = $ENV{RETRO68_TOOLCHAIN_PATH} . "/bin/powerpc-apple-macos-ar"; add_cflags("-DCLASSIC_MAC_OS"); add_cflags("-DSTBI_NO_THREAD_LOCALS"); diff --git a/pl/ostype/NetBSD.pl b/pl/ostype/NetBSD.pl index 936725069..6556cab20 100644 --- a/pl/ostype/NetBSD.pl +++ b/pl/ostype/NetBSD.pl @@ -4,4 +4,6 @@ add_libdir( use_backend("x11"); add_libs("-lpthread"); +add_cflags("-DUSE_DBUS"); + 1; diff --git a/pl/rules.pl b/pl/rules.pl index 4d68cb94d..6f64a174c 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -31,6 +31,7 @@ if (grep(/^gdi$/, @backends)) { } if (grep(/^classicmacos$/, @backends)) { + #add_cflags("-DCLASSIC_MAC_OS"); new_object("src/backend/classicmacos.c"); @@ -56,18 +57,20 @@ if (grep(/^wayland$/, @backends)) { scan_wayland_protocol("unstable", "pointer-constraints", "-unstable-v1"); scan_wayland_protocol("unstable", "relative-pointer", "-unstable-v1"); - add_cflags(`pkg-config --cflags dbus-1`); - $gl_libs = "-lGL -lGLU"; } +if (grep(/( |^)-DUSE_DBUS( |$)/, $cflags)) { + add_cflags(`pkg-config --cflags dbus-1`); +} + if (grep(/^cocoa$/, @backends) || param_get("gnustep")) { add_cflags("-DUSE_COCOA"); new_object("src/backend/cocoa.m"); - if(param_get("gnustep")){ - add_incdir("-I".`gnustep-config --variable=GNUSTEP_SYSTEM_HEADERS`); - add_libdir("-L".`gnustep-config --variable=GNUSTEP_SYSTEM_LIBRARIES`); + if (param_get("gnustep")) { + add_incdir("-I" . `gnustep-config --variable=GNUSTEP_SYSTEM_HEADERS`); + add_libdir("-L" . `gnustep-config --variable=GNUSTEP_SYSTEM_LIBRARIES`); add_cflags("-fobjc-runtime=gnustep-2.0 -fblocks"); add_ldflags("-lobjc -lgnustep-base -lm -lgnustep-gui"); } diff --git a/src/backend/call.c b/src/backend/call.c index 07cf1e08f..14338ecc9 100644 --- a/src/backend/call.c +++ b/src/backend/call.c @@ -55,7 +55,7 @@ MwLLGetCursorCoord = MwLLGetCursorCoordImpl; \ MwLLGetScreenSize = MwLLGetScreenSizeImpl; \ \ - MwLLSetDarkTheme = MwLLSetDarkThemeImpl; \ + MwLLSetDarkTheme = MwLLSetDarkThemeImpl; \ \ return 0; \ } diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 3177d14c2..cfac1add0 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -1084,7 +1084,7 @@ static void MwLLEndStateChangeImpl(MwLL handle) { MwLLShow(handle, 1); } -static void MwLLSetDarkThemeImpl(MwLL handle, int toggle){ +static void MwLLSetDarkThemeImpl(MwLL handle, int toggle) { (void)handle; (void)toggle; } diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 8813ba24b..055b6c26d 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -11,7 +11,7 @@ typedef struct userdata { static struct symtbl { void* lib_dwmapi; - HRESULT (WINAPI *DwmSetWindowAttribute)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute); + HRESULT(WINAPI* DwmSetWindowAttribute)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute); } wsymtbl; #define DwmSetWindowAttribute wsymtbl.DwmSetWindowAttribute @@ -34,7 +34,7 @@ static void detect_darktheme(MwLL handle) { t = dw ? 0 : 1; - if(t && DwmSetWindowAttribute != NULL){ + if(t && DwmSetWindowAttribute != NULL) { LPARAM style = GetWindowLongPtr(handle->gdi.hWnd, GWL_STYLE); if(!(style & WS_CHILD)) MwLLSetDarkTheme(handle, 1); } @@ -819,11 +819,10 @@ static void MwLLEndStateChangeImpl(MwLL handle) { (void)handle; } -static void MwLLSetDarkThemeImpl(MwLL handle, int toggle){ +static void MwLLSetDarkThemeImpl(MwLL handle, int toggle) { BOOL v = toggle ? TRUE : FALSE; DwmSetWindowAttribute(handle->gdi.hWnd, 20, &v, sizeof(v)); - } static int MwLLGDICallInitImpl(void) { diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 425308d7e..fc4a67fc4 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1817,6 +1817,7 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh } } +#ifdef USE_DBUS static void detect_dark_theme(MwLL handle) { MwU32 value = 0; MwU32 dark_theme = 0; @@ -1826,6 +1827,7 @@ static void detect_dark_theme(MwLL handle) { MwLLDispatch(handle, dark_theme, &dark_theme); } +#endif static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { MwLL r; @@ -1876,9 +1878,11 @@ static void MwLLDestroyImpl(MwLL handle) { pthread_mutex_unlock(&handle->wayland.eventsMutex); pthread_mutex_destroy(&handle->wayland.eventsMutex); +#ifdef USE_DBUS if(!wl_call_tbl.has_dbus) { MwLLDBusFreeContext(&wl_call_tbl.dbus, &handle->wayland.dbus); } +#endif buffer_destroy(&handle->wayland.cursor); wl_region_destroy(handle->wayland.region); @@ -2161,11 +2165,13 @@ static int MwLLPendingImpl(MwLL handle) { int pending = 0; if(handle->wayland.dark_theme_detection) { + handle->wayland.dark_theme_detection = MwFALSE; +#ifdef USE_DBUS if(wl_call_tbl.has_dbus) { detect_dark_theme(handle); - handle->wayland.dark_theme_detection = MwFALSE; MwLLDispatch(handle, draw, NULL); } +#endif } if(!handle->wayland.did_initial_resize) { @@ -2622,7 +2628,7 @@ static void MwLLEndStateChangeImpl(MwLL handle) { } } -static void MwLLSetDarkThemeImpl(MwLL handle, int toggle){ +static void MwLLSetDarkThemeImpl(MwLL handle, int toggle) { (void)handle; (void)toggle; } diff --git a/src/backend/x11.c b/src/backend/x11.c index a556c1c6f..898da85c0 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -9,8 +9,10 @@ static struct symtbl { void* lib_xrender; MwBool has_xrender; +#ifdef USE_DBUS MwLLDBusFuncTable dbus; MwBool has_dbus; +#endif int (*XClearWindow)(Display* display, Window w); XImage* (*XCreateImage)(Display*, Visual*, unsigned int, int, int, char*, unsigned int, unsigned int, int, int); @@ -311,6 +313,7 @@ static XVisualInfo* get_visual_info(Display* display) { return XGetVisualInfo(display, VisualIDMask, &xvi, &n); } +#ifdef USE_DBUS static void detect_dark_theme(MwLL handle) { MwU32 value = 0; MwU32 dark_theme = 0; @@ -320,6 +323,7 @@ static void detect_dark_theme(MwLL handle) { MwLLDispatch(handle, dark_theme, &dark_theme); } +#endif static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { MwLL r; @@ -470,9 +474,11 @@ static void MwLLDestroyImpl(MwLL handle) { if(handle->x11.toplevel) XCloseDisplay(handle->x11.display); +#ifdef USE_DBUS if(!xsymtbl.has_dbus) { MwLLDBusFreeContext(&xsymtbl.dbus, &handle->x11.dbus); } +#endif free(handle); } @@ -633,11 +639,13 @@ static int MwLLPendingImpl(MwLL handle) { XEvent ev; if(handle->x11.dark_theme_detection) { + handle->x11.dark_theme_detection = MwFALSE; +#ifdef USE_DBUS if(xsymtbl.has_dbus) { detect_dark_theme(handle); - handle->x11.dark_theme_detection = MwFALSE; MwLLDispatch(handle, draw, NULL); } +#endif } if(handle->x11.clipboard_pending && (MwTimeGetTick() - handle->x11.clipboard_time) >= ClipboardTimeout) { @@ -1258,9 +1266,12 @@ static void MwLLSetClipboardImpl(MwLL handle, const char* text, int clipboard_ty (void)handle; (void)text; + (void)clipboard_type; } static void MwLLGetClipboardImpl(MwLL handle, int clipboard_type) { + (void)clipboard_type; + if(handle->x11.clipboard_pending) return; XConvertSelection(handle->x11.display, handle->x11.clipboard, handle->x11.utf8_string, handle->x11.selection, handle->x11.window, CurrentTime); @@ -1308,7 +1319,7 @@ static void MwLLEndStateChangeImpl(MwLL handle) { MwLLShow(handle, 1); } -static void MwLLSetDarkThemeImpl(MwLL handle, int toggle){ +static void MwLLSetDarkThemeImpl(MwLL handle, int toggle) { (void)handle; (void)toggle; } @@ -1427,7 +1438,9 @@ static int MwLLX11CallInitImpl(void) { XRENDER_FUNC_LOAD(XRenderComposite) #endif +#ifdef USE_DBUS xsymtbl.has_dbus = MwLLDBusFuncSetup(&xsymtbl.dbus); +#endif return 0; } diff --git a/src/core.c b/src/core.c index 6c08970a8..0404fa72b 100644 --- a/src/core.c +++ b/src/core.c @@ -533,7 +533,7 @@ void MwSetInteger(MwWidget handle, const char* key, int n) { force_render_all(handle); } - if(strcmp(key, MwNdarkTheme) == 0){ + if(strcmp(key, MwNdarkTheme) == 0) { MwWidget h = handle; while(h->parent != NULL && h->parent->widget_class != NULL) h = h->parent; diff --git a/src/draw.c b/src/draw.c index 68f6862e6..8dde8418e 100644 --- a/src/draw.c +++ b/src/draw.c @@ -308,7 +308,7 @@ static void MwDrawFrameEx_simple(MwWidget handle, MwRect* rect, MwLLColor color, static void frame_border_complex(MwWidget handle, MwRect* rect, MwLLColor lighter, MwLLColor darker, int invert, int border, int diff, int same) { MwPoint p[7]; - + (void)diff; (void)same; diff --git a/src/string.c b/src/string.c index a7c23381c..f56b9acb7 100644 --- a/src/string.c +++ b/src/string.c @@ -52,7 +52,7 @@ void MwStringPrintIntoBuffer(char* out, MwU32 size, const char* fmt, ...) { MWDECL MwBool MwStringIsKeyUTF8(MwU32 key) { unsigned char bytes[4]; - int i; + int i; bytes[0] = (key & 0x000000FF); bytes[1] = (key & 0x0000FF00) >> 8; bytes[2] = (key & 0x00FF0000) >> 16; diff --git a/src/widget/scrollbar.c b/src/widget/scrollbar.c index a1df9b2db..bed80c0b2 100644 --- a/src/widget/scrollbar.c +++ b/src/widget/scrollbar.c @@ -58,9 +58,9 @@ static void draw(MwWidget handle) { MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); MwLLColor dark = MwLightenColor(handle, base, -64, -64, -64); MwScrollBar scr = handle->internal; - int or; - int uy, dy, ux, dx; - MwLLPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); + int or ; + int uy, dy, ux, dx; + MwLLPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap); r.x = 0; r.y = 0; From b82e13cb2e4ba772e342c68cbe30bb3ac210120f Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Thu, 16 Apr 2026 23:53:29 +0900 Subject: [PATCH 185/195] define opengl/vulkan symbols anyways --- CMakeLists.txt | 10 +++++----- pl/rules.pl | 6 ++++-- src/widget/opengl.c | 7 +++++++ src/widget/vulkan.c | 11 ++++++++++- 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c0c7f0b9d..a4f4eb3ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,9 +45,6 @@ file( external/libz/src/*.c src/*.c src/cursor/*.c src/icon/*.c src/widget/*.c src/text/*.c src/text/font/*.c src/dialog/*.c src/abstract/*.c external/*.c ) -list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/opengl.c") -list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/vulkan.c") - if(NOT MW_USE_STB_IMAGE) list(REMOVE_ITEM SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/external/stb_image.c") endif() @@ -65,7 +62,11 @@ if(MW_TRY_OPENGL) find_package(OpenGL) if(OpenGL_FOUND) set(MW_BUILD_OPENGL ON) - list(APPEND SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/opengl.c") + target_compile_definitions( + Mw + PRIVATE + MW_OPENGL + ) if(APPLE) list(APPEND SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/opengl_cocoa.m") endif() @@ -79,7 +80,6 @@ if(MW_TRY_VULKAN) check_include_files(vulkan/vulkan.h HAVE_VULKAN_VULKAN_H) if(HAVE_VULKAN_VULKAN_H) set(MW_BUILD_VULKAN ON) - list(APPEND SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/vulkan.c") target_compile_definitions( Mw PRIVATE diff --git a/pl/rules.pl b/pl/rules.pl index 6f64a174c..7ad414db7 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -139,12 +139,14 @@ new_object("src/widget/treeview.c"); new_object("src/widget/viewport.c"); new_object("src/widget/window.c"); +new_object("src/widget/opengl.c"); +new_object("src/widget/vulkan.c"); + if (param_get("opengl")) { - new_object("src/widget/opengl.c"); + add_cflags("-DMW_OPENGL"); } if (param_get("vulkan")) { add_cflags("-DMW_VULKAN"); - new_object("src/widget/vulkan.c"); } new_object("src/dialog/*.c"); diff --git a/src/widget/opengl.c b/src/widget/opengl.c index 39b5510c8..e8b222c25 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -1,6 +1,8 @@ #ifndef __APPLE__ #include + +#ifdef MW_OPENGL #include #ifdef USE_GDI @@ -516,5 +518,10 @@ MwClassRec MwOpenGLClassRec = {wcreate, /* create */ NULL, /* clipboard */ NULL, NULL, NULL, NULL}; MwClass MwOpenGLClass = &MwOpenGLClassRec; +#else +MWDECL MwClass MwOpenGLClass; + +MwClass MwOpenGLClass = NULL; +#endif #endif diff --git a/src/widget/vulkan.c b/src/widget/vulkan.c index 7cb33122a..394c9e5a0 100644 --- a/src/widget/vulkan.c +++ b/src/widget/vulkan.c @@ -1,10 +1,12 @@ #include -#include /** * ioixd maintains this file. nishi doesn't know vulkan at all */ +#ifdef MW_VULKAN +#include + #ifdef USE_GDI #define VK_USE_PLATFORM_WIN32_KHR 1 #endif @@ -165,6 +167,8 @@ static int _destroy(MwWidget handle) { static void destroy(MwWidget handle) { int err = _destroy(handle); + + (void)err; } static void* vulkan_lib_load() { @@ -577,3 +581,8 @@ MwClassRec MwVulkanClassRec = { NULL, NULL}; MwClass MwVulkanClass = &MwVulkanClassRec; +#else +MWDECL MwClass MwVulkanClass; + +MwClass MwVulkanClass = NULL; +#endif From 5201c46a219a8225d28206c1015b93e168ba1f84 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Fri, 17 Apr 2026 00:20:29 +0900 Subject: [PATCH 186/195] update vulkan/opengl --- include/Mw/Widget/Vulkan.h | 14 ++++---- milsko.xml | 69 +++++++++++++++++++++++++++++++------- src/widget/opengl.c | 5 ++- src/widget/vulkan.c | 29 ++++++++++++---- 4 files changed, 92 insertions(+), 25 deletions(-) diff --git a/include/Mw/Widget/Vulkan.h b/include/Mw/Widget/Vulkan.h index 3297d2271..217f0e56e 100644 --- a/include/Mw/Widget/Vulkan.h +++ b/include/Mw/Widget/Vulkan.h @@ -15,8 +15,10 @@ #error Vulkan is unsupported on the requested platform. #endif +#if !defined(MW_VULKAN_NO_INCLUDE) #include #include +#endif #include #include @@ -46,19 +48,19 @@ MWDECL void MwVulkanEnableLayer(const char* ext_name); /*! * @brief Configuration options that can be passed to setup Vulkan before a widget is created. */ -typedef struct MwVulkanConfig_T { +typedef struct _MwVulkanConfig { /*! * @brief Vulkan API version (default: VK_API_VERSION_1_0) */ - uint32_t api_version; + MwU32 api_version; /*! * @brief Vulkan version (default: VK_VERSION_1_0) */ - uint32_t vk_version; + MwU32 vk_version; /*! * @brief Whether or not to enable validation layers (default: false) */ - VkBool32 validation_layers; + int validation_layers; } MwVulkanConfig; /*! @@ -71,7 +73,7 @@ MWDECL void MwVulkanConfigure(MwVulkanConfig cfg); /*! * @brief Field that can be gotten from Vulkan. */ -typedef enum MwVulkanField_T { +typedef enum _MwVulkanField { /*! * @brief The address of the vulkan widget's vkGetInstanceProcAddr function (PFN_vkGetInstanceProcAddr) */ @@ -120,7 +122,7 @@ MwInline void* MwVulkanGetField(MwWidget handle, MwVulkanField field, int* out) /*! * @brief Return whether Vulkan is installed on the target platform. */ -MWDECL VkBool32 MwVulkanSupported(void); +MWDECL int MwVulkanSupported(void); #ifdef __cplusplus } diff --git a/milsko.xml b/milsko.xml index d42f7e961..2e522bd1d 100644 --- a/milsko.xml +++ b/milsko.xml @@ -67,10 +67,6 @@ - @@ -88,6 +84,9 @@ + + + @@ -150,9 +149,20 @@ - 0 + 0 + + 0 + + + + + + + + + 0x0fffffff @@ -409,14 +419,14 @@ - + - - + + @@ -502,6 +512,8 @@
+ + @@ -721,15 +733,48 @@ - - - + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/widget/opengl.c b/src/widget/opengl.c index e8b222c25..252d7ad56 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -2,9 +2,12 @@ #include -#ifdef MW_OPENGL +#ifndef MW_OPENGL +#define MW_OPENGL_NO_INCLUDE +#endif #include +#ifdef MW_OPENGL #ifdef USE_GDI typedef HGLRC(WINAPI* MWwglCreateContext)(HDC); typedef BOOL(WINAPI* MWwglMakeCurrent)(HDC, HGLRC); diff --git a/src/widget/vulkan.c b/src/widget/vulkan.c index 394c9e5a0..e87164627 100644 --- a/src/widget/vulkan.c +++ b/src/widget/vulkan.c @@ -4,9 +4,12 @@ * ioixd maintains this file. nishi doesn't know vulkan at all */ -#ifdef MW_VULKAN +#ifndef MW_VULKAN +#define MW_VULKAN_NO_INCLUDE +#endif #include +#ifdef MW_VULKAN #ifdef USE_GDI #define VK_USE_PLATFORM_WIN32_KHR 1 #endif @@ -498,7 +501,7 @@ void MwVulkanEnableLayer(const char* name) { arrput(enabledLayers, name); } -VkBool32 MwVulkanSupported(void) { +int MwVulkanSupported(void) { if(vulkan_supported == VULKAN_SUPPORTED_UNKNOWN) { void* lib = vulkan_lib_load(); if(lib == NULL) { @@ -509,9 +512,9 @@ VkBool32 MwVulkanSupported(void) { } } if(vulkan_supported == VULKAN_SUPPORTED_YES) { - return VK_TRUE; + return 1; } else { - return VK_FALSE; + return 0; } }; @@ -582,7 +585,21 @@ MwClassRec MwVulkanClassRec = { NULL}; MwClass MwVulkanClass = &MwVulkanClassRec; #else -MWDECL MwClass MwVulkanClass; - MwClass MwVulkanClass = NULL; + +void MwVulkanEnableExtension(const char* ext_name) { + (void)ext_name; +} + +void MwVulkanEnableLayer(const char* ext_name) { + (void)ext_name; +} + +void MwVulkanConfigure(MwVulkanConfig cfg) { + (void)cfg; +} + +int MwVulkanSupported(void) { + return 0; +} #endif From 13a2db7fa85c57bc5d3426d73248ee58c4d24d1e Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Fri, 17 Apr 2026 00:26:02 +0900 Subject: [PATCH 187/195] better for binding --- include/Mw/Widget/Vulkan.h | 2 +- milsko.xml | 6 +++--- src/widget/vulkan.c | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/Mw/Widget/Vulkan.h b/include/Mw/Widget/Vulkan.h index 217f0e56e..4f8a5e3db 100644 --- a/include/Mw/Widget/Vulkan.h +++ b/include/Mw/Widget/Vulkan.h @@ -113,7 +113,7 @@ typedef enum _MwVulkanField { * @brief Function for getting a field from within Vulkan. * @warning Consult the documentation for MwVulkanField to know what type is expected for out. */ -MwInline void* MwVulkanGetField(MwWidget handle, MwVulkanField field, int* out) { +MwInline void* MwVulkanGetField(MwWidget handle, int field, int* out) { void* field_out; MwVaWidgetExecute(handle, "mwVulkanGetField", &field_out, field, out); return field_out; diff --git a/milsko.xml b/milsko.xml index 2e522bd1d..253a4fee8 100644 --- a/milsko.xml +++ b/milsko.xml @@ -419,14 +419,14 @@ - + - + @@ -770,7 +770,7 @@ - + diff --git a/src/widget/vulkan.c b/src/widget/vulkan.c index e87164627..817644c3e 100644 --- a/src/widget/vulkan.c +++ b/src/widget/vulkan.c @@ -518,7 +518,7 @@ int MwVulkanSupported(void) { } }; -static void* mwVulkanGetFieldImpl(MwWidget handle, MwVulkanField field, int* out) { +static void* mwVulkanGetFieldImpl(MwWidget handle, int field, int* out) { vulkan_t* o = handle->internal; char buf[1024]; @@ -556,9 +556,9 @@ static void* mwVulkanGetFieldImpl(MwWidget handle, MwVulkanField field, int* out static void func_handler(MwWidget handle, const char* name, void* out, va_list va) { if(strcmp(name, "mwVulkanGetField") == 0) { - MwVulkanField field = va_arg(va, MwVulkanField); - int* err = va_arg(va, int*); - *(void**)out = mwVulkanGetFieldImpl(handle, field, err); + int field = va_arg(va, int); + int* err = va_arg(va, int*); + *(void**)out = mwVulkanGetFieldImpl(handle, field, err); } } From 7a2ca3aa2dcb4f42c383d696694bffd6d049375b Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Fri, 17 Apr 2026 00:27:04 +0900 Subject: [PATCH 188/195] oops --- milsko.xml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/milsko.xml b/milsko.xml index 253a4fee8..cca24fc6b 100644 --- a/milsko.xml +++ b/milsko.xml @@ -417,17 +417,17 @@ - - - - + + + + - - - - - + + + + + @@ -770,8 +770,8 @@ - - + + From 5220f742be8f1304415848f669f3c9444e805c2d Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Fri, 17 Apr 2026 01:03:14 +0900 Subject: [PATCH 189/195] some changes --- include/Mw/Widget/Vulkan.h | 2 +- milsko.xml | 19 +++++++++++++++++++ src/widget/vulkan.c | 6 +++--- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/include/Mw/Widget/Vulkan.h b/include/Mw/Widget/Vulkan.h index 4f8a5e3db..1b008e5a4 100644 --- a/include/Mw/Widget/Vulkan.h +++ b/include/Mw/Widget/Vulkan.h @@ -68,7 +68,7 @@ typedef struct _MwVulkanConfig { * @warning This must be called before MwCreateWidget. * @warning The configuration provided will be used for future initializations of the Vulkan widget (unless it's changed) */ -MWDECL void MwVulkanConfigure(MwVulkanConfig cfg); +MWDECL void MwVulkanConfigure(MwVulkanConfig* cfg); /*! * @brief Field that can be gotten from Vulkan. diff --git a/milsko.xml b/milsko.xml index cca24fc6b..76d4755e2 100644 --- a/milsko.xml +++ b/milsko.xml @@ -38,6 +38,11 @@
+ + + + + +
+ + + + + + + + + + +
diff --git a/src/widget/vulkan.c b/src/widget/vulkan.c index 817644c3e..e836ac379 100644 --- a/src/widget/vulkan.c +++ b/src/widget/vulkan.c @@ -489,8 +489,8 @@ static int vulkan_devices_setup(MwWidget handle, vulkan_t* o) { return 0; } -void MwVulkanConfigure(MwVulkanConfig cfg) { - vulkan_config = cfg; +void MwVulkanConfigure(MwVulkanConfig* cfg) { + vulkan_config = *cfg; } void MwVulkanEnableExtension(const char* name) { @@ -595,7 +595,7 @@ void MwVulkanEnableLayer(const char* ext_name) { (void)ext_name; } -void MwVulkanConfigure(MwVulkanConfig cfg) { +void MwVulkanConfigure(MwVulkanConfig* cfg) { (void)cfg; } From 570f05540ef6dc88bfd2f8cedb9de10bab0313e1 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Fri, 17 Apr 2026 01:36:34 +0900 Subject: [PATCH 190/195] many things changed --- examples/basic/clipboard.c | 4 +- examples/gldemos/tripaint.c | 6 +-- examples/vkdemos/vulkan.c | 18 ++++----- include/Mw/Constants.h | 22 +++++++++++ include/Mw/LowLevel.h | 14 ------- include/Mw/StringDefs.h | 41 ++++++++++---------- include/Mw/TypeDefs.h | 20 +++------- include/Mw/Widget/Vulkan.h | 24 ++++++------ milsko.xml | 74 ++++++++++++++++++++++++++++++------- src/backend/cocoa.m | 68 +++++++++++++++++----------------- src/backend/gdi.c | 24 ++++++------ src/backend/wayland.c | 34 ++++++++--------- src/backend/x11.c | 24 ++++++------ src/core.c | 17 +++++---- src/dialog/colorpicker.c | 2 +- src/dialog/filechooser.c | 4 +- src/widget/combobox.c | 2 +- src/widget/entry.c | 8 ++-- src/widget/listbox.c | 14 +++---- src/widget/menu.c | 4 +- src/widget/numberentry.c | 4 +- src/widget/scrollbar.c | 8 ++-- src/widget/submenu.c | 2 +- src/widget/treeview.c | 10 ++--- src/widget/vulkan.c | 18 ++++----- 25 files changed, 258 insertions(+), 208 deletions(-) diff --git a/examples/basic/clipboard.c b/examples/basic/clipboard.c index 38084a184..94a192f22 100644 --- a/examples/basic/clipboard.c +++ b/examples/basic/clipboard.c @@ -42,9 +42,9 @@ static void clipboard(MwWidget handle, void* user_data, void* call_data) { static void tick(MwWidget handle, void* user_data, void* call_data) { cur_text = text1; - MwGetClipboard(handle, MwClipboardMain); + MwGetClipboard(handle, MwCLIPBOARD_MAIN); cur_text = text2; - MwGetClipboard(handle, MwClipboardPrimary); + MwGetClipboard(handle, MwCLIPBOARD_PRIMARY); MwForceRender(window); } diff --git a/examples/gldemos/tripaint.c b/examples/gldemos/tripaint.c index 2cc7aa844..1208b26ae 100644 --- a/examples/gldemos/tripaint.c +++ b/examples/gldemos/tripaint.c @@ -51,12 +51,12 @@ static void tick(MwWidget handle, void* user, void* call) { } static void mouse(MwWidget handle, void* user, void* call) { - MwLLMouse* mouse = call; + MwMouse* mouse = call; (void)handle; (void)user; - if(mouse->button == MwLLMouseLeft) { + if(mouse->button == MwMOUSE_LEFT) { t[ct].points[click * 2 + 0] = mouse->point.x; t[ct].points[click * 2 + 1] = mouse->point.y; click++; @@ -82,7 +82,7 @@ static void mouse(MwWidget handle, void* user, void* call) { for(i = 0; i < ct; i++) t[i] = old[i]; free(old); } - } else if(mouse->button == MwLLMouseRight) { + } else if(mouse->button == MwMOUSE_RIGHT) { if(click > 0) { click = 0; } else if(ct > 0) { diff --git a/examples/vkdemos/vulkan.c b/examples/vkdemos/vulkan.c index 0c59891ad..7e20a5be7 100644 --- a/examples/vkdemos/vulkan.c +++ b/examples/vkdemos/vulkan.c @@ -232,15 +232,15 @@ void vulkan_setup(MwWidget handle) { VkFenceCreateInfo fenceInfo = {}; int err = 0; - _vkGetInstanceProcAddr = MwVulkanGetField(handle, MwVulkanField_GetInstanceProcAddr, &err); - instance = MwVulkanGetField(handle, MwVulkanField_Instance, &err); - device = MwVulkanGetField(handle, MwVulkanField_LogicalDevice, &err); - physicalDevice = MwVulkanGetField(handle, MwVulkanField_PhysicalDevice, &err); - graphicsQueue = MwVulkanGetField(handle, MwVulkanField_GraphicsQueue, &err); - presentQueue = MwVulkanGetField(handle, MwVulkanField_PresentQueue, &err); - surface = MwVulkanGetField(handle, MwVulkanField_Surface, &err); - presentQueueIndex = MwVulkanGetField(handle, MwVulkanField_PresentQueueIndex, &err); - graphicsQueueIndex = MwVulkanGetField(handle, MwVulkanField_GraphicsQueueIndex, &err); + _vkGetInstanceProcAddr = MwVulkanGetField(handle, MwVULKANFIELD_GETINSTANCEPROCADDR, &err); + instance = MwVulkanGetField(handle, MwVULKANFIELD_INSTANCE, &err); + device = MwVulkanGetField(handle, MwVULKANFIELD_LOGICALDEVICE, &err); + physicalDevice = MwVulkanGetField(handle, MwVULKANFIELD_PHYSICALDEVICE, &err); + graphicsQueue = MwVulkanGetField(handle, MwVULKANFIELD_GRAPHICSQUEUE, &err); + presentQueue = MwVulkanGetField(handle, MwVULKANFIELD_PRESENTQUEUE, &err); + surface = MwVulkanGetField(handle, MwVULKANFIELD_SURFACE, &err); + presentQueueIndex = MwVulkanGetField(handle, MwVULKANFIELD_PRESENTQUEUEINDEX, &err); + graphicsQueueIndex = MwVulkanGetField(handle, MwVULKANFIELD_GRAPHICSQUEUEINDEX, &err); LOAD_VK_FUNCTION(vkCreateShaderModule); LOAD_VK_FUNCTION(vkCreatePipelineLayout); diff --git a/include/Mw/Constants.h b/include/Mw/Constants.h index bc4757f49..d710ca006 100644 --- a/include/Mw/Constants.h +++ b/include/Mw/Constants.h @@ -99,4 +99,26 @@ enum MwMB_ICON { */ #define MwMB_BUTTONYESNOCANCEL (MwMB_BUTTONYES | MwMB_BUTTONNO | MwMB_BUTTONCANCEL) +/* Whether or not GetXY/SetXY works with global or local coordinates */ +enum MwCOORDINATE { + MwCOORDINATE_GLOBAL = 0, + MwCOORDINATE_LOCAL, +}; + +/* The clipboard type that MwGetClipboard should return */ +enum MwCLIPBOARD { + /* the clipboard that is present on every platform that supports it */ + MwCLIPBOARD_MAIN = 0, + /* the "primary" clipboard that Wayland stores to emulate X11's behavior. */ + MwCLIPBOARD_PRIMARY, +}; + +enum MwMOUSE { + MwMOUSE_LEFT = 1, + MwMOUSE_MIDDLE, + MwMOUSE_RIGHT, + MwMOUSE_WHEELUP, + MwMOUSE_WHEELDOWN +}; + #endif diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index ea31aefea..cbc67f9e0 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -10,7 +10,6 @@ #include typedef struct _MwLLHandler* MwLLHandler; -typedef struct _MwLLMouse MwLLMouse; typedef struct _MwLLCommon* MwLLCommon; typedef struct _MwLLCommonColor* MwLLCommonColor; typedef struct _MwLLCommonPixmap* MwLLCommonPixmap; @@ -187,19 +186,6 @@ enum MwLLKeyEnum { #define MwLLControlMask MwLLKeyMask | (1 << 30) #define MwLLAltMask MwLLKeyMask | (1 << 29) -enum MwLLMouseEnum { - MwLLMouseLeft = 1, - MwLLMouseMiddle, - MwLLMouseRight, - MwLLMouseWheelUp, - MwLLMouseWheelDown -}; - -struct _MwLLMouse { - MwPoint point; - int button; -}; - struct _MwLLHandler { void (*draw)(MwLL handle, void* data); void (*up)(MwLL handle, void* data); diff --git a/include/Mw/StringDefs.h b/include/Mw/StringDefs.h index cac605a5e..c657a637e 100644 --- a/include/Mw/StringDefs.h +++ b/include/Mw/StringDefs.h @@ -60,24 +60,27 @@ #define MwNmonospaceFont "VmonospaceFont" #define MwNboldMonospaceFont "VboldMonospaceFont" -#define MwNactivateHandler "Cactivate" /* NULL/int* (MwListBox)/void* (MwTreeView) */ -#define MwNresizeHandler "Cresize" /* NULL */ -#define MwNtickHandler "Ctick" /* NULL */ -#define MwNmenuHandler "Cmenu" /* MwMenu */ -#define MwNmouseDownHandler "CmouseDown" /* MwLLMouse* */ -#define MwNmouseUpHandler "CmouseUp" /* same as MwNmouseDownHandler */ -#define MwNmouseMoveHandler "CmouseMove" /* MwPoint* */ -#define MwNchangedHandler "Cchanged" /* NULL/int* (MwComboBox) */ -#define MwNkeyHandler "Ckey" /* int* (MwLLKeyEnum or character code) */ -#define MwNkeyReleaseHandler "CkeyRelease" /* same as MwNkeyHandler */ -#define MwNcloseHandler "Cclose" /* NULL */ -#define MwNfocusInHandler "CfocusIn" /* NULL */ -#define MwNfocusOutHandler "CfocusOut" /* NULL */ -#define MwNfileChosenHandler "CfileChosen" /* char* */ -#define MwNdirectoryChosenHandler "CdirectoryChosen" /* char* */ -#define MwNcolorChosenHandler "CcolorChosen" /* MwRGB* */ -#define MwNdrawHandler "Cdraw" /* NULL */ -#define MwNclipboardHandler "Cclipboard" /* char* */ -#define MwNdarkThemeHandler "CdarkTheme" /* int* */ +#define MwNactivateHandler "Cactivate" /* NULL */ +#define MwNlistBoxActivateHandler "ClistBoxActivate" /* int* */ +#define MwNtreeViewActivateHandler "CtreeViewActivate" /* void* */ +#define MwNresizeHandler "Cresize" /* NULL */ +#define MwNtickHandler "Ctick" /* NULL */ +#define MwNmenuHandler "Cmenu" /* MwMenu */ +#define MwNmouseDownHandler "CmouseDown" /* MwMouse* */ +#define MwNmouseUpHandler "CmouseUp" /* same as MwNmouseDownHandler */ +#define MwNmouseMoveHandler "CmouseMove" /* MwPoint* */ +#define MwNchangedHandler "Cchanged" /* NULL */ +#define MwNcomboBoxChangedHandler "CcomboBoxChanged" /* int* */ +#define MwNkeyHandler "Ckey" /* int* (MwLLKeyEnum or character code) */ +#define MwNkeyReleaseHandler "CkeyRelease" /* same as MwNkeyHandler */ +#define MwNcloseHandler "Cclose" /* NULL */ +#define MwNfocusInHandler "CfocusIn" /* NULL */ +#define MwNfocusOutHandler "CfocusOut" /* NULL */ +#define MwNfileChosenHandler "CfileChosen" /* char* */ +#define MwNdirectoryChosenHandler "CdirectoryChosen" /* char* */ +#define MwNcolorChosenHandler "CcolorChosen" /* MwRGB* */ +#define MwNdrawHandler "Cdraw" /* NULL */ +#define MwNclipboardHandler "Cclipboard" /* char* */ +#define MwNdarkThemeHandler "CdarkTheme" /* int* */ #endif diff --git a/include/Mw/TypeDefs.h b/include/Mw/TypeDefs.h index bd0af3d78..ca8e32b05 100644 --- a/include/Mw/TypeDefs.h +++ b/include/Mw/TypeDefs.h @@ -28,6 +28,7 @@ typedef struct _MwTreeViewEntry MwTreeViewEntry; typedef struct _MwDirectoryEntry MwDirectoryEntry; typedef struct _MwListBoxPacket MwListBoxPacket; typedef struct _MwBox* MwBox; +typedef struct _MwMouse MwMouse; #ifdef _MILSKO typedef struct _MwWidget* MwWidget; #else @@ -210,6 +211,11 @@ struct _MwBox { int layout; }; +struct _MwMouse { + MwPoint point; + int button; +}; + struct _MwClass { MwHandlerWithStatus create; MwHandler destroy; @@ -233,18 +239,4 @@ struct _MwClass { void* reserved4; }; -/* Whether or not GetXY/SetXY works with global or local coordinates */ -enum MwCoordinateType { - MwCoordinatesGlobal = 0, - MwCoordinatesLocal, -}; - -/* The clipboard type that MwGetClipboard should return */ -enum MwClipboardType { - /* the clipboard that is present on every platform that supports it */ - MwClipboardMain = 0, - /* the "primary" clipboard that Wayland stores to emulate X11's behavior. */ - MwClipboardPrimary, -}; - #endif diff --git a/include/Mw/Widget/Vulkan.h b/include/Mw/Widget/Vulkan.h index 1b008e5a4..ccfb02446 100644 --- a/include/Mw/Widget/Vulkan.h +++ b/include/Mw/Widget/Vulkan.h @@ -73,45 +73,45 @@ MWDECL void MwVulkanConfigure(MwVulkanConfig* cfg); /*! * @brief Field that can be gotten from Vulkan. */ -typedef enum _MwVulkanField { +enum MwVULKANFIELD { /*! * @brief The address of the vulkan widget's vkGetInstanceProcAddr function (PFN_vkGetInstanceProcAddr) */ - MwVulkanField_GetInstanceProcAddr = 0, + MwVULKANFIELD_GETINSTANCEPROCADDR = 0, /*! * @brief The address of the vulkan widget's instance (VkInstance) */ - MwVulkanField_Instance, + MwVULKANFIELD_INSTANCE, /*! * @brief The address of the vulkan widget's surface (VkSurfaceKHR) */ - MwVulkanField_Surface, + MwVULKANFIELD_SURFACE, /*! * @brief The address of the vulkan widget's physical device (VkPhysicalDevice) */ - MwVulkanField_PhysicalDevice, + MwVULKANFIELD_PHYSICALDEVICE, /*! * @brief The address of the vulkan widget's logical device (VkDevice) */ - MwVulkanField_LogicalDevice, + MwVULKANFIELD_LOGICALDEVICE, /*! * @brief The address of the index that the vulkan widget uses for the graphics queue (uint32_t *) */ - MwVulkanField_GraphicsQueueIndex, + MwVULKANFIELD_GRAPHICSQUEUEINDEX, /*! * @brief The address of the index that the vulkan widget uses for the present queue (uint32_t *) */ - MwVulkanField_PresentQueueIndex, - MwVulkanField_GraphicsQueue, + MwVULKANFIELD_PRESENTQUEUEINDEX, + MwVULKANFIELD_GRAPHICSQUEUE, /*! * @brief The address of the vulkan widget's graphics queue (VkQueue) */ - MwVulkanField_PresentQueue, -} MwVulkanField; + MwVULKANFIELD_PRESENTQUEUE, +}; /*! * @brief Function for getting a field from within Vulkan. - * @warning Consult the documentation for MwVulkanField to know what type is expected for out. + * @warning Consult the documentation for MwVULKANFIELD to know what type is expected for out. */ MwInline void* MwVulkanGetField(MwWidget handle, int field, int* out) { void* field_out; diff --git a/milsko.xml b/milsko.xml index 76d4755e2..2edcd4169 100644 --- a/milsko.xml +++ b/milsko.xml @@ -38,6 +38,10 @@
+ + + + @@ -109,24 +113,55 @@ + + + + + + - - - - + + + + + + + + + + + + - - + + + + + + + + + - - - + + + + + + + + + - - + + + + + +
@@ -153,9 +188,20 @@ - - 0 - + + 0 + + + + 0 + + + + 1 + + + + 0 diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index cfac1add0..d9c6382ee 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -347,12 +347,12 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { } - (void)mouseMoved:(NSEvent*)ev { - MwLLMouse mouse; - NSPoint mousePoint = pointFlip([ev locationInWindow]); - MwLL this = [((MilskoFakePointer*)[[self subviews] objectAtIndex:0]) pointer]; - mouse.button = MwLLMouseLeft; - mouse.point.x = mousePoint.x; - mouse.point.y = mousePoint.y; + MwMouse mouse; + NSPoint mousePoint = pointFlip([ev locationInWindow]); + MwLL this = [((MilskoFakePointer*)[[self subviews] objectAtIndex:0]) pointer]; + mouse.button = MwMOUSE_LEFT; + mouse.point.x = mousePoint.x; + mouse.point.y = mousePoint.y; MwLLDispatch(this, move, &mouse); [this->cocoa.real nudge]; [super mouseMoved:ev]; @@ -362,51 +362,51 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) { } - (void)mouseDown:(NSEvent*)ev { - MwLLMouse mouse; - NSPoint mousePoint = [ev locationInWindow]; - MwLL this = [((MilskoFakePointer*)[[self subviews] objectAtIndex:0]) pointer]; - mousePoint.y = [[ev window] frame].size.height - mousePoint.y; - mouse.button = MwLLMouseLeft; - mouse.point.x = mousePoint.x; - mouse.point.y = mousePoint.y; + MwMouse mouse; + NSPoint mousePoint = [ev locationInWindow]; + MwLL this = [((MilskoFakePointer*)[[self subviews] objectAtIndex:0]) pointer]; + mousePoint.y = [[ev window] frame].size.height - mousePoint.y; + mouse.button = MwMOUSE_LEFT; + mouse.point.x = mousePoint.x; + mouse.point.y = mousePoint.y; MwLLDispatch(this, down, &mouse); [this->cocoa.real nudge]; [super mouseDown:ev]; } - (void)mouseUp:(NSEvent*)ev { - MwLLMouse mouse; - NSPoint mousePoint = [ev locationInWindow]; - MwLL this = [((MilskoFakePointer*)[[self subviews] objectAtIndex:0]) pointer]; - mousePoint.y = [[ev window] frame].size.height - mousePoint.y; - mouse.button = MwLLMouseLeft; - mouse.point.x = mousePoint.x; - mouse.point.y = mousePoint.y; + MwMouse mouse; + NSPoint mousePoint = [ev locationInWindow]; + MwLL this = [((MilskoFakePointer*)[[self subviews] objectAtIndex:0]) pointer]; + mousePoint.y = [[ev window] frame].size.height - mousePoint.y; + mouse.button = MwMOUSE_LEFT; + mouse.point.x = mousePoint.x; + mouse.point.y = mousePoint.y; MwLLDispatch(this, up, &mouse); [this->cocoa.real nudge]; [super mouseUp:ev]; } - (void)rightMouseDown:(NSEvent*)ev { - MwLLMouse mouse; - NSPoint mousePoint = [ev locationInWindow]; - MwLL this = [((MilskoFakePointer*)[[self subviews] objectAtIndex:0]) pointer]; - mousePoint.y = [[ev window] frame].size.height - mousePoint.y; - mouse.button = MwLLMouseRight; - mouse.point.x = mousePoint.x; - mouse.point.y = mousePoint.y; + MwMouse mouse; + NSPoint mousePoint = [ev locationInWindow]; + MwLL this = [((MilskoFakePointer*)[[self subviews] objectAtIndex:0]) pointer]; + mousePoint.y = [[ev window] frame].size.height - mousePoint.y; + mouse.button = MwMOUSE_RIGHT; + mouse.point.x = mousePoint.x; + mouse.point.y = mousePoint.y; MwLLDispatch(this, down, &mouse); [this->cocoa.real nudge]; [super rightMouseDown:ev]; } - (void)rightMouseUp:(NSEvent*)ev { - MwLLMouse mouse; - NSPoint mousePoint = [ev locationInWindow]; - MwLL this = [((MilskoFakePointer*)[[self subviews] objectAtIndex:0]) pointer]; - mousePoint.y = [[ev window] frame].size.height - mousePoint.y; - mouse.button = MwLLMouseRight; - mouse.point.x = mousePoint.x; - mouse.point.y = mousePoint.y; + MwMouse mouse; + NSPoint mousePoint = [ev locationInWindow]; + MwLL this = [((MilskoFakePointer*)[[self subviews] objectAtIndex:0]) pointer]; + mousePoint.y = [[ev window] frame].size.height - mousePoint.y; + mouse.button = MwMOUSE_RIGHT; + mouse.point.x = mousePoint.x; + mouse.point.y = mousePoint.y; MwLLDispatch(this, up, &mouse); [this->cocoa.real nudge]; [super rightMouseUp:ev]; diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 055b6c26d..024959e9d 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -79,44 +79,44 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { EndPaint(hWnd, &ps); } } else if(msg == WM_LBUTTONDOWN || msg == WM_MBUTTONDOWN || msg == WM_RBUTTONDOWN) { - MwLLMouse p; + MwMouse p; p.point.x = LOWORD(lp); p.point.y = HIWORD(lp); if(msg == WM_LBUTTONDOWN) { - p.button = MwLLMouseLeft; + p.button = MwMOUSE_LEFT; } else if(msg == WM_MBUTTONDOWN) { - p.button = MwLLMouseMiddle; + p.button = MwMOUSE_MIDDLE; } else if(msg == WM_RBUTTONDOWN) { - p.button = MwLLMouseRight; + p.button = MwMOUSE_RIGHT; } SetCapture(hWnd); SetFocus(hWnd); MwLLDispatch(u->ll, down, &p); } else if(msg == WM_LBUTTONUP || msg == WM_MBUTTONUP || msg == WM_RBUTTONUP) { - MwLLMouse p; + MwMouse p; p.point.x = LOWORD(lp); p.point.y = HIWORD(lp); if(msg == WM_LBUTTONUP) { - p.button = MwLLMouseLeft; + p.button = MwMOUSE_LEFT; } else if(msg == WM_MBUTTONUP) { - p.button = MwLLMouseMiddle; + p.button = MwMOUSE_MIDDLE; } else if(msg == WM_RBUTTONUP) { - p.button = MwLLMouseRight; + p.button = MwMOUSE_RIGHT; } SetCapture(NULL); MwLLDispatch(u->ll, up, &p); } else if(msg == WM_MOUSEWHEEL) { - int d = GET_WHEEL_DELTA_WPARAM(wp); - MwLLMouse p; + int d = GET_WHEEL_DELTA_WPARAM(wp); + MwMouse p; p.point.x = LOWORD(lp); p.point.y = HIWORD(lp); if(d > 0) { - p.button = MwLLMouseWheelUp; + p.button = MwMOUSE_WHEELUP; } else if(d < 0) { - p.button = MwLLMouseWheelDown; + p.button = MwMOUSE_WHEELDOWN; } MwLLDispatch(u->ll, down, &p); diff --git a/src/backend/wayland.c b/src/backend/wayland.c index fc4a67fc4..31eefb20e 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -119,7 +119,7 @@ static void recursive_dispatch_resize(MwLL handle) { }; /* Recursively dispatch a move event to a widget and its children */ -static void recursive_dispatch_move(MwLL handle, MwLLMouse* p) { +static void recursive_dispatch_move(MwLL handle, MwMouse* p) { MwWidget h = (MwWidget)handle->common.user; if(h) { int i; @@ -282,7 +282,7 @@ static void wl_clipboard_read(wl_clipboard_device_context_t* ctx, int clipboard_ timeout.tv_sec = 0; timeout.tv_usec = 100; - if(clipboard_type == MwClipboardPrimary) { + if(clipboard_type == MwCLIPBOARD_PRIMARY) { zwp_primary_selection_offer_v1_receive(ctx->offer.zwp, "text/plain", fds[1]); } else if(ctx->offer.wl) { wl_data_offer_receive(ctx->offer.wl, "text/plain", fds[1]); @@ -501,7 +501,7 @@ static void pointer_leave(void* data, struct wl_pointer* wl_pointer, MwU32 seria WAYLAND_EVENT_OP_END(self); }; -static void xdg_borderless_step(MwLL self, MwLLMouse p, MwU32 serial) { +static void xdg_borderless_step(MwLL self, MwMouse p, MwU32 serial) { if(self->wayland.type == MWLL_WAYLAND_TOPLEVEL && self->wayland.backbuffer.surface == curSurface) { if(p.point.y >= (self->wayland.wh + CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM) - 5) { if(p.point.x >= (self->wayland.ww + CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT) - 5) { @@ -535,8 +535,8 @@ static void relative_pointer_motion(void* data, wl_fixed_t dy, wl_fixed_t dxUnaccel, wl_fixed_t dyUnaccel) { - MwLL self = data; - MwLLMouse p; + MwLL self = data; + MwMouse p; WAYLAND_EVENT_OP_START(self); @@ -567,9 +567,9 @@ static void zwp_relative_pointer_manager_v1_interface_destroy(struct _MwLLWaylan /* `wl_pointer.motion` callback */ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time, wl_fixed_t surface_x, wl_fixed_t surface_y) { - MwLL self = data; - MwLL topmost_parent = self; - MwLLMouse p; + MwLL self = data; + MwLL topmost_parent = self; + MwMouse p; (void)time; (void)wl_pointer; @@ -590,9 +590,9 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time /* `wl_pointer.button` callback */ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 serial, MwU32 time, MwU32 button, MwU32 state) { - MwLL self = data; - MwLLMouse p; - MwBool inArea = MwFALSE; + MwLL self = data; + MwMouse p; + MwBool inArea = MwFALSE; (void)wl_pointer; (void)serial; @@ -613,13 +613,13 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri switch(button) { case BTN_LEFT: - p.button = MwLLMouseLeft; + p.button = MwMOUSE_LEFT; break; case BTN_MIDDLE: - p.button = MwLLMouseMiddle; + p.button = MwMOUSE_MIDDLE; break; case BTN_RIGHT: - p.button = MwLLMouseRight; + p.button = MwMOUSE_RIGHT; break; } self->wayland.held_down = state == WL_POINTER_BUTTON_STATE_PRESSED; @@ -1757,7 +1757,7 @@ static void wl_logger(const char* fmt, va_list args) { static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int height, enum _MwLLWaylandType ty) { /* Wayland does not report global coordinates ever. Compositors are not even expected to have knowledge of this. */ - r->common.coordinate_type = MwCoordinatesLocal; + r->common.coordinate_type = MwCOORDINATE_LOCAL; r->common.type = MwLLBackendWayland; @@ -2510,7 +2510,7 @@ static void MwLLSetClipboardImpl(MwLL handle, const char* text, int clipboard_ty handle->wayland.clipboard_buffer = malloc(strlen(text)); strcpy(handle->wayland.clipboard_buffer, text); - if(clipboard_type == MwClipboardPrimary) { + if(clipboard_type == MwCLIPBOARD_PRIMARY) { if(handle->wayland.supports_zwp) { for(i = 0; i < arrlen(handle->wayland.clipboard_devices_zwp); i++) { wl_clipboard_device_context_t* device = handle->wayland.clipboard_devices_zwp[i]; @@ -2529,7 +2529,7 @@ static void MwLLSetClipboardImpl(MwLL handle, const char* text, int clipboard_ty static void MwLLGetClipboardImpl(MwLL handle, int clipboard_type) { int i; - if(clipboard_type == MwClipboardPrimary) { + if(clipboard_type == MwCLIPBOARD_PRIMARY) { if(handle->wayland.supports_zwp) { for(i = 0; i < arrlen(handle->wayland.clipboard_devices_zwp); i++) { wl_clipboard_read( diff --git a/src/backend/x11.c b/src/backend/x11.c index 898da85c0..cc76ed66e 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -694,38 +694,38 @@ static void MwLLNextEventImpl(MwLL handle) { handle->x11.force_render = 0; render = 1; } else if(ev.type == ButtonPress) { - MwLLMouse p; + MwMouse p; p.point.x = ev.xbutton.x; p.point.y = ev.xbutton.y; if(ev.xbutton.button == Button1) { - p.button = MwLLMouseLeft; + p.button = MwMOUSE_LEFT; } else if(ev.xbutton.button == Button2) { - p.button = MwLLMouseMiddle; + p.button = MwMOUSE_MIDDLE; } else if(ev.xbutton.button == Button3) { - p.button = MwLLMouseRight; + p.button = MwMOUSE_RIGHT; } else if(ev.xbutton.button == Button4) { - p.button = MwLLMouseWheelUp; + p.button = MwMOUSE_WHEELUP; } else if(ev.xbutton.button == Button5) { - p.button = MwLLMouseWheelDown; + p.button = MwMOUSE_WHEELDOWN; } XSetInputFocus(handle->x11.display, handle->x11.window, RevertToNone, CurrentTime); MwLLDispatch(handle, down, &p); } else if(ev.type == ButtonRelease) { - MwLLMouse p; + MwMouse p; p.point.x = ev.xbutton.x; p.point.y = ev.xbutton.y; if(ev.xbutton.button == Button1) { - p.button = MwLLMouseLeft; + p.button = MwMOUSE_LEFT; } else if(ev.xbutton.button == Button2) { - p.button = MwLLMouseMiddle; + p.button = MwMOUSE_MIDDLE; } else if(ev.xbutton.button == Button3) { - p.button = MwLLMouseRight; + p.button = MwMOUSE_RIGHT; } else if(ev.xbutton.button == Button4) { - p.button = MwLLMouseWheelUp; + p.button = MwMOUSE_WHEELUP; } else if(ev.xbutton.button == Button5) { - p.button = MwLLMouseWheelDown; + p.button = MwMOUSE_WHEELDOWN; } MwLLDispatch(handle, up, &p); diff --git a/src/core.c b/src/core.c index 0404fa72b..0c8360ef9 100644 --- a/src/core.c +++ b/src/core.c @@ -52,22 +52,23 @@ static void lldrawhandler(MwLL handle, void* data) { } static void lluphandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; - MwLLMouse* p = data; + MwWidget h = (MwWidget)handle->common.user; + MwMouse* p = data; - if(p->button == MwLLMouseLeft) h->pressed = 0; + if(p->button == MwMOUSE_LEFT) h->pressed = 0; h->mouse_point.x = p->point.x; h->mouse_point.y = p->point.y; - if(p->button == MwLLMouseLeft) MwDispatch(h, click); + if(p->button == MwMOUSE_LEFT) MwDispatch(h, click); MwDispatch3(h, mouse_up, data); MwDispatchUserHandler(h, MwNmouseUpHandler, data); } static void lldownhandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->common.user; - MwLLMouse* p = data; - if(p->button == MwLLMouseLeft) h->pressed = 1; + MwWidget h = (MwWidget)handle->common.user; + MwMouse* p = data; + + if(p->button == MwMOUSE_LEFT) h->pressed = 1; h->mouse_point.x = p->point.x; h->mouse_point.y = p->point.y; @@ -962,7 +963,7 @@ int MwGetCoordinateType(MwWidget handle) { if(handle->parent == NULL || handle->parent->lowlevel == NULL) { return handle->lowlevel->common.coordinate_type; } else { - return MwCoordinatesLocal; + return MwCOORDINATE_LOCAL; } } diff --git a/src/dialog/colorpicker.c b/src/dialog/colorpicker.c index 3b7d33188..c08b53589 100644 --- a/src/dialog/colorpicker.c +++ b/src/dialog/colorpicker.c @@ -160,7 +160,7 @@ static void color_picker_image_update(color_picker_t* picker) { static void color_picker_click(MwWidget handle, void* user, void* call) { color_picker_t* picker = user; - MwLLMouse* mouse = call; + MwMouse* mouse = call; char hexColor[8]; int i; char fgColor[8]; diff --git a/src/dialog/filechooser.c b/src/dialog/filechooser.c index c18027677..ff1683c36 100644 --- a/src/dialog/filechooser.c +++ b/src/dialog/filechooser.c @@ -221,7 +221,7 @@ static void layout(MwWidget handle) { MwNleftPadding, 16, NULL); MwListBoxInsert(fc->nav, -1, p); - MwAddUserHandler(fc->nav, MwNactivateHandler, nav_activate, NULL); + MwAddUserHandler(fc->nav, MwNlistBoxActivateHandler, nav_activate, NULL); MwListBoxDestroyPacket(p); } else { @@ -242,7 +242,7 @@ static void layout(MwWidget handle) { MwNhasHeading, 1, MwNleftPadding, 16, NULL); - MwAddUserHandler(fc->files, MwNactivateHandler, files_activate, NULL); + MwAddUserHandler(fc->files, MwNlistBoxActivateHandler, files_activate, NULL); } else { MwVaApply(fc->files, MwNx, wx, diff --git a/src/widget/combobox.c b/src/widget/combobox.c index c061512d7..4c964f105 100644 --- a/src/widget/combobox.c +++ b/src/widget/combobox.c @@ -89,7 +89,7 @@ static void listbox_activate(MwWidget handle, void* user, void* client) { MwForceRender(handle->parent); - MwDispatchUserHandler(handle->parent, MwNchangedHandler, client); + MwDispatchUserHandler(handle->parent, MwNcomboBoxChangedHandler, client); MwDestroyWidget(handle); } diff --git a/src/widget/entry.c b/src/widget/entry.c index 846dc1979..41b976e83 100644 --- a/src/widget/entry.c +++ b/src/widget/entry.c @@ -113,7 +113,7 @@ static void key(MwWidget handle, int code) { } else if(code == MwLLKeyEnter) { MwDispatchUserHandler(handle, MwNactivateHandler, NULL); } else if(code == (MwLLControlMask | 'v')) { - MwLLGetClipboard(handle->lowlevel, MwClipboardMain); + MwLLGetClipboard(handle->lowlevel, MwCLIPBOARD_MAIN); } else if(!(code & MwLLKeyMask)) { int incr = 0; out = malloc(strlen(str) + 5 + 1); @@ -136,9 +136,9 @@ static void key(MwWidget handle, int code) { #if defined(USE_X11) || defined(USE_WAYLAND) static void mouse_up(MwWidget handle, void* ptr) { if(handle->lowlevel->common.type == MwLLBackendWayland || handle->lowlevel->common.type == MwLLBackendX11) { - MwLLMouse* mouse = ptr; - if(mouse->button == MwLLMouseMiddle) { - MwLLGetClipboard(handle->lowlevel, MwClipboardPrimary); + MwMouse* mouse = ptr; + if(mouse->button == MwMOUSE_MIDDLE) { + MwLLGetClipboard(handle->lowlevel, MwCLIPBOARD_PRIMARY); } } MwForceRender2(handle, NULL); diff --git a/src/widget/listbox.c b/src/widget/listbox.c index 98c86cf97..6f2a9db2a 100644 --- a/src/widget/listbox.c +++ b/src/widget/listbox.c @@ -119,12 +119,12 @@ static void vscroll_changed(MwWidget handle, void* user, void* call) { } static void frame_mouse_down(MwWidget handle, void* user, void* call) { - MwListBox lb = handle->parent->internal; - MwLLMouse* m = call; + MwListBox lb = handle->parent->internal; + MwMouse* m = call; (void)user; - if(m->button == MwLLMouseLeft) { + if(m->button == MwMOUSE_LEFT) { int st = 0; int i; int y = MwDefaultBorderWidth(handle); @@ -140,7 +140,7 @@ static void frame_mouse_down(MwWidget handle, void* user, void* call) { if((((t = MwTimeGetTick()) - lb->click_time) < MwDoubleClickTimeout && old == st + i) || MwGetInteger(handle->parent, MwNsingleClickSelectable)) { int n = MwGetInteger(handle->parent, MwNvalue); - MwDispatchUserHandler(handle->parent, MwNactivateHandler, &n); + MwDispatchUserHandler(handle->parent, MwNlistBoxActivateHandler, &n); } lb->click_time = t; @@ -154,12 +154,12 @@ static void frame_mouse_down(MwWidget handle, void* user, void* call) { } static void frame_mouse_up(MwWidget handle, void* user, void* call) { - MwListBox lb = handle->parent->internal; - MwLLMouse* m = call; + MwListBox lb = handle->parent->internal; + MwMouse* m = call; (void)user; - if(m->button == MwLLMouseLeft) { + if(m->button == MwMOUSE_LEFT) { lb->pressed = 0; } } diff --git a/src/widget/menu.c b/src/widget/menu.c index b66108652..1517591bc 100644 --- a/src/widget/menu.c +++ b/src/widget/menu.c @@ -118,7 +118,7 @@ static void parent_resize(MwWidget handle) { static void mouse_down(MwWidget handle, void* ptr) { MENU_LOOP_DECL; - if(((MwLLMouse*)ptr)->button != MwLLMouseLeft) return; + if(((MwMouse*)ptr)->button != MwMOUSE_LEFT) return; BEGIN_MENU_LOOP; if(in_area) { @@ -150,7 +150,7 @@ static void mouse_down(MwWidget handle, void* ptr) { static void mouse_up(MwWidget handle, void* ptr) { MENU_LOOP_DECL; - if(((MwLLMouse*)ptr)->button != MwLLMouseLeft) return; + if(((MwMouse*)ptr)->button != MwMOUSE_LEFT) return; BEGIN_MENU_LOOP; if(in_area && m->sub[i]->wsub != NULL) { diff --git a/src/widget/numberentry.c b/src/widget/numberentry.c index 05d590f5c..69ee4c9d5 100644 --- a/src/widget/numberentry.c +++ b/src/widget/numberentry.c @@ -98,7 +98,7 @@ static void mouse_up(MwWidget handle, void* ptr) { int h = MwGetInteger(handle, MwNheight); const char* str = MwGetText(handle, MwNtext); - if(((MwLLMouse*)ptr)->button != MwLLMouseLeft) return; + if(((MwMouse*)ptr)->button != MwMOUSE_LEFT) return; if(e->mouse.x >= (w - e->right)) { char s[512]; @@ -116,7 +116,7 @@ static void mouse_up(MwWidget handle, void* ptr) { static void mouse_down(MwWidget handle, void* ptr) { MwEntry e = handle->internal; - if(((MwLLMouse*)ptr)->button != MwLLMouseLeft) return; + if(((MwMouse*)ptr)->button != MwMOUSE_LEFT) return; e->mouse = handle->mouse_point; diff --git a/src/widget/scrollbar.c b/src/widget/scrollbar.c index bed80c0b2..58ed578b2 100644 --- a/src/widget/scrollbar.c +++ b/src/widget/scrollbar.c @@ -170,9 +170,9 @@ static void mouse_down(MwWidget handle, void* ptr) { int wh = MwGetInteger(handle, MwNheight); int or = MwGetInteger(handle, MwNorientation); MwScrollBar scr = handle->internal; - MwLLMouse* m = ptr; + MwMouse* m = ptr; - if(m->button == MwLLMouseWheelUp) { + if(m->button == MwMOUSE_WHEELUP) { int min = MwGetInteger(handle, MwNminValue); int val = MwGetInteger(handle, MwNvalue); int diff = MwGetInteger(handle, MwNareaShown); @@ -184,7 +184,7 @@ static void mouse_down(MwWidget handle, void* ptr) { MwSetInteger(handle, MwNvalue, val); MwSetInteger(handle, MwNchangedBy, -diff); MwDispatchUserHandler(handle, MwNchangedHandler, NULL); - } else if(m->button == MwLLMouseWheelDown) { + } else if(m->button == MwMOUSE_WHEELDOWN) { int max = MwGetInteger(handle, MwNmaxValue); int val = MwGetInteger(handle, MwNvalue); int diff = MwGetInteger(handle, MwNareaShown); @@ -197,7 +197,7 @@ static void mouse_down(MwWidget handle, void* ptr) { MwSetInteger(handle, MwNchangedBy, diff); MwDispatchUserHandler(handle, MwNchangedHandler, NULL); } - if(m->button != MwLLMouseLeft) return; + if(m->button != MwMOUSE_LEFT) return; scr->point = handle->mouse_point; scr->drag = 0; diff --git a/src/widget/submenu.c b/src/widget/submenu.c index f14d6d5f4..c937a9ca4 100644 --- a/src/widget/submenu.c +++ b/src/widget/submenu.c @@ -183,7 +183,7 @@ static void mwSubMenuAppearImpl(MwWidget handle, MwMenu menu, MwPoint* point, in MwLLMakeToolWindow(handle->lowlevel); MwLLDetach(handle->lowlevel, &p); - if(handle->lowlevel->common.coordinate_type == MwCoordinatesGlobal) { + if(handle->lowlevel->common.coordinate_type == MwCOORDINATE_GLOBAL) { if(MwGetInteger(handle, MwNy) + sz.height > rc.height) { MwVaApply(handle, MwNy, rc.height - sz.height, diff --git a/src/widget/treeview.c b/src/widget/treeview.c index 9d3320699..99f12e27e 100644 --- a/src/widget/treeview.c +++ b/src/widget/treeview.c @@ -128,7 +128,7 @@ static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry** set_all(root, 0); tree->selected = 1; if(((t = MwTimeGetTick()) - tree->click_time) < MwDoubleClickTimeout || MwGetInteger(handle->parent, MwNsingleClickSelectable)) { - MwDispatchUserHandler(handle->parent, MwNactivateHandler, tree); + MwDispatchUserHandler(handle->parent, MwNtreeViewActivateHandler, tree); } tree->click_time = t; @@ -213,11 +213,11 @@ static int recursive_length(MwTreeViewEntry** e) { static void frame_mouse_down(MwWidget handle, void* user, void* call) { MwTreeView tv = handle->parent->internal; - MwLLMouse* mouse = call; + MwMouse* mouse = call; (void)user; - if(mouse->button == MwLLMouseLeft) tv->pressed = mouse->point; + if(mouse->button == MwMOUSE_LEFT) tv->pressed = mouse->point; } static void resize(MwWidget handle); @@ -227,11 +227,11 @@ static void frame_mouse_up(MwWidget handle, void* user, void* call) { int shared = 0; int skip = MwGetInteger(tv->vscroll, MwNvalue) * (MwGetInteger(tv->vscroll, MwNmaxValue) - MwGetInteger(tv->vscroll, MwNareaShown)) / MwGetInteger(tv->vscroll, MwNmaxValue); MwPoint p; - MwLLMouse* mouse = call; + MwMouse* mouse = call; (void)user; - if(mouse->button == MwLLMouseLeft) { + if(mouse->button == MwMOUSE_LEFT) { int i; p.x = MwDefaultBorderWidth(tv->frame); p.y = MwDefaultBorderWidth(tv->frame); diff --git a/src/widget/vulkan.c b/src/widget/vulkan.c index e836ac379..0116cb974 100644 --- a/src/widget/vulkan.c +++ b/src/widget/vulkan.c @@ -523,23 +523,23 @@ static void* mwVulkanGetFieldImpl(MwWidget handle, int field, int* out) { char buf[1024]; switch(field) { - case MwVulkanField_GetInstanceProcAddr: + case MwVULKANFIELD_GETINSTANCEPROCADDR: return o->vkGetInstanceProcAddr; - case MwVulkanField_Instance: + case MwVULKANFIELD_INSTANCE: return o->vkInstance; - case MwVulkanField_Surface: + case MwVULKANFIELD_SURFACE: return o->vkSurface; - case MwVulkanField_PhysicalDevice: + case MwVULKANFIELD_PHYSICALDEVICE: return o->vkPhysicalDevice; - case MwVulkanField_LogicalDevice: + case MwVULKANFIELD_LOGICALDEVICE: return o->vkLogicalDevice; - case MwVulkanField_GraphicsQueueIndex: + case MwVULKANFIELD_GRAPHICSQUEUEINDEX: return &o->vkGraphicsFamilyIDX; - case MwVulkanField_PresentQueueIndex: + case MwVULKANFIELD_PRESENTQUEUEINDEX: return &o->vkPresentFamilyIDX; - case MwVulkanField_GraphicsQueue: + case MwVULKANFIELD_GRAPHICSQUEUE: return o->vkGraphicsQueue; - case MwVulkanField_PresentQueue: + case MwVULKANFIELD_PRESENTQUEUE: return o->vkPresentQueue; default: MwStringPrintIntoBuffer(buf, 1024, "Unknown vulkan field request (%d given)", field); From 6259f5767793fcdf4c7a25f01e4c44c93ff8bec3 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Fri, 17 Apr 2026 01:39:59 +0900 Subject: [PATCH 191/195] fix cmake --- CMakeLists.txt | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a4f4eb3ee..948a83c82 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,11 +62,6 @@ if(MW_TRY_OPENGL) find_package(OpenGL) if(OpenGL_FOUND) set(MW_BUILD_OPENGL ON) - target_compile_definitions( - Mw - PRIVATE - MW_OPENGL - ) if(APPLE) list(APPEND SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/widget/opengl_cocoa.m") endif() @@ -80,11 +75,6 @@ if(MW_TRY_VULKAN) check_include_files(vulkan/vulkan.h HAVE_VULKAN_VULKAN_H) if(HAVE_VULKAN_VULKAN_H) set(MW_BUILD_VULKAN ON) - target_compile_definitions( - Mw - PRIVATE - MW_VULKAN - ) message(STATUS "Vulkan widget has been enabled") else() message(WARNING "Vulkan widget has been disabled") @@ -363,6 +353,14 @@ target_link_libraries( ${LIBRARIES} ) +if(MW_BUILD_OPENGL) + target_compile_definitions( + Mw + PRIVATE + MW_OPENGL + ) +endif() + if(MW_BUILD_VULKAN) check_include_files(vulkan/vk_enum_string_helper.h HAS_VK_ENUM_STRING_HELPER) if(HAS_VK_ENUM_STRING_HELPER) @@ -372,6 +370,12 @@ if(MW_BUILD_VULKAN) HAS_VK_ENUM_STRING_HELPER ) endif() + + target_compile_definitions( + Mw + PRIVATE + MW_VULKAN + ) endif() target_compile_definitions( From c0e36df063279f116da5d54ccbba12d1c6490075 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Fri, 17 Apr 2026 01:44:17 +0900 Subject: [PATCH 192/195] oops --- milsko.xml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/milsko.xml b/milsko.xml index 2edcd4169..62fb422ad 100644 --- a/milsko.xml +++ b/milsko.xml @@ -694,20 +694,6 @@ - - - - - - - - - - - - - - From d6538d44104be5184fe620f289b44342ffd31803 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Fri, 17 Apr 2026 01:46:47 +0900 Subject: [PATCH 193/195] fix --- include/Mw/Widget/Vulkan.h | 6 +++--- milsko.xml | 2 +- src/widget/vulkan.c | 14 +++++++------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/Mw/Widget/Vulkan.h b/include/Mw/Widget/Vulkan.h index ccfb02446..0565022e5 100644 --- a/include/Mw/Widget/Vulkan.h +++ b/include/Mw/Widget/Vulkan.h @@ -111,11 +111,11 @@ enum MwVULKANFIELD { /*! * @brief Function for getting a field from within Vulkan. - * @warning Consult the documentation for MwVULKANFIELD to know what type is expected for out. + * @note Consult the documentation for MwVULKANFIELD to know what type is expected for output. */ -MwInline void* MwVulkanGetField(MwWidget handle, int field, int* out) { +MwInline void* MwVulkanGetField(MwWidget handle, int field, int* err) { void* field_out; - MwVaWidgetExecute(handle, "mwVulkanGetField", &field_out, field, out); + MwVaWidgetExecute(handle, "mwVulkanGetField", &field_out, field, err); return field_out; } diff --git a/milsko.xml b/milsko.xml index 62fb422ad..5d7a6374b 100644 --- a/milsko.xml +++ b/milsko.xml @@ -822,7 +822,7 @@ - + diff --git a/src/widget/vulkan.c b/src/widget/vulkan.c index 0116cb974..1e67ea923 100644 --- a/src/widget/vulkan.c +++ b/src/widget/vulkan.c @@ -518,7 +518,7 @@ int MwVulkanSupported(void) { } }; -static void* mwVulkanGetFieldImpl(MwWidget handle, int field, int* out) { +static void* mwVulkanGetFieldImpl(MwWidget handle, int field, int* err) { vulkan_t* o = handle->internal; char buf[1024]; @@ -544,21 +544,21 @@ static void* mwVulkanGetFieldImpl(MwWidget handle, int field, int* out) { default: MwStringPrintIntoBuffer(buf, 1024, "Unknown vulkan field request (%d given)", field); MwDispatchError(1, buf); - if(out != NULL) { - *out = 1; + if(err != NULL) { + *err = 1; } return NULL; } - if(out != NULL) { - *out = 0; + if(err != NULL) { + *err = 0; } }; -static void func_handler(MwWidget handle, const char* name, void* out, va_list va) { +static void func_handler(MwWidget handle, const char* name, void* output, va_list va) { if(strcmp(name, "mwVulkanGetField") == 0) { int field = va_arg(va, int); int* err = va_arg(va, int*); - *(void**)out = mwVulkanGetFieldImpl(handle, field, err); + *(void**)output = mwVulkanGetFieldImpl(handle, field, err); } } From 9caa50b94d1d774a69355b77191ee1e8e4ea1848 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Fri, 17 Apr 2026 01:52:04 +0900 Subject: [PATCH 194/195] fix enum --- milsko.xml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/milsko.xml b/milsko.xml index 5d7a6374b..5c8370430 100644 --- a/milsko.xml +++ b/milsko.xml @@ -203,16 +203,16 @@ - - 0 - - - - - - - - + + 0 + + + + + + + + From fa9a16c0d567882fdf675b2314f3be2343694a0b Mon Sep 17 00:00:00 2001 From: maelstrom Date: Thu, 16 Apr 2026 23:05:41 +0200 Subject: [PATCH 195/195] auto detect dark theme change via dbus signals --- include/Mw/LowLevel.h | 4 +++ src/backend/wayland.c | 26 +++++++++++++----- src/lowlevel.c | 63 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 7 deletions(-) diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index cbc67f9e0..2ba3ff0ba 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -83,11 +83,15 @@ typedef struct _MwLLDBusContext { DBusMessageIter dbus_args, dbus_variant, dbus_inner_variant; } 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. */ MWDECL MwBool MwLLDBusFuncSetup(MwLLDBusFuncTable* tbl); 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 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); #endif diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 31eefb20e..be5a7a181 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -17,6 +17,8 @@ wayland_call_table_t wl_call_tbl; 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. */ #define WAYLAND_EVENT_OP_START(self) \ do { \ @@ -1818,14 +1820,21 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh } #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) { 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); + 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 @@ -2164,15 +2173,18 @@ static int MwLLPendingImpl(MwLL handle) { }; int pending = 0; - if(handle->wayland.dark_theme_detection) { - handle->wayland.dark_theme_detection = MwFALSE; #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); 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) { recursive_dispatch_resize(handle); diff --git a/src/lowlevel.c b/src/lowlevel.c index 2a874e6c8..935bf9b3d 100644 --- a/src/lowlevel.c +++ b/src/lowlevel.c @@ -176,6 +176,69 @@ MWDECL MwBool MwLLDBusPortalGet(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx, co 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) { if(!tbl->lib) { return;