From 8b28b3e1b0207ae061caebda0a6f62ce68ffb1be Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Tue, 27 Jan 2026 17:34:25 +0900 Subject: [PATCH 01/94] might be functional --- include/Mw/LowLevel.h | 1 + include/Mw/LowLevel/GDI.h | 1 + src/backend/gdi.c | 23 ++++++++++++++++++++++- src/core.c | 8 ++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index 6bea6cd3..b5483288 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -163,6 +163,7 @@ struct _MwLLHandler { void (*focus_in)(MwLL handle, void* data); void (*focus_out)(MwLL handle, void* data); void (*clipboard)(MwLL handle, void* data); + void (*dark_theme)(MwLL handle, void* data); }; #ifdef __cplusplus diff --git a/include/Mw/LowLevel/GDI.h b/include/Mw/LowLevel/GDI.h index 1bf997c2..c695cbd1 100644 --- a/include/Mw/LowLevel/GDI.h +++ b/include/Mw/LowLevel/GDI.h @@ -22,6 +22,7 @@ struct _MwLLGDI { int grabbed; int force_render; int get_clipboard; + int get_darktheme; }; struct _MwLLGDIColor { diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 764e9838..20c47b26 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -8,6 +8,17 @@ typedef struct userdata { int max_set; } userdata_t; +static void detect_darktheme(MwLL handle){ + DWORD dw; + DWORD sz = sizeof(dw); + + if(RegGetValue(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", "AppsUseLightTheme", RRF_RT_REG_DWORD, NULL, &dw, &sz) == ERROR_SUCCESS){ + int t = dw ? 0 : 1; + + MwLLDispatch(handle, dark_theme, &t); + } +} + static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { userdata_t* u = (userdata_t*)GetWindowLongPtr(hWnd, GWLP_USERDATA); @@ -205,6 +216,10 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { } else if(msg == WM_USER) { InvalidateRect(hWnd, NULL, FALSE); UpdateWindow(hWnd); + } else if(msg == WM_WININICHANGE){ + char* s = (char*)lp; + + if(s != NULL && strcmp(s, "ImmersiveColorSet") == 0) detect_darktheme(u->ll); } else { return DefWindowProc(hWnd, msg, wp, lp); } @@ -238,6 +253,7 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r->common.type = MwLLBackendGDI; r->gdi.get_clipboard = 1; + r->gdi.get_darktheme = 1; r->gdi.force_render = 0; r->gdi.grabbed = 0; r->gdi.hWnd = CreateWindow("milsko", "Milsko", parent == NULL ? (WS_OVERLAPPEDWINDOW) : (WS_CHILD | WS_VISIBLE), x == MwDEFAULT ? CW_USEDEFAULT : x, y == MwDEFAULT ? CW_USEDEFAULT : y, width, height, parent == NULL ? NULL : parent->gdi.hWnd, 0, wc.hInstance, NULL); @@ -384,7 +400,7 @@ static int MwLLPendingImpl(MwLL handle) { (void)handle; - if(handle->gdi.get_clipboard) return 1; + if(handle->gdi.get_clipboard || handle->gdi.get_darktheme) return 1; return PeekMessage(&msg, handle->gdi.hWnd, 0, 0, PM_NOREMOVE) ? 1 : 0; } @@ -411,6 +427,11 @@ static void MwLLNextEventImpl(MwLL handle) { handle->gdi.get_clipboard = 0; } + if(handle->gdi.get_darktheme){ + detect_darktheme(handle); + + handle->gdi.get_clipboard = 0; + } while(PeekMessage(&msg, handle->gdi.hWnd, 0, 0, PM_NOREMOVE)) { GetMessage(&msg, handle->gdi.hWnd, 0, 0); TranslateMessage(&msg); diff --git a/src/core.c b/src/core.c index 78d2a946..9d0d18be 100644 --- a/src/core.c +++ b/src/core.c @@ -127,6 +127,13 @@ static void llclipboardhandler(MwLL handle, void* data) { */ #define IsFirstVisible(handle) ((handle)->widget_class != NULL && ((handle)->parent == NULL || (handle)->parent->widget_class == NULL)) +static void lldarkthemehandler(MwLL handle, void* data){ + MwWidget h = (MwWidget)handle->common.user; + int* ptr = data; + + if(IsFirstVisible(h)) MwToggleDarkTheme(h, *ptr); +} + MwWidget MwCreateWidget(MwClass widget_class, const char* name, MwWidget parent, int x, int y, unsigned int width, unsigned int height) { MwWidget h = malloc(sizeof(*h)); @@ -171,6 +178,7 @@ MwWidget MwCreateWidget(MwClass widget_class, const char* name, MwWidget parent, h->lowlevel->common.handler->focus_in = llfocusinhandler; h->lowlevel->common.handler->focus_out = llfocusouthandler; h->lowlevel->common.handler->clipboard = llclipboardhandler; + h->lowlevel->common.handler->dark_theme = lldarkthemehandler; } if(parent != NULL) arrput(parent->children, h); From 18457ccbcb28b4c542f19b7201647e6189ff4373 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Tue, 27 Jan 2026 17:36:21 +0900 Subject: [PATCH 02/94] tiny fix --- src/backend/gdi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 20c47b26..5c4febe1 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -218,8 +218,11 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { UpdateWindow(hWnd); } else if(msg == WM_WININICHANGE){ char* s = (char*)lp; + LPARAM style = GetWindowLongPtr(hWnd, GWL_STYLE); - if(s != NULL && strcmp(s, "ImmersiveColorSet") == 0) detect_darktheme(u->ll); + if(!(style & WS_CHILD)){ + if(s != NULL && strcmp(s, "ImmersiveColorSet") == 0) detect_darktheme(u->ll); + } } else { return DefWindowProc(hWnd, msg, wp, lp); } From 0cecae2dd16e4073b81bfbc72a2140e6f6feccbd Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Tue, 27 Jan 2026 17:58:30 +0900 Subject: [PATCH 03/94] better registry function --- src/backend/gdi.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 5c4febe1..e985c8bb 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -11,12 +11,22 @@ typedef struct userdata { static void detect_darktheme(MwLL handle){ DWORD dw; DWORD sz = sizeof(dw); + int err, t; + HKEY hkey; + DWORD type; - if(RegGetValue(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", "AppsUseLightTheme", RRF_RT_REG_DWORD, NULL, &dw, &sz) == ERROR_SUCCESS){ - int t = dw ? 0 : 1; + err = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", 0, KEY_QUERY_VALUE, &hkey); + if(err != ERROR_SUCCESS) return; - MwLLDispatch(handle, dark_theme, &t); + err = RegQueryValueEx(hkey, "AppsUseLightTheme", NULL, &type, (PBYTE)&dw, &sz); + if(err != ERROR_SUCCESS || type != REG_DWORD){ + RegCloseKey(hkey); + return; } + + t = dw ? 0 : 1; + + MwLLDispatch(handle, dark_theme, &t); } static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { From ae96b127e1b06f7d6e990a3da4985ac688c8fad9 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Tue, 27 Jan 2026 17:58:52 +0900 Subject: [PATCH 04/94] fix leak --- 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 e985c8bb..c1e0fb78 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -19,8 +19,8 @@ static void detect_darktheme(MwLL handle){ if(err != ERROR_SUCCESS) return; err = RegQueryValueEx(hkey, "AppsUseLightTheme", NULL, &type, (PBYTE)&dw, &sz); + RegCloseKey(hkey); if(err != ERROR_SUCCESS || type != REG_DWORD){ - RegCloseKey(hkey); return; } From 5e492ee5b418b8edb8ec0b0db959689eada09473 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Tue, 27 Jan 2026 18:00:44 +0900 Subject: [PATCH 05/94] 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 c1e0fb78..ae6a7a62 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -443,7 +443,7 @@ static void MwLLNextEventImpl(MwLL handle) { if(handle->gdi.get_darktheme){ detect_darktheme(handle); - handle->gdi.get_clipboard = 0; + handle->gdi.get_darktheme = 0; } while(PeekMessage(&msg, handle->gdi.hWnd, 0, 0, PM_NOREMOVE)) { GetMessage(&msg, handle->gdi.hWnd, 0, 0); From 64c3cdb4a511b0b9efcd538a4c1bc82cbbda7dc8 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Tue, 27 Jan 2026 18:03:16 +0900 Subject: [PATCH 06/94] MwSetDarkTheme instead of MwToggleDarkTheme --- examples/basic/example.c | 2 +- include/Mw/Core.h | 2 +- milsko.xml | 2 +- src/backend/gdi.c | 2 +- src/core.c | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/basic/example.c b/examples/basic/example.c index 614b4e37..9cc89db4 100644 --- a/examples/basic/example.c +++ b/examples/basic/example.c @@ -17,7 +17,7 @@ void handler_dark(MwWidget handle, void* user_data, void* call_data) { (void)call_data; toggle = toggle ? 0 : 1; - MwToggleDarkTheme(window, toggle); + MwSetDarkTheme(window, toggle); } void resize(MwWidget handle, void* user_data, void* call_data) { diff --git a/include/Mw/Core.h b/include/Mw/Core.h index cd7cabd1..aba19e11 100644 --- a/include/Mw/Core.h +++ b/include/Mw/Core.h @@ -296,7 +296,7 @@ MWDECL void MwHideCursor(MwWidget handle); * @param handle Widget * @param toggle Toggle */ -MWDECL void MwToggleDarkTheme(MwWidget handle, int toggle); +MWDECL void MwSetDarkTheme(MwWidget handle, int toggle); /*! * @brief Gets the parent widget diff --git a/milsko.xml b/milsko.xml index dc980cd8..bc73f0e2 100644 --- a/milsko.xml +++ b/milsko.xml @@ -353,7 +353,7 @@ - + diff --git a/src/backend/gdi.c b/src/backend/gdi.c index ae6a7a62..373ef875 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -266,7 +266,7 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r->common.type = MwLLBackendGDI; r->gdi.get_clipboard = 1; - r->gdi.get_darktheme = 1; + if(parent == NULL) r->gdi.get_darktheme = 1; r->gdi.force_render = 0; r->gdi.grabbed = 0; r->gdi.hWnd = CreateWindow("milsko", "Milsko", parent == NULL ? (WS_OVERLAPPEDWINDOW) : (WS_CHILD | WS_VISIBLE), x == MwDEFAULT ? CW_USEDEFAULT : x, y == MwDEFAULT ? CW_USEDEFAULT : y, width, height, parent == NULL ? NULL : parent->gdi.hWnd, 0, wc.hInstance, NULL); diff --git a/src/core.c b/src/core.c index 9d0d18be..55f667db 100644 --- a/src/core.c +++ b/src/core.c @@ -131,7 +131,7 @@ static void lldarkthemehandler(MwLL handle, void* data){ MwWidget h = (MwWidget)handle->common.user; int* ptr = data; - if(IsFirstVisible(h)) MwToggleDarkTheme(h, *ptr); + if(IsFirstVisible(h)) MwSetDarkTheme(h, *ptr); } MwWidget MwCreateWidget(MwClass widget_class, const char* name, MwWidget parent, int x, int y, unsigned int width, unsigned int height) { @@ -747,7 +747,7 @@ static void force_render_all(MwWidget handle) { if(handle->lowlevel != NULL) MwForceRender(handle); } -void MwToggleDarkTheme(MwWidget handle, int toggle) { +void MwSetDarkTheme(MwWidget handle, int toggle) { int old = handle->dark_theme; if(old != toggle) { handle->dark_theme = toggle; From 65c872710a81f95850b92fd64c5a5a0fd2e0332d Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Tue, 27 Jan 2026 18:12:36 +0900 Subject: [PATCH 07/94] it should be working now, closes #6 --- src/backend/gdi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 373ef875..79822e71 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -663,6 +663,8 @@ static void MwLLDetachImpl(MwLL handle, MwPoint* point) { rc2.bottom -= rc2.top; SetWindowPos(handle->gdi.hWnd, HWND_TOPMOST, rc.left, rc.top, rc2.right == 0 ? 1 : rc2.right, rc2.bottom == 0 ? 1 : rc2.bottom, SWP_FRAMECHANGED | SWP_NOACTIVATE); + + handle->gdi.get_darktheme = 1; } static void MwLLShowImpl(MwLL handle, int show) { From 9544404f7c0851b7f96e310008c3ce2f723cb1f0 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Tue, 27 Jan 2026 18:46:12 +0900 Subject: [PATCH 08/94] fix warning --- src/core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core.c b/src/core.c index 55f667db..0c1b4718 100644 --- a/src/core.c +++ b/src/core.c @@ -543,6 +543,7 @@ const char* MwGetText(MwWidget handle, const char* key) { return shget(handle->text, key); } +#if defined(USE_STB_TRUETYPE) || defined(USE_FREETYPE2) static void* inherit_void(MwWidget handle, const char* key) { void* v; @@ -551,6 +552,7 @@ static void* inherit_void(MwWidget handle, const char* key) { } return NULL; } +#endif void* MwGetVoid(MwWidget handle, const char* key) { void* v = shget(handle->data, key); From 626294c95f9c208c1b65dd22c49c9a5ca7c4d9ea Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Tue, 27 Jan 2026 18:50:03 +0900 Subject: [PATCH 09/94] format --- src/backend/gdi.c | 32 ++++++++++++++++---------------- src/core.c | 6 +++--- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 79822e71..4601b79d 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -8,11 +8,11 @@ typedef struct userdata { int max_set; } userdata_t; -static void detect_darktheme(MwLL handle){ +static void detect_darktheme(MwLL handle) { DWORD dw; DWORD sz = sizeof(dw); - int err, t; - HKEY hkey; + int err, t; + HKEY hkey; DWORD type; err = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", 0, KEY_QUERY_VALUE, &hkey); @@ -20,10 +20,10 @@ static void detect_darktheme(MwLL handle){ err = RegQueryValueEx(hkey, "AppsUseLightTheme", NULL, &type, (PBYTE)&dw, &sz); RegCloseKey(hkey); - if(err != ERROR_SUCCESS || type != REG_DWORD){ + if(err != ERROR_SUCCESS || type != REG_DWORD) { return; } - + t = dw ? 0 : 1; MwLLDispatch(handle, dark_theme, &t); @@ -226,11 +226,11 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { } else if(msg == WM_USER) { InvalidateRect(hWnd, NULL, FALSE); UpdateWindow(hWnd); - } else if(msg == WM_WININICHANGE){ - char* s = (char*)lp; + } else if(msg == WM_WININICHANGE) { + char* s = (char*)lp; LPARAM style = GetWindowLongPtr(hWnd, GWL_STYLE); - - if(!(style & WS_CHILD)){ + + if(!(style & WS_CHILD)) { if(s != NULL && strcmp(s, "ImmersiveColorSet") == 0) detect_darktheme(u->ll); } } else { @@ -267,12 +267,12 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r->gdi.get_clipboard = 1; if(parent == NULL) r->gdi.get_darktheme = 1; - r->gdi.force_render = 0; - r->gdi.grabbed = 0; - r->gdi.hWnd = CreateWindow("milsko", "Milsko", parent == NULL ? (WS_OVERLAPPEDWINDOW) : (WS_CHILD | WS_VISIBLE), x == MwDEFAULT ? CW_USEDEFAULT : x, y == MwDEFAULT ? CW_USEDEFAULT : y, width, height, parent == NULL ? NULL : parent->gdi.hWnd, 0, wc.hInstance, NULL); - r->gdi.hInstance = wc.hInstance; - r->gdi.cursor = NULL; - r->gdi.icon = NULL; + r->gdi.force_render = 0; + r->gdi.grabbed = 0; + r->gdi.hWnd = CreateWindow("milsko", "Milsko", parent == NULL ? (WS_OVERLAPPEDWINDOW) : (WS_CHILD | WS_VISIBLE), x == MwDEFAULT ? CW_USEDEFAULT : x, y == MwDEFAULT ? CW_USEDEFAULT : y, width, height, parent == NULL ? NULL : parent->gdi.hWnd, 0, wc.hInstance, NULL); + r->gdi.hInstance = wc.hInstance; + r->gdi.cursor = NULL; + r->gdi.icon = NULL; u->ll = r; u->min_set = 0; @@ -440,7 +440,7 @@ static void MwLLNextEventImpl(MwLL handle) { handle->gdi.get_clipboard = 0; } - if(handle->gdi.get_darktheme){ + if(handle->gdi.get_darktheme) { detect_darktheme(handle); handle->gdi.get_darktheme = 0; diff --git a/src/core.c b/src/core.c index 0c1b4718..b157bbb6 100644 --- a/src/core.c +++ b/src/core.c @@ -127,9 +127,9 @@ static void llclipboardhandler(MwLL handle, void* data) { */ #define IsFirstVisible(handle) ((handle)->widget_class != NULL && ((handle)->parent == NULL || (handle)->parent->widget_class == NULL)) -static void lldarkthemehandler(MwLL handle, void* data){ - MwWidget h = (MwWidget)handle->common.user; - int* ptr = data; +static void lldarkthemehandler(MwLL handle, void* data) { + MwWidget h = (MwWidget)handle->common.user; + int* ptr = data; if(IsFirstVisible(h)) MwSetDarkTheme(h, *ptr); } From bbb20f081ef347f074912091e0f641b8104fc69a Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Tue, 27 Jan 2026 18:51:57 +0900 Subject: [PATCH 10/94] add MwNdarkThemeHandler --- include/Mw/StringDefs.h | 1 + src/core.c | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/Mw/StringDefs.h b/include/Mw/StringDefs.h index 5d689659..db597889 100644 --- a/include/Mw/StringDefs.h +++ b/include/Mw/StringDefs.h @@ -72,5 +72,6 @@ #define MwNcolorChosenHandler "CcolorChosen" /* MwRGB* */ #define MwNdrawHandler "Cdraw" /* NULL */ #define MwNclipboardHandler "Cclipboard" /* char* */ +#define MwNdarkThemeHandler "CdarkTheme" /* int* */ #endif diff --git a/src/core.c b/src/core.c index b157bbb6..6985a02e 100644 --- a/src/core.c +++ b/src/core.c @@ -131,7 +131,11 @@ static void lldarkthemehandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; int* ptr = data; - if(IsFirstVisible(h)) MwSetDarkTheme(h, *ptr); + if(IsFirstVisible(h)) { + MwSetDarkTheme(h, *ptr); + + MwDispatchUserHandler(h, MwNdarkThemeHandler, data); + } } MwWidget MwCreateWidget(MwClass widget_class, const char* name, MwWidget parent, int x, int y, unsigned int width, unsigned int height) { From ad5aa03d11a9c14ec978da1ab03a157cfb435b2c Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Sat, 31 Jan 2026 20:42:09 +0900 Subject: [PATCH 11/94] remove non required headers --- src/backend/wayland.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 7acc0389..19f6386c 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -5,12 +5,9 @@ #include #include "../../external/stb_ds.h" -#include "Mw/BaseTypes.h" -#include "Mw/LowLevel.h" #include #include -#include #include /* TODO: From 7ad4d8202460de860aa7bb5c94129ce1265a290e Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 2 Feb 2026 23:02:42 +0900 Subject: [PATCH 12/94] c89 --- src/backend/wayland.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 19f6386c..7d8faeee 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -431,13 +431,14 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri p.point = self->wayland.cur_mouse_pos; if(p.point.x > self->wayland.x && p.point.x < self->wayland.x + self->wayland.ww && p.point.y > self->wayland.y && p.point.y < self->wayland.y + self->wayland.wh) { + int i; switch(button) { case BTN_LEFT: p.button = MwLLMouseLeft; break; case BTN_MIDDLE: p.button = MwLLMouseMiddle; - for(int i = 0; i < arrlen(self->wayland.clipboard_devices); i++) { + for(i = 0; i < arrlen(self->wayland.clipboard_devices); i++) { wl_clipboard_read( self->wayland.clipboard_devices[i]); } @@ -624,7 +625,8 @@ static void keyboard_key(void* data, if((self->wayland.mod_state & 4) == 4) { /* clipboard paste */ if(key == 'V') { - for(int i = 0; i < arrlen(self->wayland.clipboard_devices); i++) { + int i; + for(i = 0; i < arrlen(self->wayland.clipboard_devices); i++) { wl_clipboard_read( self->wayland.clipboard_devices[i]); } @@ -1851,12 +1853,14 @@ static void MwLLSetClipboardImpl(MwLL handle, const char* text) { strcpy(handle->wayland.clipboard_buffer, text); if(handle->wayland.supports_zwp) { - for(int i = 0; i < arrlen(handle->wayland.clipboard_devices); i++) { + 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); } } else { - for(int i = 0; i < arrlen(handle->wayland.clipboard_devices); i++) { + int i; + for(i = 0; i < arrlen(handle->wayland.clipboard_devices); i++) { wl_clipboard_device_context_t* device = handle->wayland.clipboard_devices[i]; wl_data_device_set_selection(device->device.wl, handle->wayland.clipboard_source.wl, handle->wayland.keyboard_serial); } From 5bc06dc8512e806dfa6364d5849acf61f7190322 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Tue, 3 Feb 2026 23:24:34 +0900 Subject: [PATCH 13/94] testing jenkins --- Jenkinsfile | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 Jenkinsfile diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 00000000..4a3c003b --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,16 @@ +pipeline { + agent { + label "built-in" + } + stages { + stage("Build document") { + steps { + } + post { + always { + notifyDiscord() + } + } + } + } +} From 12f7312d407326915fbe92e6235fc2edf8ce0971 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Tue, 3 Feb 2026 23:27:27 +0900 Subject: [PATCH 14/94] testing jenkins --- Jenkinsfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Jenkinsfile b/Jenkinsfile index 4a3c003b..719f1469 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -5,6 +5,7 @@ pipeline { stages { stage("Build document") { steps { + sh("echo Testing testing...") } post { always { From 282283609c01ca5e1dc0c901de4a59875daa91d3 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Tue, 3 Feb 2026 23:43:08 +0900 Subject: [PATCH 15/94] i wonder if doc gets generated --- Jenkinsfile | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 719f1469..8a51a786 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -5,12 +5,9 @@ pipeline { stages { stage("Build document") { steps { - sh("echo Testing testing...") - } - post { - always { - notifyDiscord() - } + sh("doxygen") + sh("rm -rf /var/www/milsko-doxygen") + sh("mv doxygen/html /var/www/milsko-doxygen") } } } From c308bd9324c6d3d953af71c9bb297e97bab93715 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Tue, 3 Feb 2026 23:46:24 +0900 Subject: [PATCH 16/94] test --- Jenkinsfile | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Jenkinsfile b/Jenkinsfile index 8a51a786..8c9eb9d2 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -10,5 +10,30 @@ pipeline { sh("mv doxygen/html /var/www/milsko-doxygen") } } + stage("Build") { + parallel { + stage("Build for Linux 64-bit") { + steps { + sh("./Makefile.pl --enable-opengl --enable-vulkan --without-vulkan-string-helper") + sh("make clean") + sh("make -j4") + } + } + stage("Build for Windows 32-bit") { + steps { + sh("./Makefile.pl --enable-opengl --enable-stb-truetype --disable-freetype2 --cross --target=Windows --host=i686-w64-mingw32") + sh("make clean") + sh("make -j4") + } + } + stage("Build for Windows 64-bit") { + steps { + sh("./Makefile.pl --enable-opengl --enable-stb-truetype --disable-freetype2 --cross --target=Windows --host=x86_64-w64-mingw32") + sh("make clean") + sh("make -j4") + } + } + } + } } } From 4a092e71d2aed7d1887ebbf970ab364cdd70b0f4 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Wed, 4 Feb 2026 00:02:21 +0900 Subject: [PATCH 17/94] testing --- Jenkinsfile | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Jenkinsfile b/Jenkinsfile index 8c9eb9d2..7b742616 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -9,6 +9,11 @@ pipeline { sh("rm -rf /var/www/milsko-doxygen") sh("mv doxygen/html /var/www/milsko-doxygen") } + post { + always { + notifyDiscord() + } + } } stage("Build") { parallel { @@ -34,6 +39,11 @@ pipeline { } } } + post { + always { + notifyDiscord() + } + } } } } From 3329184993d395e033029eaa1faed6a94401a1e6 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Wed, 4 Feb 2026 00:06:31 +0900 Subject: [PATCH 18/94] unused --- Koakumafile | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100755 Koakumafile diff --git a/Koakumafile b/Koakumafile deleted file mode 100755 index 92cb41be..00000000 --- a/Koakumafile +++ /dev/null @@ -1,24 +0,0 @@ -# vim: syntax=tcl - -proc run {project_name} { - if { "$project_name" == "MilskoDoxygen" } { - RunCommand "doxygen" - RunCommand "rm -rf /var/www/milsko-doxygen" - RunCommand "mv doxygen/html /var/www/milsko-doxygen" - } else { - foreach target {"Linux" "Win32" "Win64"} { - if { [file exists "Makefile"] == 1 } { - RunCommand "make distclean" - } - if { "$target" == "Linux" } { - RunCommand "./Makefile.pl --enable-opengl --enable-vulkan --without-vulkan-string-helper" - } elseif { "$target" == "Win32" } { - RunCommand "./Makefile.pl --enable-opengl --enable-stb-truetype --disable-freetype2 --cross --target=Windows --host=i686-w64-mingw32" - } elseif { "$target" == "Win64" } { - RunCommand "./Makefile.pl --enable-opengl --enable-stb-truetype --disable-freetype2 --cross --target=Windows --host=x86_64-w64-mingw32" - } - RunCommand "make clean" - RunCommand "make -j4" - } - } -} From 280ba93cf1f9a32609a375b6a07529c70c0a749b Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Wed, 4 Feb 2026 00:21:31 +0900 Subject: [PATCH 19/94] hmm --- Jenkinsfile | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Jenkinsfile b/Jenkinsfile index 7b742616..74776380 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -18,6 +18,9 @@ pipeline { stage("Build") { parallel { stage("Build for Linux 64-bit") { + agent { + label "built-in" + } steps { sh("./Makefile.pl --enable-opengl --enable-vulkan --without-vulkan-string-helper") sh("make clean") @@ -25,6 +28,9 @@ pipeline { } } stage("Build for Windows 32-bit") { + agent { + label "built-in" + } steps { sh("./Makefile.pl --enable-opengl --enable-stb-truetype --disable-freetype2 --cross --target=Windows --host=i686-w64-mingw32") sh("make clean") @@ -32,6 +38,9 @@ pipeline { } } stage("Build for Windows 64-bit") { + agent { + label "built-in" + } steps { sh("./Makefile.pl --enable-opengl --enable-stb-truetype --disable-freetype2 --cross --target=Windows --host=x86_64-w64-mingw32") sh("make clean") From c04f751a4f77f18c0482dd5932ba3491af680575 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Wed, 4 Feb 2026 00:25:49 +0900 Subject: [PATCH 20/94] msvc --- Jenkinsfile | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Jenkinsfile b/Jenkinsfile index 74776380..67b12d48 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -47,6 +47,15 @@ pipeline { sh("make -j4") } } + stage("Build for Windows 64-bit (MSVC)") { + agent { + label "2012r2" + } + steps { + sh("nmake -f NTMakefile clean") + sh("nmake") + } + } } post { always { From d7db903695348ed79945af1ac842b26fffdbb211 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Wed, 4 Feb 2026 00:30:22 +0900 Subject: [PATCH 21/94] msvc --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 67b12d48..58736fdb 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -52,8 +52,8 @@ pipeline { label "2012r2" } steps { - sh("nmake -f NTMakefile clean") - sh("nmake") + bat("nmake -f NTMakefile clean") + bat("nmake -f NTMakefile") } } } From 11fec984cf24c1497c6310095268986a12469fd6 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Fri, 6 Feb 2026 22:05:13 +0900 Subject: [PATCH 22/94] fix --- 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 8738b5d6..ae878178 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -251,7 +251,7 @@ static void destroy(MwWidget handle) { while(w->parent != NULL) w = w->parent; - w->berserk++; + w->berserk--; free(handle->internal); } From efa43456c18c0615a4aae8575afd032c2e0bf9c8 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 3 Mar 2026 23:24:28 -0700 Subject: [PATCH 23/94] significant macos progress, now compiles/runs on monetery --- README.txt | 46 +-- include/Mw/LowLevel/Cocoa.h | 104 +++--- src/backend/cocoa.m | 661 ++++++++++++++++++++---------------- 3 files changed, 438 insertions(+), 373 deletions(-) diff --git a/README.txt b/README.txt index 32e8630d..744e7a8e 100644 --- a/README.txt +++ b/README.txt @@ -1,23 +1,25 @@ -Greetings - Welcome to the Milsko GUI Toolkit (Version pre-1.0) +Greetings - Welcome to the Milsko GUI Toolkit (Version pre-1.0) - This document contains a brief summary of the contents of this source -distributions and building instructions for Milsko GUI Toolkit. + This document contains a brief summary of the contents of this source +distributions and building instructions for Milsko GUI Toolkit. Requirements - Milsko requires the Windows environment with GDI (so anything NT or 9x) or -the Unix-like environment with X11 for runtime. + Milsko requires either + * A Windows environment with GDI (so anything NT or 9x) + * A Mac OS environment with Cocoa (10.4 is the minimum tested) + * Unix-like environment with X11 for runtime. - To build Milsko for Windows, you must have one of following compilers: - * Visual C++ 6.0 or newer - * Borland C++ 5.5 or newer - * Open Watcom 2.0 or newer - * MinGW-w64 + To build Milsko for Windows, you must have one of following compilers: + * Visual C++ 6.0 or newer + * Borland C++ 5.5 or newer + * Open Watcom 2.0 or newer + * MinGW-w64 - and for Unix-like: - * GNU C Compiler - * Clang + and for Unix-like/Mac OS: + * GNU C Compiler + * Clang Contents @@ -39,31 +41,31 @@ the Unix-like environment with X11 for runtime. Building Milsko - Building Milsko depends on the platform you use, and the compiler you use. + Building Milsko depends on the platform you use, and the compiler you use. A. Visual C++ ------------- -1) Run `nmake -f NTMakefile'. +1) Run `nmake -f NTMakefile'. B. Borland C++ -------------- -1) Run `make -f BorMakefile'. +1) Run `make -f BorMakefile'. C. Open Watcom -------------- -1) Run `wmake -f WatMakefile'. +1) Run `wmake -f WatMakefile'. D. MinGW-w64/GCC/Clang ---------------------- -1) Determine if you need Vulkan and/or OpenGL. +1) Determine if you need Vulkan and/or OpenGL. -2) Run `./Makefile.pl'. - For help, run `./Makefile.pl --help'. +2) Run `./Makefile.pl'. + For help, run `./Makefile.pl --help'. -3) Run `make'. +3) Run `make'. - -- Nishi (nishi@nishi.boats) + -- Nishi (nishi@nishi.boats) diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index 2d1d9bde..d22f6539 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -11,10 +11,9 @@ #include #ifdef __OBJC__ - -#import #import #import +#import #ifdef __APPLE__ #import @@ -23,97 +22,104 @@ #endif @interface MilskoCocoaPixmap : NSObject { - int width; - int height; - NSData* data; - NSImage* image; + MwBool valid; + int width; + int height; + NSData *data; + NSImage *image; + NSBitmapImageRep *rep; } -+ (MilskoCocoaPixmap*)newWithWidth:(int)width height:(int)height; -- (void)updateWithData:(void*)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; +/* using @property to create instance variables fucks up 10.4 gcc for some + * reason? */ +- (NSImage *)image; @end @interface MilskoCocoaView : NSView { - CGContextRef cg; - CGColorSpaceRef space; - CGDataProviderRef provider; - MwU32* buf; - float width; - float height; + NSBitmapImageRep *rep; + NSGraphicsContext *context; + MwBool valid; + CGColorSpaceRef space; + CGDataProviderRef provider; + unsigned char *buf; + float width; + float height; } -- (CGContextRef)context; +- (NSGraphicsContext *)context; @end @interface MilskoCocoa : NSObject { - NSApplication* application; - NSWindow* window; - NSRect rect; - MilskoCocoaView* view; + NSApplication *application; + NSEvent *lastEvent; + NSWindow *window; + NSRect rect; + MilskoCocoaView *view; + MwLL parent; } -+ (MilskoCocoa*)newWithParent:(MwLL)parent - x:(int)x - y:(int)y - width:(int)width - height:(int)height; -- (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; +- (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)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; @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/src/backend/cocoa.m b/src/backend/cocoa.m index 42c38a57..1e069cc2 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -1,490 +1,547 @@ #include - -#include - -#include "../../external/stb_ds.h" +#include +#include @implementation MilskoCocoaPixmap -+ (MilskoCocoaPixmap*)newWithWidth:(int)width height:(int)height { - MilskoCocoaPixmap* p = [MilskoCocoaPixmap alloc]; ++ (MilskoCocoaPixmap *)newWithWidth:(int)width height:(int)height { + MilskoCocoaPixmap *p = [MilskoCocoaPixmap alloc]; - p->width = width; - p->height = height; - p->data = NULL; - p->image = NULL; - - return p; + p->width = width; + p->height = height; + p->data = NULL; + p->image = NULL; + return p; } -- (void)updateWithData:(void*)_data { - [self destroy]; +- (void)updateWithData:(unsigned char *)_data { + [self destroy]; - self->data = [NSData dataWithBytes:_data length:self->width * self->height * 4]; - self->image = [[NSImage alloc] initWithData:self->data]; + self->rep = + [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:&_data + pixelsWide:(int)width + pixelsHigh:(int)height + bitsPerSample:8 + samplesPerPixel:4 + hasAlpha:YES + isPlanar:NO + colorSpaceName:NSDeviceRGBColorSpace + bytesPerRow:(int)width * 4 + bitsPerPixel:32]; + + assert(self->rep); + self->data = [NSData dataWithBytes:[self->rep bitmapData] + length:self->width * self->height * 4]; + assert(self->data); + self->image = [[NSImage alloc] initWithSize:NSMakeSize(width, height)]; + assert(self->image); + [self->image addRepresentation:self->rep]; } - (void)destroy { - if(self->data != NULL) { - [self->data dealloc]; - } - if(self->image != NULL) { - [self->image dealloc]; - } + if (self->data != NULL) { + [self->data dealloc]; + } + if (self->image != NULL) { + [self->image dealloc]; + } } -- (NSImage*)image { - return self->image; +- (NSImage *)image { + return self->image; } @end @implementation MilskoCocoa -+ (MilskoCocoa*)newWithParent:(MwLL)parent - x:(int)x - y:(int)y - width:(int)width - height:(int)height { - MilskoCocoa* c = [MilskoCocoa alloc]; - bool centerX = false, centerY = false; ++ (MilskoCocoa *)newWithParent:(MwLL)parent + x:(int)x + y:(int)y + width:(int)width + height:(int)height { + MilskoCocoa *c = [MilskoCocoa alloc]; + bool centerX = false, centerY = false; - if(x == MwDEFAULT) { - x = 0; - centerX = true; - } - if(y == MwDEFAULT) { - y = 0; - centerY = true; - } - c->application = [NSApplication sharedApplication]; + if (x == MwDEFAULT) { + x = 0; + centerX = true; + } + if (y == MwDEFAULT) { + y = 0; + centerY = true; + } + c->application = [NSApplication sharedApplication]; - c->rect = NSMakeRect(x, y, width, height); + c->rect = NSMakeRect(x, y, width, height); - c->window = [[NSWindow alloc] - initWithContentRect:c->rect - styleMask:parent == NULL - ? (NSTitledWindowMask | NSClosableWindowMask | - NSMiniaturizableWindowMask | - NSResizableWindowMask) - : NSBorderlessWindowMask - backing:NSBackingStoreBuffered - defer:NO]; - [c->window makeKeyAndOrderFront:c->application]; + if (parent == NULL) { + c->window = [[NSWindow alloc] + initWithContentRect:c->rect + styleMask:(NSTitledWindowMask | NSClosableWindowMask | + NSMiniaturizableWindowMask | NSResizableWindowMask) + backing:NSBackingStoreBuffered + defer:NO]; + } else { + NSWindow *parentWindow = parent->cocoa.real->window; - if(parent != NULL) { - MilskoCocoa* p = parent->cocoa.real; - [p->window addChildWindow:c->window ordered:NSWindowAbove]; - } else { - [c->application activateIgnoringOtherApps:true]; - } + c->rect = [parentWindow frameRectForContentRect:c->rect]; + c->rect.origin.y = + y - + [parentWindow contentRectForFrameRect:parentWindow.frame].size.height; - c->view = [[MilskoCocoaView alloc] initWithFrame:c->rect]; - [c->window setContentView:c->view]; + c->window = [[NSWindow alloc] initWithContentRect:c->rect + styleMask:NSBorderlessWindowMask + backing:NSBackingStoreBuffered + defer:NO]; + } - return c; + [c->window makeKeyAndOrderFront:c->application]; + + if (parent != NULL) { + MilskoCocoa *p = parent->cocoa.real; + [p->window addChildWindow:c->window ordered:NSWindowAbove]; + } else { + [c->application activateIgnoringOtherApps:true]; + } + + c->view = [[MilskoCocoaView alloc] initWithFrame:c->rect]; + [c->window setContentView:c->view]; + + c->parent = parent; + + return c; } -- (void)polygonWithPoints:(MwPoint*)points - points_count:(int)points_count - color:(MwLLColor)color { - int i; - CGContextRef cg = [self->view context]; +- (void)polygonWithPoints:(MwPoint *)points + points_count:(int)points_count + color:(MwLLColor)color { + int i; + CGContextRef cg = [self->view context]; - CGContextSetRGBFillColor(cg, color->common.red / 255., color->common.blue / 255., color->common.green / 255., 1); - CGContextBeginPath(cg); - for(i = 0; i < points_count; i++) { - CGContextMoveToPoint(cg, points[i].x, points[i].y); - if(i < points_count - 1) { - CGContextAddLineToPoint(cg, points[i + 1].x, points[i + 1].y); - } - } - CGContextFillPath(cg); + [self->view lockFocus]; - // [self->view setNeedsDisplay:true]; + CGContextSetRGBFillColor(cg, color->common.red / 255., + color->common.blue / 255., + color->common.green / 255., 1); + CGContextBeginPath(cg); + for (i = 0; i < points_count; i++) { + CGContextMoveToPoint(cg, points[i].x, points[i].y); + if (i < points_count - 1) { + CGContextAddLineToPoint(cg, points[i + 1].x, points[i + 1].y); + } + } + CGContextFillPath(cg); + [self->view unlockFocus]; + + [self->view setNeedsDisplay:true]; }; -- (void)lineWithPoints:(MwPoint*)points 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 { - NSRect frame = [self->window frame]; +- (void)getX:(int *)x Y:(int *)y W:(unsigned int *)w H:(unsigned int *)h { + NSRect frame = [self->window frame]; - *x = frame.origin.x; - *y = frame.origin.y; - *w = frame.size.width; - *h = frame.size.height; + *x = frame.origin.x; + *y = frame.origin.y - frame.size.height; + *w = frame.size.width; + *h = frame.size.height; }; - (void)setX:(int)x Y:(int)y { - NSPoint p; - p.x = x; - p.y = y; - NSRect frame = [self->window frame]; - frame.origin.x = x; - frame.origin.y = y; - [self->window setFrame:frame display:YES animate:true]; + NSRect frame = [self->window frame]; + + frame.origin.x = x; + frame.origin.y = y; + + if (self->parent) { + NSWindow *parentWindow = self->parent->cocoa.real->window; + frame = [parentWindow contentRectForFrameRect:frame]; + frame.origin.y = + [parentWindow contentRectForFrameRect:parentWindow.frame].size.height - + y; + } + + [self->window setFrame:frame display:YES animate:false]; }; - (void)setW:(int)w H:(int)h { - NSRect frame = [self->window frame]; - frame.size.width = w; - frame.size.height = h; - [self->window setFrame:frame display:YES animate:true]; + NSRect frame = [self->window frame]; + frame.size.width = w; + frame.size.height = h; + + if (self->parent) { + NSWindow *parentWindow = self->parent->cocoa.real->window; + // frame = [parentWindow contentRectForFrameRect:frame]; + } + + [self->window setFrame:frame display:YES animate:false]; }; - (int)pending { - return 1; + self->lastEvent = + [self->application nextEventMatchingMask:NSAnyEventMask + untilDate:nil + inMode:NSDefaultRunLoopMode + dequeue:YES]; + return self->lastEvent != NULL; }; - (void)getNextEvent { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSEvent* event = [self->application nextEventMatchingMask:NSAnyEventMask - untilDate:nil - inMode:NSDefaultRunLoopMode - dequeue:YES]; + if (self->lastEvent != nil) { + // printf("got event: %ld\n", self->lastEvent.type); + } - if(event != nil) { - printf("got event: %p\n", event); - } + [self->application sendEvent:self->lastEvent]; - [self->application sendEvent:event]; + /* this should be in the draw functions but it's here for now for testing */ + [self->view setNeedsDisplay:true]; - /* this should be in the draw functions but it's here for now for testing */ - [self->view setNeedsDisplay:true]; - - [pool release]; + [pool release]; }; -- (void)setTitle:(const char*)title { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - [self->window - setTitleWithRepresentedFilename:[NSString stringWithUTF8String:title]]; - [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 { - MilskoCocoaPixmap* p = pixmap->cocoa.real; - [[p image] drawAtPoint:NSMakePoint(_rect->x, _rect->y) fromRect:NSMakeRect(_rect->x, _rect->y, _rect->width, _rect->height) operation:NSCompositeClear fraction:1.0]; +- (void)drawPixmap:(MwLLPixmap)pixmap rect:(MwRect *)_rect { + MilskoCocoaPixmap *p = pixmap->cocoa.real; + NSGraphicsContext *ctx = [self->view context]; + if (ctx) { + [NSGraphicsContext saveGraphicsState]; + [NSGraphicsContext setCurrentContext:ctx]; + + [[NSColor redColor] setFill]; + [[p image] drawInRect:NSMakeRect(_rect->x, _rect->y, _rect->width, + _rect->height) + fromRect:NSZeroRect + operation:NSCompositeSourceOver + fraction:1.0 + respectFlipped:NO + hints:nil]; + + [NSGraphicsContext restoreGraphicsState]; + + [self->view setNeedsDisplay:YES]; + } }; - (void)setIcon:(MwLLPixmap)pixmap { }; - (void)forceRender { }; -- (void)setCursor:(MwCursor*)image mask:(MwCursor*)mask { +- (void)setCursor:(MwCursor *)image mask:(MwCursor *)mask { }; -- (void)detachWithPoint:(MwPoint*)point { +- (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 { - MwU32 mask = [self->window styleMask]; - if(mask & NSBorderlessWindowMask) { - mask ^= NSBorderlessWindowMask; - mask |= NSTitledWindowMask; - } else { - mask |= NSBorderlessWindowMask; - mask ^= NSTitledWindowMask; - } - [self->window initWithContentRect:self->rect - styleMask:mask - backing:NSBackingStoreBuffered - defer:NO]; + MwU32 mask = [self->window styleMask]; + if (mask & NSBorderlessWindowMask) { + 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]; + [self->window makeMainWindow]; }; - (void)grabPointer:(int)toggle { - /* MacOS didn't have a "pointer grab" function until 10.13.2 so I need to do - * this manually */ + /* MacOS didn't have a "pointer grab" function until 10.13.2 so I need to do + * this manually */ }; -- (void)setClipboard:(const char*)text { +- (void)setClipboard:(const char *)text { }; - (void)getClipboard { }; - (void)makeToolWindow { }; -- (void)getCursorCoord:(MwPoint*)point { - NSPoint p = [NSEvent mouseLocation]; - point->x = p.x; - point->y = p.y; +- (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)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->window dealloc]; + [self->window dealloc]; } @end @implementation MilskoCocoaView - (id)initWithFrame:(NSRect)frame { - self = [super initWithFrame:frame]; - self->width = frame.size.width; - self->height = frame.size.height; - self->buf = malloc(self->width * self->height * 4); - self->space = CGColorSpaceCreateDeviceRGB(); - self->cg = CGBitmapContextCreate(self->buf, - self->width, - self->height, - CHAR_BIT, - self->width * sizeof(MwU32), - self->space, kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedLast); - assert(self->cg); - printf("%p\n", self->cg); - return self; + self = [super initWithFrame:frame]; + self->width = frame.size.width; + self->height = frame.size.height; + self->buf = malloc(self->width * self->height * 4); + self->space = CGColorSpaceCreateDeviceRGB(); + + if (width == 0 || height == 0) { + self->rep = NULL; + self->context = NULL; + } else { + self->rep = + [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL + pixelsWide:width + pixelsHigh:height + bitsPerSample:8 + samplesPerPixel:4 + hasAlpha:YES + isPlanar:NO + colorSpaceName:NSDeviceRGBColorSpace + bytesPerRow:width * 4 + bitsPerPixel:32]; + assert(self->rep); + + self->context = + [NSGraphicsContext graphicsContextWithBitmapImageRep:self->rep]; + assert(self->context); + } + + return self; } -- (CGContextRef)context { - return self->cg; +- (NSGraphicsContext *)context { + return self->context; } - (void)drawRect:(NSRect)dirtyRect { - [super drawRect:dirtyRect]; - if(self) { + [super drawRect:dirtyRect]; + if (!self->rep) { + return; + } + [self->rep drawInRect:NSMakeRect(0, 0, self->width, self->height)]; - CGImageRef img = CGBitmapContextCreateImage(self->cg); - if(!img) { - return; - } - printf("printed image\n"); - - CGContextDrawImage([[NSGraphicsContext currentContext] graphicsPort], CGRectMake(0, 0, self->width, self->height), img); - CGImageRelease(img); - } - // printf("%0.2f %0.2f %0.2f %0.2f\n", dirtyRect.origin.x, dirtyRect.origin.y, dirtyRect.size.width, dirtyRect.size.height); + unsigned char *pixels = [self->rep bitmapData]; } - (void)destroy { - free(self->buf); - CGContextRelease(self->cg); - CGColorSpaceRelease(self->space); + free(self->buf); + CGColorSpaceRelease(self->space); } @end static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { - MwLL r; - (void)x; - (void)y; - (void)width; - (void)height; + MwLL r; + (void)x; + (void)y; + (void)width; + (void)height; - r = malloc(sizeof(*r)); + r = malloc(sizeof(*r)); - MwLLCreateCommon(r); + MwLLCreateCommon(r); - MilskoCocoa* o = - [MilskoCocoa newWithParent:parent - x:x - y:y - width:width - height:height]; - r->cocoa.real = o; + MilskoCocoa *o = + [MilskoCocoa newWithParent:parent x:x y:y width:width height:height]; + r->cocoa.real = o; - return r; + return r; } static void MwLLDestroyImpl(MwLL handle) { - MilskoCocoa* h = handle->cocoa.real; + MilskoCocoa *h = handle->cocoa.real; - [h destroy]; + [h destroy]; - MwLLDestroyCommon(handle); + MwLLDestroyCommon(handle); - free(handle); + free(handle); } -static void MwLLBeginDrawImpl(MwLL handle) { - (void)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) { + MilskoCocoa *h = handle->cocoa.real; + [h polygonWithPoints:points points_count:points_count color:color]; } -static void MwLLEndDrawImpl(MwLL handle) { - (void)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]; -} - -static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { - MilskoCocoa* h = handle->cocoa.real; - [h lineWithPoints:points color:color]; +static void MwLLLineImpl(MwLL handle, MwPoint *points, MwLLColor color) { + MilskoCocoa *h = handle->cocoa.real; + [h lineWithPoints:points color: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; + MwLLColor c = malloc(sizeof(*c)); + MwLLColorUpdate(handle, c, r, g, b); + return c; } static void MwLLColorUpdateImpl(MwLL handle, MwLLColor c, int r, int g, int b) { - (void)handle; + (void)handle; - c->common.red = r; - c->common.green = g; - c->common.blue = 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* height) { - MilskoCocoa* h = handle->cocoa.real; - [h getX:x Y:y W:w H:height]; +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]; } static void MwLLSetXYImpl(MwLL handle, int x, int y) { - MilskoCocoa* h = handle->cocoa.real; - [h setX:x Y:y]; + MilskoCocoa *h = handle->cocoa.real; + [h setX:x Y:y]; } static void MwLLSetWHImpl(MwLL handle, int w, int height) { - MilskoCocoa* h = handle->cocoa.real; - [h setW:w H:height]; + MilskoCocoa *h = handle->cocoa.real; + [h setW:w H:height]; } -static void MwLLFreeColorImpl(MwLLColor color) { - free(color); -} +static void MwLLFreeColorImpl(MwLLColor color) { free(color); } static int MwLLPendingImpl(MwLL handle) { - MilskoCocoa* h = handle->cocoa.real; - return [h pending]; + MilskoCocoa *h = handle->cocoa.real; + if ([h pending]) { + MwLLDispatch(handle, draw, NULL); + return 1; + }; } static void MwLLNextEventImpl(MwLL handle) { - MilskoCocoa* h = handle->cocoa.real; - [h getNextEvent]; + MilskoCocoa *h = handle->cocoa.real; + [h getNextEvent]; } -static void MwLLSetTitleImpl(MwLL handle, const char* title) { - MilskoCocoa* h = handle->cocoa.real; - [h setTitle:title]; +static void MwLLSetTitleImpl(MwLL handle, const char *title) { + MilskoCocoa *h = handle->cocoa.real; + [h setTitle:title]; } -static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, - int width, int height) { - (void)handle; +static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char *data, + int width, int height) { + (void)handle; - MwLLPixmap r = malloc(sizeof(*r)); + MwLLPixmap r = malloc(sizeof(*r)); - r->common.raw = malloc(4 * width * height); - memcpy(r->common.raw, data, 4 * width * height); + r->common.raw = malloc(4 * width * height); + memcpy(r->common.raw, data, 4 * width * height); - r->common.width = width; - r->common.height = height; + r->common.width = width; + r->common.height = height; - r->cocoa.real = [MilskoCocoaPixmap newWithWidth:width height:height]; + r->cocoa.real = [MilskoCocoaPixmap newWithWidth:width height:height]; - MwLLPixmapUpdate(r); - return r; + MwLLPixmapUpdate(r); + return r; } static void MwLLPixmapUpdateImpl(MwLLPixmap pixmap) { - MilskoCocoaPixmap* p = pixmap->cocoa.real; - [p updateWithData:pixmap->common.raw]; + MilskoCocoaPixmap *p = pixmap->cocoa.real; + [p updateWithData:pixmap->common.raw]; } static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { - MilskoCocoaPixmap* p = pixmap->cocoa.real; - [p destroy]; - free(pixmap); + MilskoCocoaPixmap *p = pixmap->cocoa.real; + [p destroy]; + free(pixmap); } -static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { - MilskoCocoa* h = handle->cocoa.real; - [h drawPixmap:pixmap rect:rect]; +static void MwLLDrawPixmapImpl(MwLL handle, MwRect *rect, MwLLPixmap pixmap) { + MilskoCocoa *h = handle->cocoa.real; + [h drawPixmap:pixmap rect:rect]; + MwLLForceRender(handle); } static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { - MilskoCocoa* h = handle->cocoa.real; - [h setIcon:pixmap]; + MilskoCocoa *h = handle->cocoa.real; + [h setIcon:pixmap]; } static void MwLLForceRenderImpl(MwLL handle) { - MilskoCocoa* h = handle->cocoa.real; - [h forceRender]; + MilskoCocoa *h = handle->cocoa.real; + [h forceRender]; } -static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { - MilskoCocoa* h = handle->cocoa.real; - [h setCursor:image mask:mask]; +static void MwLLSetCursorImpl(MwLL handle, MwCursor *image, MwCursor *mask) { + MilskoCocoa *h = handle->cocoa.real; + [h setCursor:image mask:mask]; } -static void MwLLDetachImpl(MwLL handle, MwPoint* point) { - MilskoCocoa* h = handle->cocoa.real; - [h detachWithPoint:point]; +static void MwLLDetachImpl(MwLL handle, MwPoint *point) { + MilskoCocoa *h = handle->cocoa.real; + [h detachWithPoint:point]; } static void MwLLShowImpl(MwLL handle, int show) { - MilskoCocoa* h = handle->cocoa.real; - [h show:show]; + MilskoCocoa *h = handle->cocoa.real; + [h show:show]; } static void MwLLMakePopupImpl(MwLL handle, MwLL parent) { - MilskoCocoa* h = handle->cocoa.real; - [h makePopupWithParent:parent]; + MilskoCocoa *h = handle->cocoa.real; + [h 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]; + int maxy) { + MilskoCocoa *h = handle->cocoa.real; + [h setSizeHintsWithMinX:minx MinY:miny MaxX:maxx MaxY:maxy]; } static void MwLLMakeBorderlessImpl(MwLL handle, int toggle) { - MilskoCocoa* h = handle->cocoa.real; - [h makeBorderless:toggle]; + MilskoCocoa *h = handle->cocoa.real; + [h makeBorderless:toggle]; } static void MwLLFocusImpl(MwLL handle) { - MilskoCocoa* h = handle->cocoa.real; - [h focus]; + MilskoCocoa *h = handle->cocoa.real; + [h focus]; } static void MwLLGrabPointerImpl(MwLL handle, int toggle) { - MilskoCocoa* h = handle->cocoa.real; - [h grabPointer:toggle]; + MilskoCocoa *h = handle->cocoa.real; + [h grabPointer:toggle]; } -static void MwLLSetClipboardImpl(MwLL handle, const char* text) { - MilskoCocoa* h = handle->cocoa.real; - [h setClipboard:text]; +static void MwLLSetClipboardImpl(MwLL handle, const char *text) { + MilskoCocoa *h = handle->cocoa.real; + [h setClipboard:text]; } -static void MwLLGetClipboardImpl(MwLL handle) { - (void)handle; -} +static void MwLLGetClipboardImpl(MwLL handle) { (void)handle; } static void MwLLMakeToolWindowImpl(MwLL handle) { - MilskoCocoa* h = handle->cocoa.real; - [h makeToolWindow]; + MilskoCocoa *h = handle->cocoa.real; + [h makeToolWindow]; } -static void MwLLGetCursorCoordImpl(MwLL handle, MwPoint* point) { - MilskoCocoa* h = handle->cocoa.real; - [h getCursorCoord:point]; +static void MwLLGetCursorCoordImpl(MwLL handle, MwPoint *point) { + MilskoCocoa *h = handle->cocoa.real; + [h getCursorCoord:point]; } -static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) { - MilskoCocoa* h = handle->cocoa.real; - [h getScreenSize:rect]; +static void MwLLGetScreenSizeImpl(MwLL handle, MwRect *rect) { + MilskoCocoa *h = handle->cocoa.real; + [h getScreenSize:rect]; } -static void MwLLBeginStateChangeImpl(MwLL handle) { - MwLLShow(handle, 0); -} +static void MwLLBeginStateChangeImpl(MwLL handle) { MwLLShow(handle, 0); } -static void MwLLEndStateChangeImpl(MwLL handle) { - MwLLShow(handle, 1); -} +static void MwLLEndStateChangeImpl(MwLL handle) { MwLLShow(handle, 1); } -static int MwLLCocoaCallInitImpl(void) { - return 0; -} +static int MwLLCocoaCallInitImpl(void) { return 0; } #include "call.c" CALL(Cocoa); From cc2d3008d0d263d6c7f73ddc895e849fbed5a144 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 4 Mar 2026 00:02:14 -0700 Subject: [PATCH 24/94] mac: implement polygon function --- src/backend/cocoa.m | 48 ++++++++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 1e069cc2..3117ba58 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -1,3 +1,4 @@ +#include "Mw/BaseTypes.h" #include #include #include @@ -97,6 +98,7 @@ if (parent != NULL) { MilskoCocoa *p = parent->cocoa.real; [p->window addChildWindow:c->window ordered:NSWindowAbove]; + [c->window setHasShadow:MwFALSE]; } else { [c->application activateIgnoringOtherApps:true]; } @@ -111,25 +113,40 @@ - (void)polygonWithPoints:(MwPoint *)points points_count:(int)points_count color:(MwLLColor)color { - int i; - CGContextRef cg = [self->view context]; + NSGraphicsContext *ctx = [self->view context]; + if (ctx) { + int i; + NSBezierPath *path = [NSBezierPath bezierPath]; + NSColor *nscolor = [NSColor colorWithRed:color->common.red / 255. + green:color->common.green / 255. + blue:color->common.blue / 255. + alpha:1.0]; - [self->view lockFocus]; + [NSGraphicsContext saveGraphicsState]; + [NSGraphicsContext setCurrentContext:ctx]; - CGContextSetRGBFillColor(cg, color->common.red / 255., - color->common.blue / 255., - color->common.green / 255., 1); - CGContextBeginPath(cg); - for (i = 0; i < points_count; i++) { - CGContextMoveToPoint(cg, points[i].x, points[i].y); - if (i < points_count - 1) { - CGContextAddLineToPoint(cg, points[i + 1].x, points[i + 1].y); + [nscolor setFill]; + for (i = 0; i < points_count; i++) { + if (i == 0) { + [path moveToPoint:NSMakePoint(points[i].x, + [self->window frame].size.height - + points[i].y)]; + } else { + [path lineToPoint:NSMakePoint(points[i].x, + [self->window frame].size.height - + points[i].y)]; + } } - } - CGContextFillPath(cg); - [self->view unlockFocus]; - [self->view setNeedsDisplay:true]; + [path closePath]; + [path fill]; + + [NSGraphicsContext restoreGraphicsState]; + + [self->view setNeedsDisplay:YES]; + + [nscolor dealloc]; + } }; - (void)lineWithPoints:(MwPoint *)points color:(MwLLColor)color { }; @@ -204,7 +221,6 @@ [NSGraphicsContext saveGraphicsState]; [NSGraphicsContext setCurrentContext:ctx]; - [[NSColor redColor] setFill]; [[p image] drawInRect:NSMakeRect(_rect->x, _rect->y, _rect->width, _rect->height) fromRect:NSZeroRect From b3735fa36420a43e1be0b0bb747cb16884035189 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Thu, 5 Mar 2026 04:09:01 +0900 Subject: [PATCH 25/94] rename Makefile.pl to configure --- Jenkinsfile | 6 +++--- README.txt | 46 +++++++++++++++++++--------------------- Makefile.pl => configure | 2 +- tools/readme.pl | 4 ++-- 4 files changed, 28 insertions(+), 30 deletions(-) rename Makefile.pl => configure (98%) diff --git a/Jenkinsfile b/Jenkinsfile index 58736fdb..5588f1be 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -22,7 +22,7 @@ pipeline { label "built-in" } steps { - sh("./Makefile.pl --enable-opengl --enable-vulkan --without-vulkan-string-helper") + sh("./configure --enable-opengl --enable-vulkan --without-vulkan-string-helper") sh("make clean") sh("make -j4") } @@ -32,7 +32,7 @@ pipeline { label "built-in" } steps { - sh("./Makefile.pl --enable-opengl --enable-stb-truetype --disable-freetype2 --cross --target=Windows --host=i686-w64-mingw32") + sh("./configure --enable-opengl --enable-stb-truetype --disable-freetype2 --cross --target=Windows --host=i686-w64-mingw32") sh("make clean") sh("make -j4") } @@ -42,7 +42,7 @@ pipeline { label "built-in" } steps { - sh("./Makefile.pl --enable-opengl --enable-stb-truetype --disable-freetype2 --cross --target=Windows --host=x86_64-w64-mingw32") + sh("./configure --enable-opengl --enable-stb-truetype --disable-freetype2 --cross --target=Windows --host=x86_64-w64-mingw32") sh("make clean") sh("make -j4") } diff --git a/README.txt b/README.txt index 744e7a8e..f69b6365 100644 --- a/README.txt +++ b/README.txt @@ -1,25 +1,23 @@ -Greetings - Welcome to the Milsko GUI Toolkit (Version pre-1.0) +Greetings - Welcome to the Milsko GUI Toolkit (Version pre-1.0) - This document contains a brief summary of the contents of this source -distributions and building instructions for Milsko GUI Toolkit. + This document contains a brief summary of the contents of this source +distributions and building instructions for Milsko GUI Toolkit. Requirements - Milsko requires either - * A Windows environment with GDI (so anything NT or 9x) - * A Mac OS environment with Cocoa (10.4 is the minimum tested) - * Unix-like environment with X11 for runtime. + Milsko requires the Windows environment with GDI (so anything NT or 9x) or +the Unix-like environment with X11 for runtime. - To build Milsko for Windows, you must have one of following compilers: - * Visual C++ 6.0 or newer - * Borland C++ 5.5 or newer - * Open Watcom 2.0 or newer - * MinGW-w64 + To build Milsko for Windows, you must have one of following compilers: + * Visual C++ 6.0 or newer + * Borland C++ 5.5 or newer + * Open Watcom 2.0 or newer + * MinGW-w64 - and for Unix-like/Mac OS: - * GNU C Compiler - * Clang + and for Unix-like: + * GNU C Compiler + * Clang Contents @@ -41,31 +39,31 @@ distributions and building instructions for Milsko GUI Toolkit. Building Milsko - Building Milsko depends on the platform you use, and the compiler you use. + Building Milsko depends on the platform you use, and the compiler you use. A. Visual C++ ------------- -1) Run `nmake -f NTMakefile'. +1) Run `nmake -f NTMakefile'. B. Borland C++ -------------- -1) Run `make -f BorMakefile'. +1) Run `make -f BorMakefile'. C. Open Watcom -------------- -1) Run `wmake -f WatMakefile'. +1) Run `wmake -f WatMakefile'. D. MinGW-w64/GCC/Clang ---------------------- -1) Determine if you need Vulkan and/or OpenGL. +1) Determine if you need Vulkan and/or OpenGL. -2) Run `./Makefile.pl'. - For help, run `./Makefile.pl --help'. +2) Run `./configure'. + For help, run `./configure --help'. -3) Run `make'. +3) Run `make'. - -- Nishi (nishi@nishi.boats) + -- Nishi (nishi@nishi.boats) diff --git a/Makefile.pl b/configure similarity index 98% rename from Makefile.pl rename to configure index 519781ec..5ffbe544 100755 --- a/Makefile.pl +++ b/configure @@ -187,7 +187,7 @@ print(OUT " clang-format --verbose -i `find src include examples -name \"*.c\" -or -name \"*.h\" -or -name \"*.m\"`\n" ); print(OUT -" perltidy -b -bext=\"/\" --paren-tightness=2 `find tools pl Makefile.pl -name \"*.pl\"`\n" +" perltidy -b -bext=\"/\" --paren-tightness=2 `find tools pl configure -name \"*.pl\"`\n" ); print(OUT "\n"); print(OUT "lib:"); diff --git a/tools/readme.pl b/tools/readme.pl index 573d9573..c511f794 100755 --- a/tools/readme.pl +++ b/tools/readme.pl @@ -105,8 +105,8 @@ l("1) Run `wmake -f WatMakefile'."); h("D. MinGW-w64/GCC/Clang"); l("1) Determine if you need Vulkan and/or OpenGL."); l(""); -l("2) Run `./Makefile.pl'."); -l(" For help, run `./Makefile.pl --help'."); +l("2) Run `./configure'."); +l(" For help, run `./configure --help'."); l(""); l("3) Run `make'."); l(""); From e09eccbf5fba81ef0ca2756979cb623833aec6d5 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 4 Mar 2026 13:59:28 -0600 Subject: [PATCH 26/94] refactor font.c into an MwFL section (#9) Reviewed-on: https://gitea.nishi.boats/pyrite-dev/milsko/pulls/9 Co-authored-by: IoIxD Co-committed-by: IoIxD --- BorMakefile | 12 +- CMakeLists.txt | 2 +- NTMakefile | 12 +- WatMakefile | 26 +-- include/Mw/LowLevel.h | 26 +++ pl/rules.pl | 3 +- src/core.c | 2 + src/text.c | 384 --------------------------------- src/{ => text}/font/boldfont.c | 0 src/{ => text}/font/boldttf.c | 0 src/{ => text}/font/font.c | 0 src/{ => text}/font/ttf.c | 0 src/text/ft2.c | 139 ++++++++++++ src/text/stbtt.c | 141 ++++++++++++ src/text/text.c | 158 ++++++++++++++ 15 files changed, 489 insertions(+), 416 deletions(-) delete mode 100644 src/text.c rename src/{ => text}/font/boldfont.c (100%) rename src/{ => text}/font/boldttf.c (100%) rename src/{ => text}/font/font.c (100%) rename src/{ => text}/font/ttf.c (100%) create mode 100644 src/text/ft2.c create mode 100644 src/text/stbtt.c create mode 100644 src/text/text.c diff --git a/BorMakefile b/BorMakefile index 59551b5f..b6d06277 100644 --- a/BorMakefile +++ b/BorMakefile @@ -27,10 +27,6 @@ clean: del /f /q src\dialog\messagebox.obj del /f /q src\draw.obj del /f /q src\error.obj - del /f /q src\font\boldfont.obj - del /f /q src\font\boldttf.obj - del /f /q src\font\font.obj - del /f /q src\font\ttf.obj del /f /q src\icon\back.obj del /f /q src\icon\clock.obj del /f /q src\icon\computer.obj @@ -49,7 +45,9 @@ clean: del /f /q src\icon\warning.obj del /f /q src\lowlevel.obj del /f /q src\string.obj - del /f /q src\text.obj + del /f /q src\text\ft2.obj + del /f /q src\text\stbtt.obj + del /f /q src\text\text.obj del /f /q src\unicode.obj del /f /q src\widget\box.obj del /f /q src\widget\button.obj @@ -74,8 +72,8 @@ clean: del /f /q src\Mw.dll del /f /q src\Mw.lib -src\Mw.dll: external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\error.obj src\font\boldfont.obj src\font\boldttf.obj src\font\font.obj src\font\ttf.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\checkbox.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj - $(LD) $(LDFLAGS) -e$@ external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\error.obj src\font\boldfont.obj src\font\boldttf.obj src\font\font.obj src\font\ttf.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\checkbox.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj -lopengl32.lib -lgdi32.lib -luser32.lib +src\Mw.dll: external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\error.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\ft2.obj src\text\stbtt.obj src\text\text.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\checkbox.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj + $(LD) $(LDFLAGS) -e$@ external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\error.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\ft2.obj src\text\stbtt.obj src\text\text.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\checkbox.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj -lopengl32.lib -lgdi32.lib -luser32.lib implib src\Mw.lib src\Mw.dll .c.obj: diff --git a/CMakeLists.txt b/CMakeLists.txt index 650d6d1e..09a5bd90 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ option(MW_INSTALL_HEADERS "Install headers" ON) file( GLOB SOURCES - src/*.c src/cursor/*.c src/icon/*.c src/text.c src/widget/*.c src/math/*.c src/font/*.c src/dialog/*.c src/abstract/*.c external/*.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") diff --git a/NTMakefile b/NTMakefile index 265418a7..7ba162df 100644 --- a/NTMakefile +++ b/NTMakefile @@ -27,10 +27,6 @@ clean: del /f /q src\dialog\messagebox.obj del /f /q src\draw.obj del /f /q src\error.obj - del /f /q src\font\boldfont.obj - del /f /q src\font\boldttf.obj - del /f /q src\font\font.obj - del /f /q src\font\ttf.obj del /f /q src\icon\back.obj del /f /q src\icon\clock.obj del /f /q src\icon\computer.obj @@ -49,7 +45,9 @@ clean: del /f /q src\icon\warning.obj del /f /q src\lowlevel.obj del /f /q src\string.obj - del /f /q src\text.obj + del /f /q src\text\ft2.obj + del /f /q src\text\stbtt.obj + del /f /q src\text\text.obj del /f /q src\unicode.obj del /f /q src\widget\box.obj del /f /q src\widget\button.obj @@ -74,8 +72,8 @@ clean: del /f /q src\Mw.dll del /f /q src\Mw.lib -src\Mw.dll: external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\error.obj src\font\boldfont.obj src\font\boldttf.obj src\font\font.obj src\font\ttf.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\checkbox.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj - $(LD) $(LDFLAGS) /OUT:$@ external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\error.obj src\font\boldfont.obj src\font\boldttf.obj src\font\font.obj src\font\ttf.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\checkbox.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib user32.lib +src\Mw.dll: external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\error.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\ft2.obj src\text\stbtt.obj src\text\text.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\checkbox.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj + $(LD) $(LDFLAGS) /OUT:$@ external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\error.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\ft2.obj src\text\stbtt.obj src\text\text.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\checkbox.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib user32.lib .c.obj: diff --git a/WatMakefile b/WatMakefile index dc7b1211..d8dbf5e9 100644 --- a/WatMakefile +++ b/WatMakefile @@ -26,10 +26,6 @@ clean: .SYMBOLIC %erase src/dialog/messagebox.obj %erase src/draw.obj %erase src/error.obj - %erase src/font/boldfont.obj - %erase src/font/boldttf.obj - %erase src/font/font.obj - %erase src/font/ttf.obj %erase src/icon/back.obj %erase src/icon/clock.obj %erase src/icon/computer.obj @@ -48,7 +44,9 @@ clean: .SYMBOLIC %erase src/icon/warning.obj %erase src/lowlevel.obj %erase src/string.obj - %erase src/text.obj + %erase src/text/ft2.obj + %erase src/text/stbtt.obj + %erase src/text/text.obj %erase src/unicode.obj %erase src/widget/box.obj %erase src/widget/button.obj @@ -73,8 +71,8 @@ clean: .SYMBOLIC %erase src/Mw.dll %erase src/Mw.lib -src/Mw.dll: external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/error.obj src/font/boldfont.obj src/font/boldttf.obj src/font/font.obj src/font/ttf.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/checkbox.obj src/widget/combobox.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj - $(LD) $(LDFLAGS) option implib=src/Mw.lib name $@ file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/error.obj file src/font/boldfont.obj file src/font/boldttf.obj file src/font/font.obj file src/font/ttf.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/checkbox.obj file src/widget/combobox.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library user32.lib +src/Mw.dll: external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/error.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text/ft2.obj src/text/stbtt.obj src/text/text.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/checkbox.obj src/widget/combobox.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj + $(LD) $(LDFLAGS) option implib=src/Mw.lib name $@ file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/error.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/ft2.obj file src/text/stbtt.obj file src/text/text.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/checkbox.obj file src/widget/combobox.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library user32.lib @@ -120,14 +118,6 @@ src/draw.obj: src/draw.c $(CC) $(CFLAGS) -fo=$@ $< src/error.obj: src/error.c $(CC) $(CFLAGS) -fo=$@ $< -src/font/boldfont.obj: src/font/boldfont.c - $(CC) $(CFLAGS) -fo=$@ $< -src/font/boldttf.obj: src/font/boldttf.c - $(CC) $(CFLAGS) -fo=$@ $< -src/font/font.obj: src/font/font.c - $(CC) $(CFLAGS) -fo=$@ $< -src/font/ttf.obj: src/font/ttf.c - $(CC) $(CFLAGS) -fo=$@ $< src/icon/back.obj: src/icon/back.c $(CC) $(CFLAGS) -fo=$@ $< src/icon/clock.obj: src/icon/clock.c @@ -164,7 +154,11 @@ src/lowlevel.obj: src/lowlevel.c $(CC) $(CFLAGS) -fo=$@ $< src/string.obj: src/string.c $(CC) $(CFLAGS) -fo=$@ $< -src/text.obj: src/text.c +src/text/ft2.obj: src/text/ft2.c + $(CC) $(CFLAGS) -fo=$@ $< +src/text/stbtt.obj: src/text/stbtt.c + $(CC) $(CFLAGS) -fo=$@ $< +src/text/text.obj: src/text/text.c $(CC) $(CFLAGS) -fo=$@ $< src/unicode.obj: src/unicode.c $(CC) $(CFLAGS) -fo=$@ $< diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index b5483288..dcab28d1 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -18,10 +18,12 @@ typedef struct _MwLLCommonPixmap* MwLLCommonPixmap; typedef union _MwLL* MwLL; typedef union _MwLLColor* MwLLColor; typedef union _MwLLPixmap* MwLLPixmap; +typedef struct _MwFLFont* MwFLFont; #else typedef void* MwLL; typedef void* MwLLColor; typedef void* MwLLPixmap; +typedef void* MwFLFont; #endif enum MwLLBackends { @@ -166,6 +168,14 @@ struct _MwLLHandler { void (*dark_theme)(MwLL handle, void* data); }; +struct _MwLLTextDispatchTable { + int (*drawText)(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color); + int (*textWidth)(MwWidget handle, const char* text); + int (*textHeight)(MwWidget handle, int count); + void* (*fontLoad)(unsigned char* data, unsigned int size); + void (*fontFree)(void* handle); +}; + #ifdef __cplusplus extern "C" { #endif @@ -225,6 +235,22 @@ MWDECL void (*MwLLGetClipboard)(MwLL handle); MWDECL void (*MwLLGetCursorCoord)(MwLL handle, MwPoint* point); MWDECL void (*MwLLGetScreenSize)(MwLL handle, MwRect* rect); +/*font renderer */ +MWDECL void MwFLSetup(); + +#ifdef USE_FREETYPE2 +MWDECL int MWFL_FT2Setup(); +#endif +#ifdef USE_STB_TRUETYPE +MWDECL int MwFL_STBTTSetup(); +#endif + +MWDECL int (*MwFLDrawText)(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color); +MWDECL int (*MwFLTextWidth)(MwWidget handle, const char* text); +MWDECL int (*MwFLTextHeight)(MwWidget handle, int count); +MWDECL void* (*MwFLFontLoad)(unsigned char* data, unsigned int size); +MWDECL void (*MwFLFontFree)(void* handle); + #ifdef __cplusplus } #endif diff --git a/pl/rules.pl b/pl/rules.pl index 59605a80..d4784e10 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -76,8 +76,9 @@ if (param_get("vulkan") && param_get("vulkan-string-helper")) { } new_object("src/icon/*.c"); -new_object("src/font/*.c"); new_object("src/cursor/*.c"); +new_object("src/text/*.c"); +new_object("src/text/font/*.c"); new_object("src/widget/box.c"); new_object("src/widget/button.c"); diff --git a/src/core.c b/src/core.c index 6985a02e..9902a30e 100644 --- a/src/core.c +++ b/src/core.c @@ -784,6 +784,8 @@ int MwLibraryInit(void) { NULL}; int i; + MwFLSetup(); + for(i = 0; calls[i] != NULL; i++) { if(calls[i]() == 0) return 0; } diff --git a/src/text.c b/src/text.c deleted file mode 100644 index c0e00c6d..00000000 --- a/src/text.c +++ /dev/null @@ -1,384 +0,0 @@ -#include - -#if defined(USE_FREETYPE2) -#include -#include FT_FREETYPE_H - -typedef struct ttf { - FT_Library library; - FT_Face face; - void* data; -} ttf_t; - -#define TTF -#elif defined(USE_STB_TRUETYPE) -#include "../external/stb_truetype.h" - -typedef struct ttf { - stbtt_fontinfo font; - void* data; - float scale; - int ascent; - int descent; -} ttf_t; - -#define TTF -#endif - -#define FontWidth 7 -#define FontHeight 14 - -static void bitmap_MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color) { - int i = 0, x, y, sx, sy; - int tw, th; - unsigned char* px; - MwRect r; - MwLLPixmap p; - - if(strlen(text) == 0) text = " "; - tw = MwTextWidth(handle, text); - th = MwTextHeight(handle, text); - px = malloc(tw * th * 4); - - memset(px, 0, tw * th * 4); - - sx = 0; - sy = 0; - - while(text[i] != 0) { - int out; - i += MwUTF8ToUTF32(text + i, &out); - - if(out > 0xff) { - out = 0; - } - - if(out == '\n') { - sx = 0; - sy += FontHeight; - } else { - for(y = 0; y < FontHeight; y++) { - for(x = 0; x < FontWidth; x++) { - unsigned char* ppx = &px[((sy + y) * tw + sx + x) * 4]; - if((bold ? MwBoldFontData : MwFontData)[out].data[y] & (1 << ((FontWidth - 1) - x))) { - ppx[0] = color->common.red; - ppx[1] = color->common.green; - ppx[2] = color->common.blue; - ppx[3] = 255; - } else { - ppx[0] = 0; - ppx[1] = 0; - ppx[2] = 0; - ppx[3] = 0; - } - } - } - sx += FontWidth; - } - } - - p = MwLoadRaw(handle, px, tw, th); - r.x = point->x; - r.y = point->y - th / 2; - r.width = tw; - r.height = th; - - if(align == MwALIGNMENT_CENTER) { - r.x -= tw / 2; - } else if(align == MwALIGNMENT_END) { - r.x -= tw; - } - - MwLLDrawPixmap(handle->lowlevel, &r, p); - MwLLDestroyPixmap(p); - free(px); -} - -#if defined(USE_STB_TRUETYPE) -static int ttf_MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color) { - ttf_t* ttf = MwGetVoid(handle, bold ? MwNboldFont : MwNfont); - unsigned char* px; - int tw, th; - MwRect r; - MwLLPixmap p; - int ax, lsb; - int x = 0, y = 0; - if(ttf == NULL) return 1; - - tw = MwTextWidth(handle, text); - th = MwTextHeight(handle, text); - px = malloc(tw * th * 4); - - memset(px, 0, tw * th * 4); - while(text[0] != 0) { - int c; - int x0, y0, x1, y1, cx, cy; - int ow, oh; - unsigned char* out; - - text += MwUTF8ToUTF32(text, &c); - if(c == '\n') { - x = 0; - y += (ttf->ascent - ttf->descent) * ttf->scale; - continue; - } - - stbtt_GetCodepointHMetrics(&ttf->font, c, &ax, &lsb); - - stbtt_GetCodepointBitmapBox(&ttf->font, c, ttf->scale, ttf->scale, &x0, &y0, &x1, &y1); - ow = x1 - x0; - oh = y1 - y0; - out = malloc(ow * oh); - stbtt_MakeCodepointBitmap(&ttf->font, out, ow, oh, ow, ttf->scale, ttf->scale, c); - - for(cy = 0; cy < oh; cy++) { - for(cx = 0; cx < ow; cx++) { - int ox = x + (lsb * ttf->scale) + cx; - int oy = y + (ttf->ascent * ttf->scale) + y0 + cy; - unsigned char* opx = &px[(oy * tw + ox) * 4]; - - opx[0] = color->common.red; - opx[1] = color->common.green; - opx[2] = color->common.blue; - opx[3] = out[cy * ow + cx]; - } - } - - x += ax * ttf->scale; - - free(out); - } - - p = MwLoadRaw(handle, px, tw, th); - r.x = point->x; - r.y = point->y - th / 2; - r.width = tw; - r.height = th; - - if(align == MwALIGNMENT_CENTER) { - r.x -= tw / 2; - } else if(align == MwALIGNMENT_END) { - r.x -= tw; - } - - MwLLDrawPixmap(handle->lowlevel, &r, p); - MwLLDestroyPixmap(p); - free(px); - - return 0; -} - -static int ttf_MwTextWidth(MwWidget handle, const char* text) { - ttf_t* ttf = MwGetVoid(handle, MwNfont); - int ax, lsb; - int tw = 0; - if(ttf == NULL) return -1; - - while(text[0] != 0) { - int c; - text += MwUTF8ToUTF32(text, &c); - - stbtt_GetCodepointHMetrics(&ttf->font, c, &ax, &lsb); - - tw += ax * ttf->scale; - } - - return tw; -} - -static int ttf_MwTextHeight(MwWidget handle, int count) { - ttf_t* ttf = MwGetVoid(handle, MwNfont); - if(ttf == NULL) return -1; - - return (ttf->ascent - ttf->descent) * ttf->scale * count; -} -#elif defined(USE_FREETYPE2) -static int ttf_MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color) { - ttf_t* ttf = MwGetVoid(handle, bold ? MwNboldFont : MwNfont); - int tw, th; - unsigned char* px; - MwLLPixmap p; - MwRect r; - int x = 0, y = 0; - if(ttf == NULL) return 1; - - tw = MwTextWidth(handle, text); - th = MwTextHeight(handle, text); - px = malloc(tw * th * 4); - - memset(px, 0, tw * th * 4); - while(text[0] != 0) { - int c; - FT_Bitmap* bmp; - int cy, cx; - int l = MwUTF8ToUTF32(text, &c); - if(l <= 0) break; - text += l; - - if(c == '\n') { - x = 0; - y += ttf->face->height * 14 / ttf->face->units_per_EM; - continue; - } - - FT_Load_Char(ttf->face, c, FT_LOAD_RENDER); - bmp = &ttf->face->glyph->bitmap; - - for(cy = 0; cy < bmp->rows; cy++) { - for(cx = 0; cx < bmp->width; cx++) { - int ox = x + cx + ttf->face->glyph->bitmap_left; - int oy = y + (ttf->face->height * 14 / ttf->face->units_per_EM) - ttf->face->glyph->bitmap_top + cy + (ttf->face->descender * 14 / ttf->face->units_per_EM); - unsigned char* opx = &px[(oy * tw + ox) * 4]; - - opx[0] = color->common.red; - opx[1] = color->common.green; - opx[2] = color->common.blue; - opx[3] = bmp->buffer[cy * bmp->pitch + cx]; - } - } - - x += ttf->face->glyph->metrics.horiAdvance / 64; - } - - p = MwLoadRaw(handle, px, tw, th); - r.x = point->x; - r.y = point->y - th / 2; - r.width = tw; - r.height = th; - - if(align == MwALIGNMENT_CENTER) { - r.x -= tw / 2; - } else if(align == MwALIGNMENT_END) { - r.x -= tw; - } - - MwLLDrawPixmap(handle->lowlevel, &r, p); - MwLLDestroyPixmap(p); - free(px); - - return 0; -} - -static int ttf_MwTextWidth(MwWidget handle, const char* text) { - ttf_t* ttf = MwGetVoid(handle, MwNfont); - int tw = 0, mtw = 0; - if(ttf == NULL) return -1; - - while(text[0] != 0) { - int c; - int l = MwUTF8ToUTF32(text, &c); - if(l <= 0) break; - text += l; - if(c == '\n') { - tw = 0; - continue; - } - - FT_Load_Char(ttf->face, c, FT_LOAD_RENDER); - - tw += ttf->face->glyph->metrics.horiAdvance / 64; - if(tw > mtw) mtw = tw; - } - - return mtw; -} - -static int ttf_MwTextHeight(MwWidget handle, int count) { - ttf_t* ttf = MwGetVoid(handle, MwNfont); - if(ttf == NULL) return -1; - - return (ttf->face->height * 14 / ttf->face->units_per_EM) * count; -} -#endif - -void MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color) { - if(strlen(text) == 0) return; -#ifdef TTF - if(MwGetInteger(handle, MwNbitmapFont) || ttf_MwDrawText(handle, point, text, bold, align, color)) -#endif - bitmap_MwDrawText(handle, point, text, bold, align, color); -} - -int MwTextWidth(MwWidget handle, const char* text) { - /* TODO: check newline */ -#ifdef TTF - int st; - - if(!MwGetInteger(handle, MwNbitmapFont) && (st = ttf_MwTextWidth(handle, text)) != -1) return st; -#else - (void)handle; - -#endif - return MwUTF8Length(text) * FontWidth; -} - -int MwTextHeight(MwWidget handle, const char* text) { - int c = 1; - int i = 0; -#ifdef TTF - int st; -#endif - - (void)handle; - (void)text; - - while(text[i] != 0) { - int out; - int l = MwUTF8ToUTF32(text + i, &out); - if(l == 0) break; - i += l; - - if(out == '\n') c++; - } -#ifdef TTF - if(!MwGetInteger(handle, MwNbitmapFont) && (st = ttf_MwTextHeight(handle, c)) != -1) return st; -#endif - return FontHeight * c; -} - -void* MwFontLoad(unsigned char* data, unsigned int size) { -#if defined(USE_FREETYPE2) - ttf_t* ttf = malloc(sizeof(*ttf)); - ttf->data = malloc(size); - memcpy(ttf->data, data, size); - FT_Init_FreeType(&ttf->library); - FT_New_Memory_Face(ttf->library, ttf->data, size, 0, &ttf->face); - - FT_Set_Pixel_Sizes(ttf->face, 0, 14); - - return ttf; -#elif defined(USE_STB_TRUETYPE) - ttf_t* ttf = malloc(sizeof(*ttf)); - ttf->data = malloc(size); - memcpy(ttf->data, data, size); - stbtt_InitFont(&ttf->font, ttf->data, 0); - - ttf->scale = stbtt_ScaleForPixelHeight(&ttf->font, 16); - stbtt_GetFontVMetrics(&ttf->font, &ttf->ascent, &ttf->descent, 0); - - return ttf; -#else - (void)data; - (void)size; - return NULL; -#endif -} - -void MwFontFree(void* handle) { -#if defined(USE_FREETYPE2) - ttf_t* ttf = handle; - - FT_Done_Face(ttf->face); - FT_Done_FreeType(ttf->library); - - free(ttf->data); - free(ttf); -#elif defined(USE_STB_TRUETYPE) - ttf_t* ttf = handle; - - free(ttf->data); - free(ttf); -#else - (void)handle; -#endif -} diff --git a/src/font/boldfont.c b/src/text/font/boldfont.c similarity index 100% rename from src/font/boldfont.c rename to src/text/font/boldfont.c diff --git a/src/font/boldttf.c b/src/text/font/boldttf.c similarity index 100% rename from src/font/boldttf.c rename to src/text/font/boldttf.c diff --git a/src/font/font.c b/src/text/font/font.c similarity index 100% rename from src/font/font.c rename to src/text/font/font.c diff --git a/src/font/ttf.c b/src/text/font/ttf.c similarity index 100% rename from src/font/ttf.c rename to src/text/font/ttf.c diff --git a/src/text/ft2.c b/src/text/ft2.c new file mode 100644 index 00000000..a5fb9202 --- /dev/null +++ b/src/text/ft2.c @@ -0,0 +1,139 @@ +#ifdef USE_FREETYPE2 +#include + +#include +#include FT_FREETYPE_H + +struct _MwFLFont { + FT_Library library; + FT_Face face; + void* data; +}; +static int ft2_MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color) { + MwFLFont ttf = MwGetVoid(handle, bold ? MwNboldFont : MwNfont); + int tw, th; + unsigned char* px; + MwLLPixmap p; + MwRect r; + int x = 0, y = 0; + if(ttf == NULL) return 1; + + tw = MwTextWidth(handle, text); + th = MwTextHeight(handle, text); + px = malloc(tw * th * 4); + + memset(px, 0, tw * th * 4); + while(text[0] != 0) { + int c; + FT_Bitmap* bmp; + int cy, cx; + int l = MwUTF8ToUTF32(text, &c); + if(l <= 0) break; + text += l; + + if(c == '\n') { + x = 0; + y += ttf->face->height * 14 / ttf->face->units_per_EM; + continue; + } + + FT_Load_Char(ttf->face, c, FT_LOAD_RENDER); + bmp = &ttf->face->glyph->bitmap; + + for(cy = 0; cy < bmp->rows; cy++) { + for(cx = 0; cx < bmp->width; cx++) { + int ox = x + cx + ttf->face->glyph->bitmap_left; + int oy = y + (ttf->face->height * 14 / ttf->face->units_per_EM) - ttf->face->glyph->bitmap_top + cy + (ttf->face->descender * 14 / ttf->face->units_per_EM); + unsigned char* opx = &px[(oy * tw + ox) * 4]; + + opx[0] = color->common.red; + opx[1] = color->common.green; + opx[2] = color->common.blue; + opx[3] = bmp->buffer[cy * bmp->pitch + cx]; + } + } + + x += ttf->face->glyph->metrics.horiAdvance / 64; + } + + p = MwLoadRaw(handle, px, tw, th); + r.x = point->x; + r.y = point->y - th / 2; + r.width = tw; + r.height = th; + + if(align == MwALIGNMENT_CENTER) { + r.x -= tw / 2; + } else if(align == MwALIGNMENT_END) { + r.x -= tw; + } + + MwLLDrawPixmap(handle->lowlevel, &r, p); + MwLLDestroyPixmap(p); + free(px); + + return 0; +} + +static int ft2_MwTextWidth(MwWidget handle, const char* text) { + MwFLFont ttf = MwGetVoid(handle, MwNfont); + int tw = 0, mtw = 0; + if(ttf == NULL) return -1; + + while(text[0] != 0) { + int c; + int l = MwUTF8ToUTF32(text, &c); + if(l <= 0) break; + text += l; + if(c == '\n') { + tw = 0; + continue; + } + + FT_Load_Char(ttf->face, c, FT_LOAD_RENDER); + + tw += ttf->face->glyph->metrics.horiAdvance / 64; + if(tw > mtw) mtw = tw; + } + + return mtw; +} + +static int ft2_MwTextHeight(MwWidget handle, int count) { + MwFLFont ttf = MwGetVoid(handle, MwNfont); + if(ttf == NULL) return -1; + + return (ttf->face->height * 14 / ttf->face->units_per_EM) * count; +} + +static void* ft2_MwFontLoad(unsigned char* data, unsigned int size) { + MwFLFont ttf = malloc(sizeof(*ttf)); + ttf->data = malloc(size); + memcpy(ttf->data, data, size); + FT_Init_FreeType(&ttf->library); + FT_New_Memory_Face(ttf->library, ttf->data, size, 0, &ttf->face); + + FT_Set_Pixel_Sizes(ttf->face, 0, 14); + + return ttf; +} + +static void ft2_MwFontFree(void* handle) { + MwFLFont ttf = handle; + + FT_Done_Face(ttf->face); + FT_Done_FreeType(ttf->library); + + free(ttf->data); + free(ttf); +} + +int MWFL_FT2Setup() { + MwFLDrawText = ft2_MwDrawText; + MwFLTextWidth = ft2_MwTextWidth; + MwFLTextHeight = ft2_MwTextHeight; + MwFLFontLoad = ft2_MwFontLoad; + MwFLFontFree = ft2_MwFontFree; + return 0; +} +#endif diff --git a/src/text/stbtt.c b/src/text/stbtt.c new file mode 100644 index 00000000..fb5e783e --- /dev/null +++ b/src/text/stbtt.c @@ -0,0 +1,141 @@ +#ifdef USE_STB_TRUETYPE +#include +#include + +#include "../../external/stb_truetype.h" + +struct _MwFLFont { + stbtt_fontinfo font; + void* data; + float scale; + int ascent; + int descent; +}; + +static int stbtt_MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color) { + MwFLFont ttf = MwGetVoid(handle, bold ? MwNboldFont : MwNfont); + unsigned char* px; + int tw, th; + MwRect r; + MwLLPixmap p; + int ax, lsb; + int x = 0, y = 0; + if(ttf == NULL) return 1; + + tw = MwTextWidth(handle, text); + th = MwTextHeight(handle, text); + px = malloc(tw * th * 4); + + memset(px, 0, tw * th * 4); + while(text[0] != 0) { + int c; + int x0, y0, x1, y1, cx, cy; + int ow, oh; + unsigned char* out; + + text += MwUTF8ToUTF32(text, &c); + if(c == '\n') { + x = 0; + y += (ttf->ascent - ttf->descent) * ttf->scale; + continue; + } + + stbtt_GetCodepointHMetrics(&ttf->font, c, &ax, &lsb); + + stbtt_GetCodepointBitmapBox(&ttf->font, c, ttf->scale, ttf->scale, &x0, &y0, &x1, &y1); + ow = x1 - x0; + oh = y1 - y0; + out = malloc(ow * oh); + stbtt_MakeCodepointBitmap(&ttf->font, out, ow, oh, ow, ttf->scale, ttf->scale, c); + + for(cy = 0; cy < oh; cy++) { + for(cx = 0; cx < ow; cx++) { + int ox = x + (lsb * ttf->scale) + cx; + int oy = y + (ttf->ascent * ttf->scale) + y0 + cy; + unsigned char* opx = &px[(oy * tw + ox) * 4]; + + opx[0] = color->common.red; + opx[1] = color->common.green; + opx[2] = color->common.blue; + opx[3] = out[cy * ow + cx]; + } + } + + x += ax * ttf->scale; + + free(out); + } + + p = MwLoadRaw(handle, px, tw, th); + r.x = point->x; + r.y = point->y - th / 2; + r.width = tw; + r.height = th; + + if(align == MwALIGNMENT_CENTER) { + r.x -= tw / 2; + } else if(align == MwALIGNMENT_END) { + r.x -= tw; + } + + MwLLDrawPixmap(handle->lowlevel, &r, p); + MwLLDestroyPixmap(p); + free(px); + + return 0; +} + +static int stbtt_MwTextWidth(MwWidget handle, const char* text) { + MwFLFont ttf = MwGetVoid(handle, MwNfont); + int ax, lsb; + int tw = 0; + if(ttf == NULL) return -1; + + while(text[0] != 0) { + int c; + text += MwUTF8ToUTF32(text, &c); + + stbtt_GetCodepointHMetrics(&ttf->font, c, &ax, &lsb); + + tw += ax * ttf->scale; + } + + return tw; +} + +static int stbtt_MwTextHeight(MwWidget handle, int count) { + MwFLFont ttf = MwGetVoid(handle, MwNfont); + if(ttf == NULL) return -1; + + return (ttf->ascent - ttf->descent) * ttf->scale * count; +} + +static void* stbtt_MwFontLoad(unsigned char* data, unsigned int size) { + MwFLFont ttf = malloc(sizeof(*ttf)); + ttf->data = malloc(size); + memcpy(ttf->data, data, size); + stbtt_InitFont(&ttf->font, ttf->data, 0); + + ttf->scale = stbtt_ScaleForPixelHeight(&ttf->font, 16); + stbtt_GetFontVMetrics(&ttf->font, &ttf->ascent, &ttf->descent, 0); + + return ttf; +} + +static void stbtt_MwFontFree(void* handle) { + MwFLFont ttf = handle; + + free(ttf->data); + free(ttf); +} + +int MwFL_STBTTSetup() { + MwFLDrawText = stbtt_MwDrawText; + MwFLTextWidth = stbtt_MwTextWidth; + MwFLTextHeight = stbtt_MwTextHeight; + MwFLFontLoad = stbtt_MwFontLoad; + MwFLFontFree = stbtt_MwFontFree; + return 0; +} + +#endif diff --git a/src/text/text.c b/src/text/text.c new file mode 100644 index 00000000..e25d28b2 --- /dev/null +++ b/src/text/text.c @@ -0,0 +1,158 @@ +#include + +int (*MwFLDrawText)(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color) = NULL; +int (*MwFLTextWidth)(MwWidget handle, const char* text) = NULL; +int (*MwFLTextHeight)(MwWidget handle, int count) = NULL; +void* (*MwFLFontLoad)(unsigned char* data, unsigned int size) = NULL; +void (*MwFLFontFree)(void* handle) = NULL; + +#if defined(USE_FREETYPE2) || defined(USE_STB_TRUETYPE) +#define TTF +#endif + +#define FontWidth 7 +#define FontHeight 14 + +static void bitmap_MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color); + +void MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color) { + if(strlen(text) == 0) return; +#ifdef TTF + if(MwFLDrawText) + if(MwGetInteger(handle, MwNbitmapFont) || MwFLDrawText(handle, point, text, bold, align, color)) +#endif + bitmap_MwDrawText(handle, point, text, bold, align, color); +} + +int MwTextWidth(MwWidget handle, const char* text) { + /* TODO: check newline */ +#ifdef TTF + int st; + + if(MwFLTextWidth) + if(!MwGetInteger(handle, MwNbitmapFont) && (st = MwFLTextWidth(handle, text)) != -1) return st; +#else + (void)handle; + +#endif + return MwUTF8Length(text) * FontWidth; +} + +int MwTextHeight(MwWidget handle, const char* text) { + int c = 1; + int i = 0; +#ifdef TTF + int st; +#endif + + (void)handle; + (void)text; + + while(text[i] != 0) { + int out; + int l = MwUTF8ToUTF32(text + i, &out); + if(l == 0) break; + i += l; + + if(out == '\n') c++; + } +#ifdef TTF + if(MwFLTextHeight) + if(!MwGetInteger(handle, MwNbitmapFont) && (st = MwFLTextHeight(handle, c)) != -1) return st; +#endif + return FontHeight * c; +} + +void* MwFontLoad(unsigned char* data, unsigned int size) { + if(MwFLFontLoad) + return MwFLFontLoad(data, size); + return NULL; +} + +void MwFontFree(void* handle) { + if(MwFLFontFree) + return MwFLFontFree(handle); +} + +static void bitmap_MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color) { + int i = 0, x, y, sx, sy; + int tw, th; + unsigned char* px; + MwRect r; + MwLLPixmap p; + + if(strlen(text) == 0) text = " "; + tw = MwTextWidth(handle, text); + th = MwTextHeight(handle, text); + px = malloc(tw * th * 4); + + memset(px, 0, tw * th * 4); + + sx = 0; + sy = 0; + + while(text[i] != 0) { + int out; + i += MwUTF8ToUTF32(text + i, &out); + + if(out > 0xff) { + out = 0; + } + + if(out == '\n') { + sx = 0; + sy += FontHeight; + } else { + for(y = 0; y < FontHeight; y++) { + for(x = 0; x < FontWidth; x++) { + unsigned char* ppx = &px[((sy + y) * tw + sx + x) * 4]; + if((bold ? MwBoldFontData : MwFontData)[out].data[y] & (1 << ((FontWidth - 1) - x))) { + ppx[0] = color->common.red; + ppx[1] = color->common.green; + ppx[2] = color->common.blue; + ppx[3] = 255; + } else { + ppx[0] = 0; + ppx[1] = 0; + ppx[2] = 0; + ppx[3] = 0; + } + } + } + sx += FontWidth; + } + } + + p = MwLoadRaw(handle, px, tw, th); + r.x = point->x; + r.y = point->y - th / 2; + r.width = tw; + r.height = th; + + if(align == MwALIGNMENT_CENTER) { + r.x -= tw / 2; + } else if(align == MwALIGNMENT_END) { + r.x -= tw; + } + + MwLLDrawPixmap(handle->lowlevel, &r, p); + MwLLDestroyPixmap(p); + free(px); +} + +typedef int (*call_t)(); +void MwFLSetup() { + call_t calls[] = { +#ifdef USE_FREETYPE2 + MWFL_FT2Setup, +#endif +#ifdef USE_STB_TRUETYPE + MwFL_STBTTSetup, +#endif + NULL}; + int i; + + for(i = 0; calls[i] != NULL; i++) { + if(calls[i]() == 0) return; + } +} From de1e8da6f92e06d9545cd5d5a2fa18cc34a94912 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 4 Mar 2026 13:05:38 -0700 Subject: [PATCH 27/94] fix generated mkfiles --- tools/genmk.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/genmk.pl b/tools/genmk.pl index 77545d8f..1cd0a9ed 100755 --- a/tools/genmk.pl +++ b/tools/genmk.pl @@ -147,7 +147,7 @@ scan("src/icon"); scan("src/cursor"); scan("src/widget"); scan("src/text"); -scan("src/font"); +scan("src/text/font"); scan("src/dialog"); scan("src/abstract"); push(@cfiles, "src/backend/gdi.c"); From 890294cd55ced334ba1866bacb2dd9b7d839b20c Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 4 Mar 2026 13:18:01 -0700 Subject: [PATCH 28/94] update macos readme --- README.txt | 53 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/README.txt b/README.txt index f69b6365..b116f7c1 100644 --- a/README.txt +++ b/README.txt @@ -1,23 +1,25 @@ -Greetings - Welcome to the Milsko GUI Toolkit (Version pre-1.0) +Greetings - Welcome to the Milsko GUI Toolkit (Version pre-1.0) - This document contains a brief summary of the contents of this source -distributions and building instructions for Milsko GUI Toolkit. + This document contains a brief summary of the contents of this source +distributions and building instructions for Milsko GUI Toolkit. Requirements - Milsko requires the Windows environment with GDI (so anything NT or 9x) or -the Unix-like environment with X11 for runtime. + Milsko requires either + * A Windows environment with GDI (so anything NT or 9x) + * A MacOS environment with XCode Tools, including perl and Make + * A Unix-like environment with X11 for runtime. - To build Milsko for Windows, you must have one of following compilers: - * Visual C++ 6.0 or newer - * Borland C++ 5.5 or newer - * Open Watcom 2.0 or newer - * MinGW-w64 + To build Milsko for Windows, you must have one of following compilers: + * Visual C++ 6.0 or newer + * Borland C++ 5.5 or newer + * Open Watcom 2.0 or newer + * MinGW-w64 - and for Unix-like: - * GNU C Compiler - * Clang + and for Unix-like and MacOS: + * GNU C Compiler + * Clang Contents @@ -39,31 +41,38 @@ the Unix-like environment with X11 for runtime. Building Milsko - Building Milsko depends on the platform you use, and the compiler you use. + Building Milsko depends on the platform you use, and the compiler you use. A. Visual C++ ------------- -1) Run `nmake -f NTMakefile'. +1) Run `nmake -f NTMakefile'. B. Borland C++ -------------- -1) Run `make -f BorMakefile'. +1) Run `make -f BorMakefile'. C. Open Watcom -------------- -1) Run `wmake -f WatMakefile'. +1) Run `wmake -f WatMakefile'. D. MinGW-w64/GCC/Clang ---------------------- -1) Determine if you need Vulkan and/or OpenGL. +1) Determine if you need Vulkan and/or OpenGL. -2) Run `./configure'. - For help, run `./configure --help'. +2) Run `./configure'. + For help, run `./configure --help'. -3) Run `make'. +3) Run `make'. - -- Nishi (nishi@nishi.boats) +E. MacOS +---------------------- + +Currently there is not an .xcodeproj file. The plan for the future is +to write something that automatically generates it, so for now, you +just follow step D + + -- Nishi (nishi@nishi.boats) From 5eeba311aba93af501ba5531c884141f2650aa04 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 4 Mar 2026 13:22:00 -0700 Subject: [PATCH 29/94] i fixed the makefiles but forgot to run the script --- BorMakefile | 8 ++++++-- NTMakefile | 8 ++++++-- WatMakefile | 16 ++++++++++++++-- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/BorMakefile b/BorMakefile index b6d06277..f8eaced6 100644 --- a/BorMakefile +++ b/BorMakefile @@ -45,6 +45,10 @@ clean: del /f /q src\icon\warning.obj del /f /q src\lowlevel.obj del /f /q src\string.obj + del /f /q src\text\font\boldfont.obj + del /f /q src\text\font\boldttf.obj + del /f /q src\text\font\font.obj + del /f /q src\text\font\ttf.obj del /f /q src\text\ft2.obj del /f /q src\text\stbtt.obj del /f /q src\text\text.obj @@ -72,8 +76,8 @@ clean: del /f /q src\Mw.dll del /f /q src\Mw.lib -src\Mw.dll: external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\error.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\ft2.obj src\text\stbtt.obj src\text\text.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\checkbox.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj - $(LD) $(LDFLAGS) -e$@ external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\error.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\ft2.obj src\text\stbtt.obj src\text\text.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\checkbox.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj -lopengl32.lib -lgdi32.lib -luser32.lib +src\Mw.dll: external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\error.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\ttf.obj src\text\ft2.obj src\text\stbtt.obj src\text\text.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\checkbox.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj + $(LD) $(LDFLAGS) -e$@ external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\error.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\ttf.obj src\text\ft2.obj src\text\stbtt.obj src\text\text.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\checkbox.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj -lopengl32.lib -lgdi32.lib -luser32.lib implib src\Mw.lib src\Mw.dll .c.obj: diff --git a/NTMakefile b/NTMakefile index 7ba162df..3177f048 100644 --- a/NTMakefile +++ b/NTMakefile @@ -45,6 +45,10 @@ clean: del /f /q src\icon\warning.obj del /f /q src\lowlevel.obj del /f /q src\string.obj + del /f /q src\text\font\boldfont.obj + del /f /q src\text\font\boldttf.obj + del /f /q src\text\font\font.obj + del /f /q src\text\font\ttf.obj del /f /q src\text\ft2.obj del /f /q src\text\stbtt.obj del /f /q src\text\text.obj @@ -72,8 +76,8 @@ clean: del /f /q src\Mw.dll del /f /q src\Mw.lib -src\Mw.dll: external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\error.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\ft2.obj src\text\stbtt.obj src\text\text.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\checkbox.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj - $(LD) $(LDFLAGS) /OUT:$@ external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\error.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\ft2.obj src\text\stbtt.obj src\text\text.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\checkbox.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib user32.lib +src\Mw.dll: external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\error.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\ttf.obj src\text\ft2.obj src\text\stbtt.obj src\text\text.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\checkbox.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj + $(LD) $(LDFLAGS) /OUT:$@ external\stb_ds.obj external\stb_image.obj external\stb_truetype.obj src\abstract\directory.obj src\abstract\dynamic.obj src\abstract\time.obj src\backend\gdi.obj src\color.obj src\core.obj src\cursor\arrow.obj src\cursor\cross.obj src\cursor\default.obj src\cursor\hidden.obj src\cursor\text.obj src\default.obj src\dialog\colorpicker.obj src\dialog\directorychooser.obj src\dialog\filechooser.obj src\dialog\messagebox.obj src\draw.obj src\error.obj src\icon\back.obj src\icon\clock.obj src\icon\computer.obj src\icon\directory.obj src\icon\down.obj src\icon\error.obj src\icon\file.obj src\icon\forward.obj src\icon\info.obj src\icon\left.obj src\icon\news.obj src\icon\note.obj src\icon\right.obj src\icon\search.obj src\icon\up.obj src\icon\warning.obj src\lowlevel.obj src\string.obj src\text\font\boldfont.obj src\text\font\boldttf.obj src\text\font\font.obj src\text\font\ttf.obj src\text\ft2.obj src\text\stbtt.obj src\text\text.obj src\unicode.obj src\widget\box.obj src\widget\button.obj src\widget\checkbox.obj src\widget\combobox.obj src\widget\entry.obj src\widget\frame.obj src\widget\image.obj src\widget\label.obj src\widget\listbox.obj src\widget\menu.obj src\widget\numberentry.obj src\widget\opengl.obj src\widget\progressbar.obj src\widget\radiobox.obj src\widget\scrollbar.obj src\widget\separator.obj src\widget\submenu.obj src\widget\treeview.obj src\widget\viewport.obj src\widget\window.obj opengl32.lib gdi32.lib user32.lib .c.obj: diff --git a/WatMakefile b/WatMakefile index d8dbf5e9..5177e050 100644 --- a/WatMakefile +++ b/WatMakefile @@ -44,6 +44,10 @@ clean: .SYMBOLIC %erase src/icon/warning.obj %erase src/lowlevel.obj %erase src/string.obj + %erase src/text/font/boldfont.obj + %erase src/text/font/boldttf.obj + %erase src/text/font/font.obj + %erase src/text/font/ttf.obj %erase src/text/ft2.obj %erase src/text/stbtt.obj %erase src/text/text.obj @@ -71,8 +75,8 @@ clean: .SYMBOLIC %erase src/Mw.dll %erase src/Mw.lib -src/Mw.dll: external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/error.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text/ft2.obj src/text/stbtt.obj src/text/text.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/checkbox.obj src/widget/combobox.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj - $(LD) $(LDFLAGS) option implib=src/Mw.lib name $@ file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/error.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/ft2.obj file src/text/stbtt.obj file src/text/text.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/checkbox.obj file src/widget/combobox.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library user32.lib +src/Mw.dll: external/stb_ds.obj external/stb_image.obj external/stb_truetype.obj src/abstract/directory.obj src/abstract/dynamic.obj src/abstract/time.obj src/backend/gdi.obj src/color.obj src/core.obj src/cursor/arrow.obj src/cursor/cross.obj src/cursor/default.obj src/cursor/hidden.obj src/cursor/text.obj src/default.obj src/dialog/colorpicker.obj src/dialog/directorychooser.obj src/dialog/filechooser.obj src/dialog/messagebox.obj src/draw.obj src/error.obj src/icon/back.obj src/icon/clock.obj src/icon/computer.obj src/icon/directory.obj src/icon/down.obj src/icon/error.obj src/icon/file.obj src/icon/forward.obj src/icon/info.obj src/icon/left.obj src/icon/news.obj src/icon/note.obj src/icon/right.obj src/icon/search.obj src/icon/up.obj src/icon/warning.obj src/lowlevel.obj src/string.obj src/text/font/boldfont.obj src/text/font/boldttf.obj src/text/font/font.obj src/text/font/ttf.obj src/text/ft2.obj src/text/stbtt.obj src/text/text.obj src/unicode.obj src/widget/box.obj src/widget/button.obj src/widget/checkbox.obj src/widget/combobox.obj src/widget/entry.obj src/widget/frame.obj src/widget/image.obj src/widget/label.obj src/widget/listbox.obj src/widget/menu.obj src/widget/numberentry.obj src/widget/opengl.obj src/widget/progressbar.obj src/widget/radiobox.obj src/widget/scrollbar.obj src/widget/separator.obj src/widget/submenu.obj src/widget/treeview.obj src/widget/viewport.obj src/widget/window.obj + $(LD) $(LDFLAGS) option implib=src/Mw.lib name $@ file external/stb_ds.obj file external/stb_image.obj file external/stb_truetype.obj file src/abstract/directory.obj file src/abstract/dynamic.obj file src/abstract/time.obj file src/backend/gdi.obj file src/color.obj file src/core.obj file src/cursor/arrow.obj file src/cursor/cross.obj file src/cursor/default.obj file src/cursor/hidden.obj file src/cursor/text.obj file src/default.obj file src/dialog/colorpicker.obj file src/dialog/directorychooser.obj file src/dialog/filechooser.obj file src/dialog/messagebox.obj file src/draw.obj file src/error.obj file src/icon/back.obj file src/icon/clock.obj file src/icon/computer.obj file src/icon/directory.obj file src/icon/down.obj file src/icon/error.obj file src/icon/file.obj file src/icon/forward.obj file src/icon/info.obj file src/icon/left.obj file src/icon/news.obj file src/icon/note.obj file src/icon/right.obj file src/icon/search.obj file src/icon/up.obj file src/icon/warning.obj file src/lowlevel.obj file src/string.obj file src/text/font/boldfont.obj file src/text/font/boldttf.obj file src/text/font/font.obj file src/text/font/ttf.obj file src/text/ft2.obj file src/text/stbtt.obj file src/text/text.obj file src/unicode.obj file src/widget/box.obj file src/widget/button.obj file src/widget/checkbox.obj file src/widget/combobox.obj file src/widget/entry.obj file src/widget/frame.obj file src/widget/image.obj file src/widget/label.obj file src/widget/listbox.obj file src/widget/menu.obj file src/widget/numberentry.obj file src/widget/opengl.obj file src/widget/progressbar.obj file src/widget/radiobox.obj file src/widget/scrollbar.obj file src/widget/separator.obj file src/widget/submenu.obj file src/widget/treeview.obj file src/widget/viewport.obj file src/widget/window.obj library clib3r.lib library opengl32.lib library gdi32.lib library user32.lib @@ -154,6 +158,14 @@ src/lowlevel.obj: src/lowlevel.c $(CC) $(CFLAGS) -fo=$@ $< src/string.obj: src/string.c $(CC) $(CFLAGS) -fo=$@ $< +src/text/font/boldfont.obj: src/text/font/boldfont.c + $(CC) $(CFLAGS) -fo=$@ $< +src/text/font/boldttf.obj: src/text/font/boldttf.c + $(CC) $(CFLAGS) -fo=$@ $< +src/text/font/font.obj: src/text/font/font.c + $(CC) $(CFLAGS) -fo=$@ $< +src/text/font/ttf.obj: src/text/font/ttf.c + $(CC) $(CFLAGS) -fo=$@ $< src/text/ft2.obj: src/text/ft2.c $(CC) $(CFLAGS) -fo=$@ $< src/text/stbtt.obj: src/text/stbtt.c From 2e4e2a1c7fffd2e603043ce8637863a0854cc15a Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 4 Mar 2026 13:31:25 -0700 Subject: [PATCH 30/94] Remove xcodetools note --- README.txt | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/README.txt b/README.txt index b116f7c1..8fa1a37b 100644 --- a/README.txt +++ b/README.txt @@ -8,7 +8,7 @@ distributions and building instructions for Milsko GUI Toolkit. Milsko requires either * A Windows environment with GDI (so anything NT or 9x) - * A MacOS environment with XCode Tools, including perl and Make + * A MacOS environment with Xcode Tools * A Unix-like environment with X11 for runtime. To build Milsko for Windows, you must have one of following compilers: @@ -68,11 +68,4 @@ D. MinGW-w64/GCC/Clang 3) Run `make'. -E. MacOS ----------------------- - -Currently there is not an .xcodeproj file. The plan for the future is -to write something that automatically generates it, so for now, you -just follow step D - -- Nishi (nishi@nishi.boats) From f9c35cded4c3ec8bb3ffa60417fe46c2ebc76e81 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 4 Mar 2026 13:32:39 -0700 Subject: [PATCH 31/94] macos note in readme should just be the version, my bad --- README.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.txt b/README.txt index 8fa1a37b..d4522abe 100644 --- a/README.txt +++ b/README.txt @@ -8,7 +8,7 @@ distributions and building instructions for Milsko GUI Toolkit. Milsko requires either * A Windows environment with GDI (so anything NT or 9x) - * A MacOS environment with Xcode Tools + * A MacOS environment with Cocoa (10.4 or above supported) * A Unix-like environment with X11 for runtime. To build Milsko for Windows, you must have one of following compilers: From 0832533c514e97120cc20cd36793155792d4af2f Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 4 Mar 2026 16:52:19 -0700 Subject: [PATCH 32/94] Oops the readme is generated --- README.txt | 48 ++++++++++++++++++++++++------------------------ tools/readme.pl | 8 +++++--- 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/README.txt b/README.txt index d4522abe..dc9d6bf2 100644 --- a/README.txt +++ b/README.txt @@ -1,25 +1,25 @@ -Greetings - Welcome to the Milsko GUI Toolkit (Version pre-1.0) +Greetings - Welcome to the Milsko GUI Toolkit (Version pre-1.0) - This document contains a brief summary of the contents of this source -distributions and building instructions for Milsko GUI Toolkit. + This document contains a brief summary of the contents of this source +distributions and building instructions for Milsko GUI Toolkit. Requirements - Milsko requires either - * A Windows environment with GDI (so anything NT or 9x) - * A MacOS environment with Cocoa (10.4 or above supported) - * A Unix-like environment with X11 for runtime. + Milsko requires either + * A Windows environment with GDI (so anything NT or 9x) + * A MacOS environment with Cocoa (10.4 or above supported) + * A Unix-like environment with X11 for runtime. - To build Milsko for Windows, you must have one of following compilers: - * Visual C++ 6.0 or newer - * Borland C++ 5.5 or newer - * Open Watcom 2.0 or newer - * MinGW-w64 + To build Milsko for Windows, you must have one of following compilers: + * Visual C++ 6.0 or newer + * Borland C++ 5.5 or newer + * Open Watcom 2.0 or newer + * MinGW-w64 - and for Unix-like and MacOS: - * GNU C Compiler - * Clang + and for Unix-like and MacOS: + * GNU C Compiler + * Clang Contents @@ -41,31 +41,31 @@ distributions and building instructions for Milsko GUI Toolkit. Building Milsko - Building Milsko depends on the platform you use, and the compiler you use. + Building Milsko depends on the platform you use, and the compiler you use. A. Visual C++ ------------- -1) Run `nmake -f NTMakefile'. +1) Run `nmake -f NTMakefile'. B. Borland C++ -------------- -1) Run `make -f BorMakefile'. +1) Run `make -f BorMakefile'. C. Open Watcom -------------- -1) Run `wmake -f WatMakefile'. +1) Run `wmake -f WatMakefile'. D. MinGW-w64/GCC/Clang ---------------------- -1) Determine if you need Vulkan and/or OpenGL. +1) Determine if you need Vulkan and/or OpenGL. -2) Run `./configure'. - For help, run `./configure --help'. +2) Run `./configure'. + For help, run `./configure --help'. -3) Run `make'. +3) Run `make'. - -- Nishi (nishi@nishi.boats) + -- Nishi (nishi@nishi.boats) diff --git a/tools/readme.pl b/tools/readme.pl index c511f794..7070312d 100755 --- a/tools/readme.pl +++ b/tools/readme.pl @@ -59,8 +59,10 @@ l(""); c("Requirements"); l(""); l( -" Milsko requires the Windows environment with GDI (so anything NT or 9x) or the Unix-like environment with X11 for runtime." -); +" 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."); l(""); l(" To build Milsko for Windows, you must have one of following compilers:"); l(" * Visual C++ 6.0 or newer"); @@ -68,7 +70,7 @@ l(" * Borland C++ 5.5 or newer"); l(" * Open Watcom 2.0 or newer"); l(" * MinGW-w64"); l(""); -l(" and for Unix-like:"); +l(" and for Unix-like and MacOS:"); l(" * GNU C Compiler"); l(" * Clang"); l(""); From 943500a7ecaa938d8d4070bd37820f688fbecf76 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 4 Mar 2026 19:34:19 -0700 Subject: [PATCH 33/94] mac: got a bunch of events handled. failed to get resizing working though --- include/Mw/LowLevel/Cocoa.h | 28 +++- src/backend/cocoa.m | 267 +++++++++++++++++++++++++++++++----- 2 files changed, 261 insertions(+), 34 deletions(-) diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index d22f6539..2659b3c1 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -21,6 +21,21 @@ #import #endif +@interface MilskoCocoaWindowDelegate : NSObject { + NSWindow *w; +} +- (instancetype)initWithWin:(NSWindow *)win; +@end + +@interface MilskoFakePointer : NSView { + void *ptr; +} + +- (void)setPointer:(void *)ptr; +- (void *)pointer; + +@end + @interface MilskoCocoaPixmap : NSObject { MwBool valid; int width; @@ -46,28 +61,34 @@ MwBool valid; CGColorSpaceRef space; CGDataProviderRef provider; - unsigned char *buf; float width; float height; } - (NSGraphicsContext *)context; +- (void)destroy; +- (NSBitmapImageRep *)getRep; + @end @interface MilskoCocoa : NSObject { NSApplication *application; NSEvent *lastEvent; + MwBool _forceRender; NSWindow *window; NSRect rect; MilskoCocoaView *view; MwLL parent; + MilskoFakePointer *handle; + MwBool doWHResize; } + (MilskoCocoa *)newWithParent:(MwLL)parent x:(int)x y:(int)y width:(int)width - height:(int)height; + height:(int)height + handle:(MwLL)handle; - (void)polygonWithPoints:(MwPoint *)points points_count:(int)points_count color:(MwLLColor)color; @@ -97,6 +118,9 @@ - (void)getCursorCoord:(MwPoint *)point; - (void)getScreenSize:(MwRect *)rect; - (void)destroy; +- (void)setHandle:(MwLL)h; + +- (NSWindow *)parentWindow; @end #define OBJC(x) x diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 3117ba58..5d6f5c6c 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -1,7 +1,6 @@ #include "Mw/BaseTypes.h" +#include "Mw/LowLevel.h" #include -#include -#include @implementation MilskoCocoaPixmap @@ -56,7 +55,8 @@ x:(int)x y:(int)y width:(int)width - height:(int)height { + height:(int)height + handle:(MwLL)r { MilskoCocoa *c = [MilskoCocoa alloc]; bool centerX = false, centerY = false; @@ -92,6 +92,8 @@ backing:NSBackingStoreBuffered defer:NO]; } + c->window.delegate = + [[MilskoCocoaWindowDelegate alloc] initWithWin:c->window]; [c->window makeKeyAndOrderFront:c->application]; @@ -100,14 +102,20 @@ [p->window addChildWindow:c->window ordered:NSWindowAbove]; [c->window setHasShadow:MwFALSE]; } else { - [c->application activateIgnoringOtherApps:true]; + // [c->application activateIgnoringOtherApps:true]; } c->view = [[MilskoCocoaView alloc] initWithFrame:c->rect]; + c->handle = [[MilskoFakePointer alloc] initWithFrame:NSMakeRect(0, 0, 1, 1)]; + [c->handle setPointer:r]; + [c->view addSubview:c->handle]; + [c->window setContentView:c->view]; c->parent = parent; + c->_forceRender = MwTRUE; + return c; } - (void)polygonWithPoints:(MwPoint *)points @@ -154,7 +162,8 @@ NSRect frame = [self->window frame]; *x = frame.origin.x; - *y = frame.origin.y - frame.size.height; + *y = frame.origin.y; + *w = frame.size.width; *h = frame.size.height; }; @@ -165,11 +174,12 @@ frame.origin.y = y; if (self->parent) { - NSWindow *parentWindow = self->parent->cocoa.real->window; - frame = [parentWindow contentRectForFrameRect:frame]; - frame.origin.y = - [parentWindow contentRectForFrameRect:parentWindow.frame].size.height - - y; + NSWindow *parentWindow = [self parentWindow]; + CGFloat ny; + NSRect realFrame = parentWindow.frame; + NSRect correctedFrame = [parentWindow contentRectForFrameRect:realFrame]; + ny = (correctedFrame.size.height - y); + frame.origin.y = ny; } [self->window setFrame:frame display:YES animate:false]; @@ -178,11 +188,7 @@ NSRect frame = [self->window frame]; frame.size.width = w; frame.size.height = h; - - if (self->parent) { - NSWindow *parentWindow = self->parent->cocoa.real->window; - // frame = [parentWindow contentRectForFrameRect:frame]; - } + self->rect = frame; [self->window setFrame:frame display:YES animate:false]; }; @@ -192,22 +198,144 @@ untilDate:nil inMode:NSDefaultRunLoopMode dequeue:YES]; + if (_forceRender) { + _forceRender = MwFALSE; + return 1; + } return self->lastEvent != NULL; }; - (void)getNextEvent { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - if (self->lastEvent != nil) { + NSWindow *win = [self->lastEvent window]; + NSWindow *parentWindow = [self parentWindow]; + NSRect realFrame = parentWindow.frame; + NSRect correctedFrame = + [parentWindow frameRectForContentRect:parentWindow.frame]; + CGFloat offset = realFrame.size.height - correctedFrame.size.height; + MwLL h; + + if ([win contentView].subviews.count == 0) { + NSLog(@"[WARNING] no subviews on this window, cannot process events.\n"); + return; + } + + h = [((MilskoFakePointer *)[win contentView].subviews[0]) pointer]; + switch (self->lastEvent.type) { + case NSEventTypeLeftMouseDown: + case NSEventTypeRightMouseDown: + case NSEventTypeOtherMouseDown: + case NSEventTypeLeftMouseUp: + case NSEventTypeRightMouseUp: + case NSEventTypeOtherMouseUp: { + MwLLMouse mouse = {}; + MwBool isDown = MwTRUE; + switch (self->lastEvent.type) { + case NSEventTypeLeftMouseUp: + isDown = MwFALSE; + case NSEventTypeLeftMouseDown: + mouse.button = MwLLMouseLeft; + break; + case NSEventTypeRightMouseUp: + isDown = MwFALSE; + case NSEventTypeRightMouseDown: + mouse.button = MwLLMouseRight; + break; + case NSEventTypeOtherMouseUp: + isDown = MwFALSE; + case NSEventTypeOtherMouseDown: + mouse.button = MwLLMouseMiddle; + break; + default: + break; + } + mouse.point.x = [lastEvent locationInWindow].x; + mouse.point.y = [win contentRectForFrameRect:win.frame].size.height - + [lastEvent locationInWindow].y; + + if (isDown) { + MwLLDispatch(h, down, &mouse); + } else { + MwLLDispatch(h, up, &mouse); + } + break; + } + + break; + case NSEventTypeMouseMoved: { + MwPoint pos; + pos.x = [lastEvent locationInWindow].x; + pos.y = [win contentRectForFrameRect:win.frame].size.height - + [lastEvent locationInWindow].y; + MwLLDispatch(h, move, &pos); + break; + } + case NSEventTypeLeftMouseDragged: + MwLLDispatch(h, focus_in, NULL); + break; + case NSEventTypeRightMouseDragged: + MwLLDispatch(h, focus_out, NULL); + break; + case NSEventTypeMouseEntered: + break; + case NSEventTypeMouseExited: + break; + case NSEventTypeKeyDown: + [win interpretKeyEvents:[NSArray arrayWithObject:lastEvent]]; + break; + case NSEventTypeKeyUp: + [win interpretKeyEvents:[NSArray arrayWithObject:lastEvent]]; + break; + case NSEventTypeFlagsChanged: + break; + case NSEventTypeAppKitDefined: + break; + case NSEventTypeSystemDefined: + break; + case NSEventTypeApplicationDefined: + break; + case NSEventTypePeriodic: + break; + case NSEventTypeCursorUpdate: + break; + case NSEventTypeScrollWheel: + break; + case NSEventTypeTabletPoint: + break; + case NSEventTypeTabletProximity: + break; + break; + case NSEventTypeOtherMouseDragged: + break; + case NSEventTypeGesture: + break; + case NSEventTypeMagnify: + break; + case NSEventTypeSwipe: + break; + case NSEventTypeRotate: + break; + case NSEventTypeBeginGesture: + break; + case NSEventTypeEndGesture: + break; + case NSEventTypeSmartMagnify: + break; + case NSEventTypeQuickLook: + break; + case NSEventTypePressure: + break; + case NSEventTypeDirectTouch: + break; + case NSEventTypeChangeMode: + break; + }; // printf("got event: %ld\n", self->lastEvent.type); + [self->application sendEvent:self->lastEvent]; } - [self->application sendEvent:self->lastEvent]; - - /* this should be in the draw functions but it's here for now for testing */ [self->view setNeedsDisplay:true]; - - [pool release]; }; + - (void)setTitle:(const char *)title { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [self->window @@ -237,6 +365,7 @@ - (void)setIcon:(MwLLPixmap)pixmap { }; - (void)forceRender { + _forceRender = MwTRUE; }; - (void)setCursor:(MwCursor *)image mask:(MwCursor *)mask { }; @@ -269,8 +398,8 @@ [self->window makeMainWindow]; }; - (void)grabPointer:(int)toggle { - /* MacOS didn't have a "pointer grab" function until 10.13.2 so I need to do - * this manually */ + /* MacOS didn't have a "pointer grab" function + * until 10.13.2 so I need to do this manually */ }; - (void)setClipboard:(const char *)text { }; @@ -294,14 +423,23 @@ [self->window dealloc]; } +- (void)setDoWHResize:(MwBool)d { + doWHResize = d; +}; + +- (NSWindow *)parentWindow { + NSWindow *topmostWindow = self->window; + while (topmostWindow.parentWindow) + topmostWindow = topmostWindow.parentWindow; + return topmostWindow; +} @end @implementation MilskoCocoaView - (id)initWithFrame:(NSRect)frame { + width = frame.size.width; + height = frame.size.height; self = [super initWithFrame:frame]; - self->width = frame.size.width; - self->height = frame.size.height; - self->buf = malloc(self->width * self->height * 4); self->space = CGColorSpaceCreateDeviceRGB(); if (width == 0 || height == 0) { @@ -333,23 +471,84 @@ return self->context; } +- (NSBitmapImageRep *)getRep { + return self->rep; +} + - (void)drawRect:(NSRect)dirtyRect { + NSSize sz = [self->rep size]; + unsigned char *pixels; [super drawRect:dirtyRect]; if (!self->rep) { return; } - [self->rep drawInRect:NSMakeRect(0, 0, self->width, self->height)]; - unsigned char *pixels = [self->rep bitmapData]; + [self->rep drawInRect:NSMakeRect(0, 0, width, height)]; + + pixels = [self->rep bitmapData]; } - (void)destroy { - free(self->buf); CGColorSpaceRelease(self->space); } +- (void)setFrameSize:(NSSize)newSize { + [super setFrameSize:newSize]; + if (newSize.width != 0 && newSize.height != 0) { + // [self->rep setSize:newSize]; + // width = newSize.width; + // height = newSize.height; + // [self->context setImageInterpolation:NSImageInterpolationHigh]; + } +} + +- (void)displayRect:(NSRect)rect { +}; +@end + +@implementation MilskoFakePointer +- (void)viewDidMoveToSuperview { +} +- (void)setPointer:(void *)pointer { + self.frame = *(NSRect *)&pointer; + self->ptr = pointer; +}; +- (void *)pointer { + return self->ptr; +}; + +- (void)drawRect:(NSRect)dirtyRect { + /* explicitly do nothing */ +} + +- (void)destroy { +} + @end +@implementation MilskoCocoaWindowDelegate + +- (NSSize)windowWillResize:(NSWindow *)win toSize:(NSSize)frameSize; +{ + if (win.contentView.subviews.count >= 1) { + MilskoFakePointer *ptr = win.contentView.subviews[0]; + MwLL h = [ptr pointer]; + + // MwLLDispatch(h, resize, NULL); + MwLLDispatch(h, draw, NULL); + } + return frameSize; +} + +- (void)windowDidResize:(NSNotification *)notification { +} + +- (instancetype)initWithWin:(NSWindow *)win { + self->w = win; + return self; +} + +@end static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { MwLL r; (void)x; @@ -361,8 +560,12 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { MwLLCreateCommon(r); - MilskoCocoa *o = - [MilskoCocoa newWithParent:parent x:x y:y width:width height:height]; + MilskoCocoa *o = [MilskoCocoa newWithParent:parent + x:x + y:y + width:width + height:height + handle:r]; r->cocoa.real = o; return r; From b585ad69b74542fbcd6a2784dc6f2af5ec8991e1 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 4 Mar 2026 20:44:25 -0700 Subject: [PATCH 34/94] code cleanup --- include/Mw/LowLevel/Cocoa.h | 1 - src/backend/cocoa.m | 19 +++++-------------- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index 2659b3c1..22bb29c2 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -80,7 +80,6 @@ MilskoCocoaView *view; MwLL parent; MilskoFakePointer *handle; - MwBool doWHResize; } + (MilskoCocoa *)newWithParent:(MwLL)parent diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 5d6f5c6c..b9d10800 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -162,7 +162,7 @@ NSRect frame = [self->window frame]; *x = frame.origin.x; - *y = frame.origin.y; + *y = frame.origin.y - frame.size.height; *w = frame.size.width; *h = frame.size.height; @@ -175,11 +175,9 @@ if (self->parent) { NSWindow *parentWindow = [self parentWindow]; - CGFloat ny; - NSRect realFrame = parentWindow.frame; - NSRect correctedFrame = [parentWindow contentRectForFrameRect:realFrame]; - ny = (correctedFrame.size.height - y); - frame.origin.y = ny; + NSRect correctedFrame = + [parentWindow contentRectForFrameRect:parentWindow.frame]; + frame.origin.y = (correctedFrame.size.height - y); } [self->window setFrame:frame display:YES animate:false]; @@ -423,10 +421,6 @@ [self->window dealloc]; } -- (void)setDoWHResize:(MwBool)d { - doWHResize = d; -}; - - (NSWindow *)parentWindow { NSWindow *topmostWindow = self->window; while (topmostWindow.parentWindow) @@ -477,7 +471,6 @@ - (void)drawRect:(NSRect)dirtyRect { NSSize sz = [self->rep size]; - unsigned char *pixels; [super drawRect:dirtyRect]; if (!self->rep) { return; @@ -485,7 +478,7 @@ [self->rep drawInRect:NSMakeRect(0, 0, width, height)]; - pixels = [self->rep bitmapData]; + [self->rep bitmapData]; } - (void)destroy { @@ -507,8 +500,6 @@ @end @implementation MilskoFakePointer -- (void)viewDidMoveToSuperview { -} - (void)setPointer:(void *)pointer { self.frame = *(NSRect *)&pointer; self->ptr = pointer; From f700e90d23d5752585a728c54ecf35d4d93dbb0f Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 4 Mar 2026 20:47:55 -0700 Subject: [PATCH 35/94] did some code cleanup --- include/Mw/LowLevel/Cocoa.h | 1 - src/backend/cocoa.m | 11 ++++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index 22bb29c2..a36dbfde 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -117,7 +117,6 @@ - (void)getCursorCoord:(MwPoint *)point; - (void)getScreenSize:(MwRect *)rect; - (void)destroy; -- (void)setHandle:(MwLL)h; - (NSWindow *)parentWindow; diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index b9d10800..23e9373c 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -1,7 +1,8 @@ -#include "Mw/BaseTypes.h" -#include "Mw/LowLevel.h" #include +#pragma clang push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + @implementation MilskoCocoaPixmap + (MilskoCocoaPixmap *)newWithWidth:(int)width height:(int)height { @@ -92,8 +93,8 @@ backing:NSBackingStoreBuffered defer:NO]; } - c->window.delegate = - [[MilskoCocoaWindowDelegate alloc] initWithWin:c->window]; + c->window.delegate = (id)[[MilskoCocoaWindowDelegate alloc] + initWithWin:c->window]; [c->window makeKeyAndOrderFront:c->application]; @@ -625,10 +626,10 @@ static int MwLLPendingImpl(MwLL handle) { MwLLDispatch(handle, draw, NULL); return 1; }; + return 0; } static void MwLLNextEventImpl(MwLL handle) { - MilskoCocoa *h = handle->cocoa.real; [h getNextEvent]; } From db577bb01f5488e1dfa441a0826cd06916e36823 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 4 Mar 2026 22:56:04 -0700 Subject: [PATCH 36/94] mac opengl support. proper coordinate flipping --- examples/gldemos/cube.c | 113 +++---- include/Mw/LowLevel/Cocoa.h | 1 + include/Mw/Widget/OpenGL.h | 21 +- pl/rules.pl | 9 +- src/backend/cocoa.m | 80 +++-- src/widget/opengl.c | 590 +++++++++++++++++++----------------- src/widget/opengl_cocoa.m | 128 ++++++++ 7 files changed, 581 insertions(+), 361 deletions(-) create mode 100644 src/widget/opengl_cocoa.m diff --git a/examples/gldemos/cube.c b/examples/gldemos/cube.c index c1ba9917..2d1954c5 100644 --- a/examples/gldemos/cube.c +++ b/examples/gldemos/cube.c @@ -1,78 +1,89 @@ #define TITLE "cube" #include "glutlayer.c" +#if defined(__APPLE__) +#include +#include +#else +#include #include +#endif 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 a36dbfde..91679db7 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -119,6 +119,7 @@ - (void)destroy; - (NSWindow *)parentWindow; +- (NSView *)getView; @end #define OBJC(x) x diff --git a/include/Mw/Widget/OpenGL.h b/include/Mw/Widget/OpenGL.h index 26f44abf..c3fab76e 100644 --- a/include/Mw/Widget/OpenGL.h +++ b/include/Mw/Widget/OpenGL.h @@ -5,17 +5,24 @@ #ifndef __MW_WIDGET_OPENGL_H__ #define __MW_WIDGET_OPENGL_H__ +#include #include #include -#include #if !defined(MW_OPENGL_NO_INCLUDE) && !defined(__gl_h_) #ifdef _WIN32 #include +#elif defined(__APPLE__) #else #include #endif +#if defined(__APPLE__) +#include +#include +#else #include +#include +#endif #ifndef GLAPIENTRY #define GLAPIENTRY APIENTRY @@ -36,7 +43,7 @@ MWDECL MwClass MwOpenGLClass; * @param handle Widget */ MwInline void MwOpenGLMakeCurrent(MwWidget handle) { - MwVaWidgetExecute(handle, "mwOpenGLMakeCurrent", NULL); + MwVaWidgetExecute(handle, "mwOpenGLMakeCurrent", NULL); } /*! @@ -45,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; } /*! @@ -56,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 d4784e10..45bb6daf 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -50,7 +50,14 @@ if (grep(/^cocoa$/, @backends)) { add_cflags("-DUSE_COCOA"); new_object("src/backend/cocoa.m"); - $gl_libs = "-lGL -lGLU"; + if (param_get("opengl")) { + 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 + add_cflags("-DGL_SILENCE_DEPRECATION"); + + $gl_libs = "-framework OpenGL"; } if (param_get("stb-image")) { diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 23e9373c..700ebdb8 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -3,6 +3,29 @@ #pragma clang push #pragma clang diagnostic ignored "-Wdeprecated-declarations" +static CGRect rectFlip(CGRect originFrame) { + NSScreen *zeroScreen = NSScreen.screens[0]; + double screenHeight = zeroScreen.frame.size.height; + double originY = originFrame.origin.y; + double frameHeight = originFrame.size.height; + double destinationY = screenHeight - (originY + frameHeight); + CGRect destinationFrame = originFrame; + destinationFrame.origin.y = destinationY; + if (destinationFrame.origin.x < 0) + destinationFrame.origin.x = 0; + if (destinationFrame.origin.y < 0) + destinationFrame.origin.y = 0; + if (destinationFrame.size.width < 0) + destinationFrame.size.width = 0; + if (destinationFrame.size.height < 0) + destinationFrame.size.height = 0; + return destinationFrame; +} + +static CGPoint pointFlip(CGPoint point) { + return rectFlip(NSMakeRect(point.x, point.y, 0, 0)).origin; +} + @implementation MilskoCocoaPixmap + (MilskoCocoaPixmap *)newWithWidth:(int)width height:(int)height { @@ -70,8 +93,7 @@ centerY = true; } c->application = [NSApplication sharedApplication]; - - c->rect = NSMakeRect(x, y, width, height); + c->rect = rectFlip(NSMakeRect(x, y, width, height)); if (parent == NULL) { c->window = [[NSWindow alloc] @@ -81,12 +103,12 @@ backing:NSBackingStoreBuffered defer:NO]; } else { + double offset = 0; NSWindow *parentWindow = parent->cocoa.real->window; - - c->rect = [parentWindow frameRectForContentRect:c->rect]; - c->rect.origin.y = - y - + offset = + [parentWindow frameRectForContentRect:parentWindow.frame].size.height - [parentWindow contentRectForFrameRect:parentWindow.frame].size.height; + c->rect.origin.y -= offset; c->window = [[NSWindow alloc] initWithContentRect:c->rect styleMask:NSBorderlessWindowMask @@ -160,10 +182,10 @@ - (void)lineWithPoints:(MwPoint *)points color:(MwLLColor)color { }; - (void)getX:(int *)x Y:(int *)y W:(unsigned int *)w H:(unsigned int *)h { - NSRect frame = [self->window frame]; + NSRect frame = rectFlip([self->window frame]); *x = frame.origin.x; - *y = frame.origin.y - frame.size.height; + *y = frame.origin.y; *w = frame.size.width; *h = frame.size.height; @@ -174,12 +196,17 @@ frame.origin.x = x; frame.origin.y = y; - if (self->parent) { - NSWindow *parentWindow = [self parentWindow]; - NSRect correctedFrame = - [parentWindow contentRectForFrameRect:parentWindow.frame]; - frame.origin.y = (correctedFrame.size.height - y); + frame = rectFlip(frame); + + if (parent) { + double offset = 0; + NSWindow *parentWindow = parent->cocoa.real->window; + offset = + [parentWindow frameRectForContentRect:parentWindow.frame].size.height - + [parentWindow contentRectForFrameRect:parentWindow.frame].size.height; + frame.origin.y -= offset; } + [self->view setFrameSize:frame.size]; [self->window setFrame:frame display:YES animate:false]; }; @@ -187,8 +214,10 @@ NSRect frame = [self->window frame]; frame.size.width = w; frame.size.height = h; + self->rect = frame; + [self->view setFrameSize:frame.size]; [self->window setFrame:frame display:YES animate:false]; }; - (int)pending { @@ -207,10 +236,6 @@ if (self->lastEvent != nil) { NSWindow *win = [self->lastEvent window]; NSWindow *parentWindow = [self parentWindow]; - NSRect realFrame = parentWindow.frame; - NSRect correctedFrame = - [parentWindow frameRectForContentRect:parentWindow.frame]; - CGFloat offset = realFrame.size.height - correctedFrame.size.height; MwLL h; if ([win contentView].subviews.count == 0) { @@ -228,6 +253,7 @@ case NSEventTypeOtherMouseUp: { MwLLMouse mouse = {}; MwBool isDown = MwTRUE; + CGPoint mousePoint = pointFlip([lastEvent locationInWindow]); switch (self->lastEvent.type) { case NSEventTypeLeftMouseUp: isDown = MwFALSE; @@ -247,9 +273,8 @@ default: break; } - mouse.point.x = [lastEvent locationInWindow].x; - mouse.point.y = [win contentRectForFrameRect:win.frame].size.height - - [lastEvent locationInWindow].y; + mouse.point.x = mousePoint.x; + mouse.point.y = mousePoint.y; if (isDown) { MwLLDispatch(h, down, &mouse); @@ -428,6 +453,10 @@ topmostWindow = topmostWindow.parentWindow; return topmostWindow; } + +- (NSView *)getView { + return view; +} @end @implementation MilskoCocoaView @@ -471,13 +500,13 @@ } - (void)drawRect:(NSRect)dirtyRect { - NSSize sz = [self->rep size]; + NSSize sz = self->rep.size; [super drawRect:dirtyRect]; if (!self->rep) { return; } - [self->rep drawInRect:NSMakeRect(0, 0, width, height)]; + [self->rep drawInRect:NSMakeRect(0, 0, sz.width, sz.height)]; [self->rep bitmapData]; } @@ -488,12 +517,7 @@ - (void)setFrameSize:(NSSize)newSize { [super setFrameSize:newSize]; - if (newSize.width != 0 && newSize.height != 0) { - // [self->rep setSize:newSize]; - // width = newSize.width; - // height = newSize.height; - // [self->context setImageInterpolation:NSImageInterpolationHigh]; - } + [self->rep setSize:newSize]; } - (void)displayRect:(NSRect)rect { diff --git a/src/widget/opengl.c b/src/widget/opengl.c index ae878178..0f9c5c24 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -1,44 +1,49 @@ +#ifndef __APPLE__ + #include #include #ifdef USE_GDI -typedef HGLRC(WINAPI* MWwglCreateContext)(HDC); -typedef BOOL(WINAPI* MWwglMakeCurrent)(HDC, HGLRC); -typedef PROC(WINAPI* MWwglGetProcAddress)(LPCSTR); -typedef BOOL(WINAPI* MWwglDeleteContext)(HGLRC); +typedef HGLRC(WINAPI *MWwglCreateContext)(HDC); +typedef BOOL(WINAPI *MWwglMakeCurrent)(HDC, HGLRC); +typedef PROC(WINAPI *MWwglGetProcAddress)(LPCSTR); +typedef BOOL(WINAPI *MWwglDeleteContext)(HGLRC); typedef struct gdiopengl { - HDC dc; - HGLRC gl; + HDC dc; + HGLRC gl; - void* lib; + void *lib; - MWwglCreateContext wglCreateContext; - MWwglMakeCurrent wglMakeCurrent; - MWwglDeleteContext wglDeleteContext; - MWwglGetProcAddress wglGetProcAddress; + MWwglCreateContext wglCreateContext; + MWwglMakeCurrent wglMakeCurrent; + MWwglDeleteContext wglDeleteContext; + MWwglGetProcAddress wglGetProcAddress; } gdiopengl_t; #endif #ifdef USE_X11 -typedef XVisualInfo* (*MWglXChooseVisual)(Display* dpy, int screen, int* attribList); -typedef GLXContext (*MWglXCreateContext)(Display* dpy, XVisualInfo* vis, GLXContext shareList, Bool direct); -typedef void (*MWglXDestroyContext)(Display* dpy, GLXContext ctx); -typedef Bool (*MWglXMakeCurrent)(Display* dpy, GLXDrawable drawable, GLXContext ctx); -typedef void (*MWglXSwapBuffers)(Display* dpy, GLXDrawable drawable); -typedef void* (*MWglXGetProcAddress)(const GLubyte* procname); +typedef XVisualInfo *(*MWglXChooseVisual)(Display *dpy, int screen, + int *attribList); +typedef GLXContext (*MWglXCreateContext)(Display *dpy, XVisualInfo *vis, + GLXContext shareList, Bool direct); +typedef void (*MWglXDestroyContext)(Display *dpy, GLXContext ctx); +typedef Bool (*MWglXMakeCurrent)(Display *dpy, GLXDrawable drawable, + GLXContext ctx); +typedef void (*MWglXSwapBuffers)(Display *dpy, GLXDrawable drawable); +typedef void *(*MWglXGetProcAddress)(const GLubyte *procname); typedef struct x11opengl { - XVisualInfo* visual; - GLXContext gl; + XVisualInfo *visual; + GLXContext gl; - void* lib; + void *lib; - MWglXChooseVisual glXChooseVisual; - MWglXCreateContext glXCreateContext; - MWglXDestroyContext glXDestroyContext; - MWglXMakeCurrent glXMakeCurrent; - MWglXSwapBuffers glXSwapBuffers; - MWglXGetProcAddress glXGetProcAddress; + MWglXChooseVisual glXChooseVisual; + MWglXCreateContext glXCreateContext; + MWglXDestroyContext glXDestroyContext; + MWglXMakeCurrent glXMakeCurrent; + MWglXSwapBuffers glXSwapBuffers; + MWglXGetProcAddress glXGetProcAddress; } x11opengl_t; #endif @@ -47,348 +52,385 @@ typedef struct x11opengl { #include typedef struct waylandopengl { - EGLNativeWindowType egl_window_native; - EGLDisplay egl_display; - EGLContext egl_context; - EGLSurface egl_surface; - EGLConfig egl_config; + EGLNativeWindowType egl_window_native; + EGLDisplay egl_display; + EGLContext egl_context; + EGLSurface egl_surface; + EGLConfig egl_config; } waylandopengl_t; #endif static int create(MwWidget handle) { - void* r = NULL; - MwWidget w = handle; + void *r = NULL; + MwWidget w = handle; #ifdef USE_GDI - if(handle->lowlevel->common.type == MwLLBackendGDI) { - PIXELFORMATDESCRIPTOR pfd; - int pf; - gdiopengl_t* o = r = malloc(sizeof(*o)); + if (handle->lowlevel->common.type == MwLLBackendGDI) { + PIXELFORMATDESCRIPTOR pfd; + int pf; + gdiopengl_t *o = r = malloc(sizeof(*o)); - memset(&pfd, 0, sizeof(pfd)); - pfd.nSize = sizeof(pfd); - pfd.nVersion = 1; - pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; - pfd.cDepthBits = 32; - pfd.cColorBits = 32; + memset(&pfd, 0, sizeof(pfd)); + pfd.nSize = sizeof(pfd); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + pfd.cDepthBits = 32; + pfd.cColorBits = 32; - o->dc = GetDC(handle->lowlevel->gdi.hWnd); + o->dc = GetDC(handle->lowlevel->gdi.hWnd); - pf = ChoosePixelFormat(o->dc, &pfd); - SetPixelFormat(o->dc, pf, &pfd); + pf = ChoosePixelFormat(o->dc, &pfd); + SetPixelFormat(o->dc, pf, &pfd); - o->lib = MwDynamicOpen("opengl32.dll"); + o->lib = MwDynamicOpen("opengl32.dll"); - o->wglCreateContext = (MWwglCreateContext)(void*)MwDynamicSymbol(o->lib, "wglCreateContext"); - o->wglMakeCurrent = (MWwglMakeCurrent)(void*)MwDynamicSymbol(o->lib, "wglMakeCurrent"); - o->wglDeleteContext = (MWwglDeleteContext)(void*)MwDynamicSymbol(o->lib, "wglDeleteContext"); - o->wglGetProcAddress = (MWwglGetProcAddress)(void*)MwDynamicSymbol(o->lib, "wglGetProcAddress"); + o->wglCreateContext = + (MWwglCreateContext)(void *)MwDynamicSymbol(o->lib, "wglCreateContext"); + o->wglMakeCurrent = + (MWwglMakeCurrent)(void *)MwDynamicSymbol(o->lib, "wglMakeCurrent"); + o->wglDeleteContext = + (MWwglDeleteContext)(void *)MwDynamicSymbol(o->lib, "wglDeleteContext"); + o->wglGetProcAddress = (MWwglGetProcAddress)(void *)MwDynamicSymbol( + o->lib, "wglGetProcAddress"); - o->gl = o->wglCreateContext(o->dc); - } + o->gl = o->wglCreateContext(o->dc); + } #endif #ifdef USE_X11 - if(handle->lowlevel->common.type == MwLLBackendX11) { - int attribs[5]; - const char* glpath[] = { - "libGL.so", - "/usr/local/lib/libGL.so", - "/usr/X11R7/lib/libGL.so", - "/usr/pkg/lib/libGL.so"}; - int glincr = 0; - x11opengl_t* o = r = malloc(sizeof(*o)); + if (handle->lowlevel->common.type == MwLLBackendX11) { + int attribs[5]; + const char *glpath[] = {"libGL.so", "/usr/local/lib/libGL.so", + "/usr/X11R7/lib/libGL.so", "/usr/pkg/lib/libGL.so"}; + int glincr = 0; + x11opengl_t *o = r = malloc(sizeof(*o)); - attribs[0] = GLX_RGBA; - attribs[1] = GLX_DOUBLEBUFFER; - attribs[2] = GLX_DEPTH_SIZE; - attribs[3] = 24; - attribs[4] = None; + attribs[0] = GLX_RGBA; + attribs[1] = GLX_DOUBLEBUFFER; + attribs[2] = GLX_DEPTH_SIZE; + attribs[3] = 24; + attribs[4] = None; - while(glpath[glincr] != NULL && (o->lib = MwDynamicOpen(glpath[glincr++])) == NULL); + while (glpath[glincr] != NULL && + (o->lib = MwDynamicOpen(glpath[glincr++])) == NULL) + ; - o->glXChooseVisual = (MWglXChooseVisual)MwDynamicSymbol(o->lib, "glXChooseVisual"); - o->glXCreateContext = (MWglXCreateContext)MwDynamicSymbol(o->lib, "glXCreateContext"); - o->glXDestroyContext = (MWglXDestroyContext)MwDynamicSymbol(o->lib, "glXDestroyContext"); - o->glXMakeCurrent = (MWglXMakeCurrent)MwDynamicSymbol(o->lib, "glXMakeCurrent"); - o->glXSwapBuffers = (MWglXSwapBuffers)MwDynamicSymbol(o->lib, "glXSwapBuffers"); - o->glXGetProcAddress = (MWglXGetProcAddress)MwDynamicSymbol(o->lib, "glXGetProcAddress"); + o->glXChooseVisual = + (MWglXChooseVisual)MwDynamicSymbol(o->lib, "glXChooseVisual"); + o->glXCreateContext = + (MWglXCreateContext)MwDynamicSymbol(o->lib, "glXCreateContext"); + o->glXDestroyContext = + (MWglXDestroyContext)MwDynamicSymbol(o->lib, "glXDestroyContext"); + o->glXMakeCurrent = + (MWglXMakeCurrent)MwDynamicSymbol(o->lib, "glXMakeCurrent"); + o->glXSwapBuffers = + (MWglXSwapBuffers)MwDynamicSymbol(o->lib, "glXSwapBuffers"); + o->glXGetProcAddress = + (MWglXGetProcAddress)MwDynamicSymbol(o->lib, "glXGetProcAddress"); - /* XXX: fix this */ - o->visual = o->glXChooseVisual(handle->lowlevel->x11.display, DefaultScreen(handle->lowlevel->x11.display), attribs); - o->gl = o->glXCreateContext(handle->lowlevel->x11.display, o->visual, NULL, GL_TRUE); - } + /* XXX: fix this */ + o->visual = o->glXChooseVisual(handle->lowlevel->x11.display, + DefaultScreen(handle->lowlevel->x11.display), + attribs); + o->gl = o->glXCreateContext(handle->lowlevel->x11.display, o->visual, NULL, + GL_TRUE); + } #endif #ifdef USE_WAYLAND - if(handle->lowlevel->common.type == MwLLBackendWayland) { - int err; - EGLint numConfigs; - EGLint majorVersion; - EGLint minorVersion; - EGLContext context; - EGLSurface surface; - EGLint fbAttribs[] = - { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_DEPTH_SIZE, 24, - EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, - EGL_NONE}; - EGLint contextAttribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 1, - EGL_CONTEXT_MAJOR_VERSION, 1, - EGL_CONTEXT_MINOR_VERSION, 1, - EGL_NONE}; - EGLDisplay display; - waylandopengl_t* o = r = malloc(sizeof(*o)); - MwLL topmost_parent = handle->lowlevel->wayland.parent; - topmost_parent->wayland.always_render = MwTRUE; + if (handle->lowlevel->common.type == MwLLBackendWayland) { + int err; + EGLint numConfigs; + EGLint majorVersion; + EGLint minorVersion; + EGLContext context; + EGLSurface surface; + EGLint fbAttribs[] = {EGL_SURFACE_TYPE, + EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, + EGL_OPENGL_ES2_BIT, + EGL_RED_SIZE, + 8, + EGL_GREEN_SIZE, + 8, + EGL_BLUE_SIZE, + 8, + EGL_DEPTH_SIZE, + 24, + EGL_RENDERABLE_TYPE, + EGL_OPENGL_BIT, + EGL_NONE}; + EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, + 1, + EGL_CONTEXT_MAJOR_VERSION, + 1, + EGL_CONTEXT_MINOR_VERSION, + 1, + EGL_NONE}; + EGLDisplay display; + waylandopengl_t *o = r = malloc(sizeof(*o)); + MwLL topmost_parent = handle->lowlevel->wayland.parent; + topmost_parent->wayland.always_render = MwTRUE; - while(topmost_parent->wayland.parent != NULL) { - topmost_parent = topmost_parent->wayland.parent; - topmost_parent->wayland.always_render = MwTRUE; - } + while (topmost_parent->wayland.parent != NULL) { + topmost_parent = topmost_parent->wayland.parent; + topmost_parent->wayland.always_render = MwTRUE; + } - display = eglGetDisplay((EGLNativeDisplayType)handle->lowlevel->wayland.display); - if(display == EGL_NO_DISPLAY) { - printf("ERROR: eglGetDisplay, %0X\n", eglGetError()); - return MwFALSE; - } - /* Initialize EGL */ - if(!eglInitialize(display, &majorVersion, &minorVersion)) { - printf("ERROR: eglInitialize, %0X\n", eglGetError()); - return MwFALSE; - } + display = + eglGetDisplay((EGLNativeDisplayType)handle->lowlevel->wayland.display); + if (display == EGL_NO_DISPLAY) { + printf("ERROR: eglGetDisplay, %0X\n", eglGetError()); + return MwFALSE; + } + /* Initialize EGL */ + if (!eglInitialize(display, &majorVersion, &minorVersion)) { + printf("ERROR: eglInitialize, %0X\n", eglGetError()); + return MwFALSE; + } - /* Get configs */ - if((eglGetConfigs(display, NULL, 0, &numConfigs) != EGL_TRUE) || (numConfigs == 0)) { - printf("ERROR: eglGetConfigs, %0X\n", eglGetError()); - return MwFALSE; - } + /* Get configs */ + if ((eglGetConfigs(display, NULL, 0, &numConfigs) != EGL_TRUE) || + (numConfigs == 0)) { + printf("ERROR: eglGetConfigs, %0X\n", eglGetError()); + return MwFALSE; + } - /* Choose config */ - if((eglChooseConfig(display, fbAttribs, &o->egl_config, 1, &numConfigs) != EGL_TRUE) || (numConfigs != 1)) { - printf("ERROR: eglChooseConfig, %0X\n", eglGetError()); - return MwFALSE; - } + /* Choose config */ + if ((eglChooseConfig(display, fbAttribs, &o->egl_config, 1, &numConfigs) != + EGL_TRUE) || + (numConfigs != 1)) { + printf("ERROR: eglChooseConfig, %0X\n", eglGetError()); + return MwFALSE; + } - o->egl_window_native = - (EGLNativeWindowType)wl_egl_window_create(handle->lowlevel->wayland.framebuffer.surface, handle->lowlevel->wayland.ww, handle->lowlevel->wayland.wh); - if(!o->egl_window_native) { - printf("ERROR: wl_egl_window_create, EGL_NO_SURFACE\n"); - return MwFALSE; - } + o->egl_window_native = (EGLNativeWindowType)wl_egl_window_create( + handle->lowlevel->wayland.framebuffer.surface, + handle->lowlevel->wayland.ww, handle->lowlevel->wayland.wh); + if (!o->egl_window_native) { + printf("ERROR: wl_egl_window_create, EGL_NO_SURFACE\n"); + return MwFALSE; + } - /* Create a surface */ - surface = eglCreateWindowSurface(display, o->egl_config, o->egl_window_native, NULL); - if(surface == EGL_NO_SURFACE) { - printf("ERROR: eglCreateWindowSurface, %0X\n", eglGetError()); - return MwFALSE; - } + /* Create a surface */ + surface = eglCreateWindowSurface(display, o->egl_config, + o->egl_window_native, NULL); + if (surface == EGL_NO_SURFACE) { + printf("ERROR: eglCreateWindowSurface, %0X\n", eglGetError()); + return MwFALSE; + } - eglBindAPI(EGL_OPENGL_API); + eglBindAPI(EGL_OPENGL_API); - /* Create a GL context */ - context = eglCreateContext(display, o->egl_config, EGL_NO_CONTEXT, contextAttribs); - if(context == EGL_NO_CONTEXT) { - printf("ERROR: eglCreateContext, %0X\n", eglGetError()); - return MwFALSE; - } + /* Create a GL context */ + context = eglCreateContext(display, o->egl_config, EGL_NO_CONTEXT, + contextAttribs); + if (context == EGL_NO_CONTEXT) { + printf("ERROR: eglCreateContext, %0X\n", eglGetError()); + return MwFALSE; + } - if(!eglMakeCurrent(display, surface, surface, context)) { - printf("ERROR: eglMakeCurrent (setup): %0X\n", eglGetError()); - } + if (!eglMakeCurrent(display, surface, surface, context)) { + printf("ERROR: eglMakeCurrent (setup): %0X\n", eglGetError()); + } - o->egl_display = display; - o->egl_surface = surface; - o->egl_context = context; - } + o->egl_display = display; + o->egl_surface = surface; + o->egl_context = context; + } #endif - handle->internal = r; - handle->lowlevel->common.copy_buffer = 0; + handle->internal = r; + 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) { - MwWidget w = handle; + MwWidget w = handle; #ifdef USE_GDI - if(handle->lowlevel->common.type == MwLLBackendGDI) { - gdiopengl_t* o = handle->internal; + if (handle->lowlevel->common.type == MwLLBackendGDI) { + gdiopengl_t *o = handle->internal; - o->wglMakeCurrent(NULL, NULL); - DeleteDC(o->dc); - o->wglDeleteContext(o->gl); + o->wglMakeCurrent(NULL, NULL); + DeleteDC(o->dc); + o->wglDeleteContext(o->gl); - MwDynamicClose(o->lib); - } + MwDynamicClose(o->lib); + } #endif #ifdef USE_X11 - if(handle->lowlevel->common.type == MwLLBackendX11) { - x11opengl_t* o = handle->internal; + if (handle->lowlevel->common.type == MwLLBackendX11) { + x11opengl_t *o = handle->internal; - o->glXMakeCurrent(handle->lowlevel->x11.display, None, NULL); - o->glXDestroyContext(handle->lowlevel->x11.display, o->gl); + o->glXMakeCurrent(handle->lowlevel->x11.display, None, NULL); + o->glXDestroyContext(handle->lowlevel->x11.display, o->gl); - MwDynamicClose(o->lib); - } + MwDynamicClose(o->lib); + } #endif #ifdef USE_WAYLAND - if(handle->lowlevel->common.type == MwLLBackendWayland) { - /* todo */ - } + if (handle->lowlevel->common.type == MwLLBackendWayland) { + /* todo */ + } #endif - while(w->parent != NULL) w = w->parent; + while (w->parent != NULL) + w = w->parent; - w->berserk--; + w->berserk--; - free(handle->internal); + free(handle->internal); } static void mwOpenGLMakeCurrentImpl(MwWidget handle) { - /* these swap interval functions belonging here actually stink! */ + /* these swap interval functions belonging here actually stink! */ #ifdef USE_GDI - if(handle->lowlevel->common.type == MwLLBackendGDI) { - gdiopengl_t* o = handle->internal; - void (*swap_interval_ext)(int) = NULL; + if (handle->lowlevel->common.type == MwLLBackendGDI) { + gdiopengl_t *o = handle->internal; + void (*swap_interval_ext)(int) = NULL; - o->wglMakeCurrent(o->dc, o->gl); + o->wglMakeCurrent(o->dc, o->gl); - if((swap_interval_ext = MwOpenGLGetProcAddress(handle, "wglSwapIntervalEXT")) != NULL) { - swap_interval_ext(1); - } - } + if ((swap_interval_ext = + MwOpenGLGetProcAddress(handle, "wglSwapIntervalEXT")) != NULL) { + swap_interval_ext(1); + } + } #endif #ifdef USE_X11 - if(handle->lowlevel->common.type == MwLLBackendX11) { - x11opengl_t* o = handle->internal; - void (*swap_interval_ext)(Display*, GLXDrawable, int) = NULL; - void (*swap_interval_mesa)(unsigned int) = NULL; - void (*swap_interval_sgi)(int) = NULL; + if (handle->lowlevel->common.type == MwLLBackendX11) { + x11opengl_t *o = handle->internal; + void (*swap_interval_ext)(Display *, GLXDrawable, int) = NULL; + void (*swap_interval_mesa)(unsigned int) = NULL; + void (*swap_interval_sgi)(int) = NULL; - o->glXMakeCurrent(handle->lowlevel->x11.display, handle->lowlevel->x11.window, o->gl); + o->glXMakeCurrent(handle->lowlevel->x11.display, + handle->lowlevel->x11.window, o->gl); - if((swap_interval_ext = MwOpenGLGetProcAddress(handle, "glXSwapIntervalEXT")) != NULL) { - swap_interval_ext(handle->lowlevel->x11.display, handle->lowlevel->x11.window, 1); - } + if ((swap_interval_ext = + MwOpenGLGetProcAddress(handle, "glXSwapIntervalEXT")) != NULL) { + swap_interval_ext(handle->lowlevel->x11.display, + handle->lowlevel->x11.window, 1); + } - if((swap_interval_mesa = MwOpenGLGetProcAddress(handle, "glXSwapIntervalMESA")) != NULL) { - swap_interval_mesa(1); - } + if ((swap_interval_mesa = + MwOpenGLGetProcAddress(handle, "glXSwapIntervalMESA")) != NULL) { + swap_interval_mesa(1); + } - if((swap_interval_sgi = MwOpenGLGetProcAddress(handle, "glXSwapIntervalSGI")) != NULL) { - swap_interval_sgi(1); - } - } + if ((swap_interval_sgi = + MwOpenGLGetProcAddress(handle, "glXSwapIntervalSGI")) != NULL) { + swap_interval_sgi(1); + } + } #endif #ifdef USE_WAYLAND - if(handle->lowlevel->common.type == MwLLBackendWayland) { - waylandopengl_t* o = handle->internal; + if (handle->lowlevel->common.type == MwLLBackendWayland) { + waylandopengl_t *o = handle->internal; - if(!eglMakeCurrent(o->egl_display, o->egl_surface, o->egl_surface, o->egl_context)) { - printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); - } + if (!eglMakeCurrent(o->egl_display, o->egl_surface, o->egl_surface, + o->egl_context)) { + printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); + } - eglSwapInterval(o->egl_display, 1); - } + eglSwapInterval(o->egl_display, 1); + } #endif } static void mwOpenGLSwapBufferImpl(MwWidget handle) { #ifdef USE_GDI - if(handle->lowlevel->common.type == MwLLBackendGDI) { - gdiopengl_t* o = handle->internal; + if (handle->lowlevel->common.type == MwLLBackendGDI) { + gdiopengl_t *o = handle->internal; - SwapBuffers(o->dc); - } + SwapBuffers(o->dc); + } #endif #ifdef USE_X11 - if(handle->lowlevel->common.type == MwLLBackendX11) { - x11opengl_t* o = handle->internal; + if (handle->lowlevel->common.type == MwLLBackendX11) { + x11opengl_t *o = handle->internal; - o->glXSwapBuffers(handle->lowlevel->x11.display, handle->lowlevel->x11.window); - } + o->glXSwapBuffers(handle->lowlevel->x11.display, + handle->lowlevel->x11.window); + } #endif #ifdef USE_WAYLAND - if(handle->lowlevel->common.type == MwLLBackendWayland) { - waylandopengl_t* o = handle->internal; - eglSwapInterval(o->egl_display, 0); - if(!eglSwapBuffers(o->egl_display, o->egl_surface)) { - printf("ERROR: eglSwapBuffers, %0X\n", eglGetError()); - }; - wl_egl_window_resize((struct wl_egl_window*)o->egl_window_native, handle->lowlevel->wayland.ww, handle->lowlevel->wayland.wh, 0, 0); - MwLLForceRender(handle->lowlevel); - } + if (handle->lowlevel->common.type == MwLLBackendWayland) { + waylandopengl_t *o = handle->internal; + eglSwapInterval(o->egl_display, 0); + if (!eglSwapBuffers(o->egl_display, o->egl_surface)) { + printf("ERROR: eglSwapBuffers, %0X\n", eglGetError()); + }; + wl_egl_window_resize((struct wl_egl_window *)o->egl_window_native, + handle->lowlevel->wayland.ww, + handle->lowlevel->wayland.wh, 0, 0); + MwLLForceRender(handle->lowlevel); + } #endif } -static void* mwOpenGLGetProcAddressImpl(MwWidget handle, const char* name) { +static void *mwOpenGLGetProcAddressImpl(MwWidget handle, const char *name) { #ifdef USE_GDI - if(handle->lowlevel->common.type == MwLLBackendGDI) { - gdiopengl_t* o = handle->internal; + if (handle->lowlevel->common.type == MwLLBackendGDI) { + gdiopengl_t *o = handle->internal; - return o->wglGetProcAddress(name); - } + return o->wglGetProcAddress(name); + } #endif #ifdef USE_X11 - if(handle->lowlevel->common.type == MwLLBackendX11) { - x11opengl_t* o = handle->internal; + if (handle->lowlevel->common.type == MwLLBackendX11) { + x11opengl_t *o = handle->internal; - return o->glXGetProcAddress((const GLubyte*)name); - } + return o->glXGetProcAddress((const GLubyte *)name); + } #endif #ifdef USE_WAYLAND - if(handle->lowlevel->common.type == MwLLBackendWayland) { - return eglGetProcAddress(name); - } + if (handle->lowlevel->common.type == MwLLBackendWayland) { + return eglGetProcAddress(name); + } #endif - return NULL; + return NULL; } -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); + } } -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}; +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; + +#endif \ No newline at end of file diff --git a/src/widget/opengl_cocoa.m b/src/widget/opengl_cocoa.m new file mode 100644 index 00000000..88e17e39 --- /dev/null +++ b/src/widget/opengl_cocoa.m @@ -0,0 +1,128 @@ +#include "Mw/Core.h" +#include "Mw/StringDefs.h" +#include +#include +#import + +@interface MacOpenGLWidget : NSObject { + NSOpenGLPixelFormat *pixelFormat; + NSOpenGLContext *glc; +} + +- (MacOpenGLWidget *)initWithView:(NSView *)view; +- (void)destroy; +- (void)makeCurrent; +- (void)swapBuffer; +- (void *)getProcAddressWithName:(const char *)name; + +@end + +static int create(MwWidget 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); + + printf("%d %d\n", width, height); + + MacOpenGLWidget *o = r = [[MacOpenGLWidget alloc] + initWithView:[handle->lowlevel->cocoa.real getView]]; + + handle->internal = r; + handle->lowlevel->common.copy_buffer = 0; + + MwSetDefault(handle); + + while (w->parent != NULL) + w = w->parent; + + w->berserk++; + + return 0; +} + +static void destroy(MwWidget handle) { + [(MacOpenGLWidget *)handle->internal destroy]; +} + +static void mwOpenGLMakeCurrentImpl(MwWidget handle) { + [(MacOpenGLWidget *)handle->internal makeCurrent]; +} + +static void mwOpenGLSwapBufferImpl(MwWidget handle) { + [(MacOpenGLWidget *)handle->internal swapBuffer]; +} + +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); + } +} + +@implementation MacOpenGLWidget + +- (MacOpenGLWidget *)initWithView:(NSView *)view { + 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:view]; + return self; +}; +- (void)destroy { +}; +- (void)makeCurrent { + [self->glc makeCurrentContext]; +}; +- (void)swapBuffer { + [self->glc flushBuffer]; +}; +- (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 From 39db13fa486d7cadd3d2233f523a807e5e076ef4 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 4 Mar 2026 23:06:56 -0700 Subject: [PATCH 37/94] mac: center window when MwDEFAULT is passed --- src/backend/cocoa.m | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 700ebdb8..0b230ebc 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -82,15 +82,12 @@ static CGPoint pointFlip(CGPoint point) { height:(int)height handle:(MwLL)r { MilskoCocoa *c = [MilskoCocoa alloc]; - bool centerX = false, centerY = false; if (x == MwDEFAULT) { - x = 0; - centerX = true; + x = ([NSScreen mainScreen].frame.size.width / 2.) - (width / 2.); } if (y == MwDEFAULT) { - y = 0; - centerY = true; + y = ([NSScreen mainScreen].frame.size.height / 2.) - (height / 2.); } c->application = [NSApplication sharedApplication]; c->rect = rectFlip(NSMakeRect(x, y, width, height)); @@ -108,6 +105,9 @@ static CGPoint pointFlip(CGPoint point) { offset = [parentWindow frameRectForContentRect:parentWindow.frame].size.height - [parentWindow contentRectForFrameRect:parentWindow.frame].size.height; + + c->rect.origin.x += parentWindow.frame.origin.x; + c->rect.origin.y -= parentWindow.frame.origin.y - offset; c->rect.origin.y -= offset; c->window = [[NSWindow alloc] initWithContentRect:c->rect @@ -204,7 +204,15 @@ static CGPoint pointFlip(CGPoint point) { offset = [parentWindow frameRectForContentRect:parentWindow.frame].size.height - [parentWindow contentRectForFrameRect:parentWindow.frame].size.height; - frame.origin.y -= offset; + + if (x < parentWindow.frame.origin.x) { + frame.origin.x += parentWindow.frame.origin.x; + } + + if (y < parentWindow.frame.origin.y) { + frame.origin.y -= parentWindow.frame.origin.y - offset; + frame.origin.y -= offset; + } } [self->view setFrameSize:frame.size]; From e2bcd7b9e93c8dd860d36588d5c48d2228100c56 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 5 Mar 2026 19:29:43 -0700 Subject: [PATCH 38/94] mac: keyboard events and other nice refactors. they get sent to the opengl window but the callback isn't fired for some reason --- include/Mw/LowLevel/Cocoa.h | 3 + src/backend/cocoa.m | 748 +++++++++++++++++++++++++++++------- src/widget/opengl_cocoa.m | 18 +- 3 files changed, 622 insertions(+), 147 deletions(-) diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index 91679db7..35bc5641 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -96,6 +96,7 @@ - (void)setX:(int)x Y:(int)y; - (void)setW:(int)w H:(int)h; - (int)pending; +- (void)eventProcess:(NSEvent *)ev; - (void)getNextEvent; - (void)setTitle:(const char *)title; - (void)drawPixmap:(MwLLPixmap)pixmap rect:(MwRect *)rect; @@ -120,6 +121,8 @@ - (NSWindow *)parentWindow; - (NSView *)getView; +- (NSWindow *)getWindow; +- (MilskoFakePointer *)getHandle; @end #define OBJC(x) x diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 0b230ebc..7c566a8b 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -125,7 +125,9 @@ static CGPoint pointFlip(CGPoint point) { [p->window addChildWindow:c->window ordered:NSWindowAbove]; [c->window setHasShadow:MwFALSE]; } else { - // [c->application activateIgnoringOtherApps:true]; + [c->application setActivationPolicy:NSApplicationActivationPolicyRegular]; + [c->application activateIgnoringOtherApps:true]; + [c->window makeFirstResponder:c->view]; } c->view = [[MilskoCocoaView alloc] initWithFrame:c->rect]; @@ -229,144 +231,586 @@ static CGPoint pointFlip(CGPoint point) { [self->window setFrame:frame display:YES animate:false]; }; - (int)pending { - self->lastEvent = - [self->application nextEventMatchingMask:NSAnyEventMask - untilDate:nil - inMode:NSDefaultRunLoopMode - dequeue:YES]; if (_forceRender) { _forceRender = MwFALSE; return 1; } + + self->lastEvent = [self->window nextEventMatchingMask:NSAnyEventMask + untilDate:[NSDate distantPast] + inMode:NSDefaultRunLoopMode + dequeue:YES]; return self->lastEvent != NULL; }; + - (void)getNextEvent { - if (self->lastEvent != nil) { - NSWindow *win = [self->lastEvent window]; - NSWindow *parentWindow = [self parentWindow]; - MwLL h; + int i; + NSEvent *ev; - if ([win contentView].subviews.count == 0) { - NSLog(@"[WARNING] no subviews on this window, cannot process events.\n"); - return; - } + [self eventProcess:lastEvent]; - h = [((MilskoFakePointer *)[win contentView].subviews[0]) pointer]; - switch (self->lastEvent.type) { - case NSEventTypeLeftMouseDown: - case NSEventTypeRightMouseDown: - case NSEventTypeOtherMouseDown: - case NSEventTypeLeftMouseUp: - case NSEventTypeRightMouseUp: - case NSEventTypeOtherMouseUp: { - MwLLMouse mouse = {}; - MwBool isDown = MwTRUE; - CGPoint mousePoint = pointFlip([lastEvent locationInWindow]); - switch (self->lastEvent.type) { - case NSEventTypeLeftMouseUp: - isDown = MwFALSE; - case NSEventTypeLeftMouseDown: - mouse.button = MwLLMouseLeft; - break; - case NSEventTypeRightMouseUp: - isDown = MwFALSE; - case NSEventTypeRightMouseDown: - mouse.button = MwLLMouseRight; - break; - case NSEventTypeOtherMouseUp: - isDown = MwFALSE; - case NSEventTypeOtherMouseDown: - mouse.button = MwLLMouseMiddle; - break; - default: - break; - } - mouse.point.x = mousePoint.x; - mouse.point.y = mousePoint.y; + while ((ev = [self->window nextEventMatchingMask:NSAnyEventMask + untilDate:[NSDate distantPast] + inMode:NSDefaultRunLoopMode + dequeue:YES])) { + [self eventProcess:ev]; + } +}; - if (isDown) { - MwLLDispatch(h, down, &mouse); - } else { - MwLLDispatch(h, up, &mouse); - } - break; - } - - break; - case NSEventTypeMouseMoved: { - MwPoint pos; - pos.x = [lastEvent locationInWindow].x; - pos.y = [win contentRectForFrameRect:win.frame].size.height - - [lastEvent locationInWindow].y; - MwLLDispatch(h, move, &pos); - break; - } - case NSEventTypeLeftMouseDragged: - MwLLDispatch(h, focus_in, NULL); - break; - case NSEventTypeRightMouseDragged: - MwLLDispatch(h, focus_out, NULL); - break; - case NSEventTypeMouseEntered: - break; - case NSEventTypeMouseExited: - break; - case NSEventTypeKeyDown: - [win interpretKeyEvents:[NSArray arrayWithObject:lastEvent]]; - break; - case NSEventTypeKeyUp: - [win interpretKeyEvents:[NSArray arrayWithObject:lastEvent]]; - break; - case NSEventTypeFlagsChanged: - break; - case NSEventTypeAppKitDefined: - break; - case NSEventTypeSystemDefined: - break; - case NSEventTypeApplicationDefined: - break; - case NSEventTypePeriodic: - break; - case NSEventTypeCursorUpdate: - break; - case NSEventTypeScrollWheel: - break; - case NSEventTypeTabletPoint: - break; - case NSEventTypeTabletProximity: - break; - break; - case NSEventTypeOtherMouseDragged: - break; - case NSEventTypeGesture: - break; - case NSEventTypeMagnify: - break; - case NSEventTypeSwipe: - break; - case NSEventTypeRotate: - break; - case NSEventTypeBeginGesture: - break; - case NSEventTypeEndGesture: - break; - case NSEventTypeSmartMagnify: - break; - case NSEventTypeQuickLook: - break; - case NSEventTypePressure: - break; - case NSEventTypeDirectTouch: - break; - case NSEventTypeChangeMode: - break; - }; - // printf("got event: %ld\n", self->lastEvent.type); - [self->application sendEvent:self->lastEvent]; +- (void)eventProcess:(NSEvent *)ev { + NSWindow *win = [ev window]; + NSWindow *parentWindow = [self parentWindow]; + MwLL h; + MwBool doSendEvent = MwTRUE; + if (!win) { + return; } - [self->view setNeedsDisplay:true]; -}; + if ([win contentView].subviews.count == 0) { + printf("no subviews on %p\n", win); + return; + } else { + h = [((MilskoFakePointer *)[win contentView].subviews[0]) pointer]; + } + + switch (ev.type) { + case NSEventTypeLeftMouseDown: + case NSEventTypeRightMouseDown: + case NSEventTypeOtherMouseDown: + case NSEventTypeLeftMouseUp: + case NSEventTypeRightMouseUp: + case NSEventTypeOtherMouseUp: { + MwLLMouse mouse = {}; + MwBool isDown = MwTRUE; + CGPoint mousePoint = pointFlip([ev locationInWindow]); + switch (ev.type) { + case NSEventTypeLeftMouseUp: + isDown = MwFALSE; + case NSEventTypeLeftMouseDown: + mouse.button = MwLLMouseLeft; + break; + case NSEventTypeRightMouseUp: + isDown = MwFALSE; + case NSEventTypeRightMouseDown: + mouse.button = MwLLMouseRight; + break; + case NSEventTypeOtherMouseUp: + isDown = MwFALSE; + case NSEventTypeOtherMouseDown: + mouse.button = MwLLMouseMiddle; + break; + default: + break; + } + mouse.point.x = mousePoint.x; + mouse.point.y = mousePoint.y; + + if (isDown) { + MwLLDispatch(h, down, &mouse); + } else { + MwLLDispatch(h, up, &mouse); + } + break; + } + case NSEventTypeLeftMouseDragged: + case NSEventTypeRightMouseDragged: + case NSEventTypeOtherMouseDragged: + case NSEventTypeMouseMoved: { + MwPoint pos; + pos.x = [ev locationInWindow].x; + pos.y = [win contentRectForFrameRect:win.frame].size.height - + [ev locationInWindow].y; + MwLLDispatch(h, move, &pos); + break; + } + case NSEventTypeMouseEntered: + MwLLDispatch(h, focus_in, NULL); + break; + case NSEventTypeMouseExited: + MwLLDispatch(h, focus_out, NULL); + break; + case NSEventTypeKeyDown: + case NSEventTypeKeyUp: { + 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_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C, + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightCommand = 0x36, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E + }; + // [view.nextResponder + // interpretKeyEvents:[NSArray arrayWithObject:lastEvent]]; + switch (ev.keyCode) { + case kVK_ANSI_A: + ch = 'a'; + break; + case kVK_ANSI_B: + ch = 'b'; + break; + case kVK_ANSI_C: + ch = 'c'; + break; + case kVK_ANSI_D: + ch = 'd'; + break; + case kVK_ANSI_E: + ch = 'e'; + break; + case kVK_ANSI_F: + ch = 'f'; + break; + case kVK_ANSI_G: + ch = 'g'; + break; + case kVK_ANSI_H: + ch = 'h'; + break; + case kVK_ANSI_I: + ch = 'i'; + break; + case kVK_ANSI_J: + ch = 'j'; + break; + case kVK_ANSI_K: + ch = 'k'; + break; + case kVK_ANSI_L: + ch = 'l'; + break; + case kVK_ANSI_M: + ch = 'm'; + break; + case kVK_ANSI_N: + ch = 'n'; + break; + case kVK_ANSI_O: + ch = 'o'; + break; + case kVK_ANSI_P: + ch = 'p'; + break; + case kVK_ANSI_Q: + ch = 'q'; + break; + case kVK_ANSI_R: + ch = 'r'; + break; + case kVK_ANSI_S: + ch = 's'; + break; + case kVK_ANSI_T: + ch = 't'; + break; + case kVK_ANSI_U: + ch = 'u'; + break; + case kVK_ANSI_V: + ch = 'v'; + break; + case kVK_ANSI_W: + ch = 'w'; + break; + case kVK_ANSI_X: + ch = 'x'; + break; + case kVK_ANSI_Y: + ch = 'y'; + break; + case kVK_ANSI_Z: + ch = 'z'; + break; + case kVK_ANSI_0: + ch = '0'; + break; + case kVK_ANSI_1: + ch = '1'; + break; + case kVK_ANSI_2: + ch = '2'; + break; + case kVK_ANSI_3: + ch = '3'; + break; + case kVK_ANSI_4: + ch = '4'; + break; + case kVK_ANSI_5: + ch = '5'; + break; + case kVK_ANSI_6: + ch = '6'; + break; + case kVK_ANSI_7: + ch = '7'; + break; + case kVK_ANSI_8: + ch = '8'; + break; + case kVK_ANSI_9: + ch = '9'; + break; + + // case kVK_ANSI_Keypad0: + // ch = MwLLKey; + // break; + // case kVK_ANSI_Keypad1: + // ch = keypad1; + // break; + // case kVK_ANSI_Keypad2: + // ch = keypad2; + // break; + // case kVK_ANSI_Keypad3: + // ch = keypad3; + // break; + // case kVK_ANSI_Keypad4: + // ch = keypad4; + // break; + // case kVK_ANSI_Keypad5: + // ch = keypad5; + // break; + // case kVK_ANSI_Keypad6: + // ch = keypad6; + // break; + // case kVK_ANSI_Keypad7: + // ch = keypad7; + // break; + // case kVK_ANSI_Keypad8: + // ch = keypad8; + // break; + // case kVK_ANSI_Keypad9: + // ch = keypad9; + // break; + // case kVK_ANSI_KeypadClear: + // ch = keypadClear; + // break; + // case kVK_ANSI_KeypadDivide: + // ch = keypadDivide; + // break; + // case kVK_ANSI_KeypadEnter: + // ch = keypadEnter; + // break; + // case kVK_ANSI_KeypadEquals: + // ch = keypadEquals; + // break; + // case kVK_ANSI_KeypadMinus: + // ch = keypadMinus; + // break; + // case kVK_ANSI_KeypadPlus: + // ch = keypadPlus; + // break; + // case kVK_PageDown: + // ch = MwLLKey; + // break; + // case kVK_PageUp: + // ch = pageUp; + // break; + // case kVK_End: + // ch = end; + // break; + // case kVK_Home: + // ch = home; + // break; + + // case kVK_F1: + // ch = f1; + // break; + // case kVK_F2: + // ch = f2; + // break; + // case kVK_F3: + // ch = f3; + // break; + // case kVK_F4: + // ch = f4; + // break; + // case kVK_F5: + // ch = f5; + // break; + // case kVK_F6: + // ch = f6; + // break; + // case kVK_F7: + // ch = f7; + // break; + // case kVK_F8: + // ch = f8; + // break; + // case kVK_F9: + // ch = f9; + // break; + // case kVK_F10: + // ch = f10; + // break; + // case kVK_F11: + // ch = f11; + // break; + // case kVK_F12: + // ch = f12; + // break; + // case kVK_F13: + // ch = f13; + // break; + // case kVK_F14: + // ch = f14; + // break; + // case kVK_F15: + // ch = f15; + // break; + // case kVK_F16: + // ch = f16; + // break; + // case kVK_F17: + // ch = f17; + // break; + // case kVK_F18: + // ch = f18; + // break; + // case kVK_F19: + // ch = f19; + // break; + // case kVK_F20: + // ch = f20; + // break; + // case kVK_ANSI_KeypadDecimal: + // ch = decimal; + // break; + + case kVK_ANSI_Quote: + ch = '\"'; + break; + case kVK_ANSI_Grave: + ch = '`'; + break; + case kVK_ANSI_Backslash: + ch = '/'; + break; + case kVK_ANSI_Comma: + ch = ','; + break; + // case kVK_Delete: + // ch = delete; + // break; + // case kVK_ANSI_Equal: + // ch = equals; + // break; + case kVK_Escape: + ch = MwLLKeyEscape; + break; + // case kVK_ANSI_LeftBracket: + // ch = leftBracket; + // break; + // case kVK_ANSI_Minus: + // ch = minus; + // break; + // case kVK_ANSI_KeypadMultiply: + // ch = multiply; + // break; + // case kVK_ANSI_Period: + // ch = period; + // break; + case kVK_Return: + ch = MwLLKeyEnter; + break; + // case kVK_ANSI_RightBracket: + // ch = rightBracket; + // break; + case kVK_ANSI_Semicolon: + ch = ';'; + break; + case kVK_ANSI_Slash: + ch = '\\'; + break; + case kVK_Space: + ch = ' '; + break; + // case kVK_Tab: + // ch = tab; + // break; + + // case kVK_Mute: + // ch = mute; + // break; + // case kVK_VolumeDown: + // ch = volumeDown; + // break; + // case kVK_VolumeUp: + // ch = volumeUp; + // break; + + // case kVK_Command: + // ch = MwLLKey; + // break; + // case kVK_RightCommand: + // ch = rightCommand; + // break; + case kVK_Control: + ch = MwLLKeyControl; + break; + case kVK_RightControl: + ch = MwLLKeyControl; + break; + // case kVK_Function: + // ch = function; + // break; + // case kVK_Option: + // ch = option; + // break; + // case kVK_RightOption: + // ch = rightOption; + // break; + case kVK_Shift: + ch = MwLLKeyLeftShift; + break; + case kVK_RightShift: + ch = MwLLKeyRightShift; + break; + + case kVK_DownArrow: + ch = MwLLKeyDown; + break; + case kVK_LeftArrow: + ch = MwLLKeyLeft; + break; + case kVK_RightArrow: + ch = MwLLKeyRight; + break; + case kVK_UpArrow: + ch = MwLLKeyUp; + break; + } + switch (ev.type) { + case NSEventTypeKeyDown: + MwLLDispatch(h, key, &ch); + break; + case NSEventTypeKeyUp: + MwLLDispatch(h, key_released, &ch); + break; + default: + break; + } + doSendEvent = MwFALSE; + break; + } + case NSEventTypeCursorUpdate: + break; + case NSEventTypeScrollWheel: + break; + default: + break; + }; + if (doSendEvent) { + [win sendEvent:ev]; + } +} - (void)setTitle:(const char *)title { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -465,6 +909,13 @@ static CGPoint pointFlip(CGPoint point) { - (NSView *)getView { return view; } +- (NSWindow *)getWindow { + return window; +} + +- (MilskoFakePointer *)getHandle { + return handle; +} @end @implementation MilskoCocoaView @@ -530,23 +981,6 @@ static CGPoint pointFlip(CGPoint point) { - (void)displayRect:(NSRect)rect { }; -@end - -@implementation MilskoFakePointer -- (void)setPointer:(void *)pointer { - self.frame = *(NSRect *)&pointer; - self->ptr = pointer; -}; -- (void *)pointer { - return self->ptr; -}; - -- (void)drawRect:(NSRect)dirtyRect { - /* explicitly do nothing */ -} - -- (void)destroy { -} @end @@ -567,11 +1001,37 @@ static CGPoint pointFlip(CGPoint point) { - (void)windowDidResize:(NSNotification *)notification { } +// This will close/terminate the application when the main window is closed. +- (void)windowWillClose:(NSNotification *)notification { + // MilskoCocoa *window = notification.object; + // MwLL handle = [window getHandle].pointer; + // MwLLDispatch(handle, close, NULL); + [NSApp terminate:nil]; +} + - (instancetype)initWithWin:(NSWindow *)win { self->w = win; return self; } +@end + +@implementation MilskoFakePointer +- (void)setPointer:(void *)pointer { + self.frame = *(NSRect *)&pointer; + self->ptr = pointer; +}; +- (void *)pointer { + return self->ptr; +}; + +- (void)drawRect:(NSRect)dirtyRect { + /* explicitly do nothing */ +} + +- (void)destroy { +} + @end static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { MwLL r; diff --git a/src/widget/opengl_cocoa.m b/src/widget/opengl_cocoa.m index 88e17e39..c33e3754 100644 --- a/src/widget/opengl_cocoa.m +++ b/src/widget/opengl_cocoa.m @@ -1,3 +1,4 @@ +#include "Mw/BaseTypes.h" #include "Mw/Core.h" #include "Mw/StringDefs.h" #include @@ -28,10 +29,8 @@ static int create(MwWidget handle) { printf("%d %d\n", width, height); - MacOpenGLWidget *o = r = [[MacOpenGLWidget alloc] + handle->internal = [[MacOpenGLWidget alloc] initWithView:[handle->lowlevel->cocoa.real getView]]; - - handle->internal = r; handle->lowlevel->common.copy_buffer = 0; MwSetDefault(handle); @@ -96,6 +95,19 @@ static void func_handler(MwWidget handle, const char *name, void *out, [self->glc makeCurrentContext]; }; - (void)swapBuffer { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSEvent *event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined + 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]; + [self->glc flushBuffer]; }; - (void *)getProcAddressWithName:(const char *)name { From 9be36b0755e7c69c9b1188d8e9168e285f66648a Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 5 Mar 2026 20:19:19 -0700 Subject: [PATCH 39/94] mac: have key events get sent to parent --- src/backend/cocoa.m | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 7c566a8b..d9add8e3 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -247,7 +247,9 @@ static CGPoint pointFlip(CGPoint point) { int i; NSEvent *ev; - [self eventProcess:lastEvent]; + if (lastEvent) { + [self eventProcess:lastEvent]; + } while ((ev = [self->window nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast] @@ -262,6 +264,8 @@ static CGPoint pointFlip(CGPoint point) { NSWindow *parentWindow = [self parentWindow]; MwLL h; MwBool doSendEvent = MwTRUE; + MwLL this = self->handle.pointer; + if (!win) { return; } @@ -789,10 +793,10 @@ static CGPoint pointFlip(CGPoint point) { } switch (ev.type) { case NSEventTypeKeyDown: - MwLLDispatch(h, key, &ch); + MwLLDispatch(this, key, &ch); break; case NSEventTypeKeyUp: - MwLLDispatch(h, key_released, &ch); + MwLLDispatch(this, key_released, &ch); break; default: break; From 9d7a75394ce111724e0cf86cff00f82eb97c6a31 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 5 Mar 2026 21:58:22 -0700 Subject: [PATCH 40/94] mac: implement clipboard (At the cost of making the pending function a crime against god) --- include/Mw/LowLevel/Cocoa.h | 3 ++ src/backend/cocoa.m | 56 ++++++++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index 35bc5641..c0974d46 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -80,6 +80,8 @@ MilskoCocoaView *view; MwLL parent; MilskoFakePointer *handle; + NSUInteger strHash; + MwBool pendingTicker; } + (MilskoCocoa *)newWithParent:(MwLL)parent @@ -118,6 +120,7 @@ - (void)getCursorCoord:(MwPoint *)point; - (void)getScreenSize:(MwRect *)rect; - (void)destroy; +- (void)sendClipboardEvent; - (NSWindow *)parentWindow; - (NSView *)getView; diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index d9add8e3..47e44e78 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -1,3 +1,5 @@ +#include "Mw/BaseTypes.h" +#include "Mw/LowLevel.h" #include #pragma clang push @@ -140,6 +142,7 @@ static CGPoint pointFlip(CGPoint point) { c->parent = parent; c->_forceRender = MwTRUE; + c->strHash = 0; return c; } @@ -235,12 +238,23 @@ static CGPoint pointFlip(CGPoint point) { _forceRender = MwFALSE; return 1; } - +// Apple does not give you a reliable way to tell when events are coming. I +// found this out by accident by stumbling upon a comment wxWidget's code, +// thought I could figure out something better, and I ended up with the same +// solution they tried and can confirm it doesn't work. +// Thanks Tim Cook. +#if 0 self->lastEvent = [self->window nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES]; + + return self->lastEvent != NULL; +#endif + // And unlike wxWidgets we can't just return 1, so instead we alternate + // between such. + return (self->pendingTicker = !self->pendingTicker); }; - (void)getNextEvent { @@ -257,6 +271,8 @@ static CGPoint pointFlip(CGPoint point) { dequeue:YES])) { [self eventProcess:ev]; } + + [self sendClipboardEvent]; }; - (void)eventProcess:(NSEvent *)ev { @@ -816,6 +832,39 @@ static CGPoint pointFlip(CGPoint point) { } } +- (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)setTitle:(const char *)title { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [self->window @@ -882,6 +931,11 @@ static CGPoint pointFlip(CGPoint point) { * until 10.13.2 so I need to do this manually */ }; - (void)setClipboard:(const char *)text { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; + [pasteboard declareTypes:@[ NSPasteboardTypeString ] owner:nil]; + [pasteboard setString:@(text) forType:NSPasteboardTypeString]; + [pool release]; }; - (void)getClipboard { }; From ea046f3a52f524a9f3ff5f8aedebcfbe0d92d8bf Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 5 Mar 2026 22:41:09 -0700 Subject: [PATCH 41/94] mac: fix memory leaks somewhat. --- include/Mw/LowLevel/Cocoa.h | 2 -- src/backend/cocoa.m | 49 +++++++++++++++++-------------------- 2 files changed, 22 insertions(+), 29 deletions(-) diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index c0974d46..889cdf70 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -40,7 +40,6 @@ MwBool valid; int width; int height; - NSData *data; NSImage *image; NSBitmapImageRep *rep; } @@ -73,7 +72,6 @@ @interface MilskoCocoa : NSObject { NSApplication *application; - NSEvent *lastEvent; MwBool _forceRender; NSWindow *window; NSRect rect; diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 47e44e78..93f68d77 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -35,11 +35,11 @@ static CGPoint pointFlip(CGPoint point) { p->width = width; p->height = height; - p->data = NULL; p->image = NULL; return p; } - (void)updateWithData:(unsigned char *)_data { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [self destroy]; self->rep = @@ -53,21 +53,17 @@ static CGPoint pointFlip(CGPoint point) { colorSpaceName:NSDeviceRGBColorSpace bytesPerRow:(int)width * 4 bitsPerPixel:32]; - assert(self->rep); - self->data = [NSData dataWithBytes:[self->rep bitmapData] - length:self->width * self->height * 4]; - assert(self->data); + [self->rep retain]; self->image = [[NSImage alloc] initWithSize:NSMakeSize(width, height)]; assert(self->image); [self->image addRepresentation:self->rep]; + [self->image retain]; + [pool release]; } - (void)destroy { - if (self->data != NULL) { - [self->data dealloc]; - } if (self->image != NULL) { - [self->image dealloc]; + [self->image release]; } } - (NSImage *)image { @@ -84,6 +80,7 @@ static CGPoint pointFlip(CGPoint point) { height:(int)height handle:(MwLL)r { MilskoCocoa *c = [MilskoCocoa alloc]; + [c retain]; if (x == MwDEFAULT) { x = ([NSScreen mainScreen].frame.size.width / 2.) - (width / 2.); @@ -121,6 +118,7 @@ static CGPoint pointFlip(CGPoint point) { initWithWin:c->window]; [c->window makeKeyAndOrderFront:c->application]; + [c->window retain]; if (parent != NULL) { MilskoCocoa *p = parent->cocoa.real; @@ -149,6 +147,7 @@ static CGPoint pointFlip(CGPoint point) { - (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; @@ -180,9 +179,8 @@ static CGPoint pointFlip(CGPoint point) { [NSGraphicsContext restoreGraphicsState]; [self->view setNeedsDisplay:YES]; - - [nscolor dealloc]; } + [pool release]; }; - (void)lineWithPoints:(MwPoint *)points color:(MwLLColor)color { }; @@ -258,13 +256,9 @@ static CGPoint pointFlip(CGPoint point) { }; - (void)getNextEvent { - int i; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSEvent *ev; - if (lastEvent) { - [self eventProcess:lastEvent]; - } - while ((ev = [self->window nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode @@ -273,9 +267,11 @@ static CGPoint pointFlip(CGPoint point) { } [self sendClipboardEvent]; + [pool release]; }; - (void)eventProcess:(NSEvent *)ev { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSWindow *win = [ev window]; NSWindow *parentWindow = [self parentWindow]; MwLL h; @@ -283,11 +279,13 @@ static CGPoint pointFlip(CGPoint point) { MwLL this = self->handle.pointer; 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[0]) pointer]; @@ -756,16 +754,6 @@ static CGPoint pointFlip(CGPoint point) { // ch = tab; // break; - // case kVK_Mute: - // ch = mute; - // break; - // case kVK_VolumeDown: - // ch = volumeDown; - // break; - // case kVK_VolumeUp: - // ch = volumeUp; - // break; - // case kVK_Command: // ch = MwLLKey; // break; @@ -830,6 +818,8 @@ static CGPoint pointFlip(CGPoint point) { if (doSendEvent) { [win sendEvent:ev]; } + + [pool release]; } - (void)sendClipboardEvent { @@ -872,6 +862,7 @@ static CGPoint pointFlip(CGPoint point) { [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) { @@ -890,6 +881,7 @@ static CGPoint pointFlip(CGPoint point) { [self->view setNeedsDisplay:YES]; } + [pool release]; }; - (void)setIcon:(MwLLPixmap)pixmap { }; @@ -954,7 +946,7 @@ static CGPoint pointFlip(CGPoint point) { _rect->height = [screen frame].size.height; }; - (void)destroy { - [self->window dealloc]; + [self->window release]; } - (NSWindow *)parentWindow { @@ -1017,15 +1009,18 @@ static CGPoint pointFlip(CGPoint point) { } - (void)drawRect:(NSRect)dirtyRect { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSSize sz = self->rep.size; [super drawRect:dirtyRect]; if (!self->rep) { + [pool release]; return; } [self->rep drawInRect:NSMakeRect(0, 0, sz.width, sz.height)]; [self->rep bitmapData]; + [pool release]; } - (void)destroy { From 306f7916419317398adaf36e50ba4f8435407147 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 5 Mar 2026 22:52:25 -0700 Subject: [PATCH 42/94] mac: apple doesn't give us a reliable way to check if events are pending but we have to do the nextEventMatching trick anyways because the alternating pending implementation breaks opengl. --- include/Mw/LowLevel/Cocoa.h | 2 +- src/backend/cocoa.m | 11 ----------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index 889cdf70..58401b2e 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -79,7 +79,7 @@ MwLL parent; MilskoFakePointer *handle; NSUInteger strHash; - MwBool pendingTicker; + NSEvent *lastEvent; } + (MilskoCocoa *)newWithParent:(MwLL)parent diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 93f68d77..0f21dd38 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -236,23 +236,12 @@ static CGPoint pointFlip(CGPoint point) { _forceRender = MwFALSE; return 1; } -// Apple does not give you a reliable way to tell when events are coming. I -// found this out by accident by stumbling upon a comment wxWidget's code, -// thought I could figure out something better, and I ended up with the same -// solution they tried and can confirm it doesn't work. -// Thanks Tim Cook. -#if 0 self->lastEvent = [self->window nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES]; - return self->lastEvent != NULL; -#endif - // And unlike wxWidgets we can't just return 1, so instead we alternate - // between such. - return (self->pendingTicker = !self->pendingTicker); }; - (void)getNextEvent { From 0fde05fa03e3ff051c90a93f2278a468f2615654 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sun, 8 Mar 2026 07:06:12 +0900 Subject: [PATCH 43/94] fix some parts --- include/Mw/LowLevel.h | 8 ++++---- src/text/ft2.c | 2 +- src/text/stbtt.c | 3 +-- src/text/text.c | 4 ++-- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index dcab28d1..9766d052 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -235,14 +235,14 @@ MWDECL void (*MwLLGetClipboard)(MwLL handle); MWDECL void (*MwLLGetCursorCoord)(MwLL handle, MwPoint* point); MWDECL void (*MwLLGetScreenSize)(MwLL handle, MwRect* rect); -/*font renderer */ -MWDECL void MwFLSetup(); +/* font renderer */ +MWDECL void MwFLSetup(void); #ifdef USE_FREETYPE2 -MWDECL int MWFL_FT2Setup(); +MWDECL int MWFL_FT2Setup(void); #endif #ifdef USE_STB_TRUETYPE -MWDECL int MwFL_STBTTSetup(); +MWDECL int MwFL_STBTTSetup(void); #endif MWDECL int (*MwFLDrawText)(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color); diff --git a/src/text/ft2.c b/src/text/ft2.c index a5fb9202..c30f3da0 100644 --- a/src/text/ft2.c +++ b/src/text/ft2.c @@ -128,7 +128,7 @@ static void ft2_MwFontFree(void* handle) { free(ttf); } -int MWFL_FT2Setup() { +int MWFL_FT2Setup(void) { MwFLDrawText = ft2_MwDrawText; MwFLTextWidth = ft2_MwTextWidth; MwFLTextHeight = ft2_MwTextHeight; diff --git a/src/text/stbtt.c b/src/text/stbtt.c index fb5e783e..ab9d539c 100644 --- a/src/text/stbtt.c +++ b/src/text/stbtt.c @@ -1,5 +1,4 @@ #ifdef USE_STB_TRUETYPE -#include #include #include "../../external/stb_truetype.h" @@ -129,7 +128,7 @@ static void stbtt_MwFontFree(void* handle) { free(ttf); } -int MwFL_STBTTSetup() { +int MwFL_STBTTSetup(void) { MwFLDrawText = stbtt_MwDrawText; MwFLTextWidth = stbtt_MwTextWidth; MwFLTextHeight = stbtt_MwTextHeight; diff --git a/src/text/text.c b/src/text/text.c index e25d28b2..8d19de83 100644 --- a/src/text/text.c +++ b/src/text/text.c @@ -140,8 +140,8 @@ static void bitmap_MwDrawText(MwWidget handle, MwPoint* point, const char* text, free(px); } -typedef int (*call_t)(); -void MwFLSetup() { +typedef int (*call_t)(void); +void MwFLSetup(void) { call_t calls[] = { #ifdef USE_FREETYPE2 MWFL_FT2Setup, From 4319ea25b5b27bdbad0c8b85059c2106f691f735 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Sun, 8 Mar 2026 16:05:57 -0700 Subject: [PATCH 44/94] mac: fix a bunch of memory leaks --- include/Mw/LowLevel/Cocoa.h | 3 + src/backend/cocoa.m | 727 +++++++++++------------------------- 2 files changed, 220 insertions(+), 510 deletions(-) diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index 58401b2e..0ebe7751 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -40,6 +40,7 @@ MwBool valid; int width; int height; + unsigned char *buf; NSImage *image; NSBitmapImageRep *rep; } @@ -97,6 +98,8 @@ - (void)setW:(int)w H:(int)h; - (int)pending; - (void)eventProcess:(NSEvent *)ev; +- (void)handleKeyEvent:(NSEvent *)ev; +- (void)handleMouseEvent:(NSEvent *)ev ll:(MwLL)ll; - (void)getNextEvent; - (void)setTitle:(const char *)title; - (void)drawPixmap:(MwLLPixmap)pixmap rect:(MwRect *)rect; diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 0f21dd38..c3cfc3f8 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -1,6 +1,7 @@ #include "Mw/BaseTypes.h" #include "Mw/LowLevel.h" #include +#include #pragma clang push #pragma clang diagnostic ignored "-Wdeprecated-declarations" @@ -36,14 +37,11 @@ static CGPoint pointFlip(CGPoint point) { p->width = width; p->height = height; p->image = NULL; - return p; -} -- (void)updateWithData:(unsigned char *)_data { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - [self destroy]; - self->rep = - [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:&_data + p->buf = malloc(width * height * 4); + + p->rep = + [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:&p->buf pixelsWide:(int)width pixelsHigh:(int)height bitsPerSample:8 @@ -53,18 +51,22 @@ static CGPoint pointFlip(CGPoint point) { colorSpaceName:NSDeviceRGBColorSpace bytesPerRow:(int)width * 4 bitsPerPixel:32]; - assert(self->rep); - [self->rep retain]; - self->image = [[NSImage alloc] initWithSize:NSMakeSize(width, height)]; - assert(self->image); - [self->image addRepresentation:self->rep]; - [self->image retain]; - [pool release]; + 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); } - (void)destroy { - if (self->image != NULL) { - [self->image release]; - } + free(self->buf); + [self->image removeRepresentation:self->rep]; + [self->image dealloc]; + [self->rep dealloc]; } - (NSImage *)image { return self->image; @@ -175,6 +177,7 @@ static CGPoint pointFlip(CGPoint point) { [path closePath]; [path fill]; + [nscolor release]; [NSGraphicsContext restoreGraphicsState]; @@ -186,6 +189,7 @@ static CGPoint pointFlip(CGPoint point) { }; - (void)getX:(int *)x Y:(int *)y W:(unsigned int *)w H:(unsigned int *)h { NSRect frame = rectFlip([self->window frame]); + frame = rectFlip(frame); *x = frame.origin.x; *y = frame.origin.y; @@ -232,8 +236,11 @@ static CGPoint pointFlip(CGPoint point) { [self->window setFrame:frame display:YES animate:false]; }; - (int)pending { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + MwBool isPending = MwFALSE; if (_forceRender) { _forceRender = MwFALSE; + [pool release]; return 1; } self->lastEvent = [self->window nextEventMatchingMask:NSAnyEventMask @@ -241,11 +248,12 @@ static CGPoint pointFlip(CGPoint point) { inMode:NSDefaultRunLoopMode dequeue:YES]; - return self->lastEvent != NULL; + isPending = self->lastEvent != NULL; + [pool release]; + return isPending; }; - (void)getNextEvent { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSEvent *ev; while ((ev = [self->window nextEventMatchingMask:NSAnyEventMask @@ -253,10 +261,10 @@ static CGPoint pointFlip(CGPoint point) { inMode:NSDefaultRunLoopMode dequeue:YES])) { [self eventProcess:ev]; + [ev release]; } [self sendClipboardEvent]; - [pool release]; }; - (void)eventProcess:(NSEvent *)ev { @@ -265,7 +273,6 @@ static CGPoint pointFlip(CGPoint point) { NSWindow *parentWindow = [self parentWindow]; MwLL h; MwBool doSendEvent = MwTRUE; - MwLL this = self->handle.pointer; if (!win) { [pool release]; @@ -287,37 +294,7 @@ static CGPoint pointFlip(CGPoint point) { case NSEventTypeLeftMouseUp: case NSEventTypeRightMouseUp: case NSEventTypeOtherMouseUp: { - MwLLMouse mouse = {}; - MwBool isDown = MwTRUE; - CGPoint mousePoint = pointFlip([ev locationInWindow]); - switch (ev.type) { - case NSEventTypeLeftMouseUp: - isDown = MwFALSE; - case NSEventTypeLeftMouseDown: - mouse.button = MwLLMouseLeft; - break; - case NSEventTypeRightMouseUp: - isDown = MwFALSE; - case NSEventTypeRightMouseDown: - mouse.button = MwLLMouseRight; - break; - case NSEventTypeOtherMouseUp: - isDown = MwFALSE; - case NSEventTypeOtherMouseDown: - mouse.button = MwLLMouseMiddle; - break; - default: - break; - } - mouse.point.x = mousePoint.x; - mouse.point.y = mousePoint.y; - - if (isDown) { - MwLLDispatch(h, down, &mouse); - } else { - MwLLDispatch(h, up, &mouse); - } - break; + [self handleMouseEvent:ev ll:h]; } case NSEventTypeLeftMouseDragged: case NSEventTypeRightMouseDragged: @@ -338,464 +315,8 @@ static CGPoint pointFlip(CGPoint point) { break; case NSEventTypeKeyDown: case NSEventTypeKeyUp: { - 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_ANSI_KeypadDecimal = 0x41, - kVK_ANSI_KeypadMultiply = 0x43, - kVK_ANSI_KeypadPlus = 0x45, - kVK_ANSI_KeypadClear = 0x47, - kVK_ANSI_KeypadDivide = 0x4B, - kVK_ANSI_KeypadEnter = 0x4C, - kVK_ANSI_KeypadMinus = 0x4E, - kVK_ANSI_KeypadEquals = 0x51, - kVK_ANSI_Keypad0 = 0x52, - kVK_ANSI_Keypad1 = 0x53, - kVK_ANSI_Keypad2 = 0x54, - kVK_ANSI_Keypad3 = 0x55, - kVK_ANSI_Keypad4 = 0x56, - kVK_ANSI_Keypad5 = 0x57, - kVK_ANSI_Keypad6 = 0x58, - kVK_ANSI_Keypad7 = 0x59, - kVK_ANSI_Keypad8 = 0x5B, - kVK_ANSI_Keypad9 = 0x5C, - kVK_Return = 0x24, - kVK_Tab = 0x30, - kVK_Space = 0x31, - kVK_Delete = 0x33, - kVK_Escape = 0x35, - kVK_Command = 0x37, - kVK_Shift = 0x38, - kVK_CapsLock = 0x39, - kVK_Option = 0x3A, - kVK_Control = 0x3B, - kVK_RightCommand = 0x36, - kVK_RightShift = 0x3C, - kVK_RightOption = 0x3D, - kVK_RightControl = 0x3E, - kVK_Function = 0x3F, - kVK_F17 = 0x40, - kVK_VolumeUp = 0x48, - kVK_VolumeDown = 0x49, - kVK_Mute = 0x4A, - kVK_F18 = 0x4F, - kVK_F19 = 0x50, - kVK_F20 = 0x5A, - kVK_F5 = 0x60, - kVK_F6 = 0x61, - kVK_F7 = 0x62, - kVK_F3 = 0x63, - kVK_F8 = 0x64, - kVK_F9 = 0x65, - kVK_F11 = 0x67, - kVK_F13 = 0x69, - kVK_F16 = 0x6A, - kVK_F14 = 0x6B, - kVK_F10 = 0x6D, - kVK_F12 = 0x6F, - kVK_F15 = 0x71, - kVK_Help = 0x72, - kVK_Home = 0x73, - kVK_PageUp = 0x74, - kVK_ForwardDelete = 0x75, - kVK_F4 = 0x76, - kVK_End = 0x77, - kVK_F2 = 0x78, - kVK_PageDown = 0x79, - kVK_F1 = 0x7A, - kVK_LeftArrow = 0x7B, - kVK_RightArrow = 0x7C, - kVK_DownArrow = 0x7D, - kVK_UpArrow = 0x7E - }; - // [view.nextResponder - // interpretKeyEvents:[NSArray arrayWithObject:lastEvent]]; - switch (ev.keyCode) { - case kVK_ANSI_A: - ch = 'a'; - break; - case kVK_ANSI_B: - ch = 'b'; - break; - case kVK_ANSI_C: - ch = 'c'; - break; - case kVK_ANSI_D: - ch = 'd'; - break; - case kVK_ANSI_E: - ch = 'e'; - break; - case kVK_ANSI_F: - ch = 'f'; - break; - case kVK_ANSI_G: - ch = 'g'; - break; - case kVK_ANSI_H: - ch = 'h'; - break; - case kVK_ANSI_I: - ch = 'i'; - break; - case kVK_ANSI_J: - ch = 'j'; - break; - case kVK_ANSI_K: - ch = 'k'; - break; - case kVK_ANSI_L: - ch = 'l'; - break; - case kVK_ANSI_M: - ch = 'm'; - break; - case kVK_ANSI_N: - ch = 'n'; - break; - case kVK_ANSI_O: - ch = 'o'; - break; - case kVK_ANSI_P: - ch = 'p'; - break; - case kVK_ANSI_Q: - ch = 'q'; - break; - case kVK_ANSI_R: - ch = 'r'; - break; - case kVK_ANSI_S: - ch = 's'; - break; - case kVK_ANSI_T: - ch = 't'; - break; - case kVK_ANSI_U: - ch = 'u'; - break; - case kVK_ANSI_V: - ch = 'v'; - break; - case kVK_ANSI_W: - ch = 'w'; - break; - case kVK_ANSI_X: - ch = 'x'; - break; - case kVK_ANSI_Y: - ch = 'y'; - break; - case kVK_ANSI_Z: - ch = 'z'; - break; - case kVK_ANSI_0: - ch = '0'; - break; - case kVK_ANSI_1: - ch = '1'; - break; - case kVK_ANSI_2: - ch = '2'; - break; - case kVK_ANSI_3: - ch = '3'; - break; - case kVK_ANSI_4: - ch = '4'; - break; - case kVK_ANSI_5: - ch = '5'; - break; - case kVK_ANSI_6: - ch = '6'; - break; - case kVK_ANSI_7: - ch = '7'; - break; - case kVK_ANSI_8: - ch = '8'; - break; - case kVK_ANSI_9: - ch = '9'; - break; - - // case kVK_ANSI_Keypad0: - // ch = MwLLKey; - // break; - // case kVK_ANSI_Keypad1: - // ch = keypad1; - // break; - // case kVK_ANSI_Keypad2: - // ch = keypad2; - // break; - // case kVK_ANSI_Keypad3: - // ch = keypad3; - // break; - // case kVK_ANSI_Keypad4: - // ch = keypad4; - // break; - // case kVK_ANSI_Keypad5: - // ch = keypad5; - // break; - // case kVK_ANSI_Keypad6: - // ch = keypad6; - // break; - // case kVK_ANSI_Keypad7: - // ch = keypad7; - // break; - // case kVK_ANSI_Keypad8: - // ch = keypad8; - // break; - // case kVK_ANSI_Keypad9: - // ch = keypad9; - // break; - // case kVK_ANSI_KeypadClear: - // ch = keypadClear; - // break; - // case kVK_ANSI_KeypadDivide: - // ch = keypadDivide; - // break; - // case kVK_ANSI_KeypadEnter: - // ch = keypadEnter; - // break; - // case kVK_ANSI_KeypadEquals: - // ch = keypadEquals; - // break; - // case kVK_ANSI_KeypadMinus: - // ch = keypadMinus; - // break; - // case kVK_ANSI_KeypadPlus: - // ch = keypadPlus; - // break; - // case kVK_PageDown: - // ch = MwLLKey; - // break; - // case kVK_PageUp: - // ch = pageUp; - // break; - // case kVK_End: - // ch = end; - // break; - // case kVK_Home: - // ch = home; - // break; - - // case kVK_F1: - // ch = f1; - // break; - // case kVK_F2: - // ch = f2; - // break; - // case kVK_F3: - // ch = f3; - // break; - // case kVK_F4: - // ch = f4; - // break; - // case kVK_F5: - // ch = f5; - // break; - // case kVK_F6: - // ch = f6; - // break; - // case kVK_F7: - // ch = f7; - // break; - // case kVK_F8: - // ch = f8; - // break; - // case kVK_F9: - // ch = f9; - // break; - // case kVK_F10: - // ch = f10; - // break; - // case kVK_F11: - // ch = f11; - // break; - // case kVK_F12: - // ch = f12; - // break; - // case kVK_F13: - // ch = f13; - // break; - // case kVK_F14: - // ch = f14; - // break; - // case kVK_F15: - // ch = f15; - // break; - // case kVK_F16: - // ch = f16; - // break; - // case kVK_F17: - // ch = f17; - // break; - // case kVK_F18: - // ch = f18; - // break; - // case kVK_F19: - // ch = f19; - // break; - // case kVK_F20: - // ch = f20; - // break; - // case kVK_ANSI_KeypadDecimal: - // ch = decimal; - // break; - - case kVK_ANSI_Quote: - ch = '\"'; - break; - case kVK_ANSI_Grave: - ch = '`'; - break; - case kVK_ANSI_Backslash: - ch = '/'; - break; - case kVK_ANSI_Comma: - ch = ','; - break; - // case kVK_Delete: - // ch = delete; - // break; - // case kVK_ANSI_Equal: - // ch = equals; - // break; - case kVK_Escape: - ch = MwLLKeyEscape; - break; - // case kVK_ANSI_LeftBracket: - // ch = leftBracket; - // break; - // case kVK_ANSI_Minus: - // ch = minus; - // break; - // case kVK_ANSI_KeypadMultiply: - // ch = multiply; - // break; - // case kVK_ANSI_Period: - // ch = period; - // break; - case kVK_Return: - ch = MwLLKeyEnter; - break; - // case kVK_ANSI_RightBracket: - // ch = rightBracket; - // break; - case kVK_ANSI_Semicolon: - ch = ';'; - break; - case kVK_ANSI_Slash: - ch = '\\'; - break; - case kVK_Space: - ch = ' '; - break; - // case kVK_Tab: - // ch = tab; - // break; - - // case kVK_Command: - // ch = MwLLKey; - // break; - // case kVK_RightCommand: - // ch = rightCommand; - // break; - case kVK_Control: - ch = MwLLKeyControl; - break; - case kVK_RightControl: - ch = MwLLKeyControl; - break; - // case kVK_Function: - // ch = function; - // break; - // case kVK_Option: - // ch = option; - // break; - // case kVK_RightOption: - // ch = rightOption; - // break; - case kVK_Shift: - ch = MwLLKeyLeftShift; - break; - case kVK_RightShift: - ch = MwLLKeyRightShift; - break; - - case kVK_DownArrow: - ch = MwLLKeyDown; - break; - case kVK_LeftArrow: - ch = MwLLKeyLeft; - break; - case kVK_RightArrow: - ch = MwLLKeyRight; - break; - case kVK_UpArrow: - ch = MwLLKeyUp; - break; - } - switch (ev.type) { - case NSEventTypeKeyDown: - MwLLDispatch(this, key, &ch); - break; - case NSEventTypeKeyUp: - MwLLDispatch(this, key_released, &ch); - break; - default: - break; - } + [self handleKeyEvent:ev]; doSendEvent = MwFALSE; - break; } case NSEventTypeCursorUpdate: break; @@ -811,6 +332,178 @@ static CGPoint pointFlip(CGPoint point) { [pool release]; } +- (void)handleMouseEvent:(NSEvent *)ev ll:(MwLL)ll { + MwLLMouse mouse = {}; + MwBool isDown = MwTRUE; + CGPoint mousePoint = pointFlip([ev locationInWindow]); + switch (ev.type) { + case NSEventTypeLeftMouseUp: + isDown = MwFALSE; + case NSEventTypeLeftMouseDown: + mouse.button = MwLLMouseLeft; + break; + case NSEventTypeRightMouseUp: + isDown = MwFALSE; + case NSEventTypeRightMouseDown: + mouse.button = MwLLMouseRight; + break; + case NSEventTypeOtherMouseUp: + isDown = MwFALSE; + case NSEventTypeOtherMouseDown: + mouse.button = MwLLMouseMiddle; + break; + default: + break; + } + mouse.point.x = mousePoint.x; + mouse.point.y = mousePoint.y; + + if (isDown) { + MwLLDispatch(ll, down, &mouse); + } else { + MwLLDispatch(ll, up, &mouse); + } +} + +- (void)handleKeyEvent:(NSEvent *)ev { + 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 NSEventTypeKeyDown: + MwLLDispatch(this, key, &ch); + break; + case NSEventTypeKeyUp: + MwLLDispatch(this, key_released, &ch); + break; + default: + break; + } +} + - (void)sendClipboardEvent { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; @@ -935,7 +628,14 @@ static CGPoint pointFlip(CGPoint point) { _rect->height = [screen frame].size.height; }; - (void)destroy { + if (self->lastEvent) { + [self->lastEvent release]; + [self->lastEvent dealloc]; + } + [self->handle release]; + [self->handle dealloc]; [self->window release]; + [self->window dealloc]; } - (NSWindow *)parentWindow { @@ -1014,11 +714,16 @@ static CGPoint pointFlip(CGPoint point) { - (void)destroy { CGColorSpaceRelease(self->space); + [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; } - (void)displayRect:(NSRect)rect { @@ -1034,7 +739,7 @@ static CGPoint pointFlip(CGPoint point) { MilskoFakePointer *ptr = win.contentView.subviews[0]; MwLL h = [ptr pointer]; - // MwLLDispatch(h, resize, NULL); + MwLLDispatch(h, resize, NULL); MwLLDispatch(h, draw, NULL); } return frameSize; @@ -1188,6 +893,7 @@ static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char *data, r->cocoa.real = [MilskoCocoaPixmap newWithWidth:width height:height]; MwLLPixmapUpdate(r); + free(r->common.raw); return r; } @@ -1199,6 +905,7 @@ static void MwLLPixmapUpdateImpl(MwLLPixmap pixmap) { static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { MilskoCocoaPixmap *p = pixmap->cocoa.real; [p destroy]; + [p dealloc]; free(pixmap); } From 4549e4f75b8bc30850a643146ccfc9ab0cebead3 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Sun, 8 Mar 2026 17:07:48 -0700 Subject: [PATCH 45/94] mac: remove nscolor release call after realizing it's likely UB and crashes high sierra --- src/backend/cocoa.m | 1 - 1 file changed, 1 deletion(-) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index c3cfc3f8..8b4e61da 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -177,7 +177,6 @@ static CGPoint pointFlip(CGPoint point) { [path closePath]; [path fill]; - [nscolor release]; [NSGraphicsContext restoreGraphicsState]; From 3b78872ce80919ccf251b912177329526f9048f1 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 8 Mar 2026 18:04:37 -0700 Subject: [PATCH 46/94] mac: took a detour and got it working in 10.4, before accidentally fixing the remaining memory leak I think --- include/Mw/LowLevel/Cocoa.h | 139 ++-- src/backend/cocoa.m | 1474 ++++++++++++++++++----------------- 2 files changed, 825 insertions(+), 788 deletions(-) diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index 0ebe7751..38129e56 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -21,135 +21,136 @@ #import #endif -@interface MilskoCocoaWindowDelegate : NSObject { - NSWindow *w; +// Note: implements NSWindowDelegate +@interface MilskoCocoaWindowDelegate : NSObject { + NSWindow* w; } -- (instancetype)initWithWin:(NSWindow *)win; +- (MilskoCocoaWindowDelegate*)initWithWin:(NSWindow*)win; @end @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; } -- (NSGraphicsContext *)context; +- (NSGraphicsContext*)context; - (void)destroy; -- (NSBitmapImageRep *)getRep; +- (NSBitmapImageRep*)getRep; @end @interface MilskoCocoa : NSObject { - NSApplication *application; - MwBool _forceRender; - NSWindow *window; - NSRect rect; - MilskoCocoaView *view; - MwLL parent; - MilskoFakePointer *handle; - NSUInteger strHash; - NSEvent *lastEvent; + NSApplication* application; + MwBool _forceRender; + NSWindow* window; + NSRect rect; + MilskoCocoaView* view; + MwLL parent; + MilskoFakePointer* handle; + unsigned int strHash; + NSEvent* lastEvent; } -+ (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; -- (void)handleMouseEvent:(NSEvent *)ev ll:(MwLL)ll; +- (void)eventProcess:(NSEvent*)ev; +- (void)handleKeyEvent:(NSEvent*)ev; +- (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; -- (NSWindow *)parentWindow; -- (NSView *)getView; -- (NSWindow *)getWindow; -- (MilskoFakePointer *)getHandle; +- (NSWindow*)parentWindow; +- (NSView*)getView; +- (NSWindow*)getWindow; +- (MilskoFakePointer*)getHandle; @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/src/backend/cocoa.m b/src/backend/cocoa.m index 8b4e61da..af486249 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -1,778 +1,800 @@ -#include "Mw/BaseTypes.h" -#include "Mw/LowLevel.h" #include #include +#ifdef __clang__ #pragma clang push #pragma clang diagnostic ignored "-Wdeprecated-declarations" +#endif -static CGRect rectFlip(CGRect originFrame) { - NSScreen *zeroScreen = NSScreen.screens[0]; - double screenHeight = zeroScreen.frame.size.height; - double originY = originFrame.origin.y; - double frameHeight = originFrame.size.height; - double destinationY = screenHeight - (originY + frameHeight); - CGRect destinationFrame = originFrame; - destinationFrame.origin.y = destinationY; - if (destinationFrame.origin.x < 0) - destinationFrame.origin.x = 0; - if (destinationFrame.origin.y < 0) - destinationFrame.origin.y = 0; - if (destinationFrame.size.width < 0) - destinationFrame.size.width = 0; - if (destinationFrame.size.height < 0) - destinationFrame.size.height = 0; - return destinationFrame; +static NSRect rectFlip(NSRect originFrame) { + NSScreen* zeroScreen = [[NSScreen screens] objectAtIndex:0]; + double screenHeight = [zeroScreen frame].size.height; + double originY = originFrame.origin.y; + double frameHeight = originFrame.size.height; + double destinationY = screenHeight - (originY + frameHeight); + NSRect destinationFrame = originFrame; + destinationFrame.origin.y = destinationY; + if(destinationFrame.origin.x < 0) + destinationFrame.origin.x = 0; + if(destinationFrame.origin.y < 0) + destinationFrame.origin.y = 0; + if(destinationFrame.size.width < 0) + destinationFrame.size.width = 0; + if(destinationFrame.size.height < 0) + destinationFrame.size.height = 0; + return destinationFrame; } -static CGPoint pointFlip(CGPoint point) { - return rectFlip(NSMakeRect(point.x, point.y, 0, 0)).origin; +static NSPoint pointFlip(NSPoint point) { + return rectFlip(NSMakeRect(point.x, point.y, 0, 0)).origin; } @implementation MilskoCocoaPixmap -+ (MilskoCocoaPixmap *)newWithWidth:(int)width height:(int)height { - MilskoCocoaPixmap *p = [MilskoCocoaPixmap alloc]; ++ (MilskoCocoaPixmap*)newWithWidth:(int)width height:(int)height { + MilskoCocoaPixmap* p = [MilskoCocoaPixmap alloc]; - p->width = width; - p->height = height; - p->image = NULL; + p->width = width; + p->height = height; + p->image = NULL; - p->buf = malloc(width * height * 4); + 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->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]; + p->image = [[NSImage alloc] initWithSize:NSMakeSize(width, height)]; + assert(p->image); + [p->image addRepresentation:p->rep]; - return p; + return p; } -- (void)updateWithData:(unsigned char *)_data { - memcpy(self->buf, _data, width * height * 4); +- (void)updateWithData:(unsigned char*)_data { + memcpy(self->buf, _data, width * height * 4); } - (void)destroy { - free(self->buf); - [self->image removeRepresentation:self->rep]; - [self->image dealloc]; - [self->rep dealloc]; + free(self->buf); + [self->image removeRepresentation:self->rep]; + [self->image dealloc]; + [self->rep dealloc]; } -- (NSImage *)image { - return self->image; +- (NSImage*)image { + return self->image; } @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]; - [c retain]; ++ (MilskoCocoa*)newWithParent:(MwLL)parent + x:(int)x + y:(int)y + width:(int)width + height:(int)height + handle:(MwLL)r { + MilskoCocoa* c = [MilskoCocoa alloc]; + [c retain]; - if (x == MwDEFAULT) { - x = ([NSScreen mainScreen].frame.size.width / 2.) - (width / 2.); - } - if (y == MwDEFAULT) { - y = ([NSScreen mainScreen].frame.size.height / 2.) - (height / 2.); - } - c->application = [NSApplication sharedApplication]; - c->rect = rectFlip(NSMakeRect(x, y, width, height)); + if(x == MwDEFAULT) { + x = ([[NSScreen mainScreen] frame].size.width / 2.) - (width / 2.); + } + if(y == MwDEFAULT) { + y = ([[NSScreen mainScreen] frame].size.height / 2.) - (height / 2.); + } + c->application = [NSApplication sharedApplication]; + c->rect = rectFlip(NSMakeRect(x, y, width, height)); - if (parent == NULL) { - c->window = [[NSWindow alloc] - initWithContentRect:c->rect - styleMask:(NSTitledWindowMask | NSClosableWindowMask | - NSMiniaturizableWindowMask | NSResizableWindowMask) - backing:NSBackingStoreBuffered - defer:NO]; - } else { - double offset = 0; - NSWindow *parentWindow = parent->cocoa.real->window; - offset = - [parentWindow frameRectForContentRect:parentWindow.frame].size.height - - [parentWindow contentRectForFrameRect:parentWindow.frame].size.height; + if(parent == NULL) { + c->window = [[NSWindow alloc] + initWithContentRect:c->rect + styleMask:(NSTitledWindowMask | NSClosableWindowMask | + NSMiniaturizableWindowMask | NSResizableWindowMask) + backing:NSBackingStoreBuffered + defer:NO]; + } else { + double offset = 0; + NSWindow* parentWindow = parent->cocoa.real->window; + offset = + [parentWindow frameRectForContentRect:[parentWindow frame]].size.height - + [parentWindow contentRectForFrameRect:[parentWindow frame]].size.height; - c->rect.origin.x += parentWindow.frame.origin.x; - c->rect.origin.y -= parentWindow.frame.origin.y - offset; - c->rect.origin.y -= offset; + c->rect.origin.x += [parentWindow frame].origin.x; + c->rect.origin.y -= [parentWindow frame].origin.y - offset; + c->rect.origin.y -= offset; - c->window = [[NSWindow alloc] initWithContentRect:c->rect - styleMask:NSBorderlessWindowMask - backing:NSBackingStoreBuffered - defer:NO]; - } - c->window.delegate = (id)[[MilskoCocoaWindowDelegate alloc] - initWithWin:c->window]; + c->window = [[NSWindow alloc] initWithContentRect:c->rect + styleMask:NSBorderlessWindowMask + backing:NSBackingStoreBuffered + defer:NO]; + } + [c->window setDelegate:[[MilskoCocoaWindowDelegate alloc] + initWithWin:c->window]]; - [c->window makeKeyAndOrderFront:c->application]; - [c->window retain]; + [c->window makeKeyAndOrderFront:c->application]; + [c->window retain]; - if (parent != NULL) { - MilskoCocoa *p = parent->cocoa.real; - [p->window addChildWindow:c->window ordered:NSWindowAbove]; - [c->window setHasShadow:MwFALSE]; - } else { - [c->application setActivationPolicy:NSApplicationActivationPolicyRegular]; - [c->application activateIgnoringOtherApps:true]; - [c->window makeFirstResponder:c->view]; - } + if(parent != NULL) { + MilskoCocoa* p = parent->cocoa.real; + [p->window addChildWindow:c->window ordered:NSWindowAbove]; + [c->window setHasShadow:MwFALSE]; + } else { + [c->application activateIgnoringOtherApps:true]; + [c->window makeFirstResponder:c->view]; + } - c->view = [[MilskoCocoaView alloc] initWithFrame:c->rect]; - c->handle = [[MilskoFakePointer alloc] initWithFrame:NSMakeRect(0, 0, 1, 1)]; - [c->handle setPointer:r]; - [c->view addSubview:c->handle]; + c->view = [[MilskoCocoaView alloc] initWithFrame:c->rect]; + [c->view retain]; + c->handle = [[MilskoFakePointer alloc] initWithFrame:NSMakeRect(0, 0, 1, 1)]; + [c->handle retain]; + [c->handle setPointer:r]; + [c->view addSubview:c->handle]; - [c->window setContentView:c->view]; + [c->window setContentView:c->view]; - c->parent = parent; + c->parent = parent; - c->_forceRender = MwTRUE; - c->strHash = 0; + c->_forceRender = MwTRUE; + c->strHash = 0; - return c; + 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]; - NSColor *nscolor = [NSColor colorWithRed:color->common.red / 255. - green:color->common.green / 255. - blue:color->common.blue / 255. - alpha:1.0]; +- (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]; + 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]; + [NSGraphicsContext saveGraphicsState]; + [NSGraphicsContext setCurrentContext:ctx]; - [nscolor setFill]; - for (i = 0; i < points_count; i++) { - if (i == 0) { - [path moveToPoint:NSMakePoint(points[i].x, - [self->window frame].size.height - - points[i].y)]; - } else { - [path lineToPoint:NSMakePoint(points[i].x, - [self->window frame].size.height - - points[i].y)]; - } - } + [nscolor setFill]; + for(i = 0; i < points_count; i++) { + if(i == 0) { + [path moveToPoint:NSMakePoint(points[i].x, + [self->window frame].size.height - + points[i].y)]; + } else { + [path lineToPoint:NSMakePoint(points[i].x, + [self->window frame].size.height - + points[i].y)]; + } + } - [path closePath]; - [path fill]; + [path closePath]; + [path fill]; - [NSGraphicsContext restoreGraphicsState]; + [NSGraphicsContext restoreGraphicsState]; - [self->view setNeedsDisplay:YES]; - } - [pool release]; + [self->view setNeedsDisplay:YES]; + } + [pool release]; }; -- (void)lineWithPoints:(MwPoint *)points color:(MwLLColor)color { +- (void)lineWithPoints:(MwPoint*)points color:(MwLLColor)color { + (void)points; + (void)color; }; -- (void)getX:(int *)x Y:(int *)y W:(unsigned int *)w H:(unsigned int *)h { - NSRect frame = rectFlip([self->window frame]); - frame = rectFlip(frame); +- (void)getX:(int*)x Y:(int*)y W:(unsigned int*)w H:(unsigned int*)h { + NSRect frame = rectFlip([self->window frame]); + frame = rectFlip(frame); - *x = frame.origin.x; - *y = frame.origin.y; + *x = frame.origin.x; + *y = frame.origin.y; - *w = frame.size.width; - *h = frame.size.height; + *w = frame.size.width; + *h = frame.size.height; }; - (void)setX:(int)x Y:(int)y { - NSRect frame = [self->window frame]; + NSRect frame = [self->window frame]; - frame.origin.x = x; - frame.origin.y = y; + frame.origin.x = x; + frame.origin.y = y; - frame = rectFlip(frame); + frame = rectFlip(frame); - if (parent) { - double offset = 0; - NSWindow *parentWindow = parent->cocoa.real->window; - offset = - [parentWindow frameRectForContentRect:parentWindow.frame].size.height - - [parentWindow contentRectForFrameRect:parentWindow.frame].size.height; + if(parent) { + double offset = 0; + NSWindow* parentWindow = parent->cocoa.real->window; + offset = + [parentWindow frameRectForContentRect:[parentWindow frame]].size.height - + [parentWindow contentRectForFrameRect:[parentWindow frame]].size.height; - if (x < parentWindow.frame.origin.x) { - frame.origin.x += parentWindow.frame.origin.x; - } + if(x < [parentWindow frame].origin.x) { + frame.origin.x += [parentWindow frame].origin.x; + } - if (y < parentWindow.frame.origin.y) { - frame.origin.y -= parentWindow.frame.origin.y - offset; - frame.origin.y -= offset; - } - } - [self->view setFrameSize:frame.size]; + frame.origin.y -= [parentWindow frame].origin.y - offset; + frame.origin.y -= offset; + } + [self->view setFrameSize:frame.size]; - [self->window setFrame:frame display:YES animate:false]; + [self->window setFrame:frame display:YES animate:false]; }; - (void)setW:(int)w H:(int)h { - NSRect frame = [self->window frame]; - frame.size.width = w; - frame.size.height = h; + NSRect frame = [self->window frame]; + frame.size.width = w; + frame.size.height = h; - self->rect = frame; + self->rect = frame; - [self->view setFrameSize:frame.size]; - [self->window setFrame:frame display:YES animate:false]; + [self->view setFrameSize:frame.size]; + [self->window setFrame:frame display:YES animate:false]; }; - (int)pending { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - MwBool isPending = MwFALSE; - if (_forceRender) { - _forceRender = MwFALSE; - [pool release]; - return 1; - } - self->lastEvent = [self->window nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantPast] - inMode:NSDefaultRunLoopMode - dequeue:YES]; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + MwBool isPending = MwFALSE; + if(_forceRender) { + _forceRender = MwFALSE; + [pool release]; + return 1; + } + self->lastEvent = [self->window nextEventMatchingMask:NSAnyEventMask + untilDate:[NSDate distantPast] + inMode:NSDefaultRunLoopMode + dequeue:YES]; - isPending = self->lastEvent != NULL; - [pool release]; - return isPending; + isPending = self->lastEvent != NULL; + [pool release]; + return isPending; }; - (void)getNextEvent { - NSEvent *ev; - while ((ev = [self->window nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantPast] - inMode:NSDefaultRunLoopMode - dequeue:YES])) { - [self eventProcess:ev]; - [ev release]; - } + while(true) { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSEvent* ev = [self->window nextEventMatchingMask:NSAnyEventMask + untilDate:[NSDate distantPast] + inMode:NSDefaultRunLoopMode + dequeue:YES]; + if(!ev) { + [pool release]; + break; + } + [self eventProcess:ev]; + [pool release]; + } - [self sendClipboardEvent]; + [self sendClipboardEvent]; }; -- (void)eventProcess:(NSEvent *)ev { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSWindow *win = [ev window]; - NSWindow *parentWindow = [self parentWindow]; - MwLL h; - MwBool doSendEvent = MwTRUE; +- (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) { + [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[0]) pointer]; - } + 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 NSEventTypeLeftMouseDown: - case NSEventTypeRightMouseDown: - case NSEventTypeOtherMouseDown: - case NSEventTypeLeftMouseUp: - case NSEventTypeRightMouseUp: - case NSEventTypeOtherMouseUp: { - [self handleMouseEvent:ev ll:h]; - } - case NSEventTypeLeftMouseDragged: - case NSEventTypeRightMouseDragged: - case NSEventTypeOtherMouseDragged: - case NSEventTypeMouseMoved: { - MwPoint pos; - pos.x = [ev locationInWindow].x; - pos.y = [win contentRectForFrameRect:win.frame].size.height - - [ev locationInWindow].y; - MwLLDispatch(h, move, &pos); - break; - } - case NSEventTypeMouseEntered: - MwLLDispatch(h, focus_in, NULL); - break; - case NSEventTypeMouseExited: - MwLLDispatch(h, focus_out, NULL); - break; - case NSEventTypeKeyDown: - case NSEventTypeKeyUp: { - [self handleKeyEvent:ev]; - doSendEvent = MwFALSE; - } - case NSEventTypeCursorUpdate: - break; - case NSEventTypeScrollWheel: - break; - default: - break; - }; - if (doSendEvent) { - [win sendEvent:ev]; - } + switch([ev type]) { + case NSLeftMouseDown: + case NSRightMouseDown: + case NSOtherMouseDown: + case NSLeftMouseUp: + case NSRightMouseUp: + case NSOtherMouseUp: { + [self handleMouseEvent:ev ll:h]; + } + case NSLeftMouseDragged: + case NSRightMouseDragged: + case NSOtherMouseDragged: + case NSMouseMoved: { + MwPoint pos; + pos.x = [ev locationInWindow].x; + pos.y = [win contentRectForFrameRect:[win frame]].size.height - + [ev locationInWindow].y; + MwLLDispatch(h, move, &pos); + break; + } + case NSMouseEntered: + MwLLDispatch(h, focus_in, NULL); + break; + case NSMouseExited: + MwLLDispatch(h, focus_out, NULL); + break; + case NSKeyDown: + case NSKeyUp: { + [self handleKeyEvent:ev]; + doSendEvent = MwFALSE; + } + case NSCursorUpdate: + break; + case NSScrollWheel: + break; + default: + break; + }; + if(doSendEvent) { + [win sendEvent:ev]; + } - [pool release]; + [pool release]; } -- (void)handleMouseEvent:(NSEvent *)ev ll:(MwLL)ll { - MwLLMouse mouse = {}; - MwBool isDown = MwTRUE; - CGPoint mousePoint = pointFlip([ev locationInWindow]); - switch (ev.type) { - case NSEventTypeLeftMouseUp: - isDown = MwFALSE; - case NSEventTypeLeftMouseDown: - mouse.button = MwLLMouseLeft; - break; - case NSEventTypeRightMouseUp: - isDown = MwFALSE; - case NSEventTypeRightMouseDown: - mouse.button = MwLLMouseRight; - break; - case NSEventTypeOtherMouseUp: - isDown = MwFALSE; - case NSEventTypeOtherMouseDown: - mouse.button = MwLLMouseMiddle; - break; - default: - break; - } - mouse.point.x = mousePoint.x; - mouse.point.y = mousePoint.y; +- (void)handleMouseEvent:(NSEvent*)ev ll:(MwLL)ll { + MwLLMouse mouse; + MwBool isDown = MwTRUE; + NSPoint mousePoint = pointFlip([ev locationInWindow]); + switch([ev type]) { + case NSLeftMouseUp: + isDown = MwFALSE; + case NSLeftMouseDown: + mouse.button = MwLLMouseLeft; + break; + case NSRightMouseUp: + isDown = MwFALSE; + case NSRightMouseDown: + mouse.button = MwLLMouseRight; + break; + case NSOtherMouseUp: + isDown = MwFALSE; + case NSOtherMouseDown: + mouse.button = MwLLMouseMiddle; + break; + default: + break; + } + mouse.point.x = mousePoint.x; + mouse.point.y = mousePoint.y; - if (isDown) { - MwLLDispatch(ll, down, &mouse); - } else { - MwLLDispatch(ll, up, &mouse); - } + if(isDown) { + MwLLDispatch(ll, down, &mouse); + } else { + MwLLDispatch(ll, up, &mouse); + } } -- (void)handleKeyEvent:(NSEvent *)ev { - 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 NSEventTypeKeyDown: - MwLLDispatch(this, key, &ch); - break; - case NSEventTypeKeyUp: - MwLLDispatch(this, key_released, &ch); - break; - default: - break; - } +- (void)handleKeyEvent:(NSEvent*)ev { + 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); + break; + case NSKeyUp: + MwLLDispatch(this, key_released, &ch); + break; + default: + break; + } } - (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; + /*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]; - } - } - } - } + 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]; + [pool release];*/ } -- (void)setTitle:(const char *)title { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - [self->window - setTitleWithRepresentedFilename:[NSString stringWithUTF8String:title]]; - [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]; +- (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:NSMakeRect(_rect->x, _rect->y, _rect->width, - _rect->height) - fromRect:NSZeroRect - operation:NSCompositeSourceOver - fraction:1.0 - respectFlipped:NO - hints:nil]; + [[p image] drawInRect:NSMakeRect(_rect->x, _rect->y, _rect->width, + _rect->height) + fromRect:NSZeroRect + operation:NSCompositeSourceOver + fraction:1.0]; - [NSGraphicsContext restoreGraphicsState]; + [NSGraphicsContext restoreGraphicsState]; - [self->view setNeedsDisplay:YES]; - } - [pool release]; + [self->view setNeedsDisplay:YES]; + } + [pool release]; }; - (void)setIcon:(MwLLPixmap)pixmap { + (void)pixmap; }; - (void)forceRender { - _forceRender = MwTRUE; + _forceRender = MwTRUE; }; -- (void)setCursor:(MwCursor *)image mask:(MwCursor *)mask { +- (void)setCursor:(MwCursor*)image mask:(MwCursor*)mask { + (void)image; + (void)mask; }; -- (void)detachWithPoint:(MwPoint *)point { +- (void)detachWithPoint:(MwPoint*)point { + (void)point; }; - (void)show:(int)show { + (void)show; }; -- (void)makePopupWithParent:(MwLL)parent { +- (void)makePopupWithParent:(MwLL)_parent { + (void)_parent; }; - (void)setSizeHintsWithMinX:(int)minx - MinY:(int)miny - MaxX:(int)maxx - MaxY:(int)maxy { + MinY:(int)miny + MaxX:(int)maxx + MaxY:(int)maxy { + (void)minx; + (void)miny; + (void)maxx; + (void)maxy; }; - (void)makeBorderless:(int)toggle { - MwU32 mask = [self->window styleMask]; - if (mask & NSBorderlessWindowMask) { - mask ^= NSBorderlessWindowMask; - mask |= NSTitledWindowMask; - } else { - mask |= NSBorderlessWindowMask; - mask ^= NSTitledWindowMask; - } - [self->window initWithContentRect:self->rect - styleMask:mask - backing:NSBackingStoreBuffered - defer:NO]; + 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]; + [self->window makeMainWindow]; }; - (void)grabPointer:(int)toggle { - /* MacOS didn't have a "pointer grab" function - * until 10.13.2 so I need to do this manually */ + (void)toggle; + /* MacOS didn't have a "pointer grab" function + * until 10.13.2 so I need to do this manually */ }; -- (void)setClipboard:(const char *)text { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; - [pasteboard declareTypes:@[ NSPasteboardTypeString ] owner:nil]; - [pasteboard setString:@(text) forType:NSPasteboardTypeString]; - [pool release]; +- (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)getClipboard { }; - (void)makeToolWindow { }; -- (void)getCursorCoord:(MwPoint *)point { - NSPoint p = [NSEvent mouseLocation]; - point->x = p.x; - point->y = p.y; +- (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)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 { - if (self->lastEvent) { - [self->lastEvent release]; - [self->lastEvent dealloc]; - } - [self->handle release]; - [self->handle dealloc]; - [self->window release]; - [self->window dealloc]; + if(self->lastEvent) { + [self->lastEvent release]; + [self->lastEvent dealloc]; + } + [self->handle release]; + [self->handle dealloc]; + [self->window release]; + [self->window dealloc]; } -- (NSWindow *)parentWindow { - NSWindow *topmostWindow = self->window; - while (topmostWindow.parentWindow) - topmostWindow = topmostWindow.parentWindow; - return topmostWindow; +- (NSWindow*)parentWindow { + NSWindow* topmostWindow = self->window; + while([topmostWindow parentWindow]) + topmostWindow = [topmostWindow parentWindow]; + return topmostWindow; } -- (NSView *)getView { - return view; +- (NSView*)getView { + return view; } -- (NSWindow *)getWindow { - return window; +- (NSWindow*)getWindow { + return window; } -- (MilskoFakePointer *)getHandle { - return handle; +- (MilskoFakePointer*)getHandle { + return handle; } @end @implementation MilskoCocoaView - (id)initWithFrame:(NSRect)frame { - width = frame.size.width; - height = frame.size.height; - self = [super initWithFrame:frame]; - self->space = CGColorSpaceCreateDeviceRGB(); + width = frame.size.width; + height = frame.size.height; + self = [super initWithFrame:frame]; + self->space = CGColorSpaceCreateDeviceRGB(); - if (width == 0 || height == 0) { - self->rep = NULL; - self->context = NULL; - } else { - self->rep = - [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL - pixelsWide:width - pixelsHigh:height - bitsPerSample:8 - samplesPerPixel:4 - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSDeviceRGBColorSpace - bytesPerRow:width * 4 - bitsPerPixel:32]; - assert(self->rep); + if(width == 0 || height == 0) { + self->rep = NULL; + self->context = NULL; + } else { + self->rep = + [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL + pixelsWide:width + pixelsHigh:height + bitsPerSample:8 + samplesPerPixel:4 + hasAlpha:YES + isPlanar:NO + colorSpaceName:NSDeviceRGBColorSpace + bytesPerRow:width * 4 + bitsPerPixel:32]; + assert(self->rep); + [self->rep retain]; - self->context = - [NSGraphicsContext graphicsContextWithBitmapImageRep:self->rep]; - assert(self->context); - } + self->context = + [NSGraphicsContext graphicsContextWithBitmapImageRep:self->rep]; + assert(self->context); + [self->context retain]; + } - return self; + return self; } -- (NSGraphicsContext *)context { - return self->context; +- (NSGraphicsContext*)context { + return self->context; } -- (NSBitmapImageRep *)getRep { - return self->rep; +- (NSBitmapImageRep*)getRep { + return self->rep; } - (void)drawRect:(NSRect)dirtyRect { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSSize sz = self->rep.size; - [super drawRect:dirtyRect]; - if (!self->rep) { - [pool release]; - return; - } + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSSize sz = [self->rep size]; + [super drawRect:dirtyRect]; + if(!self->rep) { + [pool release]; + return; + } - [self->rep drawInRect:NSMakeRect(0, 0, sz.width, sz.height)]; + [self->rep drawInRect:NSMakeRect(0, 0, sz.width, sz.height)]; - [self->rep bitmapData]; - [pool release]; + [self->rep bitmapData]; + [pool release]; } - (void)destroy { - CGColorSpaceRelease(self->space); - [self->rep release]; - [self->context release]; + CGColorSpaceRelease(self->space); + [self->rep release]; + [self->context release]; } - (void)setFrameSize:(NSSize)newSize { - [super setFrameSize:newSize]; - [self->rep setSize:newSize]; + [super setFrameSize:newSize]; + [self->rep setSize:newSize]; - self->width = newSize.width; - self->height = newSize.height; + self->width = newSize.width; + self->height = newSize.height; } - (void)displayRect:(NSRect)rect { + (void)rect; }; @end @implementation MilskoCocoaWindowDelegate -- (NSSize)windowWillResize:(NSWindow *)win toSize:(NSSize)frameSize; +- (NSSize)windowWillResize:(NSWindow*)win toSize:(NSSize)frameSize; { - if (win.contentView.subviews.count >= 1) { - MilskoFakePointer *ptr = win.contentView.subviews[0]; - MwLL h = [ptr pointer]; + 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); - } - return frameSize; + // MwLLDispatch(h, resize, NULL); + MwLLDispatch(h, draw, NULL); + } + return frameSize; } -- (void)windowDidResize:(NSNotification *)notification { +- (void)windowDidResize:(NSNotification*)notification { + (void)notification; } // This will close/terminate the application when the main window is closed. -- (void)windowWillClose:(NSNotification *)notification { - // MilskoCocoa *window = notification.object; - // MwLL handle = [window getHandle].pointer; - // MwLLDispatch(handle, close, NULL); - [NSApp terminate:nil]; +- (void)windowWillClose:(NSNotification*)notification { + (void)notification; + // MilskoCocoa *window = notification.object; + // MwLL handle = [window getHandle].pointer; + // MwLLDispatch(handle, close, NULL); + [NSApp terminate:nil]; } -- (instancetype)initWithWin:(NSWindow *)win { - self->w = win; - return self; +- (MilskoCocoaWindowDelegate*)initWithWin:(NSWindow*)win { + self->w = win; + return self; } @end @implementation MilskoFakePointer -- (void)setPointer:(void *)pointer { - self.frame = *(NSRect *)&pointer; - self->ptr = pointer; +- (void)setPointer:(void*)pointer { + [self setFrame:*(NSRect*)&pointer]; + self->ptr = pointer; }; -- (void *)pointer { - return self->ptr; +- (void*)pointer { + return self->ptr; }; - (void)drawRect:(NSRect)dirtyRect { - /* explicitly do nothing */ + /* explicitly do nothing */ + (void)dirtyRect; } - (void)destroy { @@ -780,219 +802,233 @@ static CGPoint pointFlip(CGPoint point) { @end static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { - MwLL r; - (void)x; - (void)y; - (void)width; - (void)height; + MwLL r; + (void)x; + (void)y; + (void)width; + (void)height; - r = malloc(sizeof(*r)); + r = malloc(sizeof(*r)); - MwLLCreateCommon(r); + MwLLCreateCommon(r); - MilskoCocoa *o = [MilskoCocoa newWithParent:parent - x:x - y:y - width:width - height:height - handle:r]; - r->cocoa.real = o; + MilskoCocoa* o = [MilskoCocoa newWithParent:parent + x:x + y:y + width:width + height:height + handle:r]; + r->cocoa.real = o; - return r; + return r; } static void MwLLDestroyImpl(MwLL handle) { - MilskoCocoa *h = handle->cocoa.real; + MilskoCocoa* h = handle->cocoa.real; - [h destroy]; + [h destroy]; - MwLLDestroyCommon(handle); + MwLLDestroyCommon(handle); - free(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) { - MilskoCocoa *h = handle->cocoa.real; - [h polygonWithPoints:points points_count:points_count color:color]; +static void MwLLBeginDrawImpl(MwLL handle) { + (void)handle; } -static void MwLLLineImpl(MwLL handle, MwPoint *points, MwLLColor color) { - MilskoCocoa *h = handle->cocoa.real; - [h lineWithPoints:points color:color]; +static void MwLLEndDrawImpl(MwLL handle) { + (void)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]; +} + +static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { + MilskoCocoa* h = handle->cocoa.real; + [h lineWithPoints:points color: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; + MwLLColor c = malloc(sizeof(*c)); + MwLLColorUpdate(handle, c, r, g, b); + return c; } static void MwLLColorUpdateImpl(MwLL handle, MwLLColor c, int r, int g, int b) { - (void)handle; + (void)handle; - c->common.red = r; - c->common.green = g; - c->common.blue = 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 *height) { - MilskoCocoa *h = handle->cocoa.real; - [h getX:x Y:y W:w H:height]; +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]; } static void MwLLSetXYImpl(MwLL handle, int x, int y) { - MilskoCocoa *h = handle->cocoa.real; - [h setX:x Y:y]; + MilskoCocoa* h = handle->cocoa.real; + [h setX:x Y:y]; } static void MwLLSetWHImpl(MwLL handle, int w, int height) { - MilskoCocoa *h = handle->cocoa.real; - [h setW:w H:height]; + MilskoCocoa* h = handle->cocoa.real; + [h setW:w H:height]; } -static void MwLLFreeColorImpl(MwLLColor color) { free(color); } +static void MwLLFreeColorImpl(MwLLColor color) { + free(color); +} static int MwLLPendingImpl(MwLL handle) { - MilskoCocoa *h = handle->cocoa.real; - if ([h pending]) { - MwLLDispatch(handle, draw, NULL); - return 1; - }; - return 0; + MilskoCocoa* h = handle->cocoa.real; + if([h pending]) { + MwLLDispatch(handle, draw, NULL); + return 1; + }; + return 0; } static void MwLLNextEventImpl(MwLL handle) { - MilskoCocoa *h = handle->cocoa.real; - [h getNextEvent]; + MilskoCocoa* h = handle->cocoa.real; + [h getNextEvent]; } -static void MwLLSetTitleImpl(MwLL handle, const char *title) { - MilskoCocoa *h = handle->cocoa.real; - [h setTitle:title]; +static void MwLLSetTitleImpl(MwLL handle, const char* title) { + MilskoCocoa* h = handle->cocoa.real; + [h setTitle:title]; } -static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char *data, - int width, int height) { - (void)handle; +static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, + int width, int height) { + (void)handle; - MwLLPixmap r = malloc(sizeof(*r)); + MwLLPixmap r = malloc(sizeof(*r)); - r->common.raw = malloc(4 * width * height); - memcpy(r->common.raw, data, 4 * width * height); + r->common.raw = malloc(4 * width * height); + memcpy(r->common.raw, data, 4 * width * height); - r->common.width = width; - r->common.height = height; + r->common.width = width; + r->common.height = height; - r->cocoa.real = [MilskoCocoaPixmap newWithWidth:width height:height]; + r->cocoa.real = [MilskoCocoaPixmap newWithWidth:width height:height]; - MwLLPixmapUpdate(r); - free(r->common.raw); - return r; + MwLLPixmapUpdate(r); + free(r->common.raw); + return r; } static void MwLLPixmapUpdateImpl(MwLLPixmap pixmap) { - MilskoCocoaPixmap *p = pixmap->cocoa.real; - [p updateWithData:pixmap->common.raw]; + MilskoCocoaPixmap* p = pixmap->cocoa.real; + [p updateWithData:pixmap->common.raw]; } static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { - MilskoCocoaPixmap *p = pixmap->cocoa.real; - [p destroy]; - [p dealloc]; - free(pixmap); + MilskoCocoaPixmap* p = pixmap->cocoa.real; + [p destroy]; + [p dealloc]; + free(pixmap); } -static void MwLLDrawPixmapImpl(MwLL handle, MwRect *rect, MwLLPixmap pixmap) { - MilskoCocoa *h = handle->cocoa.real; - [h drawPixmap:pixmap rect:rect]; - MwLLForceRender(handle); +static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { + MilskoCocoa* h = handle->cocoa.real; + [h drawPixmap:pixmap rect:rect]; + MwLLForceRender(handle); } static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { - MilskoCocoa *h = handle->cocoa.real; - [h setIcon:pixmap]; + MilskoCocoa* h = handle->cocoa.real; + [h setIcon:pixmap]; } static void MwLLForceRenderImpl(MwLL handle) { - MilskoCocoa *h = handle->cocoa.real; - [h forceRender]; + MilskoCocoa* h = handle->cocoa.real; + [h forceRender]; } -static void MwLLSetCursorImpl(MwLL handle, MwCursor *image, MwCursor *mask) { - MilskoCocoa *h = handle->cocoa.real; - [h setCursor:image mask:mask]; +static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { + MilskoCocoa* h = handle->cocoa.real; + [h setCursor:image mask:mask]; } -static void MwLLDetachImpl(MwLL handle, MwPoint *point) { - MilskoCocoa *h = handle->cocoa.real; - [h detachWithPoint:point]; +static void MwLLDetachImpl(MwLL handle, MwPoint* point) { + MilskoCocoa* h = handle->cocoa.real; + [h detachWithPoint:point]; } static void MwLLShowImpl(MwLL handle, int show) { - MilskoCocoa *h = handle->cocoa.real; - [h show:show]; + MilskoCocoa* h = handle->cocoa.real; + [h show:show]; } static void MwLLMakePopupImpl(MwLL handle, MwLL parent) { - MilskoCocoa *h = handle->cocoa.real; - [h makePopupWithParent:parent]; + MilskoCocoa* h = handle->cocoa.real; + [h 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]; + int maxy) { + MilskoCocoa* h = handle->cocoa.real; + [h setSizeHintsWithMinX:minx MinY:miny MaxX:maxx MaxY:maxy]; } static void MwLLMakeBorderlessImpl(MwLL handle, int toggle) { - MilskoCocoa *h = handle->cocoa.real; - [h makeBorderless:toggle]; + MilskoCocoa* h = handle->cocoa.real; + [h makeBorderless:toggle]; } static void MwLLFocusImpl(MwLL handle) { - MilskoCocoa *h = handle->cocoa.real; - [h focus]; + MilskoCocoa* h = handle->cocoa.real; + [h focus]; } static void MwLLGrabPointerImpl(MwLL handle, int toggle) { - MilskoCocoa *h = handle->cocoa.real; - [h grabPointer:toggle]; + MilskoCocoa* h = handle->cocoa.real; + [h grabPointer:toggle]; } -static void MwLLSetClipboardImpl(MwLL handle, const char *text) { - MilskoCocoa *h = handle->cocoa.real; - [h setClipboard:text]; +static void MwLLSetClipboardImpl(MwLL handle, const char* text) { + MilskoCocoa* h = handle->cocoa.real; + [h setClipboard:text]; } -static void MwLLGetClipboardImpl(MwLL handle) { (void)handle; } +static void MwLLGetClipboardImpl(MwLL handle) { + (void)handle; +} static void MwLLMakeToolWindowImpl(MwLL handle) { - MilskoCocoa *h = handle->cocoa.real; - [h makeToolWindow]; + MilskoCocoa* h = handle->cocoa.real; + [h makeToolWindow]; } -static void MwLLGetCursorCoordImpl(MwLL handle, MwPoint *point) { - MilskoCocoa *h = handle->cocoa.real; - [h getCursorCoord:point]; +static void MwLLGetCursorCoordImpl(MwLL handle, MwPoint* point) { + MilskoCocoa* h = handle->cocoa.real; + [h getCursorCoord:point]; } -static void MwLLGetScreenSizeImpl(MwLL handle, MwRect *rect) { - MilskoCocoa *h = handle->cocoa.real; - [h getScreenSize:rect]; +static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) { + MilskoCocoa* h = handle->cocoa.real; + [h getScreenSize:rect]; } -static void MwLLBeginStateChangeImpl(MwLL handle) { MwLLShow(handle, 0); } +static void MwLLBeginStateChangeImpl(MwLL handle) { + MwLLShow(handle, 0); +} -static void MwLLEndStateChangeImpl(MwLL handle) { MwLLShow(handle, 1); } +static void MwLLEndStateChangeImpl(MwLL handle) { + MwLLShow(handle, 1); +} -static int MwLLCocoaCallInitImpl(void) { return 0; } +static int MwLLCocoaCallInitImpl(void) { + return 0; +} #include "call.c" CALL(Cocoa); From c20da369e868b8d00d1fecb1a49d97c723a27bf0 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Sun, 8 Mar 2026 18:30:37 -0700 Subject: [PATCH 47/94] try and fail to have the app be activated without setting the activation policy --- include/Mw/LowLevel/Cocoa.h | 143 ++-- src/backend/cocoa.m | 1517 ++++++++++++++++++----------------- 2 files changed, 842 insertions(+), 818 deletions(-) diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index 38129e56..2789af90 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -21,136 +21,143 @@ #import #endif +// Note: implements NSApplicationDelegate +@interface MilskoCocoaApplicationDelegate : NSObject { + NSApplication *appl; +} +- (MilskoCocoaApplicationDelegate *)initWithAppl:(NSApplication *)appl; +@end + // Note: implements NSWindowDelegate @interface MilskoCocoaWindowDelegate : NSObject { - NSWindow* w; + NSWindow *w; } -- (MilskoCocoaWindowDelegate*)initWithWin:(NSWindow*)win; +- (MilskoCocoaWindowDelegate *)initWithWin:(NSWindow *)win; @end @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; } -- (NSGraphicsContext*)context; +- (NSGraphicsContext *)context; - (void)destroy; -- (NSBitmapImageRep*)getRep; +- (NSBitmapImageRep *)getRep; @end @interface MilskoCocoa : NSObject { - NSApplication* application; - MwBool _forceRender; - NSWindow* window; - NSRect rect; - MilskoCocoaView* view; - MwLL parent; - MilskoFakePointer* handle; - unsigned int strHash; - NSEvent* lastEvent; + NSApplication *application; + MwBool _forceRender; + NSWindow *window; + NSRect rect; + MilskoCocoaView *view; + MwLL parent; + MilskoFakePointer *handle; + unsigned int strHash; + NSEvent *lastEvent; } -+ (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; -- (void)handleMouseEvent:(NSEvent*)ev ll:(MwLL)ll; +- (void)eventProcess:(NSEvent *)ev; +- (void)handleKeyEvent:(NSEvent *)ev; +- (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; -- (NSWindow*)parentWindow; -- (NSView*)getView; -- (NSWindow*)getWindow; -- (MilskoFakePointer*)getHandle; +- (NSWindow *)parentWindow; +- (NSView *)getView; +- (NSWindow *)getWindow; +- (MilskoFakePointer *)getHandle; @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/src/backend/cocoa.m b/src/backend/cocoa.m index af486249..7f07ffbf 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -1,3 +1,4 @@ +#include "Mw/BaseTypes.h" #include #include @@ -7,794 +8,824 @@ #endif static NSRect rectFlip(NSRect originFrame) { - NSScreen* zeroScreen = [[NSScreen screens] objectAtIndex:0]; - double screenHeight = [zeroScreen frame].size.height; - double originY = originFrame.origin.y; - double frameHeight = originFrame.size.height; - double destinationY = screenHeight - (originY + frameHeight); - NSRect destinationFrame = originFrame; - destinationFrame.origin.y = destinationY; - if(destinationFrame.origin.x < 0) - destinationFrame.origin.x = 0; - if(destinationFrame.origin.y < 0) - destinationFrame.origin.y = 0; - if(destinationFrame.size.width < 0) - destinationFrame.size.width = 0; - if(destinationFrame.size.height < 0) - destinationFrame.size.height = 0; - return destinationFrame; + NSScreen *zeroScreen = [[NSScreen screens] objectAtIndex:0]; + double screenHeight = [zeroScreen frame].size.height; + double originY = originFrame.origin.y; + double frameHeight = originFrame.size.height; + double destinationY = screenHeight - (originY + frameHeight); + NSRect destinationFrame = originFrame; + destinationFrame.origin.y = destinationY; + if (destinationFrame.origin.x < 0) + destinationFrame.origin.x = 0; + if (destinationFrame.origin.y < 0) + destinationFrame.origin.y = 0; + if (destinationFrame.size.width < 0) + destinationFrame.size.width = 0; + if (destinationFrame.size.height < 0) + destinationFrame.size.height = 0; + return destinationFrame; } static NSPoint pointFlip(NSPoint point) { - return rectFlip(NSMakeRect(point.x, point.y, 0, 0)).origin; + return rectFlip(NSMakeRect(point.x, point.y, 0, 0)).origin; } @implementation MilskoCocoaPixmap -+ (MilskoCocoaPixmap*)newWithWidth:(int)width height:(int)height { - MilskoCocoaPixmap* p = [MilskoCocoaPixmap alloc]; ++ (MilskoCocoaPixmap *)newWithWidth:(int)width height:(int)height { + MilskoCocoaPixmap *p = [MilskoCocoaPixmap alloc]; - p->width = width; - p->height = height; - p->image = NULL; + p->width = width; + p->height = height; + p->image = NULL; - p->buf = malloc(width * height * 4); + 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->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]; + p->image = [[NSImage alloc] initWithSize:NSMakeSize(width, height)]; + assert(p->image); + [p->image addRepresentation:p->rep]; - return p; + return p; } -- (void)updateWithData:(unsigned char*)_data { - memcpy(self->buf, _data, width * height * 4); +- (void)updateWithData:(unsigned char *)_data { + memcpy(self->buf, _data, width * height * 4); } - (void)destroy { - free(self->buf); - [self->image removeRepresentation:self->rep]; - [self->image dealloc]; - [self->rep dealloc]; + free(self->buf); + [self->image removeRepresentation:self->rep]; + [self->image dealloc]; + [self->rep dealloc]; } -- (NSImage*)image { - return self->image; +- (NSImage *)image { + return self->image; } @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]; - [c retain]; ++ (MilskoCocoa *)newWithParent:(MwLL)parent + x:(int)x + y:(int)y + width:(int)width + height:(int)height + handle:(MwLL)r { + MilskoCocoa *c = [MilskoCocoa alloc]; + [c retain]; - if(x == MwDEFAULT) { - x = ([[NSScreen mainScreen] frame].size.width / 2.) - (width / 2.); - } - if(y == MwDEFAULT) { - y = ([[NSScreen mainScreen] frame].size.height / 2.) - (height / 2.); - } - c->application = [NSApplication sharedApplication]; - c->rect = rectFlip(NSMakeRect(x, y, width, height)); + if (x == MwDEFAULT) { + x = ([[NSScreen mainScreen] frame].size.width / 2.) - (width / 2.); + } + if (y == MwDEFAULT) { + y = ([[NSScreen mainScreen] frame].size.height / 2.) - (height / 2.); + } + c->application = [NSApplication sharedApplication]; + c->rect = rectFlip(NSMakeRect(x, y, width, height)); - if(parent == NULL) { - c->window = [[NSWindow alloc] - initWithContentRect:c->rect - styleMask:(NSTitledWindowMask | NSClosableWindowMask | - NSMiniaturizableWindowMask | NSResizableWindowMask) - backing:NSBackingStoreBuffered - defer:NO]; - } else { - double offset = 0; - NSWindow* parentWindow = parent->cocoa.real->window; - offset = - [parentWindow frameRectForContentRect:[parentWindow frame]].size.height - - [parentWindow contentRectForFrameRect:[parentWindow frame]].size.height; + if (parent == NULL) { + c->window = [[NSWindow alloc] + initWithContentRect:c->rect + styleMask:(NSTitledWindowMask | NSClosableWindowMask | + NSMiniaturizableWindowMask | NSResizableWindowMask) + backing:NSBackingStoreBuffered + defer:NO]; + } else { + double offset = 0; + NSWindow *parentWindow = parent->cocoa.real->window; + offset = + [parentWindow frameRectForContentRect:[parentWindow frame]] + .size.height - + [parentWindow contentRectForFrameRect:[parentWindow frame]].size.height; - c->rect.origin.x += [parentWindow frame].origin.x; - c->rect.origin.y -= [parentWindow frame].origin.y - offset; - c->rect.origin.y -= offset; + c->rect.origin.x += [parentWindow frame].origin.x; + c->rect.origin.y -= [parentWindow frame].origin.y - offset; + c->rect.origin.y -= offset; - c->window = [[NSWindow alloc] initWithContentRect:c->rect - styleMask:NSBorderlessWindowMask - backing:NSBackingStoreBuffered - defer:NO]; - } - [c->window setDelegate:[[MilskoCocoaWindowDelegate alloc] - initWithWin:c->window]]; + c->window = [[NSWindow alloc] initWithContentRect:c->rect + styleMask:NSBorderlessWindowMask + backing:NSBackingStoreBuffered + defer:NO]; + } + [c->window + setDelegate:(id)[[MilskoCocoaWindowDelegate alloc] + initWithWin:c->window]]; - [c->window makeKeyAndOrderFront:c->application]; - [c->window retain]; + [c->window makeKeyAndOrderFront:c->application]; + [c->window retain]; - if(parent != NULL) { - MilskoCocoa* p = parent->cocoa.real; - [p->window addChildWindow:c->window ordered:NSWindowAbove]; - [c->window setHasShadow:MwFALSE]; - } else { - [c->application activateIgnoringOtherApps:true]; - [c->window makeFirstResponder:c->view]; - } + if (parent != NULL) { + MilskoCocoa *p = parent->cocoa.real; + [p->window addChildWindow:c->window ordered:NSWindowAbove]; + [c->window setHasShadow:MwFALSE]; + } else { + [c->application activateIgnoringOtherApps:true]; + [c->window makeFirstResponder:c->view]; + } - c->view = [[MilskoCocoaView alloc] initWithFrame:c->rect]; - [c->view retain]; - c->handle = [[MilskoFakePointer alloc] initWithFrame:NSMakeRect(0, 0, 1, 1)]; - [c->handle retain]; - [c->handle setPointer:r]; - [c->view addSubview:c->handle]; + [c->application setDelegate:[[MilskoCocoaApplicationDelegate alloc] + initWithAppl:c->application]]; - [c->window setContentView:c->view]; + c->view = [[MilskoCocoaView alloc] initWithFrame:c->rect]; + [c->view retain]; + 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->window setContentView:c->view]; - c->_forceRender = MwTRUE; - c->strHash = 0; + c->parent = parent; - return c; + c->_forceRender = MwTRUE; + c->strHash = 0; + + [c->application finishLaunching]; + + 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]; - NSColor* nscolor = [NSColor colorWithCalibratedRed:color->common.red / 255. - green:color->common.green / 255. - blue:color->common.blue / 255. - alpha:1.0]; +- (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]; + 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]; + [NSGraphicsContext saveGraphicsState]; + [NSGraphicsContext setCurrentContext:ctx]; - [nscolor setFill]; - for(i = 0; i < points_count; i++) { - if(i == 0) { - [path moveToPoint:NSMakePoint(points[i].x, - [self->window frame].size.height - - points[i].y)]; - } else { - [path lineToPoint:NSMakePoint(points[i].x, - [self->window frame].size.height - - points[i].y)]; - } - } + [nscolor setFill]; + for (i = 0; i < points_count; i++) { + if (i == 0) { + [path moveToPoint:NSMakePoint(points[i].x, + [self->window frame].size.height - + points[i].y)]; + } else { + [path lineToPoint:NSMakePoint(points[i].x, + [self->window frame].size.height - + points[i].y)]; + } + } - [path closePath]; - [path fill]; + [path closePath]; + [path fill]; - [NSGraphicsContext restoreGraphicsState]; + [NSGraphicsContext restoreGraphicsState]; - [self->view setNeedsDisplay:YES]; - } - [pool release]; + [self->view setNeedsDisplay:YES]; + } + [pool release]; }; -- (void)lineWithPoints:(MwPoint*)points color:(MwLLColor)color { - (void)points; - (void)color; +- (void)lineWithPoints:(MwPoint *)points color:(MwLLColor)color { + (void)points; + (void)color; }; -- (void)getX:(int*)x Y:(int*)y W:(unsigned int*)w H:(unsigned int*)h { - NSRect frame = rectFlip([self->window frame]); - frame = rectFlip(frame); +- (void)getX:(int *)x Y:(int *)y W:(unsigned int *)w H:(unsigned int *)h { + NSRect frame = rectFlip([self->window frame]); + frame = rectFlip(frame); - *x = frame.origin.x; - *y = frame.origin.y; + *x = frame.origin.x; + *y = frame.origin.y; - *w = frame.size.width; - *h = frame.size.height; + *w = frame.size.width; + *h = frame.size.height; }; - (void)setX:(int)x Y:(int)y { - NSRect frame = [self->window frame]; + NSRect frame = [self->window frame]; - frame.origin.x = x; - frame.origin.y = y; + frame.origin.x = x; + frame.origin.y = y; - frame = rectFlip(frame); + frame = rectFlip(frame); - if(parent) { - double offset = 0; - NSWindow* parentWindow = parent->cocoa.real->window; - offset = - [parentWindow frameRectForContentRect:[parentWindow frame]].size.height - - [parentWindow contentRectForFrameRect:[parentWindow frame]].size.height; + if (parent) { + double offset = 0; + NSWindow *parentWindow = parent->cocoa.real->window; + offset = + [parentWindow frameRectForContentRect:[parentWindow frame]] + .size.height - + [parentWindow contentRectForFrameRect:[parentWindow frame]].size.height; - if(x < [parentWindow frame].origin.x) { - frame.origin.x += [parentWindow frame].origin.x; - } + if (x < [parentWindow frame].origin.x) { + frame.origin.x += [parentWindow frame].origin.x; + } - frame.origin.y -= [parentWindow frame].origin.y - offset; - frame.origin.y -= offset; - } - [self->view setFrameSize:frame.size]; + frame.origin.y -= [parentWindow frame].origin.y - offset; + frame.origin.y -= offset; + } + [self->view setFrameSize:frame.size]; - [self->window setFrame:frame display:YES animate:false]; + [self->window setFrame:frame display:YES animate:false]; + + [self forceRender]; }; - (void)setW:(int)w H:(int)h { - NSRect frame = [self->window frame]; - frame.size.width = w; - frame.size.height = h; + NSRect frame = [self->window frame]; + frame.size.width = w; + frame.size.height = h; - self->rect = frame; + self->rect = frame; - [self->view setFrameSize:frame.size]; - [self->window setFrame:frame display:YES animate:false]; + [self->view setFrameSize:frame.size]; + [self->window setFrame:frame display:YES animate:false]; + [self forceRender]; }; - (int)pending { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - MwBool isPending = MwFALSE; - if(_forceRender) { - _forceRender = MwFALSE; - [pool release]; - return 1; - } - self->lastEvent = [self->window nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantPast] - inMode:NSDefaultRunLoopMode - dequeue:YES]; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + MwBool isPending = MwFALSE; + if (_forceRender) { + _forceRender = MwFALSE; + [pool release]; + return 1; + } + self->lastEvent = [self->window nextEventMatchingMask:NSAnyEventMask + untilDate:[NSDate distantPast] + inMode:NSDefaultRunLoopMode + dequeue:YES]; - isPending = self->lastEvent != NULL; - [pool release]; - return isPending; + isPending = self->lastEvent != NULL; + [pool release]; + return isPending; }; - (void)getNextEvent { - while(true) { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSEvent* ev = [self->window nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantPast] - inMode:NSDefaultRunLoopMode - dequeue:YES]; - if(!ev) { - [pool release]; - break; - } - [self eventProcess:ev]; - [pool release]; - } + while (true) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSEvent *ev = [self->window nextEventMatchingMask:NSAnyEventMask + untilDate:[NSDate distantPast] + inMode:NSDefaultRunLoopMode + dequeue:YES]; + if (!ev) { + [pool release]; + break; + } + [self eventProcess:ev]; + [pool release]; + } - [self sendClipboardEvent]; + [self sendClipboardEvent]; }; -- (void)eventProcess:(NSEvent*)ev { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSWindow* win = [ev window]; - MwLL h; - MwBool doSendEvent = MwTRUE; +- (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) { + [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]; - } + 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 NSLeftMouseDown: - case NSRightMouseDown: - case NSOtherMouseDown: - case NSLeftMouseUp: - case NSRightMouseUp: - case NSOtherMouseUp: { - [self handleMouseEvent:ev ll:h]; - } - case NSLeftMouseDragged: - case NSRightMouseDragged: - case NSOtherMouseDragged: - case NSMouseMoved: { - MwPoint pos; - pos.x = [ev locationInWindow].x; - pos.y = [win contentRectForFrameRect:[win frame]].size.height - - [ev locationInWindow].y; - MwLLDispatch(h, move, &pos); - break; - } - case NSMouseEntered: - MwLLDispatch(h, focus_in, NULL); - break; - case NSMouseExited: - MwLLDispatch(h, focus_out, NULL); - break; - case NSKeyDown: - case NSKeyUp: { - [self handleKeyEvent:ev]; - doSendEvent = MwFALSE; - } - case NSCursorUpdate: - break; - case NSScrollWheel: - break; - default: - break; - }; - if(doSendEvent) { - [win sendEvent:ev]; - } + switch ([ev type]) { + case NSLeftMouseDown: + case NSRightMouseDown: + case NSOtherMouseDown: + case NSLeftMouseUp: + case NSRightMouseUp: + case NSOtherMouseUp: { + [self handleMouseEvent:ev ll:h]; + } + case NSLeftMouseDragged: + case NSRightMouseDragged: + case NSOtherMouseDragged: + case NSMouseMoved: { + MwPoint pos; + pos.x = [ev locationInWindow].x; + pos.y = [win contentRectForFrameRect:[win frame]].size.height - + [ev locationInWindow].y; + MwLLDispatch(h, move, &pos); + break; + } + case NSMouseEntered: + MwLLDispatch(h, focus_in, NULL); + break; + case NSMouseExited: + MwLLDispatch(h, focus_out, NULL); + break; + case NSKeyDown: + case NSKeyUp: { + [self handleKeyEvent:ev]; + doSendEvent = MwFALSE; + } + case NSCursorUpdate: + break; + case NSScrollWheel: + break; + default: + break; + }; + if (doSendEvent) { + [win sendEvent:ev]; + } - [pool release]; + [pool release]; } -- (void)handleMouseEvent:(NSEvent*)ev ll:(MwLL)ll { - MwLLMouse mouse; - MwBool isDown = MwTRUE; - NSPoint mousePoint = pointFlip([ev locationInWindow]); - switch([ev type]) { - case NSLeftMouseUp: - isDown = MwFALSE; - case NSLeftMouseDown: - mouse.button = MwLLMouseLeft; - break; - case NSRightMouseUp: - isDown = MwFALSE; - case NSRightMouseDown: - mouse.button = MwLLMouseRight; - break; - case NSOtherMouseUp: - isDown = MwFALSE; - case NSOtherMouseDown: - mouse.button = MwLLMouseMiddle; - break; - default: - break; - } - mouse.point.x = mousePoint.x; - mouse.point.y = mousePoint.y; +- (void)handleMouseEvent:(NSEvent *)ev ll:(MwLL)ll { + MwLLMouse mouse; + MwBool isDown = MwTRUE; + NSPoint mousePoint = pointFlip([ev locationInWindow]); + switch ([ev type]) { + case NSLeftMouseUp: + isDown = MwFALSE; + case NSLeftMouseDown: + mouse.button = MwLLMouseLeft; + break; + case NSRightMouseUp: + isDown = MwFALSE; + case NSRightMouseDown: + mouse.button = MwLLMouseRight; + break; + case NSOtherMouseUp: + isDown = MwFALSE; + case NSOtherMouseDown: + mouse.button = MwLLMouseMiddle; + break; + default: + break; + } + mouse.point.x = mousePoint.x; + mouse.point.y = mousePoint.y; - if(isDown) { - MwLLDispatch(ll, down, &mouse); - } else { - MwLLDispatch(ll, up, &mouse); - } + if (isDown) { + MwLLDispatch(ll, down, &mouse); + } else { + MwLLDispatch(ll, up, &mouse); + } } -- (void)handleKeyEvent:(NSEvent*)ev { - 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); - break; - case NSKeyUp: - MwLLDispatch(this, key_released, &ch); - break; - default: - break; - } +- (void)handleKeyEvent:(NSEvent *)ev { + 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); + break; + case NSKeyUp: + MwLLDispatch(this, key_released, &ch); + break; + default: + break; + } } - (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; + /*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]; - } - } - } - } + 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];*/ + [pool release];*/ } -- (void)setTitle:(const char*)title { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - [self->window - setTitleWithRepresentedFilename:[NSString stringWithUTF8String:title]]; - [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]; +- (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:NSMakeRect(_rect->x, _rect->y, _rect->width, - _rect->height) - fromRect:NSZeroRect - operation:NSCompositeSourceOver - fraction:1.0]; + [[p image] + drawInRect:NSMakeRect(_rect->x, _rect->y, _rect->width, _rect->height) + fromRect:NSZeroRect + operation:NSCompositeSourceOver + fraction:1.0]; - [NSGraphicsContext restoreGraphicsState]; + [NSGraphicsContext restoreGraphicsState]; - [self->view setNeedsDisplay:YES]; - } - [pool release]; + [self->view setNeedsDisplay:YES]; + } + [pool release]; }; - (void)setIcon:(MwLLPixmap)pixmap { - (void)pixmap; + (void)pixmap; }; - (void)forceRender { - _forceRender = MwTRUE; + NSEvent *event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined + location:NSMakePoint(0, 0) + modifierFlags:0 + timestamp:0 + windowNumber:0 + context:nil + subtype:0 + data1:0 + data2:0]; + [NSApp postEvent:event atStart:YES]; }; -- (void)setCursor:(MwCursor*)image mask:(MwCursor*)mask { - (void)image; - (void)mask; +- (void)setCursor:(MwCursor *)image mask:(MwCursor *)mask { + (void)image; + (void)mask; }; -- (void)detachWithPoint:(MwPoint*)point { - (void)point; +- (void)detachWithPoint:(MwPoint *)point { + (void)point; }; - (void)show:(int)show { - (void)show; + (void)show; }; - (void)makePopupWithParent:(MwLL)_parent { - (void)_parent; + (void)_parent; }; - (void)setSizeHintsWithMinX:(int)minx - MinY:(int)miny - MaxX:(int)maxx - MaxY:(int)maxy { - (void)minx; - (void)miny; - (void)maxx; - (void)maxy; + MinY:(int)miny + MaxX:(int)maxx + MaxY:(int)maxy { + (void)minx; + (void)miny; + (void)maxx; + (void)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]; + 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]; + [self->window makeMainWindow]; }; - (void)grabPointer:(int)toggle { - (void)toggle; - /* MacOS didn't have a "pointer grab" function - * until 10.13.2 so I need to do this manually */ + (void)toggle; + /* MacOS didn't have a "pointer grab" function + * until 10.13.2 so I need to do this manually */ }; -- (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)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)getClipboard { }; - (void)makeToolWindow { }; -- (void)getCursorCoord:(MwPoint*)point { - NSPoint p = [NSEvent mouseLocation]; - point->x = p.x; - point->y = p.y; +- (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)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 { - if(self->lastEvent) { - [self->lastEvent release]; - [self->lastEvent dealloc]; - } - [self->handle release]; - [self->handle dealloc]; - [self->window release]; - [self->window dealloc]; + if (self->lastEvent) { + [self->lastEvent release]; + [self->lastEvent dealloc]; + } + [self->handle release]; + [self->handle dealloc]; + [self->window release]; + [self->window dealloc]; } -- (NSWindow*)parentWindow { - NSWindow* topmostWindow = self->window; - while([topmostWindow parentWindow]) - topmostWindow = [topmostWindow parentWindow]; - return topmostWindow; +- (NSWindow *)parentWindow { + NSWindow *topmostWindow = self->window; + while ([topmostWindow parentWindow]) + topmostWindow = [topmostWindow parentWindow]; + return topmostWindow; } -- (NSView*)getView { - return view; +- (NSView *)getView { + return view; } -- (NSWindow*)getWindow { - return window; +- (NSWindow *)getWindow { + return window; } -- (MilskoFakePointer*)getHandle { - return handle; +- (MilskoFakePointer *)getHandle { + return handle; } @end @implementation MilskoCocoaView - (id)initWithFrame:(NSRect)frame { - width = frame.size.width; - height = frame.size.height; - self = [super initWithFrame:frame]; - self->space = CGColorSpaceCreateDeviceRGB(); + width = frame.size.width; + height = frame.size.height; + self = [super initWithFrame:frame]; + self->space = CGColorSpaceCreateDeviceRGB(); - if(width == 0 || height == 0) { - self->rep = NULL; - self->context = NULL; - } else { - self->rep = - [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL - pixelsWide:width - pixelsHigh:height - bitsPerSample:8 - samplesPerPixel:4 - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSDeviceRGBColorSpace - bytesPerRow:width * 4 - bitsPerPixel:32]; - assert(self->rep); - [self->rep retain]; + if (width == 0 || height == 0) { + self->rep = NULL; + self->context = NULL; + } else { + self->rep = + [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL + pixelsWide:width + pixelsHigh:height + bitsPerSample:8 + samplesPerPixel:4 + hasAlpha:YES + isPlanar:NO + colorSpaceName:NSDeviceRGBColorSpace + bytesPerRow:width * 4 + bitsPerPixel:32]; + assert(self->rep); + [self->rep retain]; - self->context = - [NSGraphicsContext graphicsContextWithBitmapImageRep:self->rep]; - assert(self->context); - [self->context retain]; - } + self->context = + [NSGraphicsContext graphicsContextWithBitmapImageRep:self->rep]; + assert(self->context); + [self->context retain]; + } - return self; + return self; } -- (NSGraphicsContext*)context { - return self->context; +- (NSGraphicsContext *)context { + return self->context; } -- (NSBitmapImageRep*)getRep { - return self->rep; +- (NSBitmapImageRep *)getRep { + return self->rep; } - (void)drawRect:(NSRect)dirtyRect { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSSize sz = [self->rep size]; - [super drawRect:dirtyRect]; - if(!self->rep) { - [pool release]; - return; - } + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSSize sz = [self->rep size]; + [super drawRect:dirtyRect]; + if (!self->rep) { + [pool release]; + return; + } - [self->rep drawInRect:NSMakeRect(0, 0, sz.width, sz.height)]; + [self->rep drawInRect:NSMakeRect(0, 0, sz.width, sz.height)]; - [self->rep bitmapData]; - [pool release]; + [self->rep bitmapData]; + [pool release]; } - (void)destroy { - CGColorSpaceRelease(self->space); - [self->rep release]; - [self->context release]; + CGColorSpaceRelease(self->space); + [self->rep release]; + [self->context release]; } - (void)setFrameSize:(NSSize)newSize { - [super setFrameSize:newSize]; - [self->rep setSize:newSize]; + [super setFrameSize:newSize]; + [self->rep setSize:newSize]; - self->width = newSize.width; - self->height = newSize.height; + self->width = newSize.width; + self->height = newSize.height; } - (void)displayRect:(NSRect)rect { - (void)rect; + (void)rect; }; @end +@implementation MilskoCocoaApplicationDelegate +- (MilskoCocoaApplicationDelegate *)initWithAppl:(NSApplication *)_appl { + self->appl = _appl; + return self; +} +- (void)applicationDidFinishLaunching:(NSNotification *)notification { + [self->appl activateIgnoringOtherApps:MwTRUE]; +} +@end + @implementation MilskoCocoaWindowDelegate -- (NSSize)windowWillResize:(NSWindow*)win toSize:(NSSize)frameSize; +- (NSSize)windowWillResize:(NSWindow *)win toSize:(NSSize)frameSize; { - if([[[win contentView] subviews] count] >= 1) { - MilskoFakePointer* ptr = [[[win contentView] subviews] objectAtIndex:0]; - MwLL h = [ptr pointer]; + 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); - } - return frameSize; + // MwLLDispatch(h, resize, NULL); + MwLLDispatch(h, draw, NULL); + } + return frameSize; } -- (void)windowDidResize:(NSNotification*)notification { - (void)notification; +- (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); - [NSApp terminate:nil]; +- (void)windowWillClose:(NSNotification *)notification { + (void)notification; + // MilskoCocoa *window = notification.object; + // MwLL handle = [window getHandle].pointer; + // MwLLDispatch(handle, close, NULL); + [NSApp terminate:nil]; } -- (MilskoCocoaWindowDelegate*)initWithWin:(NSWindow*)win { - self->w = win; - return self; +- (MilskoCocoaWindowDelegate *)initWithWin:(NSWindow *)win { + self->w = win; + return self; } @end @implementation MilskoFakePointer -- (void)setPointer:(void*)pointer { - [self setFrame:*(NSRect*)&pointer]; - self->ptr = pointer; +- (void)setPointer:(void *)pointer { + [self setFrame:*(NSRect *)&pointer]; + self->ptr = pointer; }; -- (void*)pointer { - return self->ptr; +- (void *)pointer { + return self->ptr; }; - (void)drawRect:(NSRect)dirtyRect { - /* explicitly do nothing */ - (void)dirtyRect; + /* explicitly do nothing */ + (void)dirtyRect; } - (void)destroy { @@ -802,233 +833,219 @@ static NSPoint pointFlip(NSPoint point) { @end static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { - MwLL r; - (void)x; - (void)y; - (void)width; - (void)height; + MwLL r; + (void)x; + (void)y; + (void)width; + (void)height; - r = malloc(sizeof(*r)); + r = malloc(sizeof(*r)); - MwLLCreateCommon(r); + MwLLCreateCommon(r); - MilskoCocoa* o = [MilskoCocoa newWithParent:parent - x:x - y:y - width:width - height:height - handle:r]; - r->cocoa.real = o; + MilskoCocoa *o = [MilskoCocoa newWithParent:parent + x:x + y:y + width:width + height:height + handle:r]; + r->cocoa.real = o; - return r; + return r; } static void MwLLDestroyImpl(MwLL handle) { - MilskoCocoa* h = handle->cocoa.real; + MilskoCocoa *h = handle->cocoa.real; - [h destroy]; + [h destroy]; - MwLLDestroyCommon(handle); + MwLLDestroyCommon(handle); - free(handle); + free(handle); } -static void MwLLBeginDrawImpl(MwLL handle) { - (void)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) { + MilskoCocoa *h = handle->cocoa.real; + [h polygonWithPoints:points points_count:points_count color:color]; } -static void MwLLEndDrawImpl(MwLL handle) { - (void)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]; -} - -static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { - MilskoCocoa* h = handle->cocoa.real; - [h lineWithPoints:points color:color]; +static void MwLLLineImpl(MwLL handle, MwPoint *points, MwLLColor color) { + MilskoCocoa *h = handle->cocoa.real; + [h lineWithPoints:points color: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; + MwLLColor c = malloc(sizeof(*c)); + MwLLColorUpdate(handle, c, r, g, b); + return c; } static void MwLLColorUpdateImpl(MwLL handle, MwLLColor c, int r, int g, int b) { - (void)handle; + (void)handle; - c->common.red = r; - c->common.green = g; - c->common.blue = 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* height) { - MilskoCocoa* h = handle->cocoa.real; - [h getX:x Y:y W:w H:height]; +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]; } static void MwLLSetXYImpl(MwLL handle, int x, int y) { - MilskoCocoa* h = handle->cocoa.real; - [h setX:x Y:y]; + MilskoCocoa *h = handle->cocoa.real; + [h setX:x Y:y]; } static void MwLLSetWHImpl(MwLL handle, int w, int height) { - MilskoCocoa* h = handle->cocoa.real; - [h setW:w H:height]; + MilskoCocoa *h = handle->cocoa.real; + [h setW:w H:height]; } -static void MwLLFreeColorImpl(MwLLColor color) { - free(color); -} +static void MwLLFreeColorImpl(MwLLColor color) { free(color); } static int MwLLPendingImpl(MwLL handle) { - MilskoCocoa* h = handle->cocoa.real; - if([h pending]) { - MwLLDispatch(handle, draw, NULL); - return 1; - }; - return 0; + MilskoCocoa *h = handle->cocoa.real; + if ([h pending]) { + MwLLDispatch(handle, draw, NULL); + return 1; + }; + return 0; } static void MwLLNextEventImpl(MwLL handle) { - MilskoCocoa* h = handle->cocoa.real; - [h getNextEvent]; + MilskoCocoa *h = handle->cocoa.real; + [h getNextEvent]; } -static void MwLLSetTitleImpl(MwLL handle, const char* title) { - MilskoCocoa* h = handle->cocoa.real; - [h setTitle:title]; +static void MwLLSetTitleImpl(MwLL handle, const char *title) { + MilskoCocoa *h = handle->cocoa.real; + [h setTitle:title]; } -static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, - int width, int height) { - (void)handle; +static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char *data, + int width, int height) { + (void)handle; - MwLLPixmap r = malloc(sizeof(*r)); + MwLLPixmap r = malloc(sizeof(*r)); - r->common.raw = malloc(4 * width * height); - memcpy(r->common.raw, data, 4 * width * height); + r->common.raw = malloc(4 * width * height); + memcpy(r->common.raw, data, 4 * width * height); - r->common.width = width; - r->common.height = height; + r->common.width = width; + r->common.height = height; - r->cocoa.real = [MilskoCocoaPixmap newWithWidth:width height:height]; + r->cocoa.real = [MilskoCocoaPixmap newWithWidth:width height:height]; - MwLLPixmapUpdate(r); - free(r->common.raw); - return r; + MwLLPixmapUpdate(r); + free(r->common.raw); + return r; } static void MwLLPixmapUpdateImpl(MwLLPixmap pixmap) { - MilskoCocoaPixmap* p = pixmap->cocoa.real; - [p updateWithData:pixmap->common.raw]; + MilskoCocoaPixmap *p = pixmap->cocoa.real; + [p updateWithData:pixmap->common.raw]; } static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { - MilskoCocoaPixmap* p = pixmap->cocoa.real; - [p destroy]; - [p dealloc]; - free(pixmap); + MilskoCocoaPixmap *p = pixmap->cocoa.real; + [p destroy]; + [p dealloc]; + free(pixmap); } -static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { - MilskoCocoa* h = handle->cocoa.real; - [h drawPixmap:pixmap rect:rect]; - MwLLForceRender(handle); +static void MwLLDrawPixmapImpl(MwLL handle, MwRect *rect, MwLLPixmap pixmap) { + MilskoCocoa *h = handle->cocoa.real; + [h drawPixmap:pixmap rect:rect]; + MwLLForceRender(handle); } static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { - MilskoCocoa* h = handle->cocoa.real; - [h setIcon:pixmap]; + MilskoCocoa *h = handle->cocoa.real; + [h setIcon:pixmap]; } static void MwLLForceRenderImpl(MwLL handle) { - MilskoCocoa* h = handle->cocoa.real; - [h forceRender]; + MilskoCocoa *h = handle->cocoa.real; + [h forceRender]; } -static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { - MilskoCocoa* h = handle->cocoa.real; - [h setCursor:image mask:mask]; +static void MwLLSetCursorImpl(MwLL handle, MwCursor *image, MwCursor *mask) { + MilskoCocoa *h = handle->cocoa.real; + [h setCursor:image mask:mask]; } -static void MwLLDetachImpl(MwLL handle, MwPoint* point) { - MilskoCocoa* h = handle->cocoa.real; - [h detachWithPoint:point]; +static void MwLLDetachImpl(MwLL handle, MwPoint *point) { + MilskoCocoa *h = handle->cocoa.real; + [h detachWithPoint:point]; } static void MwLLShowImpl(MwLL handle, int show) { - MilskoCocoa* h = handle->cocoa.real; - [h show:show]; + MilskoCocoa *h = handle->cocoa.real; + [h show:show]; } static void MwLLMakePopupImpl(MwLL handle, MwLL parent) { - MilskoCocoa* h = handle->cocoa.real; - [h makePopupWithParent:parent]; + MilskoCocoa *h = handle->cocoa.real; + [h 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]; + int maxy) { + MilskoCocoa *h = handle->cocoa.real; + [h setSizeHintsWithMinX:minx MinY:miny MaxX:maxx MaxY:maxy]; } static void MwLLMakeBorderlessImpl(MwLL handle, int toggle) { - MilskoCocoa* h = handle->cocoa.real; - [h makeBorderless:toggle]; + MilskoCocoa *h = handle->cocoa.real; + [h makeBorderless:toggle]; } static void MwLLFocusImpl(MwLL handle) { - MilskoCocoa* h = handle->cocoa.real; - [h focus]; + MilskoCocoa *h = handle->cocoa.real; + [h focus]; } static void MwLLGrabPointerImpl(MwLL handle, int toggle) { - MilskoCocoa* h = handle->cocoa.real; - [h grabPointer:toggle]; + MilskoCocoa *h = handle->cocoa.real; + [h grabPointer:toggle]; } -static void MwLLSetClipboardImpl(MwLL handle, const char* text) { - MilskoCocoa* h = handle->cocoa.real; - [h setClipboard:text]; +static void MwLLSetClipboardImpl(MwLL handle, const char *text) { + MilskoCocoa *h = handle->cocoa.real; + [h setClipboard:text]; } -static void MwLLGetClipboardImpl(MwLL handle) { - (void)handle; -} +static void MwLLGetClipboardImpl(MwLL handle) { (void)handle; } static void MwLLMakeToolWindowImpl(MwLL handle) { - MilskoCocoa* h = handle->cocoa.real; - [h makeToolWindow]; + MilskoCocoa *h = handle->cocoa.real; + [h makeToolWindow]; } -static void MwLLGetCursorCoordImpl(MwLL handle, MwPoint* point) { - MilskoCocoa* h = handle->cocoa.real; - [h getCursorCoord:point]; +static void MwLLGetCursorCoordImpl(MwLL handle, MwPoint *point) { + MilskoCocoa *h = handle->cocoa.real; + [h getCursorCoord:point]; } -static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) { - MilskoCocoa* h = handle->cocoa.real; - [h getScreenSize:rect]; +static void MwLLGetScreenSizeImpl(MwLL handle, MwRect *rect) { + MilskoCocoa *h = handle->cocoa.real; + [h getScreenSize:rect]; } -static void MwLLBeginStateChangeImpl(MwLL handle) { - MwLLShow(handle, 0); -} +static void MwLLBeginStateChangeImpl(MwLL handle) { MwLLShow(handle, 0); } -static void MwLLEndStateChangeImpl(MwLL handle) { - MwLLShow(handle, 1); -} +static void MwLLEndStateChangeImpl(MwLL handle) { MwLLShow(handle, 1); } -static int MwLLCocoaCallInitImpl(void) { - return 0; -} +static int MwLLCocoaCallInitImpl(void) { return 0; } #include "call.c" CALL(Cocoa); From 75c9af91d1848d835f6fd870bb6386ab79f870e8 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 8 Mar 2026 19:15:17 -0700 Subject: [PATCH 48/94] mac: try and fix positioning for child windows --- include/Mw/LowLevel/Cocoa.h | 2 +- src/backend/cocoa.m | 70 ++++++++++++++++++++++--------------- 2 files changed, 43 insertions(+), 29 deletions(-) diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index 2789af90..dc81195e 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -22,7 +22,7 @@ #endif // Note: implements NSApplicationDelegate -@interface MilskoCocoaApplicationDelegate : NSObject { +@interface MilskoCocoaApplicationDelegate : NSObject { NSApplication *appl; } - (MilskoCocoaApplicationDelegate *)initWithAppl:(NSApplication *)appl; diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 7f07ffbf..3e30503e 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -1,5 +1,7 @@ #include "Mw/BaseTypes.h" +#include #include +#include #include #ifdef __clang__ @@ -102,24 +104,23 @@ static NSPoint pointFlip(NSPoint point) { backing:NSBackingStoreBuffered defer:NO]; } else { - double offset = 0; - NSWindow *parentWindow = parent->cocoa.real->window; - offset = - [parentWindow frameRectForContentRect:[parentWindow frame]] - .size.height - - [parentWindow contentRectForFrameRect:[parentWindow frame]].size.height; + double offset = 0; + NSWindow* parentWindow = parent->cocoa.real->window; + offset = + [parentWindow frameRectForContentRect:[parentWindow frame]].size.height - + [parentWindow contentRectForFrameRect:[parentWindow frame]].size.height; - c->rect.origin.x += [parentWindow frame].origin.x; - c->rect.origin.y -= [parentWindow frame].origin.y - offset; - c->rect.origin.y -= offset; + c->rect.origin.x += [parentWindow frame].origin.x; + c->rect.origin.y -= [parentWindow frame].origin.y - offset; + c->rect.origin.y -= offset; - c->window = [[NSWindow alloc] initWithContentRect:c->rect - styleMask:NSBorderlessWindowMask - backing:NSBackingStoreBuffered - defer:NO]; + c->window = [[NSWindow alloc] initWithContentRect:c->rect + styleMask:NSBorderlessWindowMask + backing:NSBackingStoreBuffered + defer:NO]; } [c->window - setDelegate:(id)[[MilskoCocoaWindowDelegate alloc] + setDelegate:[[MilskoCocoaWindowDelegate alloc] initWithWin:c->window]]; [c->window makeKeyAndOrderFront:c->application]; @@ -127,8 +128,17 @@ static NSPoint pointFlip(NSPoint point) { if (parent != NULL) { MilskoCocoa *p = parent->cocoa.real; + double offset = 0; + offset = + [p->window frameRectForContentRect:[p->window frame]].size.height - + [p->window contentRectForFrameRect:[p->window frame]].size.height; [p->window addChildWindow:c->window ordered:NSWindowAbove]; [c->window setHasShadow:MwFALSE]; + [c->window setParentWindow:p->window]; + + c->rect.origin.x += [p->window frame].origin.x; + c->rect.origin.y -= [p->window frame].origin.y - offset; + c->rect.origin.y -= offset; } else { [c->application activateIgnoringOtherApps:true]; [c->window makeFirstResponder:c->view]; @@ -202,6 +212,11 @@ static NSPoint pointFlip(NSPoint point) { NSRect frame = rectFlip([self->window frame]); frame = rectFlip(frame); + if(parent) { + frame.origin.x -= [parent->cocoa.real->window frame].origin.x; + frame.origin.y += [parent->cocoa.real->window frame].origin.y; + } + *x = frame.origin.x; *y = frame.origin.y; @@ -216,24 +231,21 @@ static NSPoint pointFlip(NSPoint point) { frame = rectFlip(frame); - if (parent) { - double offset = 0; - NSWindow *parentWindow = parent->cocoa.real->window; - offset = - [parentWindow frameRectForContentRect:[parentWindow frame]] - .size.height - - [parentWindow contentRectForFrameRect:[parentWindow frame]].size.height; - - if (x < [parentWindow frame].origin.x) { - frame.origin.x += [parentWindow frame].origin.x; - } + if(parent) { + double offset = 0; + NSWindow* parentWindow = parent->cocoa.real->window; + offset = + [parentWindow frameRectForContentRect:[parentWindow frame]].size.height - + [parentWindow contentRectForFrameRect:[parentWindow frame]].size.height; + frame.origin.x += [parentWindow frame].origin.x; frame.origin.y -= [parentWindow frame].origin.y - offset; frame.origin.y -= offset; - } + } + [self->view setFrameSize:frame.size]; - [self->window setFrame:frame display:YES animate:false]; + [self->window setFrameOrigin:frame.origin]; [self forceRender]; }; @@ -583,7 +595,8 @@ static NSPoint pointFlip(NSPoint point) { (void)pixmap; }; - (void)forceRender { - NSEvent *event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSEvent *event = [NSEvent otherEventWithType:NSApplicationDefined location:NSMakePoint(0, 0) modifierFlags:0 timestamp:0 @@ -593,6 +606,7 @@ static NSPoint pointFlip(NSPoint point) { data1:0 data2:0]; [NSApp postEvent:event atStart:YES]; + [pool release]; }; - (void)setCursor:(MwCursor *)image mask:(MwCursor *)mask { (void)image; From 21d5625ec70fc4a76376b9727c13ee1f0c8bca4f Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Sun, 8 Mar 2026 20:03:47 -0700 Subject: [PATCH 49/94] fix forceRender, at the cost of breaking the rotate example --- src/backend/cocoa.m | 28 +++++++++++++++------------- src/widget/opengl_cocoa.m | 25 ++++++++----------------- 2 files changed, 23 insertions(+), 30 deletions(-) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 3e30503e..169cb1cc 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -140,6 +140,7 @@ static NSPoint pointFlip(NSPoint point) { c->rect.origin.y -= [p->window frame].origin.y - offset; c->rect.origin.y -= offset; } else { + [c->application setActivationPolicy:NSApplicationActivationPolicyRegular]; [c->application activateIgnoringOtherApps:true]; [c->window makeFirstResponder:c->view]; } @@ -279,7 +280,7 @@ static NSPoint pointFlip(NSPoint point) { }; - (void)getNextEvent { - + [self eventProcess:self->lastEvent]; while (true) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSEvent *ev = [self->window nextEventMatchingMask:NSAnyEventMask @@ -595,18 +596,19 @@ static NSPoint pointFlip(NSPoint point) { (void)pixmap; }; - (void)forceRender { - 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]; + 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 { (void)image; diff --git a/src/widget/opengl_cocoa.m b/src/widget/opengl_cocoa.m index c33e3754..15c1198d 100644 --- a/src/widget/opengl_cocoa.m +++ b/src/widget/opengl_cocoa.m @@ -1,5 +1,6 @@ #include "Mw/BaseTypes.h" #include "Mw/Core.h" +#include "Mw/LowLevel/Cocoa.h" #include "Mw/StringDefs.h" #include #include @@ -8,9 +9,10 @@ @interface MacOpenGLWidget : NSObject { NSOpenGLPixelFormat *pixelFormat; NSOpenGLContext *glc; + MilskoCocoa * _win; } -- (MacOpenGLWidget *)initWithView:(NSView *)view; +- (MacOpenGLWidget *)initWithWindow:(MilskoCocoa *)w; - (void)destroy; - (void)makeCurrent; - (void)swapBuffer; @@ -30,7 +32,7 @@ static int create(MwWidget handle) { printf("%d %d\n", width, height); handle->internal = [[MacOpenGLWidget alloc] - initWithView:[handle->lowlevel->cocoa.real getView]]; + initWithWindow:handle->lowlevel->cocoa.real]; handle->lowlevel->common.copy_buffer = 0; MwSetDefault(handle); @@ -75,7 +77,7 @@ static void func_handler(MwWidget handle, const char *name, void *out, @implementation MacOpenGLWidget -- (MacOpenGLWidget *)initWithView:(NSView *)view { +- (MacOpenGLWidget *)initWithWindow:(MilskoCocoa *)w { NSOpenGLPixelFormatAttribute pixelFormatAttributes[] = { NSOpenGLPFAColorSize, 24, NSOpenGLPFAStencilSize, 8, @@ -86,7 +88,8 @@ static void func_handler(MwWidget handle, const char *name, void *out, [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttributes]; self->glc = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil]; - [self->glc setView:view]; + [self->glc setView:[w getView]]; + self->_win = w; return self; }; - (void)destroy { @@ -95,19 +98,7 @@ static void func_handler(MwWidget handle, const char *name, void *out, [self->glc makeCurrentContext]; }; - (void)swapBuffer { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSEvent *event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined - 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]; - + [self->_win forceRender]; [self->glc flushBuffer]; }; - (void *)getProcAddressWithName:(const char *)name { From 9eda46d981eb5d3362c6577bf3b073940eb7d48b Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Sun, 8 Mar 2026 23:38:57 -0500 Subject: [PATCH 50/94] mac: remove accidental includes --- src/backend/cocoa.m | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 169cb1cc..6ab2272c 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -1,8 +1,4 @@ -#include "Mw/BaseTypes.h" -#include #include -#include -#include #ifdef __clang__ #pragma clang push From 65afd85439d95e9819867e2f37e8cfb42fcab5df Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Mon, 9 Mar 2026 14:01:54 -0700 Subject: [PATCH 51/94] mac: most window functions now implemented (save for makeToolWindow) --- include/Mw/LowLevel/Cocoa.h | 17 ++-- src/backend/cocoa.m | 164 +++++++++++++++++++++++++++--------- 2 files changed, 134 insertions(+), 47 deletions(-) diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index dc81195e..865d774c 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -28,11 +28,15 @@ - (MilskoCocoaApplicationDelegate *)initWithAppl:(NSApplication *)appl; @end +@interface MilskoCocoaWindow : NSWindow { +} +@end + // Note: implements NSWindowDelegate @interface MilskoCocoaWindowDelegate : NSObject { - NSWindow *w; + MilskoCocoaWindow *w; } -- (MilskoCocoaWindowDelegate *)initWithWin:(NSWindow *)win; +- (MilskoCocoaWindowDelegate *)initWithWin:(MilskoCocoaWindow *)win; @end @interface MilskoFakePointer : NSView { @@ -82,13 +86,16 @@ @interface MilskoCocoa : NSObject { NSApplication *application; MwBool _forceRender; - NSWindow *window; + MilskoCocoaWindow *window; NSRect rect; MilskoCocoaView *view; MwLL parent; MilskoFakePointer *handle; unsigned int strHash; NSEvent *lastEvent; + + MilskoCocoaPixmap *cursorPixmap; + NSCursor *cursor; } + (MilskoCocoa *)newWithParent:(MwLL)parent @@ -131,9 +138,9 @@ - (void)destroy; - (void)sendClipboardEvent; -- (NSWindow *)parentWindow; +- (MilskoCocoaWindow *)parentWindow; - (NSView *)getView; -- (NSWindow *)getWindow; +- (MilskoCocoaWindow *)getWindow; - (MilskoFakePointer *)getHandle; @end diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 6ab2272c..5aa52bc9 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -1,3 +1,4 @@ +#include "Mw/BaseTypes.h" #include #ifdef __clang__ @@ -93,41 +94,43 @@ static NSPoint pointFlip(NSPoint point) { c->rect = rectFlip(NSMakeRect(x, y, width, height)); if (parent == NULL) { - c->window = [[NSWindow alloc] + c->window = [[MilskoCocoaWindow alloc] initWithContentRect:c->rect - styleMask:(NSTitledWindowMask | NSClosableWindowMask | - NSMiniaturizableWindowMask | NSResizableWindowMask) + styleMask:(NSTitledWindowMask | + NSTexturedBackgroundWindowMask | + NSClosableWindowMask | NSMiniaturizableWindowMask | + NSResizableWindowMask) backing:NSBackingStoreBuffered defer:NO]; } else { - double offset = 0; - NSWindow* parentWindow = parent->cocoa.real->window; - offset = - [parentWindow frameRectForContentRect:[parentWindow frame]].size.height - - [parentWindow contentRectForFrameRect:[parentWindow frame]].size.height; + double offset = 0; + MilskoCocoaWindow *parentWindow = parent->cocoa.real->window; + offset = + [parentWindow frameRectForContentRect:[parentWindow frame]] + .size.height - + [parentWindow contentRectForFrameRect:[parentWindow frame]].size.height; - c->rect.origin.x += [parentWindow frame].origin.x; - c->rect.origin.y -= [parentWindow frame].origin.y - offset; - c->rect.origin.y -= offset; + c->rect.origin.x += [parentWindow frame].origin.x; + c->rect.origin.y -= [parentWindow frame].origin.y - offset; + c->rect.origin.y -= offset; - c->window = [[NSWindow alloc] initWithContentRect:c->rect - styleMask:NSBorderlessWindowMask - backing:NSBackingStoreBuffered - defer:NO]; + c->window = + [[MilskoCocoaWindow alloc] initWithContentRect:c->rect + styleMask:NSBorderlessWindowMask + backing:NSBackingStoreBuffered + defer:NO]; } [c->window - setDelegate:[[MilskoCocoaWindowDelegate alloc] - initWithWin:c->window]]; + setDelegate:[[MilskoCocoaWindowDelegate alloc] initWithWin:c->window]]; [c->window makeKeyAndOrderFront:c->application]; [c->window retain]; if (parent != NULL) { MilskoCocoa *p = parent->cocoa.real; - double offset = 0; - offset = - [p->window frameRectForContentRect:[p->window frame]].size.height - - [p->window contentRectForFrameRect:[p->window frame]].size.height; + double offset = 0; + offset = [p->window frameRectForContentRect:[p->window frame]].size.height - + [p->window contentRectForFrameRect:[p->window frame]].size.height; [p->window addChildWindow:c->window ordered:NSWindowAbove]; [c->window setHasShadow:MwFALSE]; [c->window setParentWindow:p->window]; @@ -139,10 +142,11 @@ static NSPoint pointFlip(NSPoint point) { [c->application setActivationPolicy:NSApplicationActivationPolicyRegular]; [c->application activateIgnoringOtherApps:true]; [c->window makeFirstResponder:c->view]; + [c->window makeKeyAndOrderFront:nil]; } - [c->application setDelegate:[[MilskoCocoaApplicationDelegate alloc] initWithAppl:c->application]]; + [c->application retain]; c->view = [[MilskoCocoaView alloc] initWithFrame:c->rect]; [c->view retain]; @@ -158,6 +162,8 @@ static NSPoint pointFlip(NSPoint point) { c->_forceRender = MwTRUE; c->strHash = 0; + c->cursorPixmap = NULL; + [c->application finishLaunching]; return c; @@ -209,7 +215,7 @@ static NSPoint pointFlip(NSPoint point) { NSRect frame = rectFlip([self->window frame]); frame = rectFlip(frame); - if(parent) { + if (parent) { frame.origin.x -= [parent->cocoa.real->window frame].origin.x; frame.origin.y += [parent->cocoa.real->window frame].origin.y; } @@ -228,17 +234,18 @@ static NSPoint pointFlip(NSPoint point) { frame = rectFlip(frame); - if(parent) { - double offset = 0; - NSWindow* parentWindow = parent->cocoa.real->window; - offset = - [parentWindow frameRectForContentRect:[parentWindow frame]].size.height - - [parentWindow contentRectForFrameRect:[parentWindow frame]].size.height; + if (parent) { + double offset = 0; + MilskoCocoaWindow *parentWindow = parent->cocoa.real->window; + offset = + [parentWindow frameRectForContentRect:[parentWindow frame]] + .size.height - + [parentWindow contentRectForFrameRect:[parentWindow frame]].size.height; frame.origin.x += [parentWindow frame].origin.x; frame.origin.y -= [parentWindow frame].origin.y - offset; frame.origin.y -= offset; - } + } [self->view setFrameSize:frame.size]; @@ -336,9 +343,11 @@ static NSPoint pointFlip(NSPoint point) { } 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: { @@ -346,10 +355,12 @@ static NSPoint pointFlip(NSPoint point) { doSendEvent = MwFALSE; } case NSCursorUpdate: + [self->cursor set]; break; case NSScrollWheel: break; default: + doSendEvent = MwFALSE; break; }; if (doSendEvent) { @@ -589,7 +600,7 @@ static NSPoint pointFlip(NSPoint point) { [pool release]; }; - (void)setIcon:(MwLLPixmap)pixmap { - (void)pixmap; + [self->application setApplicationIconImage:[pixmap->cocoa.real image]]; }; - (void)forceRender { self->_forceRender = MwTRUE; @@ -607,11 +618,63 @@ static NSPoint pointFlip(NSPoint point) { // [pool release]; }; - (void)setCursor:(MwCursor *)image mask:(MwCursor *)mask { - (void)image; - (void)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 { - (void)point; + [self->window setParentWindow:NULL]; }; - (void)show:(int)show { (void)show; @@ -623,10 +686,8 @@ static NSPoint pointFlip(NSPoint point) { MinY:(int)miny MaxX:(int)maxx MaxY:(int)maxy { - (void)minx; - (void)miny; - (void)maxx; - (void)maxy; + [self->window setMinSize:NSMakeSize(minx, miny)]; + [self->window setMaxSize:NSMakeSize(maxx, maxy)]; }; - (void)makeBorderless:(int)toggle { MwU32 mask = [self->window styleMask]; @@ -659,8 +720,6 @@ static NSPoint pointFlip(NSPoint point) { // owner:nil]; [pasteboard setString:[NSString stringWithUTF8String:text] // forType:NSPasteboardTypeString]; [pool release]; }; -- (void)getClipboard { -}; - (void)makeToolWindow { }; - (void)getCursorCoord:(MwPoint *)point { @@ -703,6 +762,7 @@ static NSPoint pointFlip(NSPoint point) { - (MilskoFakePointer *)getHandle { return handle; } + @end @implementation MilskoCocoaView @@ -787,8 +847,15 @@ static NSPoint pointFlip(NSPoint point) { self->appl = _appl; return self; } +- (void)applicationDidBecomeActive:(NSNotification *)notification { + printf("test\n"); +} +- (void)applicationWillFinishLaunching:(NSNotification *)notification { + // printf("test\n"); + // [self->appl activateIgnoringOtherApps:MwTRUE]; +} - (void)applicationDidFinishLaunching:(NSNotification *)notification { - [self->appl activateIgnoringOtherApps:MwTRUE]; + // [self->appl activateIgnoringOtherApps:MwTRUE]; } @end @@ -806,6 +873,10 @@ static NSPoint pointFlip(NSPoint point) { return frameSize; } +- (void)windowDidBecomeMain:(NSNotification *)notification { + printf("waow\n"); +} + - (void)windowDidResize:(NSNotification *)notification { (void)notification; } @@ -842,8 +913,17 @@ static NSPoint pointFlip(NSPoint point) { - (void)destroy { } - @end + +@implementation MilskoCocoaWindow +- (BOOL)canBecomeKeyWindow { + return true; +} +- (BOOL)canBecomeMainWindow { + return true; +} +@end + static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { MwLL r; (void)x; From 128a1ec5243ebd5e84d9d9b32fe8a47833e75147 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Mon, 9 Mar 2026 15:07:46 -0700 Subject: [PATCH 52/94] mac: 'implement' tool windows --- src/backend/cocoa.m | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 5aa52bc9..56a68fd8 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -294,11 +294,15 @@ static NSPoint pointFlip(NSPoint point) { [pool release]; break; } + /* run through the switch case on ev.type, before calling sendEvent on any + * events we handle */ [self eventProcess:ev]; [pool release]; } [self sendClipboardEvent]; + + [self->application updateWindows]; }; - (void)eventProcess:(NSEvent *)ev { @@ -721,6 +725,11 @@ static NSPoint pointFlip(NSPoint point) { // 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]; From dccc402b3d2cc6cdc27a7d4895a9e50b7d4048f5 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Mon, 9 Mar 2026 16:13:49 -0700 Subject: [PATCH 53/94] mac: send mouse/key to both event itself and window, evidently --- src/backend/cocoa.m | 46 +++++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 56a68fd8..1260c253 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -1,4 +1,3 @@ -#include "Mw/BaseTypes.h" #include #ifdef __clang__ @@ -166,6 +165,8 @@ static NSPoint pointFlip(NSPoint point) { [c->application finishLaunching]; + c->pointerLocked = MwFALSE; + return c; } - (void)polygonWithPoints:(MwPoint *)points @@ -298,10 +299,19 @@ static NSPoint pointFlip(NSPoint point) { * events we handle */ [self eventProcess:ev]; [pool release]; + [self->application updateWindows]; } [self sendClipboardEvent]; + if (self->pointerLocked && [self->window isMainWindow]) { + NSPoint pos = [window frame].origin; + pos.x += [window frame].size.width / 2; + pos.y += [window frame].size.height / 2; + + CGWarpMouseCursorPosition(pos); + } + [self->application updateWindows]; }; @@ -339,9 +349,10 @@ static NSPoint pointFlip(NSPoint point) { case NSOtherMouseDragged: case NSMouseMoved: { MwPoint pos; - pos.x = [ev locationInWindow].x; - pos.y = [win contentRectForFrameRect:[win frame]].size.height - - [ev locationInWindow].y; + NSPoint pos_translated = pointFlip([ev locationInWindow]); + pos.x = pos_translated.x; + pos.y = pos_translated.y; + printf("%d %d\n", pos.x, pos.y); MwLLDispatch(h, move, &pos); break; } @@ -355,8 +366,7 @@ static NSPoint pointFlip(NSPoint point) { break; case NSKeyDown: case NSKeyUp: { - [self handleKeyEvent:ev]; - doSendEvent = MwFALSE; + [self handleKeyEvent:ev ll:h]; } case NSCursorUpdate: [self->cursor set]; @@ -364,12 +374,9 @@ static NSPoint pointFlip(NSPoint point) { case NSScrollWheel: break; default: - doSendEvent = MwFALSE; break; }; - if (doSendEvent) { - [win sendEvent:ev]; - } + [win sendEvent:ev]; [pool release]; } @@ -378,6 +385,7 @@ static NSPoint pointFlip(NSPoint point) { MwLLMouse mouse; MwBool isDown = MwTRUE; NSPoint mousePoint = pointFlip([ev locationInWindow]); + MwLL this = [self->handle pointer]; switch ([ev type]) { case NSLeftMouseUp: isDown = MwFALSE; @@ -401,13 +409,15 @@ static NSPoint pointFlip(NSPoint point) { mouse.point.y = mousePoint.y; if (isDown) { + MwLLDispatch(this, down, &mouse); MwLLDispatch(ll, down, &mouse); } else { + MwLLDispatch(this, up, &mouse); MwLLDispatch(ll, up, &mouse); } } -- (void)handleKeyEvent:(NSEvent *)ev { +- (void)handleKeyEvent:(NSEvent *)ev ll:(MwLL)ll { int ch; MwLL this = [self->handle pointer]; enum { @@ -537,9 +547,11 @@ static NSPoint pointFlip(NSPoint point) { 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; @@ -711,9 +723,7 @@ static NSPoint pointFlip(NSPoint point) { [self->window makeMainWindow]; }; - (void)grabPointer:(int)toggle { - (void)toggle; - /* MacOS didn't have a "pointer grab" function - * until 10.13.2 so I need to do this manually */ + self->pointerLocked = toggle; }; - (void)setClipboard:(const char *)text { (void)text; @@ -849,6 +859,14 @@ static NSPoint pointFlip(NSPoint point) { (void)rect; }; +- (BOOL)acceptsFirstResponder { + return MwTRUE; +} +- (BOOL)performKeyEquivalent:(NSEvent *)event { + (void)event; + return MwTRUE; +} + @end @implementation MilskoCocoaApplicationDelegate From dd67e42054cb915195d22b413c2e1144c49b7318 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Mon, 9 Mar 2026 16:14:48 -0700 Subject: [PATCH 54/94] mac: remove debug prints --- include/Mw/LowLevel/Cocoa.h | 4 +++- src/backend/cocoa.m | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index 865d774c..2664b0d1 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -96,6 +96,8 @@ MilskoCocoaPixmap *cursorPixmap; NSCursor *cursor; + + MwBool pointerLocked; } + (MilskoCocoa *)newWithParent:(MwLL)parent @@ -113,7 +115,7 @@ - (void)setW:(int)w H:(int)h; - (int)pending; - (void)eventProcess:(NSEvent *)ev; -- (void)handleKeyEvent:(NSEvent *)ev; +- (void)handleKeyEvent:(NSEvent *)ev ll:(MwLL)ll; - (void)handleMouseEvent:(NSEvent *)ev ll:(MwLL)ll; - (void)getNextEvent; - (void)setTitle:(const char *)title; diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 1260c253..9175a07c 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -352,7 +352,6 @@ static NSPoint pointFlip(NSPoint point) { NSPoint pos_translated = pointFlip([ev locationInWindow]); pos.x = pos_translated.x; pos.y = pos_translated.y; - printf("%d %d\n", pos.x, pos.y); MwLLDispatch(h, move, &pos); break; } @@ -901,7 +900,6 @@ static NSPoint pointFlip(NSPoint point) { } - (void)windowDidBecomeMain:(NSNotification *)notification { - printf("waow\n"); } - (void)windowDidResize:(NSNotification *)notification { From 3f84b0f868f0106b01beea8174f31d7ec8374c5e Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Mon, 9 Mar 2026 16:19:12 -0700 Subject: [PATCH 55/94] mac: document MilskoFakePointer --- include/Mw/LowLevel/Cocoa.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index 2664b0d1..5543d7e2 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -39,6 +39,18 @@ - (MilskoCocoaWindowDelegate *)initWithWin:(MilskoCocoaWindow *)win; @end +/* + So we want to associate each NSWindow with its corresponding MwLL handle. The + conventional way of doing this is through "associative pointers", however + this is a feature that Apple added in 10.6 (marketted back then as "Objective + C 2" iirc). For 10.4 compatibility, we have to do a bit of an ugly hack that + might seem like horrifically undefined behavior, but I've tested this on + both 10.4 and modern Mac OS and as long as we're careful there's no + problems: we override NSView, use NSView's "frame" property to store the + pointer, and then override functions appropriately so that this frame is never + actually used. This can then be attached to an NSWindow with addSubview and + retrieved appropriately. + */ @interface MilskoFakePointer : NSView { void *ptr; } From 4ca11145f1ffb08c200f22ad053847222375358a Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 9 Mar 2026 16:35:09 -0700 Subject: [PATCH 56/94] some 10.4 fixes --- src/backend/cocoa.m | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 9175a07c..e90d5121 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -138,7 +138,9 @@ static NSPoint pointFlip(NSPoint point) { c->rect.origin.y -= [p->window frame].origin.y - offset; c->rect.origin.y -= offset; } else { - [c->application setActivationPolicy:NSApplicationActivationPolicyRegular]; + if ([c->application respondsToSelector:@selector(setActivationPolicy:)]) { + [c->application setActivationPolicy:0 /* NSApplicationActivationPolicyRegular */]; + } [c->application activateIgnoringOtherApps:true]; [c->window makeFirstResponder:c->view]; [c->window makeKeyAndOrderFront:nil]; @@ -305,9 +307,9 @@ static NSPoint pointFlip(NSPoint point) { [self sendClipboardEvent]; if (self->pointerLocked && [self->window isMainWindow]) { - NSPoint pos = [window frame].origin; - pos.x += [window frame].size.width / 2; - pos.y += [window frame].size.height / 2; + 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); } From a0e2ec7f57491aa7cc978ac7296f6c320168d450 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Mon, 9 Mar 2026 16:40:30 -0700 Subject: [PATCH 57/94] undo sending mouse event to both the parent and widget itself, forgot that that's exactly something we don't want to do --- src/backend/cocoa.m | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index e90d5121..fdf12c38 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -139,7 +139,8 @@ static NSPoint pointFlip(NSPoint point) { c->rect.origin.y -= offset; } else { if ([c->application respondsToSelector:@selector(setActivationPolicy:)]) { - [c->application setActivationPolicy:0 /* NSApplicationActivationPolicyRegular */]; + [c->application + setActivationPolicy:0 /* NSApplicationActivationPolicyRegular */]; } [c->application activateIgnoringOtherApps:true]; [c->window makeFirstResponder:c->view]; @@ -410,10 +411,8 @@ static NSPoint pointFlip(NSPoint point) { mouse.point.y = mousePoint.y; if (isDown) { - MwLLDispatch(this, down, &mouse); MwLLDispatch(ll, down, &mouse); } else { - MwLLDispatch(this, up, &mouse); MwLLDispatch(ll, up, &mouse); } } From 9f1b455341de321a146c6ba797d5c592b89e95e4 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 10 Mar 2026 15:33:20 -0700 Subject: [PATCH 58/94] mac: new event pumping architecture that sucks and i hate it but apple is happy with it so we're happy with it --- include/Mw/LowLevel/Cocoa.h | 1 + src/backend/cocoa.m | 47 ++++++++++--------------------------- 2 files changed, 14 insertions(+), 34 deletions(-) diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index 5543d7e2..445af0e5 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -156,6 +156,7 @@ - (NSView *)getView; - (MilskoCocoaWindow *)getWindow; - (MilskoFakePointer *)getHandle; ++ (void)eventCanceller:(MilskoCocoa *)this; @end #define OBJC(x) x diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index fdf12c38..edf5cfd3 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -142,9 +142,9 @@ static NSPoint pointFlip(NSPoint point) { [c->application setActivationPolicy:0 /* NSApplicationActivationPolicyRegular */]; } + [c->window makeKeyAndOrderFront:nil]; [c->application activateIgnoringOtherApps:true]; [c->window makeFirstResponder:c->view]; - [c->window makeKeyAndOrderFront:nil]; } [c->application setDelegate:[[MilskoCocoaApplicationDelegate alloc] initWithAppl:c->application]]; @@ -172,6 +172,13 @@ static NSPoint pointFlip(NSPoint point) { return c; } ++ (void)eventCanceller:(MilskoCocoa *)this { + this->lastEvent = [this->application currentEvent]; + [this eventProcess:this->lastEvent]; + + [[NSApplication sharedApplication] stop:nil]; +} + - (void)polygonWithPoints:(MwPoint *)points points_count:(int)points_count color:(MwLLColor)color { @@ -269,42 +276,14 @@ static NSPoint pointFlip(NSPoint point) { [self forceRender]; }; - (int)pending { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - MwBool isPending = MwFALSE; - if (_forceRender) { - _forceRender = MwFALSE; - [pool release]; - return 1; - } - self->lastEvent = [self->window nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantPast] - inMode:NSDefaultRunLoopMode - dequeue:YES]; - - isPending = self->lastEvent != NULL; - [pool release]; - return isPending; + [MilskoCocoa performSelectorOnMainThread:@selector(eventCanceller:) + withObject:self + waitUntilDone:NO]; + [self->application run]; + return 1; }; - (void)getNextEvent { - [self eventProcess:self->lastEvent]; - while (true) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSEvent *ev = [self->window nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantPast] - inMode:NSDefaultRunLoopMode - dequeue:YES]; - if (!ev) { - [pool release]; - break; - } - /* run through the switch case on ev.type, before calling sendEvent on any - * events we handle */ - [self eventProcess:ev]; - [pool release]; - [self->application updateWindows]; - } - [self sendClipboardEvent]; if (self->pointerLocked && [self->window isMainWindow]) { From 8f379e97513a4416541960c95c6d97f34bc58ca5 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 10 Mar 2026 15:46:46 -0700 Subject: [PATCH 59/94] add comment clarifying pending --- src/backend/cocoa.m | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index edf5cfd3..eeae8567 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -276,6 +276,21 @@ static NSPoint pointFlip(NSPoint point) { [self forceRender]; }; - (int)pending { + /* + ok so this is a crime against god but I did in fact try the better method + of using nextEventMatchingMask and then pumping events manually. However + this gives me something that only kind of works, with strange behavior such + as the window never becoming the main window (have to make it key in order + for the menu to show up) occuring. Hours of research and digging led me down + a rabbit hole that, on all sides, pointed to "just use [NSApplication run]". + So we just to do that; of course, this is a blocking function, so we + register this function that instantly cancels it and pumps whatever event + MacOS has in store for us. We do this on loop and somehow the resulting CPU + usage is managable. + + If some Apple developer with 20 years of experience in Objective C is here: + Pls god send PR if you know how to properly do this. +*/ [MilskoCocoa performSelectorOnMainThread:@selector(eventCanceller:) withObject:self waitUntilDone:NO]; From d3c30bf6d3889de3225d70d2f0779073f710c39c Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 10 Mar 2026 16:31:27 -0700 Subject: [PATCH 60/94] mac: mouse fixing, somewwhat. also just always send events for a bit --- include/Mw/LowLevel/Cocoa.h | 1 + src/backend/cocoa.m | 17 ++++++++++++++++- src/widget/opengl_cocoa.m | 7 +++---- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index 445af0e5..bc65d962 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -110,6 +110,7 @@ NSCursor *cursor; MwBool pointerLocked; + MwBool mouseMoved; } + (MilskoCocoa *)newWithParent:(MwLL)parent diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index eeae8567..8b96fe70 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -176,6 +176,21 @@ static NSPoint pointFlip(NSPoint point) { this->lastEvent = [this->application currentEvent]; [this eventProcess:this->lastEvent]; + if (this->_forceRender) { + 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]; + } + [[NSApplication sharedApplication] stop:nil]; } @@ -301,7 +316,7 @@ static NSPoint pointFlip(NSPoint point) { - (void)getNextEvent { [self sendClipboardEvent]; - if (self->pointerLocked && [self->window isMainWindow]) { + 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; diff --git a/src/widget/opengl_cocoa.m b/src/widget/opengl_cocoa.m index 15c1198d..503fe5e7 100644 --- a/src/widget/opengl_cocoa.m +++ b/src/widget/opengl_cocoa.m @@ -9,7 +9,7 @@ @interface MacOpenGLWidget : NSObject { NSOpenGLPixelFormat *pixelFormat; NSOpenGLContext *glc; - MilskoCocoa * _win; + MilskoCocoa *_win; } - (MacOpenGLWidget *)initWithWindow:(MilskoCocoa *)w; @@ -31,8 +31,8 @@ static int create(MwWidget handle) { printf("%d %d\n", width, height); - handle->internal = [[MacOpenGLWidget alloc] - initWithWindow:handle->lowlevel->cocoa.real]; + handle->internal = + [[MacOpenGLWidget alloc] initWithWindow:handle->lowlevel->cocoa.real]; handle->lowlevel->common.copy_buffer = 0; MwSetDefault(handle); @@ -98,7 +98,6 @@ static void func_handler(MwWidget handle, const char *name, void *out, [self->glc makeCurrentContext]; }; - (void)swapBuffer { - [self->_win forceRender]; [self->glc flushBuffer]; }; - (void *)getProcAddressWithName:(const char *)name { From d9ee157ee8664811d7fb24b09b306c6f625e6a3d Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 10 Mar 2026 17:10:47 -0700 Subject: [PATCH 61/94] mac: support delayed creation of the view's context, for anything whose size starts at 0x0 --- include/Mw/LowLevel/Cocoa.h | 4 ++- src/backend/cocoa.m | 65 +++++++++++++++++++++++-------------- 2 files changed, 43 insertions(+), 26 deletions(-) diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index bc65d962..7a8466b2 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -89,6 +89,7 @@ float height; } +- (void)initRepAndContextWithWidth:(float)w Height:(float)h; - (NSGraphicsContext *)context; - (void)destroy; - (NSBitmapImageRep *)getRep; @@ -153,9 +154,10 @@ - (void)destroy; - (void)sendClipboardEvent; -- (MilskoCocoaWindow *)parentWindow; +- (MwLL)getParent; - (NSView *)getView; - (MilskoCocoaWindow *)getWindow; + - (MilskoFakePointer *)getHandle; + (void)eventCanceller:(MilskoCocoa *)this; diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 8b96fe70..1d5d3ce5 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -773,11 +773,8 @@ static NSPoint pointFlip(NSPoint point) { [self->window dealloc]; } -- (NSWindow *)parentWindow { - NSWindow *topmostWindow = self->window; - while ([topmostWindow parentWindow]) - topmostWindow = [topmostWindow parentWindow]; - return topmostWindow; +- (MwLL)getParent { + return self->parent; } - (NSView *)getView { @@ -804,24 +801,7 @@ static NSPoint pointFlip(NSPoint point) { self->rep = NULL; self->context = NULL; } else { - self->rep = - [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL - pixelsWide:width - pixelsHigh:height - bitsPerSample:8 - samplesPerPixel:4 - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSDeviceRGBColorSpace - bytesPerRow:width * 4 - bitsPerPixel:32]; - assert(self->rep); - [self->rep retain]; - - self->context = - [NSGraphicsContext graphicsContextWithBitmapImageRep:self->rep]; - assert(self->context); - [self->context retain]; + [self initRepAndContextWithWidth:width Height:height]; } return self; @@ -840,8 +820,15 @@ static NSPoint pointFlip(NSPoint point) { NSSize sz = [self->rep size]; [super drawRect:dirtyRect]; if (!self->rep) { - [pool release]; - return; + 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:NSMakeRect(0, 0, sz.width, sz.height)]; @@ -850,6 +837,27 @@ static NSPoint pointFlip(NSPoint point) { [pool release]; } +- (void)initRepAndContextWithWidth:(float)w Height:(float)h { + self->rep = + [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL + 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->context = + [NSGraphicsContext graphicsContextWithBitmapImageRep:self->rep]; + assert(self->context); + [self->context retain]; +} + - (void)destroy { CGColorSpaceRelease(self->space); [self->rep release]; @@ -884,6 +892,7 @@ static NSPoint pointFlip(NSPoint point) { return self; } - (void)applicationDidBecomeActive:(NSNotification *)notification { + [self->appl activateIgnoringOtherApps:true]; printf("test\n"); } - (void)applicationWillFinishLaunching:(NSNotification *)notification { @@ -910,6 +919,12 @@ static NSPoint pointFlip(NSPoint point) { } - (void)windowDidBecomeMain:(NSNotification *)notification { + if ([[[w contentView] subviews] count] != 0) { + MwLL h = [((MilskoFakePointer *)[[[w contentView] subviews] + objectAtIndex:0]) pointer]; + MwLLDispatch(h, focus_in, NULL); + } + [self->w makeKeyAndOrderFront:nil]; } - (void)windowDidResize:(NSNotification *)notification { From 6c53df0fc5eed26a6cd2f8e763f4c21fc772546a Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 10 Mar 2026 20:09:37 -0700 Subject: [PATCH 62/94] correct pixmap updating (sadly memcpy'ing is not enough) --- src/backend/cocoa.m | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 1d5d3ce5..03cbe2cd 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -60,6 +60,22 @@ static NSPoint pointFlip(NSPoint point) { } - (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); From 02faed2f04f645a07f8fa5371d19c74104360da2 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 11 Mar 2026 13:13:16 -0700 Subject: [PATCH 63/94] reduce cpu usage on event loop --- src/backend/cocoa.m | 68 ++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 03cbe2cd..c7eb1047 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -188,27 +188,6 @@ static NSPoint pointFlip(NSPoint point) { return c; } -+ (void)eventCanceller:(MilskoCocoa *)this { - this->lastEvent = [this->application currentEvent]; - [this eventProcess:this->lastEvent]; - - if (this->_forceRender) { - 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]; - } - - [[NSApplication sharedApplication] stop:nil]; -} - (void)polygonWithPoints:(MwPoint *)points points_count:(int)points_count @@ -329,7 +308,34 @@ static NSPoint pointFlip(NSPoint point) { return 1; }; ++ (void)eventCanceller:(MilskoCocoa *)this { + 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]; + + this->lastEvent = [this->window currentEvent]; + [this eventProcess:this->lastEvent]; + + [NSApp postEvent:event atStart:YES]; + [pool release]; + + [[NSApplication sharedApplication] stop:nil]; + usleep(1000); +} + - (void)getNextEvent { + if (_forceRender) { + MwLL h = [self->handle pointer]; + MwLLDispatch(h, draw, NULL); + _forceRender = MwFALSE; + } [self sendClipboardEvent]; if (self->pointerLocked && [self->window isMainWindow] && self->lastEvent) { @@ -401,10 +407,15 @@ static NSPoint pointFlip(NSPoint point) { case NSScrollWheel: break; default: + /* mute bizarre "unknown subtype" errors that flood the console */ + if (ev.subtype > 8) { + doSendEvent = false; + } break; }; - [win sendEvent:ev]; - + if (doSendEvent) { + [win sendEvent:ev]; + } [pool release]; } @@ -909,7 +920,7 @@ static NSPoint pointFlip(NSPoint point) { } - (void)applicationDidBecomeActive:(NSNotification *)notification { [self->appl activateIgnoringOtherApps:true]; - printf("test\n"); + // printf("test\n"); } - (void)applicationWillFinishLaunching:(NSNotification *)notification { // printf("test\n"); @@ -1069,14 +1080,7 @@ static void MwLLSetWHImpl(MwLL handle, int w, int height) { static void MwLLFreeColorImpl(MwLLColor color) { free(color); } -static int MwLLPendingImpl(MwLL handle) { - MilskoCocoa *h = handle->cocoa.real; - if ([h pending]) { - MwLLDispatch(handle, draw, NULL); - return 1; - }; - return 0; -} +static int MwLLPendingImpl(MwLL handle) { return [handle->cocoa.real pending]; } static void MwLLNextEventImpl(MwLL handle) { MilskoCocoa *h = handle->cocoa.real; From 13320dce78c9dfc84bedb1f85253692506a9f16b Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 11 Mar 2026 15:49:14 -0700 Subject: [PATCH 64/94] proper event handling --- include/Mw/LowLevel/Cocoa.h | 1 + src/backend/cocoa.m | 59 ++++++++++++++++++++++--------------- 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index 7a8466b2..c92a81a4 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -109,6 +109,7 @@ MilskoCocoaPixmap *cursorPixmap; NSCursor *cursor; + NSModalSession modalSession; MwBool pointerLocked; MwBool mouseMoved; diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index c7eb1047..5981c0c2 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -185,6 +185,7 @@ static NSPoint pointFlip(NSPoint point) { [c->application finishLaunching]; c->pointerLocked = MwFALSE; + c->modalSession = [c->application beginModalSessionForWindow:c->window]; return c; } @@ -286,26 +287,27 @@ static NSPoint pointFlip(NSPoint point) { [self forceRender]; }; - (int)pending { - /* - ok so this is a crime against god but I did in fact try the better method - of using nextEventMatchingMask and then pumping events manually. However - this gives me something that only kind of works, with strange behavior such - as the window never becoming the main window (have to make it key in order - for the menu to show up) occuring. Hours of research and digging led me down - a rabbit hole that, on all sides, pointed to "just use [NSApplication run]". - So we just to do that; of course, this is a blocking function, so we - register this function that instantly cancels it and pumps whatever event - MacOS has in store for us. We do this on loop and somehow the resulting CPU - usage is managable. + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + MwBool isPending = MwFALSE; - If some Apple developer with 20 years of experience in Objective C is here: - Pls god send PR if you know how to properly do this. -*/ - [MilskoCocoa performSelectorOnMainThread:@selector(eventCanceller:) - withObject:self - waitUntilDone:NO]; - [self->application run]; - return 1; + if (_forceRender) { + _forceRender = MwFALSE; + [pool release]; + return 1; + } + self->lastEvent = [self->window nextEventMatchingMask:NSAnyEventMask + untilDate:[NSDate distantPast] + inMode:NSDefaultRunLoopMode + dequeue:YES]; + [self->lastEvent retain]; + + if (!self->lastEvent) { + [NSApp runModalSession:self->modalSession]; + } + + isPending = self->lastEvent != NULL; + [pool release]; + return isPending; }; + (void)eventCanceller:(MilskoCocoa *)this { @@ -331,6 +333,10 @@ static NSPoint pointFlip(NSPoint point) { } - (void)getNextEvent { + NSEvent *event; + + [self eventProcess:self->lastEvent]; + if (_forceRender) { MwLL h = [self->handle pointer]; MwLLDispatch(h, draw, NULL); @@ -377,6 +383,7 @@ static NSPoint pointFlip(NSPoint point) { case NSRightMouseUp: case NSOtherMouseUp: { [self handleMouseEvent:ev ll:h]; + break; } case NSLeftMouseDragged: case NSRightMouseDragged: @@ -400,6 +407,7 @@ static NSPoint pointFlip(NSPoint point) { case NSKeyDown: case NSKeyUp: { [self handleKeyEvent:ev ll:h]; + break; } case NSCursorUpdate: [self->cursor set]; @@ -790,10 +798,6 @@ static NSPoint pointFlip(NSPoint point) { _rect->height = [screen frame].size.height; }; - (void)destroy { - if (self->lastEvent) { - [self->lastEvent release]; - [self->lastEvent dealloc]; - } [self->handle release]; [self->handle dealloc]; [self->window release]; @@ -999,6 +1003,7 @@ static NSPoint pointFlip(NSPoint point) { - (BOOL)canBecomeMainWindow { return true; } + @end static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { @@ -1080,7 +1085,13 @@ static void MwLLSetWHImpl(MwLL handle, int w, int height) { static void MwLLFreeColorImpl(MwLLColor color) { free(color); } -static int MwLLPendingImpl(MwLL handle) { return [handle->cocoa.real pending]; } +static int MwLLPendingImpl(MwLL handle) { + int p = [handle->cocoa.real pending]; + if (p) { + MwLLDispatch(handle, draw, NULL); + } + return p; +} static void MwLLNextEventImpl(MwLL handle) { MilskoCocoa *h = handle->cocoa.real; From 96528ca4338800b2469174ad991a6dc4afbda117 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Wed, 11 Mar 2026 20:27:51 -0700 Subject: [PATCH 65/94] mac: don't set the xywh of parent windows twice --- 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 5981c0c2..cf240d8d 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -141,7 +141,7 @@ static NSPoint pointFlip(NSPoint point) { [c->window makeKeyAndOrderFront:c->application]; [c->window retain]; - if (parent != NULL) { + if (parent) { MilskoCocoa *p = parent->cocoa.real; double offset = 0; offset = [p->window frameRectForContentRect:[p->window frame]].size.height - @@ -149,10 +149,6 @@ static NSPoint pointFlip(NSPoint point) { [p->window addChildWindow:c->window ordered:NSWindowAbove]; [c->window setHasShadow:MwFALSE]; [c->window setParentWindow:p->window]; - - c->rect.origin.x += [p->window frame].origin.x; - c->rect.origin.y -= [p->window frame].origin.y - offset; - c->rect.origin.y -= offset; } else { if ([c->application respondsToSelector:@selector(setActivationPolicy:)]) { [c->application From db5f0ed40a615965dac3eeda81d33e3421d00ef3 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 12 Mar 2026 01:10:45 -0700 Subject: [PATCH 66/94] mac: some fixes --- src/backend/cocoa.m | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index cf240d8d..3fa41cf1 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -372,15 +372,6 @@ static NSPoint pointFlip(NSPoint point) { } switch ([ev type]) { - case NSLeftMouseDown: - case NSRightMouseDown: - case NSOtherMouseDown: - case NSLeftMouseUp: - case NSRightMouseUp: - case NSOtherMouseUp: { - [self handleMouseEvent:ev ll:h]; - break; - } case NSLeftMouseDragged: case NSRightMouseDragged: case NSOtherMouseDragged: @@ -390,8 +381,18 @@ static NSPoint pointFlip(NSPoint point) { 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]; @@ -412,9 +413,6 @@ static NSPoint pointFlip(NSPoint point) { break; default: /* mute bizarre "unknown subtype" errors that flood the console */ - if (ev.subtype > 8) { - doSendEvent = false; - } break; }; if (doSendEvent) { @@ -426,22 +424,27 @@ static NSPoint pointFlip(NSPoint point) { - (void)handleMouseEvent:(NSEvent *)ev ll:(MwLL)ll { MwLLMouse mouse; MwBool isDown = MwTRUE; - NSPoint mousePoint = pointFlip([ev locationInWindow]); + 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: From 43dd61ffbed7805925e8c89c04afc5e28a3375a8 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Sat, 14 Mar 2026 05:09:53 +0900 Subject: [PATCH 67/94] clean old things --- Jenkinsfile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Jenkinsfile b/Jenkinsfile index 5588f1be..e2686d3a 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -2,8 +2,14 @@ pipeline { agent { label "built-in" } + options { + buildDiscarder(logRotator(numToKeepStr: '16', artifactNumToKeepStr: '16')) + } stages { stage("Build document") { + when { + branch "master" + } steps { sh("doxygen") sh("rm -rf /var/www/milsko-doxygen") From 8f04ccdb686ab4a14d853e6b9d29a11499e22b6f Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Sat, 14 Mar 2026 05:16:27 +0900 Subject: [PATCH 68/94] cleanup --- Jenkinsfile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index e2686d3a..3dd03694 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,10 +1,9 @@ +discardBuilds() + pipeline { agent { label "built-in" } - options { - buildDiscarder(logRotator(numToKeepStr: '16', artifactNumToKeepStr: '16')) - } stages { stage("Build document") { when { From 3260643ada9e7c5ca0c3455c8e265d3b68da0c55 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Sat, 14 Mar 2026 05:21:53 +0900 Subject: [PATCH 69/94] i wonder if this works --- Jenkinsfile | 2 -- 1 file changed, 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 3dd03694..7921f0c6 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,5 +1,3 @@ -discardBuilds() - pipeline { agent { label "built-in" From c64d7778cd479937f86f74516ebaac55a177c3ad Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Mon, 16 Mar 2026 16:08:25 -0700 Subject: [PATCH 70/94] mac: convert child windows to subviews --- include/Mw/LowLevel/Cocoa.h | 1 + src/backend/cocoa.m | 1790 +++++++++++++++++------------------ 2 files changed, 886 insertions(+), 905 deletions(-) diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index c92a81a4..19e0bc3c 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -113,6 +113,7 @@ MwBool pointerLocked; MwBool mouseMoved; + } + (MilskoCocoa *)newWithParent:(MwLL)parent diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 3fa41cf1..c05fae59 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -1,3 +1,4 @@ +#include "Mw/BaseTypes.h" #include #ifdef __clang__ @@ -6,989 +7,959 @@ #endif static NSRect rectFlip(NSRect originFrame) { - NSScreen *zeroScreen = [[NSScreen screens] objectAtIndex:0]; - double screenHeight = [zeroScreen frame].size.height; - double originY = originFrame.origin.y; - double frameHeight = originFrame.size.height; - double destinationY = screenHeight - (originY + frameHeight); - NSRect destinationFrame = originFrame; - destinationFrame.origin.y = destinationY; - if (destinationFrame.origin.x < 0) - destinationFrame.origin.x = 0; - if (destinationFrame.origin.y < 0) - destinationFrame.origin.y = 0; - if (destinationFrame.size.width < 0) - destinationFrame.size.width = 0; - if (destinationFrame.size.height < 0) - destinationFrame.size.height = 0; - return destinationFrame; + NSScreen* zeroScreen = [[NSScreen screens] objectAtIndex:0]; + double screenHeight = [zeroScreen frame].size.height; + double originY = originFrame.origin.y; + double frameHeight = originFrame.size.height; + double destinationY = screenHeight - (originY + frameHeight); + NSRect destinationFrame = originFrame; + destinationFrame.origin.y = destinationY; + return destinationFrame; } static NSPoint pointFlip(NSPoint point) { - return rectFlip(NSMakeRect(point.x, point.y, 0, 0)).origin; + return rectFlip(NSMakeRect(point.x, point.y, 0, 0)).origin; +} + +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); + return destinationFrame; } @implementation MilskoCocoaPixmap -+ (MilskoCocoaPixmap *)newWithWidth:(int)width height:(int)height { - MilskoCocoaPixmap *p = [MilskoCocoaPixmap alloc]; ++ (MilskoCocoaPixmap*)newWithWidth:(int)width height:(int)height { + MilskoCocoaPixmap* p = [MilskoCocoaPixmap alloc]; - p->width = width; - p->height = height; - p->image = NULL; + p->width = width; + p->height = height; + p->image = NULL; - p->buf = malloc(width * height * 4); + 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->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]; + p->image = [[NSImage alloc] initWithSize:NSMakeSize(width, height)]; + assert(p->image); + [p->image addRepresentation:p->rep]; - return p; + 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)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 dealloc]; - [self->rep dealloc]; + free(self->buf); + [self->image removeRepresentation:self->rep]; + [self->image dealloc]; + [self->rep dealloc]; } -- (NSImage *)image { - return self->image; +- (NSImage*)image { + return self->image; } @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]; - [c retain]; ++ (MilskoCocoa*)newWithParent:(MwLL)parent + x:(int)x + y:(int)y + width:(int)width + height:(int)height + handle:(MwLL)r { + MilskoCocoa* c = [MilskoCocoa alloc]; + [c retain]; - if (x == MwDEFAULT) { - x = ([[NSScreen mainScreen] frame].size.width / 2.) - (width / 2.); - } - if (y == MwDEFAULT) { - y = ([[NSScreen mainScreen] frame].size.height / 2.) - (height / 2.); - } - c->application = [NSApplication sharedApplication]; - c->rect = rectFlip(NSMakeRect(x, y, width, height)); + /* + * 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->application = [NSApplication sharedApplication]; + c->rect = NSMakeRect(x, y, width, height); - if (parent == NULL) { - c->window = [[MilskoCocoaWindow alloc] - initWithContentRect:c->rect - styleMask:(NSTitledWindowMask | - NSTexturedBackgroundWindowMask | - NSClosableWindowMask | NSMiniaturizableWindowMask | - NSResizableWindowMask) - backing:NSBackingStoreBuffered - defer:NO]; - } else { - double offset = 0; - MilskoCocoaWindow *parentWindow = parent->cocoa.real->window; - offset = - [parentWindow frameRectForContentRect:[parentWindow frame]] - .size.height - - [parentWindow contentRectForFrameRect:[parentWindow frame]].size.height; + if(parent == NULL) { + c->window = [[MilskoCocoaWindow alloc] + initWithContentRect:rectFlip(c->rect) + styleMask:(NSTitledWindowMask | + NSTexturedBackgroundWindowMask | + NSClosableWindowMask | NSMiniaturizableWindowMask | + NSResizableWindowMask) + backing:NSBackingStoreBuffered + defer:NO]; + [c->window + setDelegate:[[MilskoCocoaWindowDelegate alloc] initWithWin:c->window]]; + [c->window retain]; - c->rect.origin.x += [parentWindow frame].origin.x; - c->rect.origin.y -= [parentWindow frame].origin.y - offset; - c->rect.origin.y -= offset; + [c->window makeKeyAndOrderFront:c->application]; + [c->window makeFirstResponder:c->view]; + [c->window setAcceptsMouseMovedEvents:MwTRUE]; - c->window = - [[MilskoCocoaWindow alloc] initWithContentRect:c->rect - styleMask:NSBorderlessWindowMask - backing:NSBackingStoreBuffered - defer:NO]; - } - [c->window - setDelegate:[[MilskoCocoaWindowDelegate alloc] initWithWin:c->window]]; + c->view = [[MilskoCocoaView alloc] initWithFrame:c->rect]; + [c->view retain]; + [c->window setContentView:c->view]; - [c->window makeKeyAndOrderFront:c->application]; - [c->window retain]; + if([c->application respondsToSelector:@selector(setActivationPolicy:)]) { + [c->application + setActivationPolicy:0 /* NSApplicationActivationPolicyRegular */]; + } + [c->application activateIgnoringOtherApps:true]; + [c->application setDelegate:[[MilskoCocoaApplicationDelegate alloc] + initWithAppl:c->application]]; + [c->application retain]; + } else { + MilskoCocoa* p = parent->cocoa.real; - if (parent) { - MilskoCocoa *p = parent->cocoa.real; - double offset = 0; - offset = [p->window frameRectForContentRect:[p->window frame]].size.height - - [p->window contentRectForFrameRect:[p->window frame]].size.height; - [p->window addChildWindow:c->window ordered:NSWindowAbove]; - [c->window setHasShadow:MwFALSE]; - [c->window setParentWindow:p->window]; - } else { - if ([c->application respondsToSelector:@selector(setActivationPolicy:)]) { - [c->application - setActivationPolicy:0 /* NSApplicationActivationPolicyRegular */]; - } - [c->window makeKeyAndOrderFront:nil]; - [c->application activateIgnoringOtherApps:true]; - [c->window makeFirstResponder:c->view]; - } - [c->application setDelegate:[[MilskoCocoaApplicationDelegate alloc] - initWithAppl:c->application]]; - [c->application retain]; + c->window = p->window; - c->view = [[MilskoCocoaView alloc] initWithFrame:c->rect]; - [c->view retain]; - c->handle = [[MilskoFakePointer alloc] initWithFrame:NSMakeRect(0, 0, 1, 1)]; - [c->handle retain]; - [c->handle setPointer:r]; - [c->view addSubview:c->handle]; + 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]; + } + [c->view retain]; + [c->view setNeedsDisplay:TRUE]; + [p->view addSubview:c->view]; + [p->window setContentView:p->view]; + } - [c->window setContentView:c->view]; + 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->modalSession = [c->application beginModalSessionForWindow:c->window]; + c->parent = parent; - c->_forceRender = MwTRUE; - c->strHash = 0; + c->_forceRender = MwTRUE; + c->strHash = 0; - c->cursorPixmap = NULL; + c->cursorPixmap = NULL; - [c->application finishLaunching]; + [c->application finishLaunching]; - c->pointerLocked = MwFALSE; - c->modalSession = [c->application beginModalSessionForWindow:c->window]; + c->pointerLocked = MwFALSE; - return c; + + 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]; - NSColor *nscolor = - [NSColor colorWithCalibratedRed:color->common.red / 255. - green:color->common.green / 255. - blue:color->common.blue / 255. - alpha:1.0]; +- (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]; - [NSGraphicsContext saveGraphicsState]; - [NSGraphicsContext setCurrentContext:ctx]; + NSColor* nscolor = + [NSColor colorWithCalibratedRed:color->common.red / 255. + green:color->common.green / 255. + blue:color->common.blue / 255. + alpha:1.0]; - [nscolor setFill]; - for (i = 0; i < points_count; i++) { - if (i == 0) { - [path moveToPoint:NSMakePoint(points[i].x, - [self->window frame].size.height - - points[i].y)]; - } else { - [path lineToPoint:NSMakePoint(points[i].x, - [self->window frame].size.height - - points[i].y)]; - } - } + [NSGraphicsContext saveGraphicsState]; + [NSGraphicsContext setCurrentContext:ctx]; - [path closePath]; - [path fill]; + [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)]; + } else { + [path lineToPoint:NSMakePoint(points[i].x, _rect.size.height - + points[i].y)]; + } + } - [NSGraphicsContext restoreGraphicsState]; + [path closePath]; + [path fill]; - [self->view setNeedsDisplay:YES]; - } - [pool release]; + [NSGraphicsContext restoreGraphicsState]; + + [self->view setNeedsDisplay:YES]; + } + [pool release]; }; -- (void)lineWithPoints:(MwPoint *)points color:(MwLLColor)color { - (void)points; - (void)color; +- (void)lineWithPoints:(MwPoint*)points color:(MwLLColor)color { + (void)points; + (void)color; }; -- (void)getX:(int *)x Y:(int *)y W:(unsigned int *)w H:(unsigned int *)h { - NSRect frame = rectFlip([self->window frame]); - frame = rectFlip(frame); +- (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); - if (parent) { - frame.origin.x -= [parent->cocoa.real->window frame].origin.x; - frame.origin.y += [parent->cocoa.real->window frame].origin.y; - } + *x = frame.origin.x; + *y = frame.origin.y; - *x = frame.origin.x; - *y = frame.origin.y; - - *w = frame.size.width; - *h = frame.size.height; + *w = frame.size.width; + *h = frame.size.height; }; - (void)setX:(int)x Y:(int)y { - NSRect frame = [self->window frame]; + NSRect frame; + if(parent) { + frame = [self->view frame]; + } else { + frame = [self->window frame]; + } - frame.origin.x = x; - frame.origin.y = y; + frame.origin.x = x; + frame.origin.y = y; - frame = rectFlip(frame); - - if (parent) { - double offset = 0; - MilskoCocoaWindow *parentWindow = parent->cocoa.real->window; - offset = - [parentWindow frameRectForContentRect:[parentWindow frame]] - .size.height - - [parentWindow contentRectForFrameRect:[parentWindow frame]].size.height; - - frame.origin.x += [parentWindow frame].origin.x; - frame.origin.y -= [parentWindow frame].origin.y - offset; - frame.origin.y -= offset; - } - - [self->view setFrameSize:frame.size]; - - [self->window setFrameOrigin:frame.origin]; - - [self forceRender]; + if(!parent) { + frame = rectFlip(frame); + [self->window setFrame:frame display:TRUE animate:TRUE]; + } else { + frame = localRectFlip(frame, parent->cocoa.real->view); + [self->view setBounds:frame]; + } }; - (void)setW:(int)w H:(int)h { - NSRect frame = [self->window frame]; - frame.size.width = w; - frame.size.height = h; + NSRect frame = [self->window frame]; + frame.size.width = w; + frame.size.height = h; - self->rect = frame; + self->rect = frame; - [self->view setFrameSize:frame.size]; - [self->window setFrame:frame display:YES animate:false]; - [self forceRender]; + [self->view setFrameSize:frame.size]; + if(self->parent) { + [self->view setFrame:frame]; + } else { + [self->window setFrame:frame display:YES animate:false]; + } }; - (int)pending { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - MwBool isPending = MwFALSE; - - if (_forceRender) { - _forceRender = MwFALSE; - [pool release]; - return 1; - } - self->lastEvent = [self->window nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantPast] - inMode:NSDefaultRunLoopMode - dequeue:YES]; - [self->lastEvent retain]; - - if (!self->lastEvent) { - [NSApp runModalSession:self->modalSession]; - } - - isPending = self->lastEvent != NULL; - [pool release]; - return isPending; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [NSApp runModalSession:self->modalSession]; + [pool release]; + return 1; }; -+ (void)eventCanceller:(MilskoCocoa *)this { - 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]; - - this->lastEvent = [this->window currentEvent]; - [this eventProcess:this->lastEvent]; - - [NSApp postEvent:event atStart:YES]; - [pool release]; - - [[NSApplication sharedApplication] stop:nil]; - usleep(1000); -} - - (void)getNextEvent { - NSEvent *event; + [self eventProcess:self->lastEvent]; - [self eventProcess:self->lastEvent]; + if(_forceRender) { + MwLL h = [self->handle pointer]; + MwLLDispatch(h, draw, NULL); + [self->view setNeedsDisplay:true]; + _forceRender = MwFALSE; + } + [self sendClipboardEvent]; - if (_forceRender) { - MwLL h = [self->handle pointer]; - MwLLDispatch(h, draw, NULL); - _forceRender = MwFALSE; - } - [self sendClipboardEvent]; + 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; - 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); + } - CGWarpMouseCursorPosition(pos); - } - - [self->application updateWindows]; + [self->application updateWindows]; }; -- (void)eventProcess:(NSEvent *)ev { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSWindow *win = [ev window]; - MwLL h; - MwBool doSendEvent = MwTRUE; +- (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) { + [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]; - } + 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]; + 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]; +- (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; + 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; - if (isDown) { - MwLLDispatch(ll, down, &mouse); - } else { - MwLLDispatch(ll, up, &mouse); - } + 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)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]; - NSArray* items = @[ - @"public.utf8-plain-text", - @"public.utf16-external-plain-text", - @"com.apple.traditional-mac-plain-text", - ]; - MwLL this = self->handle.pointer; + /*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]; - } - } - } - } + 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];*/ + [pool release];*/ } -- (void)setTitle:(const char *)title { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - [self->window - setTitleWithRepresentedFilename:[NSString stringWithUTF8String:title]]; - [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]; +- (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:NSMakeRect(_rect->x, _rect->y, _rect->width, _rect->height) - fromRect:NSZeroRect - operation:NSCompositeSourceOver - fraction:1.0]; + [[p image] + drawInRect:NSMakeRect(_rect->x, _rect->y, _rect->width, _rect->height) + fromRect:NSZeroRect + operation:NSCompositeSourceOver + fraction:1.0]; - [NSGraphicsContext restoreGraphicsState]; + [NSGraphicsContext restoreGraphicsState]; - [self->view setNeedsDisplay:YES]; - } - [pool release]; + [self->view setNeedsDisplay:YES]; + } + [pool release]; }; - (void)setIcon:(MwLLPixmap)pixmap { - [self->application setApplicationIconImage:[pixmap->cocoa.real image]]; + [self->application setApplicationIconImage:[pixmap->cocoa.real image]]; }; - (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]; + 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; - unsigned char *di = malloc(image->width * image->height * 4); - memset(di, 0, image->width * image->height * 4); +- (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]; + 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; + 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; + 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) { + 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; - }; + if(d & 1) { + px = 255; + }; - di[idx] = px; - di[idx + 1] = px; - di[idx + 2] = px; - d = d >> 1; - } - } + di[idx] = px; + di[idx + 1] = px; + di[idx + 2] = px; + d = d >> 1; + } + } - [self->cursorPixmap updateWithData:di]; + [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 = [[NSCursor alloc] + initWithImage:[self->cursorPixmap image] + hotSpot:NSMakePoint(image->x, image->y + image->height)]; + [self->cursor retain]; - [self->cursor pop]; - [self->cursor push]; + [self->cursor pop]; + [self->cursor push]; - free(di); + free(di); }; -- (void)detachWithPoint:(MwPoint *)point { - [self->window setParentWindow:NULL]; +- (void)detachWithPoint:(MwPoint*)point { + [self->window setParentWindow:NULL]; }; - (void)show:(int)show { - (void)show; + (void)show; }; - (void)makePopupWithParent:(MwLL)_parent { - (void)_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)]; + 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]; + 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]; + [self->window makeMainWindow]; }; - (void)grabPointer:(int)toggle { - self->pointerLocked = 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)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]; + /* 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)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)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->handle dealloc]; - [self->window release]; - [self->window dealloc]; + [self->handle release]; + [self->handle dealloc]; + [self->window release]; + [self->window dealloc]; } - (MwLL)getParent { - return self->parent; + return self->parent; } -- (NSView *)getView { - return view; +- (NSView*)getView { + return view; } -- (NSWindow *)getWindow { - return window; +- (NSWindow*)getWindow { + return window; } -- (MilskoFakePointer *)getHandle { - return handle; +- (MilskoFakePointer*)getHandle { + return handle; } @end @implementation MilskoCocoaView - (id)initWithFrame:(NSRect)frame { - width = frame.size.width; - height = frame.size.height; - self = [super initWithFrame:frame]; - self->space = CGColorSpaceCreateDeviceRGB(); + width = frame.size.width; + height = frame.size.height; + self = [super initWithFrame:frame]; + self->space = CGColorSpaceCreateDeviceRGB(); - if (width == 0 || height == 0) { - self->rep = NULL; - self->context = NULL; - } else { - [self initRepAndContextWithWidth:width Height:height]; - } + if(width == 0 || height == 0) { + self->rep = NULL; + self->context = NULL; + } else { + [self initRepAndContextWithWidth:width Height:height]; + } - return self; + return self; } -- (NSGraphicsContext *)context { - return self->context; +- (NSGraphicsContext*)context { + return self->context; } -- (NSBitmapImageRep *)getRep { - return self->rep; +- (NSBitmapImageRep*)getRep { + return self->rep; } - (void)drawRect:(NSRect)dirtyRect { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSSize sz = [self->rep size]; - [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; - } - } + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSSize sz = [self->rep size]; + MwLL ll = [((MilskoFakePointer *)[[[[self window] contentView] subviews] + objectAtIndex:0]) pointer]; - [self->rep drawInRect:NSMakeRect(0, 0, sz.width, sz.height)]; + [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; + } + } - [self->rep bitmapData]; - [pool release]; + // MwLLDispatch(ll, draw, NULL); + + [self->rep drawInRect:dirtyRect]; + + for(NSView* subview in [self subviews]) { + NSRect bounds = [subview bounds]; + [subview drawRect:bounds]; + } + + [self->rep bitmapData]; + + [pool release]; } - (void)initRepAndContextWithWidth:(float)w Height:(float)h { - self->rep = - [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL - 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 = + [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL + 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->context = - [NSGraphicsContext graphicsContextWithBitmapImageRep:self->rep]; - assert(self->context); - [self->context retain]; + self->context = + [NSGraphicsContext graphicsContextWithBitmapImageRep:self->rep]; + assert(self->context); + [self->context retain]; } - (void)destroy { - CGColorSpaceRelease(self->space); - [self->rep release]; - [self->context release]; + CGColorSpaceRelease(self->space); + [self->rep release]; + [self->context release]; } - (void)setFrameSize:(NSSize)newSize { - [super setFrameSize:newSize]; - [self->rep setSize:newSize]; + [super setFrameSize:newSize]; + [self->rep setSize:newSize]; - self->width = newSize.width; - self->height = newSize.height; + self->width = newSize.width; + self->height = newSize.height; } - (void)displayRect:(NSRect)rect { - (void)rect; + (void)rect; }; - (BOOL)acceptsFirstResponder { - return MwTRUE; + return MwTRUE; } -- (BOOL)performKeyEquivalent:(NSEvent *)event { - (void)event; - return MwTRUE; +- (BOOL)performKeyEquivalent:(NSEvent*)event { + (void)event; + return MwTRUE; } @end @implementation MilskoCocoaApplicationDelegate -- (MilskoCocoaApplicationDelegate *)initWithAppl:(NSApplication *)_appl { - self->appl = _appl; - return self; +- (MilskoCocoaApplicationDelegate*)initWithAppl:(NSApplication*)_appl { + self->appl = _appl; + return self; } -- (void)applicationDidBecomeActive:(NSNotification *)notification { - [self->appl activateIgnoringOtherApps:true]; - // printf("test\n"); +- (void)applicationDidBecomeActive:(NSNotification*)notification { + [self->appl activateIgnoringOtherApps:true]; + // printf("test\n"); } -- (void)applicationWillFinishLaunching:(NSNotification *)notification { - // printf("test\n"); - // [self->appl activateIgnoringOtherApps:MwTRUE]; +- (void)applicationWillFinishLaunching:(NSNotification*)notification { + // printf("test\n"); + // [self->appl activateIgnoringOtherApps:MwTRUE]; } -- (void)applicationDidFinishLaunching:(NSNotification *)notification { - // [self->appl activateIgnoringOtherApps:MwTRUE]; +- (void)applicationDidFinishLaunching:(NSNotification*)notification { + // [self->appl activateIgnoringOtherApps:MwTRUE]; } @end @implementation MilskoCocoaWindowDelegate -- (NSSize)windowWillResize:(NSWindow *)win toSize:(NSSize)frameSize; +- (NSSize)windowWillResize:(NSWindow*)win toSize:(NSSize)frameSize; { - if ([[[win contentView] subviews] count] >= 1) { - MilskoFakePointer *ptr = [[[win contentView] subviews] objectAtIndex:0]; - MwLL h = [ptr pointer]; + 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); - } - return frameSize; + MwLLDispatch(h, resize, NULL); + MwLLDispatch(h, draw, NULL); + } + return frameSize; } -- (void)windowDidBecomeMain:(NSNotification *)notification { - if ([[[w contentView] subviews] count] != 0) { - MwLL h = [((MilskoFakePointer *)[[[w contentView] subviews] - objectAtIndex:0]) pointer]; - MwLLDispatch(h, focus_in, NULL); - } - [self->w makeKeyAndOrderFront:nil]; +- (void)windowDidBecomeMain:(NSNotification*)notification { + if([[[w contentView] subviews] count] != 0) { + MwLL h = [((MilskoFakePointer*)[[[w contentView] subviews] + objectAtIndex:0]) pointer]; + MwLLDispatch(h, focus_in, NULL); + } + [self->w makeKeyAndOrderFront:nil]; } -- (void)windowDidResize:(NSNotification *)notification { - (void)notification; +- (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); - [NSApp terminate:nil]; +- (void)windowWillClose:(NSNotification*)notification { + (void)notification; + // MilskoCocoa *window = notification.object; + // MwLL handle = [window getHandle].pointer; + // MwLLDispatch(handle, close, NULL); + [NSApp terminate:nil]; } -- (MilskoCocoaWindowDelegate *)initWithWin:(NSWindow *)win { - self->w = win; - return self; +- (MilskoCocoaWindowDelegate*)initWithWin:(NSWindow*)win { + self->w = win; + return self; } @end @implementation MilskoFakePointer -- (void)setPointer:(void *)pointer { - [self setFrame:*(NSRect *)&pointer]; - self->ptr = pointer; +- (void)setPointer:(void*)pointer { + [self setFrame:*(NSRect*)&pointer]; + self->ptr = pointer; }; -- (void *)pointer { - return self->ptr; +- (void*)pointer { + return self->ptr; }; - (void)drawRect:(NSRect)dirtyRect { - /* explicitly do nothing */ - (void)dirtyRect; + /* explicitly do nothing */ + (void)dirtyRect; } - (void)destroy { @@ -997,227 +968,236 @@ static NSPoint pointFlip(NSPoint point) { @implementation MilskoCocoaWindow - (BOOL)canBecomeKeyWindow { - return true; + return true; } - (BOOL)canBecomeMainWindow { - return true; + return true; } @end static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { - MwLL r; - (void)x; - (void)y; - (void)width; - (void)height; + MwLL r; + r = malloc(sizeof(*r)); - r = malloc(sizeof(*r)); + MwLLCreateCommon(r); - MwLLCreateCommon(r); + MilskoCocoa* o = [MilskoCocoa newWithParent:parent + x:x + y:y + width:width + height:height + handle:r]; + r->cocoa.real = o; - MilskoCocoa *o = [MilskoCocoa newWithParent:parent - x:x - y:y - width:width - height:height - handle:r]; - r->cocoa.real = o; - - return r; + return r; } static void MwLLDestroyImpl(MwLL handle) { - MilskoCocoa *h = handle->cocoa.real; + MilskoCocoa* h = handle->cocoa.real; - [h destroy]; + [h destroy]; - MwLLDestroyCommon(handle); + MwLLDestroyCommon(handle); - free(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) { - MilskoCocoa *h = handle->cocoa.real; - [h polygonWithPoints:points points_count:points_count color:color]; +static void MwLLBeginDrawImpl(MwLL handle) { + (void)handle; } -static void MwLLLineImpl(MwLL handle, MwPoint *points, MwLLColor color) { - MilskoCocoa *h = handle->cocoa.real; - [h lineWithPoints:points color:color]; +static void MwLLEndDrawImpl(MwLL handle) { + (void)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]; +} + +static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { + MilskoCocoa* h = handle->cocoa.real; + [h lineWithPoints:points color: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; + MwLLColor c = malloc(sizeof(*c)); + MwLLColorUpdate(handle, c, r, g, b); + return c; } static void MwLLColorUpdateImpl(MwLL handle, MwLLColor c, int r, int g, int b) { - (void)handle; + (void)handle; - c->common.red = r; - c->common.green = g; - c->common.blue = 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 *height) { - MilskoCocoa *h = handle->cocoa.real; - [h getX:x Y:y W:w H:height]; +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]; } static void MwLLSetXYImpl(MwLL handle, int x, int y) { - MilskoCocoa *h = handle->cocoa.real; - [h setX:x Y:y]; + MilskoCocoa* h = handle->cocoa.real; + [h setX:x Y:y]; } static void MwLLSetWHImpl(MwLL handle, int w, int height) { - MilskoCocoa *h = handle->cocoa.real; - [h setW:w H:height]; + MilskoCocoa* h = handle->cocoa.real; + [h setW:w H:height]; } -static void MwLLFreeColorImpl(MwLLColor color) { free(color); } +static void MwLLFreeColorImpl(MwLLColor color) { + free(color); +} static int MwLLPendingImpl(MwLL handle) { - int p = [handle->cocoa.real pending]; - if (p) { - MwLLDispatch(handle, draw, NULL); - } - return p; + int p = [handle->cocoa.real pending]; + if(p) { + MwLLDispatch(handle, draw, NULL); + } + return p; } static void MwLLNextEventImpl(MwLL handle) { - MilskoCocoa *h = handle->cocoa.real; - [h getNextEvent]; + MilskoCocoa* h = handle->cocoa.real; + [h getNextEvent]; } -static void MwLLSetTitleImpl(MwLL handle, const char *title) { - MilskoCocoa *h = handle->cocoa.real; - [h setTitle:title]; +static void MwLLSetTitleImpl(MwLL handle, const char* title) { + MilskoCocoa* h = handle->cocoa.real; + [h setTitle:title]; } -static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char *data, - int width, int height) { - (void)handle; +static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, + int width, int height) { + (void)handle; - MwLLPixmap r = malloc(sizeof(*r)); + MwLLPixmap r = malloc(sizeof(*r)); - r->common.raw = malloc(4 * width * height); - memcpy(r->common.raw, data, 4 * width * height); + r->common.raw = malloc(4 * width * height); + memcpy(r->common.raw, data, 4 * width * height); - r->common.width = width; - r->common.height = height; + r->common.width = width; + r->common.height = height; - r->cocoa.real = [MilskoCocoaPixmap newWithWidth:width height:height]; + r->cocoa.real = [MilskoCocoaPixmap newWithWidth:width height:height]; - MwLLPixmapUpdate(r); - free(r->common.raw); - return r; + MwLLPixmapUpdate(r); + free(r->common.raw); + return r; } static void MwLLPixmapUpdateImpl(MwLLPixmap pixmap) { - MilskoCocoaPixmap *p = pixmap->cocoa.real; - [p updateWithData:pixmap->common.raw]; + MilskoCocoaPixmap* p = pixmap->cocoa.real; + [p updateWithData:pixmap->common.raw]; } static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { - MilskoCocoaPixmap *p = pixmap->cocoa.real; - [p destroy]; - [p dealloc]; - free(pixmap); + MilskoCocoaPixmap* p = pixmap->cocoa.real; + [p destroy]; + [p dealloc]; + free(pixmap); } -static void MwLLDrawPixmapImpl(MwLL handle, MwRect *rect, MwLLPixmap pixmap) { - MilskoCocoa *h = handle->cocoa.real; - [h drawPixmap:pixmap rect:rect]; - MwLLForceRender(handle); +static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { + MilskoCocoa* h = handle->cocoa.real; + [h drawPixmap:pixmap rect:rect]; + MwLLForceRender(handle); } static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { - MilskoCocoa *h = handle->cocoa.real; - [h setIcon:pixmap]; + MilskoCocoa* h = handle->cocoa.real; + [h setIcon:pixmap]; } static void MwLLForceRenderImpl(MwLL handle) { - MilskoCocoa *h = handle->cocoa.real; - [h forceRender]; + MilskoCocoa* h = handle->cocoa.real; + [h forceRender]; } -static void MwLLSetCursorImpl(MwLL handle, MwCursor *image, MwCursor *mask) { - MilskoCocoa *h = handle->cocoa.real; - [h setCursor:image mask:mask]; +static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { + MilskoCocoa* h = handle->cocoa.real; + [h setCursor:image mask:mask]; } -static void MwLLDetachImpl(MwLL handle, MwPoint *point) { - MilskoCocoa *h = handle->cocoa.real; - [h detachWithPoint:point]; +static void MwLLDetachImpl(MwLL handle, MwPoint* point) { + MilskoCocoa* h = handle->cocoa.real; + [h detachWithPoint:point]; } static void MwLLShowImpl(MwLL handle, int show) { - MilskoCocoa *h = handle->cocoa.real; - [h show:show]; + MilskoCocoa* h = handle->cocoa.real; + [h show:show]; } static void MwLLMakePopupImpl(MwLL handle, MwLL parent) { - MilskoCocoa *h = handle->cocoa.real; - [h makePopupWithParent:parent]; + MilskoCocoa* h = handle->cocoa.real; + [h 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]; + int maxy) { + MilskoCocoa* h = handle->cocoa.real; + [h setSizeHintsWithMinX:minx MinY:miny MaxX:maxx MaxY:maxy]; } static void MwLLMakeBorderlessImpl(MwLL handle, int toggle) { - MilskoCocoa *h = handle->cocoa.real; - [h makeBorderless:toggle]; + MilskoCocoa* h = handle->cocoa.real; + [h makeBorderless:toggle]; } static void MwLLFocusImpl(MwLL handle) { - MilskoCocoa *h = handle->cocoa.real; - [h focus]; + MilskoCocoa* h = handle->cocoa.real; + [h focus]; } static void MwLLGrabPointerImpl(MwLL handle, int toggle) { - MilskoCocoa *h = handle->cocoa.real; - [h grabPointer:toggle]; + MilskoCocoa* h = handle->cocoa.real; + [h grabPointer:toggle]; } -static void MwLLSetClipboardImpl(MwLL handle, const char *text) { - MilskoCocoa *h = handle->cocoa.real; - [h setClipboard:text]; +static void MwLLSetClipboardImpl(MwLL handle, const char* text) { + MilskoCocoa* h = handle->cocoa.real; + [h setClipboard:text]; } -static void MwLLGetClipboardImpl(MwLL handle) { (void)handle; } +static void MwLLGetClipboardImpl(MwLL handle) { + (void)handle; +} static void MwLLMakeToolWindowImpl(MwLL handle) { - MilskoCocoa *h = handle->cocoa.real; - [h makeToolWindow]; + MilskoCocoa* h = handle->cocoa.real; + [h makeToolWindow]; } -static void MwLLGetCursorCoordImpl(MwLL handle, MwPoint *point) { - MilskoCocoa *h = handle->cocoa.real; - [h getCursorCoord:point]; +static void MwLLGetCursorCoordImpl(MwLL handle, MwPoint* point) { + MilskoCocoa* h = handle->cocoa.real; + [h getCursorCoord:point]; } -static void MwLLGetScreenSizeImpl(MwLL handle, MwRect *rect) { - MilskoCocoa *h = handle->cocoa.real; - [h getScreenSize:rect]; +static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) { + MilskoCocoa* h = handle->cocoa.real; + [h getScreenSize:rect]; } -static void MwLLBeginStateChangeImpl(MwLL handle) { MwLLShow(handle, 0); } +static void MwLLBeginStateChangeImpl(MwLL handle) { + MwLLShow(handle, 0); +} -static void MwLLEndStateChangeImpl(MwLL handle) { MwLLShow(handle, 1); } +static void MwLLEndStateChangeImpl(MwLL handle) { + MwLLShow(handle, 1); +} -static int MwLLCocoaCallInitImpl(void) { return 0; } +static int MwLLCocoaCallInitImpl(void) { + return 0; +} #include "call.c" CALL(Cocoa); From d14c17b86e9fcd9929d95b14ca0aff7d5748e446 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 17 Mar 2026 17:43:22 -0700 Subject: [PATCH 71/94] wayland fixes --- examples/basic/clipboard.c | 8 ++--- include/Mw/LowLevel/Wayland.h | 1 + src/backend/wayland.c | 61 +++++++++++++++++++++-------------- 3 files changed, 41 insertions(+), 29 deletions(-) diff --git a/examples/basic/clipboard.c b/examples/basic/clipboard.c index c8882d35..384cbc6f 100644 --- a/examples/basic/clipboard.c +++ b/examples/basic/clipboard.c @@ -3,7 +3,7 @@ MwWidget window, instructions, text; void resize(MwWidget handle, void* user_data, void* call_data) { - unsigned int w, h, mh; + unsigned int w, h; (void)user_data; (void)call_data; @@ -12,13 +12,13 @@ void resize(MwWidget handle, void* user_data, void* call_data) { h = MwGetInteger(handle, MwNheight); MwVaApply(instructions, - MwNy, 50 + mh, + MwNy, 50, MwNwidth, w - 50 * 2, MwNheight, h - 125 - 50 * 3, NULL); MwVaApply(text, - MwNy, 200 + mh, + MwNy, 200, MwNwidth, w - 50 * 2, MwNheight, h - 125 - 50 * 3, NULL); @@ -30,7 +30,7 @@ void clipboard(MwWidget handle, void* user_data, void* call_data) { (void)user_data; if(clipboard != NULL) { - MwVaApply(text, MwNtext, clipboard); + MwVaApply(text, MwNtext, clipboard, NULL); MwForceRender(text); } MwForceRender(window); diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 0375eceb..78916dcd 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -186,6 +186,7 @@ struct _MwLLWayland { MwLL parent; MwBool force_render; + MwBool did_event_loop_early; struct _MwLLWaylandShmBuffer framebuffer; struct _MwLLWaylandShmBuffer cursor; diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 7d8faeee..46b3732a 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -5,6 +5,8 @@ #include #include "../../external/stb_ds.h" +#include "Mw/BaseTypes.h" +#include "Mw/LowLevel.h" #include #include @@ -432,6 +434,9 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri p.point = self->wayland.cur_mouse_pos; if(p.point.x > self->wayland.x && p.point.x < self->wayland.x + self->wayland.ww && p.point.y > self->wayland.y && p.point.y < self->wayland.y + self->wayland.wh) { int i; + + p.point.x -= self->wayland.x; + p.point.y -= self->wayland.y; switch(button) { case BTN_LEFT: p.button = MwLLMouseLeft; @@ -1038,12 +1043,6 @@ static int event_loop(MwLL handle) { fd.fd = wl_display_get_fd(wayland->display); fd.events = POLLIN; - while(wl_display_prepare_read(handle->wayland.display) != 0) { - if(wl_display_dispatch_pending(handle->wayland.display) > 0) { - return 0; - } - } - /* If an error other than EAGAIN happens, we have likely been disconnected from the Wayland session */ while(wl_display_flush(wayland->display) == -1) { if(errno != EAGAIN) { @@ -1060,19 +1059,17 @@ static int event_loop(MwLL handle) { } } + wl_display_prepare_read(handle->wayland.display); /* Condition where no events are being sent. */ if(!poll(&fd, 1, timeout)) { - wl_display_cancel_read(handle->wayland.display); + wl_display_cancel_read(wayland->display); /* In this case, we need to commit the surface for any animations, etc. */ - wl_surface_commit(handle->wayland.framebuffer.surface); + wl_surface_commit(wayland->framebuffer.surface); return 0; } - if(fd.revents & POLLIN) { - wl_display_read_events(wayland->display); - if(wl_display_dispatch_pending(wayland->display) > 0) { - } - } else { + wl_display_read_events(wayland->display); + if(wl_display_dispatch_pending(wayland->display) < 0) { wl_display_cancel_read(handle->wayland.display); } @@ -1588,32 +1585,42 @@ static int MwLLPendingImpl(MwLL handle) { MwBool pending = MwFALSE; struct timespec timeout; int i; + timeout.tv_nsec = 1; + timeout.tv_sec = 0; + + pending = wl_display_dispatch_timeout(handle->wayland.display, &timeout); if(handle->wayland.always_render) { + event_loop(handle); + return 0; + } + // if(handle->wayland.force_render) { + // // event_loop(handle); + // // handle->wayland.force_render = 0; + // // update_buffer(&handle->wayland.framebuffer); + // return 1; + // } + if(handle->wayland.events_pending || handle->wayland.force_render) { + handle->wayland.did_event_loop_early = MwTRUE; return event_loop(handle); } - timeout.tv_nsec = 10; - timeout.tv_sec = 0; - - if(handle->wayland.force_render) { - return 1; - } - if(handle->wayland.events_pending) { - return 1; - } - - return wl_display_dispatch_timeout(handle->wayland.display, &timeout); + return pending; } static void MwLLNextEventImpl(MwLL handle) { if(!handle->wayland.always_render) { - event_loop(handle); + if(handle->wayland.did_event_loop_early) { + handle->wayland.did_event_loop_early = MwFALSE; + } else { + event_loop(handle); + } } if(handle->wayland.events_pending) { handle->wayland.events_pending = 0; } if(handle->wayland.force_render) { + update_buffer(&handle->wayland.framebuffer); handle->wayland.force_render = 0; } } @@ -1683,6 +1690,10 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { cairo_destroy(c); cairo_surface_destroy(cs); + + MwLLForceRender(handle); + // update_buffer(&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) { if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { From 1cb8fb6c534eccce5e1937e68d5f724c373b9d97 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 17 Mar 2026 20:28:58 -0700 Subject: [PATCH 72/94] wayland: SEVERAL fixes --- include/Mw/LowLevel/Wayland.h | 4 +- src/backend/wayland.c | 72 ++++++++++++++++++++++------------- src/widget/combobox.c | 2 +- 3 files changed, 49 insertions(+), 29 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 78916dcd..c09f81b1 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -178,7 +178,9 @@ struct _MwLLWayland { MwBool configured; /* Whether or not xdg_toplevel_configure has run once */ - MwU32 x, y, ww, wh; /* Window position */ + MwI32 x, y; + MwI32 ox, oy; + MwU32 ww, wh; /* Window position */ MwPoint cur_mouse_pos; /* Currently known mouse position */ MwU32 mw, mh; /* Monitor width and height as advertised by wl_output.mode */ diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 46b3732a..21cc561f 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -7,6 +7,7 @@ #include "../../external/stb_ds.h" #include "Mw/BaseTypes.h" #include "Mw/LowLevel.h" +#include "Mw/LowLevel/Wayland/xdg-shell-client-protocol.h" #include #include @@ -405,12 +406,16 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time WAYLAND_EVENT_OP_START(self); - self->wayland.cur_mouse_pos.x = wl_fixed_to_double(surface_x); - self->wayland.cur_mouse_pos.y = wl_fixed_to_double(surface_y); - - p.point = self->wayland.cur_mouse_pos; + 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; MwLLDispatch(self, move, &p); + if(self->wayland.parent != NULL) { + if(!self->wayland.parent->wayland.currentlyHeldWidget) { + MwLLDispatch(self, down, &p); + } + } /* Only draw once every 50 milliseconds */ if((self->wayland.last_time + 50) <= time) { MwLLDispatch(self, draw, NULL); @@ -429,14 +434,16 @@ 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; + WAYLAND_EVENT_OP_START(self); p.point = self->wayland.cur_mouse_pos; - if(p.point.x > self->wayland.x && p.point.x < self->wayland.x + self->wayland.ww && p.point.y > self->wayland.y && p.point.y < self->wayland.y + self->wayland.wh) { + + if(p.point.x > x && p.point.x < x + self->wayland.ww && p.point.y > y && p.point.y < y + self->wayland.wh) { int i; - p.point.x -= self->wayland.x; - p.point.y -= self->wayland.y; switch(button) { case BTN_LEFT: p.button = MwLLMouseLeft; @@ -1006,13 +1013,18 @@ static void region_invalidate(MwLL handle) { if(!handle->wayland.configured) { return; } - wl_region_subtract(handle->wayland.region, handle->wayland.x, handle->wayland.y, handle->wayland.ww, handle->wayland.wh); + wl_region_subtract(handle->wayland.region, 0, 0, handle->wayland.ww, handle->wayland.wh); } static void region_setup(MwLL handle) { if(!handle->wayland.configured) { return; } - wl_region_add(handle->wayland.region, handle->wayland.x, handle->wayland.y, handle->wayland.ww, handle->wayland.wh); + + if(handle->wayland.type == MWLL_WAYLAND_POPUP) { + wl_region_add(handle->wayland.region, 0, 0, handle->wayland.ww + abs(handle->wayland.x), handle->wayland.wh + abs(handle->wayland.y)); + } else { + wl_region_add(handle->wayland.region, handle->wayland.x, handle->wayland.y, handle->wayland.ww + abs(handle->wayland.x), handle->wayland.wh + abs(handle->wayland.y)); + } wl_surface_set_input_region(handle->wayland.framebuffer.surface, handle->wayland.region); wl_surface_set_opaque_region(handle->wayland.framebuffer.surface, handle->wayland.region); } @@ -1116,6 +1128,8 @@ static void setup_toplevel(MwLL r, int x, int y) { r->wayland.type = MWLL_WAYLAND_TOPLEVEL; r->wayland.toplevel = malloc(sizeof(struct _MwLLWaylandTopLevel)); + r->wayland.x = x; + r->wayland.y = y; setup_callbacks(&r->wayland); @@ -1251,9 +1265,9 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { /* Sublevel setup function */ static void destroy_sublevel(MwLL r) { - wl_subsurface_destroy(r->wayland.sublevel->subsurface); + framebuffer_destroy(&r->wayland); - wl_surface_destroy(r->wayland.framebuffer.surface); + wl_subsurface_destroy(r->wayland.sublevel->subsurface); free(r->wayland.sublevel); } @@ -1315,10 +1329,11 @@ static void setup_popup(MwLL r, int x, int y) { r->wayland.popup->xdg_positioner = xdg_wm_base_create_positioner(r->wayland.popup->xdg_wm_base); xdg_positioner_set_size(r->wayland.popup->xdg_positioner, r->wayland.ww, r->wayland.wh); - xdg_positioner_set_anchor(r->wayland.popup->xdg_positioner, XDG_POSITIONER_ANCHOR_NONE); xdg_positioner_set_anchor_rect( - r->wayland.popup->xdg_positioner, 0, 0, 1, 1); - xdg_positioner_set_offset(r->wayland.popup->xdg_positioner, x, y); + r->wayland.popup->xdg_positioner, + x, y, r->wayland.ww, r->wayland.wh); + xdg_positioner_set_anchor(r->wayland.popup->xdg_positioner, XDG_POSITIONER_ANCHOR_TOP_LEFT); + xdg_positioner_set_gravity(r->wayland.popup->xdg_positioner, XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT); xdg_surface = topmost_parent->wayland.toplevel->xdg_surface; @@ -1341,6 +1356,9 @@ static void setup_popup(MwLL r, int x, int y) { /* 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); } /* Popup destroy function */ @@ -1431,7 +1449,7 @@ static void MwLLDestroyImpl(MwLL handle) { pthread_mutex_unlock(&handle->wayland.eventsMutex); pthread_mutex_destroy(&handle->wayland.eventsMutex); - framebuffer_destroy(&handle->wayland); + // framebuffer_destroy(&handle->wayland); buffer_destroy(&handle->wayland.cursor); wl_region_destroy(handle->wayland.region); @@ -1482,8 +1500,6 @@ static void MwLLSetXYImpl(MwLL handle, int x, int y) { wl_subsurface_set_position(handle->wayland.sublevel->subsurface, x, y); } if(handle->wayland.type == MWLL_WAYLAND_POPUP) { - destroy_popup(handle); - setup_popup(handle, x, y); } region_setup(handle); @@ -1507,6 +1523,11 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { xdg_surface_set_window_geometry(handle->wayland.toplevel->xdg_surface, 0, 0, handle->wayland.ww, handle->wayland.wh); } + if(handle->wayland.type == MWLL_WAYLAND_POPUP) { + destroy_popup(handle); + setup_popup(handle, handle->wayland.x, handle->wayland.y); + } + refresh: region_setup(handle); @@ -1594,12 +1615,12 @@ static int MwLLPendingImpl(MwLL handle) { event_loop(handle); return 0; } - // if(handle->wayland.force_render) { - // // event_loop(handle); - // // handle->wayland.force_render = 0; - // // update_buffer(&handle->wayland.framebuffer); - // return 1; - // } + if(handle->wayland.force_render) { + // event_loop(handle); + // handle->wayland.force_render = 0; + // update_buffer(&handle->wayland.framebuffer); + return 1; + } if(handle->wayland.events_pending || handle->wayland.force_render) { handle->wayland.did_event_loop_early = MwTRUE; return event_loop(handle); @@ -1812,7 +1833,7 @@ static void MwLLDetachImpl(MwLL handle, MwPoint* point) { switch(handle->wayland.type_to_be) { case MWLL_WAYLAND_POPUP: setup_popup(handle, point->x, point->y); - return; + break; default: setup_toplevel(handle, point->x, point->y); break; @@ -1842,9 +1863,6 @@ static void MwLLMakeBorderlessImpl(MwLL handle, int toggle) { zxdg_toplevel_decoration_v1_set_mode( dec->decoration, ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE); - } else { - /* TODO: hide our custom window decorations when we have them. */ - printf("zxdg null\n"); } } } diff --git a/src/widget/combobox.c b/src/widget/combobox.c index 6b543733..591258f9 100644 --- a/src/widget/combobox.c +++ b/src/widget/combobox.c @@ -138,8 +138,8 @@ static void click(MwWidget handle) { p.x = 0; p.y = MwGetInteger(handle, MwNheight); MwLLBeginStateChange(cb->listbox->lowlevel); - MwLLDetach(cb->listbox->lowlevel, &p); MwLLMakeToolWindow(cb->listbox->lowlevel); + MwLLDetach(cb->listbox->lowlevel, &p); MwLLEndStateChange(cb->listbox->lowlevel); } else { MwLLSetCursor(handle->lowlevel, &MwCursorDefault, &MwCursorDefaultMask); From eb0919333a78355a49f03bf1f8772288c00ebf47 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 17 Mar 2026 20:39:37 -0700 Subject: [PATCH 73/94] wayland: fix several examples --- 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 21cc561f..d7d53911 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1616,7 +1616,7 @@ static int MwLLPendingImpl(MwLL handle) { return 0; } if(handle->wayland.force_render) { - // event_loop(handle); + MwLLDispatch(handle, draw, NULL); // handle->wayland.force_render = 0; // update_buffer(&handle->wayland.framebuffer); return 1; From fc7896b5ce1e018ead507f0033ec235273172847 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Tue, 17 Mar 2026 22:17:05 -0700 Subject: [PATCH 74/94] wayland: improve event loop --- src/backend/wayland.c | 29 +- src/widget/opengl.c | 627 +++++++++++++++++++++--------------------- 2 files changed, 326 insertions(+), 330 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index d7d53911..7037a5d9 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1046,8 +1046,12 @@ static void xdg_toplevel_icon_manager_v1_interface_destroy(struct _MwLLWayland* /* Standard Wayland event loop. */ static int event_loop(MwLL handle) { struct pollfd fd; - int timeout = 1; + struct timespec timeout; struct _MwLLWayland* wayland = &handle->wayland; + int res; + + timeout.tv_nsec = 1; + timeout.tv_sec = 0; if(wayland->display == NULL) { return 0; @@ -1072,19 +1076,15 @@ static int event_loop(MwLL handle) { } wl_display_prepare_read(handle->wayland.display); - /* Condition where no events are being sent. */ - if(!poll(&fd, 1, timeout)) { - wl_display_cancel_read(wayland->display); - /* In this case, we need to commit the surface for any animations, etc. */ + wl_display_read_events(wayland->display); + if((res = wl_display_dispatch_timeout(wayland->display, &timeout)) <= 0) { + if(res < 0) { + wl_display_cancel_read(handle->wayland.display); + } + wl_surface_commit(wayland->framebuffer.surface); return 0; } - - wl_display_read_events(wayland->display); - if(wl_display_dispatch_pending(wayland->display) < 0) { - wl_display_cancel_read(handle->wayland.display); - } - return 1; } @@ -1605,20 +1605,17 @@ static void MwLLFreeColorImpl(MwLLColor color) { static int MwLLPendingImpl(MwLL handle) { MwBool pending = MwFALSE; struct timespec timeout; - int i; timeout.tv_nsec = 1; timeout.tv_sec = 0; + int i; pending = wl_display_dispatch_timeout(handle->wayland.display, &timeout); if(handle->wayland.always_render) { event_loop(handle); return 0; - } - if(handle->wayland.force_render) { + } else if(handle->wayland.force_render) { MwLLDispatch(handle, draw, NULL); - // handle->wayland.force_render = 0; - // update_buffer(&handle->wayland.framebuffer); return 1; } if(handle->wayland.events_pending || handle->wayland.force_render) { diff --git a/src/widget/opengl.c b/src/widget/opengl.c index 0f9c5c24..b508ef6b 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -4,46 +4,46 @@ #include #ifdef USE_GDI -typedef HGLRC(WINAPI *MWwglCreateContext)(HDC); -typedef BOOL(WINAPI *MWwglMakeCurrent)(HDC, HGLRC); -typedef PROC(WINAPI *MWwglGetProcAddress)(LPCSTR); -typedef BOOL(WINAPI *MWwglDeleteContext)(HGLRC); +typedef HGLRC(WINAPI* MWwglCreateContext)(HDC); +typedef BOOL(WINAPI* MWwglMakeCurrent)(HDC, HGLRC); +typedef PROC(WINAPI* MWwglGetProcAddress)(LPCSTR); +typedef BOOL(WINAPI* MWwglDeleteContext)(HGLRC); typedef struct gdiopengl { - HDC dc; - HGLRC gl; + HDC dc; + HGLRC gl; - void *lib; + void* lib; - MWwglCreateContext wglCreateContext; - MWwglMakeCurrent wglMakeCurrent; - MWwglDeleteContext wglDeleteContext; - MWwglGetProcAddress wglGetProcAddress; + MWwglCreateContext wglCreateContext; + MWwglMakeCurrent wglMakeCurrent; + MWwglDeleteContext wglDeleteContext; + MWwglGetProcAddress wglGetProcAddress; } gdiopengl_t; #endif #ifdef USE_X11 -typedef XVisualInfo *(*MWglXChooseVisual)(Display *dpy, int screen, - int *attribList); -typedef GLXContext (*MWglXCreateContext)(Display *dpy, XVisualInfo *vis, - GLXContext shareList, Bool direct); -typedef void (*MWglXDestroyContext)(Display *dpy, GLXContext ctx); -typedef Bool (*MWglXMakeCurrent)(Display *dpy, GLXDrawable drawable, - GLXContext ctx); -typedef void (*MWglXSwapBuffers)(Display *dpy, GLXDrawable drawable); -typedef void *(*MWglXGetProcAddress)(const GLubyte *procname); +typedef XVisualInfo* (*MWglXChooseVisual)(Display* dpy, int screen, + int* attribList); +typedef GLXContext (*MWglXCreateContext)(Display* dpy, XVisualInfo* vis, + GLXContext shareList, Bool direct); +typedef void (*MWglXDestroyContext)(Display* dpy, GLXContext ctx); +typedef Bool (*MWglXMakeCurrent)(Display* dpy, GLXDrawable drawable, + GLXContext ctx); +typedef void (*MWglXSwapBuffers)(Display* dpy, GLXDrawable drawable); +typedef void* (*MWglXGetProcAddress)(const GLubyte* procname); typedef struct x11opengl { - XVisualInfo *visual; - GLXContext gl; + XVisualInfo* visual; + GLXContext gl; - void *lib; + void* lib; - MWglXChooseVisual glXChooseVisual; - MWglXCreateContext glXCreateContext; - MWglXDestroyContext glXDestroyContext; - MWglXMakeCurrent glXMakeCurrent; - MWglXSwapBuffers glXSwapBuffers; - MWglXGetProcAddress glXGetProcAddress; + MWglXChooseVisual glXChooseVisual; + MWglXCreateContext glXCreateContext; + MWglXDestroyContext glXDestroyContext; + MWglXMakeCurrent glXMakeCurrent; + MWglXSwapBuffers glXSwapBuffers; + MWglXGetProcAddress glXGetProcAddress; } x11opengl_t; #endif @@ -52,385 +52,384 @@ typedef struct x11opengl { #include typedef struct waylandopengl { - EGLNativeWindowType egl_window_native; - EGLDisplay egl_display; - EGLContext egl_context; - EGLSurface egl_surface; - EGLConfig egl_config; + EGLNativeWindowType egl_window_native; + EGLDisplay egl_display; + EGLContext egl_context; + EGLSurface egl_surface; + EGLConfig egl_config; } waylandopengl_t; #endif static int create(MwWidget handle) { - void *r = NULL; - MwWidget w = handle; + void* r = NULL; + MwWidget w = handle; #ifdef USE_GDI - if (handle->lowlevel->common.type == MwLLBackendGDI) { - PIXELFORMATDESCRIPTOR pfd; - int pf; - gdiopengl_t *o = r = malloc(sizeof(*o)); + if(handle->lowlevel->common.type == MwLLBackendGDI) { + PIXELFORMATDESCRIPTOR pfd; + int pf; + gdiopengl_t* o = r = malloc(sizeof(*o)); - memset(&pfd, 0, sizeof(pfd)); - pfd.nSize = sizeof(pfd); - pfd.nVersion = 1; - pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; - pfd.cDepthBits = 32; - pfd.cColorBits = 32; + memset(&pfd, 0, sizeof(pfd)); + pfd.nSize = sizeof(pfd); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + pfd.cDepthBits = 32; + pfd.cColorBits = 32; - o->dc = GetDC(handle->lowlevel->gdi.hWnd); + o->dc = GetDC(handle->lowlevel->gdi.hWnd); - pf = ChoosePixelFormat(o->dc, &pfd); - SetPixelFormat(o->dc, pf, &pfd); + pf = ChoosePixelFormat(o->dc, &pfd); + SetPixelFormat(o->dc, pf, &pfd); - o->lib = MwDynamicOpen("opengl32.dll"); + o->lib = MwDynamicOpen("opengl32.dll"); - o->wglCreateContext = - (MWwglCreateContext)(void *)MwDynamicSymbol(o->lib, "wglCreateContext"); - o->wglMakeCurrent = - (MWwglMakeCurrent)(void *)MwDynamicSymbol(o->lib, "wglMakeCurrent"); - o->wglDeleteContext = - (MWwglDeleteContext)(void *)MwDynamicSymbol(o->lib, "wglDeleteContext"); - o->wglGetProcAddress = (MWwglGetProcAddress)(void *)MwDynamicSymbol( - o->lib, "wglGetProcAddress"); + o->wglCreateContext = + (MWwglCreateContext)(void*)MwDynamicSymbol(o->lib, "wglCreateContext"); + o->wglMakeCurrent = + (MWwglMakeCurrent)(void*)MwDynamicSymbol(o->lib, "wglMakeCurrent"); + o->wglDeleteContext = + (MWwglDeleteContext)(void*)MwDynamicSymbol(o->lib, "wglDeleteContext"); + o->wglGetProcAddress = (MWwglGetProcAddress)(void*)MwDynamicSymbol( + o->lib, "wglGetProcAddress"); - o->gl = o->wglCreateContext(o->dc); - } + o->gl = o->wglCreateContext(o->dc); + } #endif #ifdef USE_X11 - if (handle->lowlevel->common.type == MwLLBackendX11) { - int attribs[5]; - const char *glpath[] = {"libGL.so", "/usr/local/lib/libGL.so", - "/usr/X11R7/lib/libGL.so", "/usr/pkg/lib/libGL.so"}; - int glincr = 0; - x11opengl_t *o = r = malloc(sizeof(*o)); + if(handle->lowlevel->common.type == MwLLBackendX11) { + int attribs[5]; + const char* glpath[] = {"libGL.so", "/usr/local/lib/libGL.so", + "/usr/X11R7/lib/libGL.so", "/usr/pkg/lib/libGL.so"}; + int glincr = 0; + x11opengl_t* o = r = malloc(sizeof(*o)); - attribs[0] = GLX_RGBA; - attribs[1] = GLX_DOUBLEBUFFER; - attribs[2] = GLX_DEPTH_SIZE; - attribs[3] = 24; - attribs[4] = None; + attribs[0] = GLX_RGBA; + attribs[1] = GLX_DOUBLEBUFFER; + attribs[2] = GLX_DEPTH_SIZE; + attribs[3] = 24; + attribs[4] = None; - while (glpath[glincr] != NULL && - (o->lib = MwDynamicOpen(glpath[glincr++])) == NULL) - ; + while(glpath[glincr] != NULL && + (o->lib = MwDynamicOpen(glpath[glincr++])) == NULL); - o->glXChooseVisual = - (MWglXChooseVisual)MwDynamicSymbol(o->lib, "glXChooseVisual"); - o->glXCreateContext = - (MWglXCreateContext)MwDynamicSymbol(o->lib, "glXCreateContext"); - o->glXDestroyContext = - (MWglXDestroyContext)MwDynamicSymbol(o->lib, "glXDestroyContext"); - o->glXMakeCurrent = - (MWglXMakeCurrent)MwDynamicSymbol(o->lib, "glXMakeCurrent"); - o->glXSwapBuffers = - (MWglXSwapBuffers)MwDynamicSymbol(o->lib, "glXSwapBuffers"); - o->glXGetProcAddress = - (MWglXGetProcAddress)MwDynamicSymbol(o->lib, "glXGetProcAddress"); + o->glXChooseVisual = + (MWglXChooseVisual)MwDynamicSymbol(o->lib, "glXChooseVisual"); + o->glXCreateContext = + (MWglXCreateContext)MwDynamicSymbol(o->lib, "glXCreateContext"); + o->glXDestroyContext = + (MWglXDestroyContext)MwDynamicSymbol(o->lib, "glXDestroyContext"); + o->glXMakeCurrent = + (MWglXMakeCurrent)MwDynamicSymbol(o->lib, "glXMakeCurrent"); + o->glXSwapBuffers = + (MWglXSwapBuffers)MwDynamicSymbol(o->lib, "glXSwapBuffers"); + o->glXGetProcAddress = + (MWglXGetProcAddress)MwDynamicSymbol(o->lib, "glXGetProcAddress"); - /* XXX: fix this */ - o->visual = o->glXChooseVisual(handle->lowlevel->x11.display, - DefaultScreen(handle->lowlevel->x11.display), - attribs); - o->gl = o->glXCreateContext(handle->lowlevel->x11.display, o->visual, NULL, - GL_TRUE); - } + /* XXX: fix this */ + o->visual = o->glXChooseVisual(handle->lowlevel->x11.display, + DefaultScreen(handle->lowlevel->x11.display), + attribs); + o->gl = o->glXCreateContext(handle->lowlevel->x11.display, o->visual, NULL, + GL_TRUE); + } #endif #ifdef USE_WAYLAND - if (handle->lowlevel->common.type == MwLLBackendWayland) { - int err; - EGLint numConfigs; - EGLint majorVersion; - EGLint minorVersion; - EGLContext context; - EGLSurface surface; - EGLint fbAttribs[] = {EGL_SURFACE_TYPE, - EGL_WINDOW_BIT, - EGL_RENDERABLE_TYPE, - EGL_OPENGL_ES2_BIT, - EGL_RED_SIZE, - 8, - EGL_GREEN_SIZE, - 8, - EGL_BLUE_SIZE, - 8, - EGL_DEPTH_SIZE, - 24, - EGL_RENDERABLE_TYPE, - EGL_OPENGL_BIT, - EGL_NONE}; - EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, - 1, - EGL_CONTEXT_MAJOR_VERSION, - 1, - EGL_CONTEXT_MINOR_VERSION, - 1, - EGL_NONE}; - EGLDisplay display; - waylandopengl_t *o = r = malloc(sizeof(*o)); - MwLL topmost_parent = handle->lowlevel->wayland.parent; - topmost_parent->wayland.always_render = MwTRUE; + if(handle->lowlevel->common.type == MwLLBackendWayland) { + int err; + EGLint numConfigs; + EGLint majorVersion; + EGLint minorVersion; + EGLContext context; + EGLSurface surface; + EGLint fbAttribs[] = {EGL_SURFACE_TYPE, + EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, + EGL_OPENGL_ES2_BIT, + EGL_RED_SIZE, + 8, + EGL_GREEN_SIZE, + 8, + EGL_BLUE_SIZE, + 8, + EGL_DEPTH_SIZE, + 24, + EGL_RENDERABLE_TYPE, + EGL_OPENGL_BIT, + EGL_NONE}; + EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, + 1, + EGL_CONTEXT_MAJOR_VERSION, + 1, + EGL_CONTEXT_MINOR_VERSION, + 1, + EGL_NONE}; + EGLDisplay display; + waylandopengl_t* o = r = malloc(sizeof(*o)); + MwLL topmost_parent = handle->lowlevel->wayland.parent; + topmost_parent->wayland.always_render = MwTRUE; - while (topmost_parent->wayland.parent != NULL) { - topmost_parent = topmost_parent->wayland.parent; - topmost_parent->wayland.always_render = MwTRUE; - } + while(topmost_parent->wayland.parent != NULL) { + topmost_parent = topmost_parent->wayland.parent; + topmost_parent->wayland.always_render = MwTRUE; + } - display = - eglGetDisplay((EGLNativeDisplayType)handle->lowlevel->wayland.display); - if (display == EGL_NO_DISPLAY) { - printf("ERROR: eglGetDisplay, %0X\n", eglGetError()); - return MwFALSE; - } - /* Initialize EGL */ - if (!eglInitialize(display, &majorVersion, &minorVersion)) { - printf("ERROR: eglInitialize, %0X\n", eglGetError()); - return MwFALSE; - } + display = + eglGetDisplay((EGLNativeDisplayType)handle->lowlevel->wayland.display); + if(display == EGL_NO_DISPLAY) { + printf("ERROR: eglGetDisplay, %0X\n", eglGetError()); + return MwFALSE; + } + /* Initialize EGL */ + if(!eglInitialize(display, &majorVersion, &minorVersion)) { + printf("ERROR: eglInitialize, %0X\n", eglGetError()); + return MwFALSE; + } - /* Get configs */ - if ((eglGetConfigs(display, NULL, 0, &numConfigs) != EGL_TRUE) || - (numConfigs == 0)) { - printf("ERROR: eglGetConfigs, %0X\n", eglGetError()); - return MwFALSE; - } + /* Get configs */ + if((eglGetConfigs(display, NULL, 0, &numConfigs) != EGL_TRUE) || + (numConfigs == 0)) { + printf("ERROR: eglGetConfigs, %0X\n", eglGetError()); + return MwFALSE; + } - /* Choose config */ - if ((eglChooseConfig(display, fbAttribs, &o->egl_config, 1, &numConfigs) != - EGL_TRUE) || - (numConfigs != 1)) { - printf("ERROR: eglChooseConfig, %0X\n", eglGetError()); - return MwFALSE; - } + /* Choose config */ + if((eglChooseConfig(display, fbAttribs, &o->egl_config, 1, &numConfigs) != + EGL_TRUE) || + (numConfigs != 1)) { + printf("ERROR: eglChooseConfig, %0X\n", eglGetError()); + return MwFALSE; + } - o->egl_window_native = (EGLNativeWindowType)wl_egl_window_create( - handle->lowlevel->wayland.framebuffer.surface, - handle->lowlevel->wayland.ww, handle->lowlevel->wayland.wh); - if (!o->egl_window_native) { - printf("ERROR: wl_egl_window_create, EGL_NO_SURFACE\n"); - return MwFALSE; - } + o->egl_window_native = (EGLNativeWindowType)wl_egl_window_create( + handle->lowlevel->wayland.framebuffer.surface, + handle->lowlevel->wayland.ww, handle->lowlevel->wayland.wh); + if(!o->egl_window_native) { + printf("ERROR: wl_egl_window_create, EGL_NO_SURFACE\n"); + return MwFALSE; + } - /* Create a surface */ - surface = eglCreateWindowSurface(display, o->egl_config, - o->egl_window_native, NULL); - if (surface == EGL_NO_SURFACE) { - printf("ERROR: eglCreateWindowSurface, %0X\n", eglGetError()); - return MwFALSE; - } + /* Create a surface */ + surface = eglCreateWindowSurface(display, o->egl_config, + o->egl_window_native, NULL); + if(surface == EGL_NO_SURFACE) { + printf("ERROR: eglCreateWindowSurface, %0X\n", eglGetError()); + return MwFALSE; + } - eglBindAPI(EGL_OPENGL_API); + eglBindAPI(EGL_OPENGL_API); - /* Create a GL context */ - context = eglCreateContext(display, o->egl_config, EGL_NO_CONTEXT, - contextAttribs); - if (context == EGL_NO_CONTEXT) { - printf("ERROR: eglCreateContext, %0X\n", eglGetError()); - return MwFALSE; - } + /* Create a GL context */ + context = eglCreateContext(display, o->egl_config, EGL_NO_CONTEXT, + contextAttribs); + if(context == EGL_NO_CONTEXT) { + printf("ERROR: eglCreateContext, %0X\n", eglGetError()); + return MwFALSE; + } - if (!eglMakeCurrent(display, surface, surface, context)) { - printf("ERROR: eglMakeCurrent (setup): %0X\n", eglGetError()); - } + if(!eglMakeCurrent(display, surface, surface, context)) { + printf("ERROR: eglMakeCurrent (setup): %0X\n", eglGetError()); + } - o->egl_display = display; - o->egl_surface = surface; - o->egl_context = context; - } + o->egl_display = display; + o->egl_surface = surface; + o->egl_context = context; + } #endif - handle->internal = r; - handle->lowlevel->common.copy_buffer = 0; + handle->internal = r; + 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) { - MwWidget w = handle; + MwWidget w = handle; #ifdef USE_GDI - if (handle->lowlevel->common.type == MwLLBackendGDI) { - gdiopengl_t *o = handle->internal; + if(handle->lowlevel->common.type == MwLLBackendGDI) { + gdiopengl_t* o = handle->internal; - o->wglMakeCurrent(NULL, NULL); - DeleteDC(o->dc); - o->wglDeleteContext(o->gl); + o->wglMakeCurrent(NULL, NULL); + DeleteDC(o->dc); + o->wglDeleteContext(o->gl); - MwDynamicClose(o->lib); - } + MwDynamicClose(o->lib); + } #endif #ifdef USE_X11 - if (handle->lowlevel->common.type == MwLLBackendX11) { - x11opengl_t *o = handle->internal; + if(handle->lowlevel->common.type == MwLLBackendX11) { + x11opengl_t* o = handle->internal; - o->glXMakeCurrent(handle->lowlevel->x11.display, None, NULL); - o->glXDestroyContext(handle->lowlevel->x11.display, o->gl); + o->glXMakeCurrent(handle->lowlevel->x11.display, None, NULL); + o->glXDestroyContext(handle->lowlevel->x11.display, o->gl); - MwDynamicClose(o->lib); - } + MwDynamicClose(o->lib); + } #endif #ifdef USE_WAYLAND - if (handle->lowlevel->common.type == MwLLBackendWayland) { - /* todo */ - } + if(handle->lowlevel->common.type == MwLLBackendWayland) { + /* todo */ + } #endif - while (w->parent != NULL) - w = w->parent; + while(w->parent != NULL) + w = w->parent; - w->berserk--; + w->berserk--; - free(handle->internal); + free(handle->internal); } static void mwOpenGLMakeCurrentImpl(MwWidget handle) { - /* these swap interval functions belonging here actually stink! */ + /* these swap interval functions belonging here actually stink! */ #ifdef USE_GDI - if (handle->lowlevel->common.type == MwLLBackendGDI) { - gdiopengl_t *o = handle->internal; - void (*swap_interval_ext)(int) = NULL; + if(handle->lowlevel->common.type == MwLLBackendGDI) { + gdiopengl_t* o = handle->internal; + void (*swap_interval_ext)(int) = NULL; - o->wglMakeCurrent(o->dc, o->gl); + o->wglMakeCurrent(o->dc, o->gl); - if ((swap_interval_ext = - MwOpenGLGetProcAddress(handle, "wglSwapIntervalEXT")) != NULL) { - swap_interval_ext(1); - } - } + if((swap_interval_ext = + MwOpenGLGetProcAddress(handle, "wglSwapIntervalEXT")) != NULL) { + swap_interval_ext(1); + } + } #endif #ifdef USE_X11 - if (handle->lowlevel->common.type == MwLLBackendX11) { - x11opengl_t *o = handle->internal; - void (*swap_interval_ext)(Display *, GLXDrawable, int) = NULL; - void (*swap_interval_mesa)(unsigned int) = NULL; - void (*swap_interval_sgi)(int) = NULL; + if(handle->lowlevel->common.type == MwLLBackendX11) { + x11opengl_t* o = handle->internal; + void (*swap_interval_ext)(Display*, GLXDrawable, int) = NULL; + void (*swap_interval_mesa)(unsigned int) = NULL; + void (*swap_interval_sgi)(int) = NULL; - o->glXMakeCurrent(handle->lowlevel->x11.display, - handle->lowlevel->x11.window, o->gl); + o->glXMakeCurrent(handle->lowlevel->x11.display, + handle->lowlevel->x11.window, o->gl); - if ((swap_interval_ext = - MwOpenGLGetProcAddress(handle, "glXSwapIntervalEXT")) != NULL) { - swap_interval_ext(handle->lowlevel->x11.display, - handle->lowlevel->x11.window, 1); - } + if((swap_interval_ext = + MwOpenGLGetProcAddress(handle, "glXSwapIntervalEXT")) != NULL) { + swap_interval_ext(handle->lowlevel->x11.display, + handle->lowlevel->x11.window, 1); + } - if ((swap_interval_mesa = - MwOpenGLGetProcAddress(handle, "glXSwapIntervalMESA")) != NULL) { - swap_interval_mesa(1); - } + if((swap_interval_mesa = + MwOpenGLGetProcAddress(handle, "glXSwapIntervalMESA")) != NULL) { + swap_interval_mesa(1); + } - if ((swap_interval_sgi = - MwOpenGLGetProcAddress(handle, "glXSwapIntervalSGI")) != NULL) { - swap_interval_sgi(1); - } - } + if((swap_interval_sgi = + MwOpenGLGetProcAddress(handle, "glXSwapIntervalSGI")) != NULL) { + swap_interval_sgi(1); + } + } #endif #ifdef USE_WAYLAND - if (handle->lowlevel->common.type == MwLLBackendWayland) { - waylandopengl_t *o = handle->internal; + if(handle->lowlevel->common.type == MwLLBackendWayland) { + waylandopengl_t* o = handle->internal; - if (!eglMakeCurrent(o->egl_display, o->egl_surface, o->egl_surface, - o->egl_context)) { - printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); - } + if(!eglMakeCurrent(o->egl_display, o->egl_surface, o->egl_surface, + o->egl_context)) { + printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); + } - eglSwapInterval(o->egl_display, 1); - } + eglSwapInterval(o->egl_display, 1); + } #endif } static void mwOpenGLSwapBufferImpl(MwWidget handle) { #ifdef USE_GDI - if (handle->lowlevel->common.type == MwLLBackendGDI) { - gdiopengl_t *o = handle->internal; + if(handle->lowlevel->common.type == MwLLBackendGDI) { + gdiopengl_t* o = handle->internal; - SwapBuffers(o->dc); - } + SwapBuffers(o->dc); + } #endif #ifdef USE_X11 - if (handle->lowlevel->common.type == MwLLBackendX11) { - x11opengl_t *o = handle->internal; + if(handle->lowlevel->common.type == MwLLBackendX11) { + x11opengl_t* o = handle->internal; - o->glXSwapBuffers(handle->lowlevel->x11.display, - handle->lowlevel->x11.window); - } + o->glXSwapBuffers(handle->lowlevel->x11.display, + handle->lowlevel->x11.window); + } #endif #ifdef USE_WAYLAND - if (handle->lowlevel->common.type == MwLLBackendWayland) { - waylandopengl_t *o = handle->internal; - eglSwapInterval(o->egl_display, 0); - if (!eglSwapBuffers(o->egl_display, o->egl_surface)) { - printf("ERROR: eglSwapBuffers, %0X\n", eglGetError()); - }; - wl_egl_window_resize((struct wl_egl_window *)o->egl_window_native, - handle->lowlevel->wayland.ww, - handle->lowlevel->wayland.wh, 0, 0); - MwLLForceRender(handle->lowlevel); - } + if(handle->lowlevel->common.type == MwLLBackendWayland) { + waylandopengl_t* o = handle->internal; + // eglSwapInterval(o->egl_display, 0); + if(!eglSwapBuffers(o->egl_display, o->egl_surface)) { + printf("ERROR: eglSwapBuffers, %0X\n", eglGetError()); + }; + wl_egl_window_resize((struct wl_egl_window*)o->egl_window_native, + handle->lowlevel->wayland.ww, + handle->lowlevel->wayland.wh, 0, 0); + // MwLLForceRender(handle->lowlevel); + } #endif } -static void *mwOpenGLGetProcAddressImpl(MwWidget handle, const char *name) { +static void* mwOpenGLGetProcAddressImpl(MwWidget handle, const char* name) { #ifdef USE_GDI - if (handle->lowlevel->common.type == MwLLBackendGDI) { - gdiopengl_t *o = handle->internal; + if(handle->lowlevel->common.type == MwLLBackendGDI) { + gdiopengl_t* o = handle->internal; - return o->wglGetProcAddress(name); - } + return o->wglGetProcAddress(name); + } #endif #ifdef USE_X11 - if (handle->lowlevel->common.type == MwLLBackendX11) { - x11opengl_t *o = handle->internal; + if(handle->lowlevel->common.type == MwLLBackendX11) { + x11opengl_t* o = handle->internal; - return o->glXGetProcAddress((const GLubyte *)name); - } + return o->glXGetProcAddress((const GLubyte*)name); + } #endif #ifdef USE_WAYLAND - if (handle->lowlevel->common.type == MwLLBackendWayland) { - return eglGetProcAddress(name); - } + if(handle->lowlevel->common.type == MwLLBackendWayland) { + return eglGetProcAddress(name); + } #endif - return NULL; + return NULL; } -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); + } } -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; +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; -#endif \ No newline at end of file +#endif From 9309b5fe83b2ac924824d24620bf44d2c19f4d8e Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 18 Mar 2026 19:24:51 -0700 Subject: [PATCH 75/94] remove old hacks from wayland code, including MwLLBeginDraw and MwLLEndDraw which was really only ever needed for wayland and not anymore --- include/Mw/LowLevel.h | 2 -- src/backend/call.c | 6 ++---- src/backend/cocoa.m | 26 ++++++++----------------- src/backend/gdi.c | 8 -------- src/backend/wayland.c | 45 ++----------------------------------------- src/backend/x11.c | 11 ++--------- src/core.c | 3 --- src/lowlevel.c | 3 --- src/widget/opengl.c | 2 -- 9 files changed, 14 insertions(+), 92 deletions(-) diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index 9766d052..30d7f310 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -190,8 +190,6 @@ MWDECL void (*MwLLDestroy)(MwLL handle); MWDECL void (*MwLLPolygon)(MwLL handle, MwPoint* points, int points_count, MwLLColor color); MWDECL void (*MwLLLine)(MwLL handle, MwPoint* points, MwLLColor color); -MWDECL void (*MwLLBeginDraw)(MwLL handle); -MWDECL void (*MwLLEndDraw)(MwLL handle); MWDECL MwLLColor (*MwLLAllocColor)(MwLL handle, int r, int g, int b); MWDECL void (*MwLLColorUpdate)(MwLL handle, MwLLColor c, int r, int g, int b); diff --git a/src/backend/call.c b/src/backend/call.c index e2ce934c..2ce5ed23 100644 --- a/src/backend/call.c +++ b/src/backend/call.c @@ -8,10 +8,8 @@ MwLLCreate = MwLLCreateImpl; \ MwLLDestroy = MwLLDestroyImpl; \ \ - MwLLPolygon = MwLLPolygonImpl; \ - MwLLLine = MwLLLineImpl; \ - MwLLBeginDraw = MwLLBeginDrawImpl; \ - MwLLEndDraw = MwLLEndDrawImpl; \ + MwLLPolygon = MwLLPolygonImpl; \ + MwLLLine = MwLLLineImpl; \ \ MwLLAllocColor = MwLLAllocColorImpl; \ MwLLColorUpdate = MwLLColorUpdateImpl; \ diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index c05fae59..738ab108 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -24,10 +24,10 @@ 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); + originFrame.origin.x, + [view bounds].size.height - (originFrame.origin.y + originFrame.size.height), + originFrame.size.width, + originFrame.size.height); return destinationFrame; } @@ -151,8 +151,8 @@ static NSRect localRectFlip(NSRect originFrame, NSView* view) { 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); + 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 { @@ -181,7 +181,6 @@ static NSRect localRectFlip(NSRect originFrame, NSView* view) { c->pointerLocked = MwFALSE; - return c; } @@ -279,7 +278,7 @@ static NSRect localRectFlip(NSRect originFrame, NSView* view) { } }; - (int)pending { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; [NSApp runModalSession:self->modalSession]; [pool release]; return 1; @@ -327,7 +326,6 @@ static NSRect localRectFlip(NSRect originFrame, NSView* view) { objectAtIndex:0]) pointer]; } - switch([ev type]) { case NSLeftMouseDragged: case NSRightMouseDragged: @@ -808,7 +806,7 @@ static NSRect localRectFlip(NSRect originFrame, NSView* view) { - (void)drawRect:(NSRect)dirtyRect { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSSize sz = [self->rep size]; - MwLL ll = [((MilskoFakePointer *)[[[[self window] contentView] subviews] + MwLL ll = [((MilskoFakePointer*)[[[[self window] contentView] subviews] objectAtIndex:0]) pointer]; [super drawRect:dirtyRect]; @@ -1003,14 +1001,6 @@ static void MwLLDestroyImpl(MwLL 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) { MilskoCocoa* h = handle->cocoa.real; diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 4601b79d..3c286a8e 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -310,14 +310,6 @@ static void MwLLDestroyImpl(MwLL 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) { POINT* p = malloc(sizeof(*p) * points_count); HPEN pen = CreatePen(PS_NULL, 0, RGB(0, 0, 0)); diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 7037a5d9..c85ca6a2 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -5,16 +5,12 @@ #include #include "../../external/stb_ds.h" -#include "Mw/BaseTypes.h" -#include "Mw/LowLevel.h" -#include "Mw/LowLevel/Wayland/xdg-shell-client-protocol.h" #include #include #include /* TODO: - * - MwLLGrabPointerImpl * - MwLLMakePopupImpl * - MwLLShowImpl */ @@ -250,8 +246,6 @@ static void wl_data_source_listener_send(void* data, if(self->wayland.clipboard_buffer != NULL) { write(fd, self->wayland.clipboard_buffer, strlen(self->wayland.clipboard_buffer)); close(fd); - - self->wayland.events_pending = 1; } WAYLAND_EVENT_OP_END(self); }; @@ -296,8 +290,6 @@ static void zwp_primary_selection_source_v1_send(void* data, if(self->wayland.clipboard_buffer != NULL) { write(fd, self->wayland.clipboard_buffer, strlen(self->wayland.clipboard_buffer)); close(fd); - - self->wayland.events_pending = 1; } WAYLAND_EVENT_OP_END(self); @@ -422,11 +414,7 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time self->wayland.last_time = time; } - self->wayland.events_pending += 1; - WAYLAND_EVENT_OP_END(self); - - /*timed_redraw(self, time, 50, &self->wayland.cooldown_timer);*/ }; /* `wl_pointer.button` callback */ @@ -481,7 +469,6 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri if(!self->wayland.always_render) { MwLLDispatch(self, draw, NULL); - self->wayland.events_pending += 1; } WAYLAND_EVENT_OP_END(self); @@ -540,7 +527,6 @@ static void keyboard_enter(void* data, self->wayland.keyboard_serial = serial; MwLLDispatch(self, focus_in, NULL); - self->wayland.events_pending += 1; WAYLAND_EVENT_OP_END(self); }; @@ -555,7 +541,6 @@ static void keyboard_leave(void* data, WAYLAND_EVENT_OP_START(self); MwLLDispatch(self, focus_out, NULL); - self->wayland.events_pending += 1; WAYLAND_EVENT_OP_END(self); }; @@ -659,7 +644,6 @@ static void keyboard_key(void* data, if(!self->wayland.always_render) { MwLLDispatch(self, draw, NULL); - self->wayland.events_pending += 1; } WAYLAND_EVENT_OP_END(self); @@ -783,7 +767,6 @@ static wayland_protocol_t* wl_seat_setup(MwU32 name, MwLL ll) { static void wl_seat_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { free(data->listener); - // wl_seat_destroy(data->context); } /* wl_output setup function */ @@ -832,7 +815,6 @@ 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) { - // xdg_wm_base_destroy(data->context); free(data->listener); } @@ -857,10 +839,6 @@ static wayland_protocol_t* zxdg_decoration_manager_v1_setup(MwU32 name, struct _ } static void zxdg_decoration_manager_v1_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { - zxdg_decoration_manager_v1_context_t* context = data->context; - - // zxdg_decoration_manager_v1_destroy(context->manager); - // zxdg_toplevel_decoration_v1_destroy(context->decoration); } /* `xdg_toplevel.close` callback */ @@ -1000,8 +978,6 @@ static void framebuffer_setup(struct _MwLLWayland* wayland) { memset(wayland->framebuffer.buf, 255, wayland->framebuffer.buf_size); update_buffer(&wayland->framebuffer); - - wayland->events_pending += 1; }; static void framebuffer_destroy(struct _MwLLWayland* wayland) { buffer_destroy(&wayland->framebuffer); @@ -1040,7 +1016,6 @@ 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) { free(data->listener); - // xdg_toplevel_icon_manager_v1_destroy(data->context); } /* Standard Wayland event loop. */ @@ -1504,7 +1479,6 @@ static void MwLLSetXYImpl(MwLL handle, int x, int y) { region_setup(handle); MwLLDispatch(handle, draw, NULL); - handle->wayland.events_pending += 1; } static void MwLLSetWHImpl(MwLL handle, int w, int h) { @@ -1551,7 +1525,7 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL cairo_close_path(handle->wayland.cairo); cairo_fill(handle->wayland.cairo); - handle->wayland.events_pending += 1; + handle->wayland.events_pending = 1; } static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { @@ -1570,16 +1544,7 @@ static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { cairo_close_path(handle->wayland.cairo); cairo_stroke(handle->wayland.cairo); - handle->wayland.events_pending += 1; -} - -static void MwLLBeginDrawImpl(MwLL handle) { -} - -static void MwLLEndDrawImpl(MwLL handle) { - update_buffer(&handle->wayland.framebuffer); - - handle->wayland.events_pending += 1; + handle->wayland.events_pending = 1; } static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { @@ -1756,12 +1721,6 @@ static void MwLLForceRenderImpl(MwLL handle) { wl_surface_damage(handle->wayland.framebuffer.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); handle->wayland.force_render = MwTRUE; - - /* - if(handle->wayland.egl_setup) { - timed_redraw_by_epoch(handle, 25); - } - */ } static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { diff --git a/src/backend/x11.c b/src/backend/x11.c index f7c6fe4b..6124ceea 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -261,15 +261,8 @@ static void MwLLDestroyImpl(MwLL 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) { +static void +MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { int i; XPoint* p = malloc(sizeof(*p) * points_count); diff --git a/src/core.c b/src/core.c index 9902a30e..c3274a15 100644 --- a/src/core.c +++ b/src/core.c @@ -6,14 +6,11 @@ static void lldrawhandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; (void)data; - MwLLBeginDraw(handle); h->bgcolor = NULL; MwDispatch(h, draw); if(h->draw_inject != NULL) h->draw_inject(h); MwDispatchUserHandler(h, MwNdrawHandler, NULL); - - MwLLEndDraw(handle); } static void lluphandler(MwLL handle, void* data) { diff --git a/src/lowlevel.c b/src/lowlevel.c index 8f8a4d93..eeabaa33 100644 --- a/src/lowlevel.c +++ b/src/lowlevel.c @@ -6,9 +6,6 @@ void (*MwLLDestroy)(MwLL handle) = NULL; void (*MwLLPolygon)(MwLL handle, MwPoint* points, int points_count, MwLLColor color) = NULL; void (*MwLLLine)(MwLL handle, MwPoint* points, MwLLColor color) = NULL; -void (*MwLLBeginDraw)(MwLL handle) = NULL; -void (*MwLLEndDraw)(MwLL handle) = NULL; - MwLLColor (*MwLLAllocColor)(MwLL handle, int r, int g, int b) = NULL; void (*MwLLColorUpdate)(MwLL handle, MwLLColor c, int r, int g, int b) = NULL; void (*MwLLFreeColor)(MwLLColor color) = NULL; diff --git a/src/widget/opengl.c b/src/widget/opengl.c index b508ef6b..779b17af 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -364,14 +364,12 @@ static void mwOpenGLSwapBufferImpl(MwWidget handle) { #ifdef USE_WAYLAND if(handle->lowlevel->common.type == MwLLBackendWayland) { waylandopengl_t* o = handle->internal; - // eglSwapInterval(o->egl_display, 0); if(!eglSwapBuffers(o->egl_display, o->egl_surface)) { printf("ERROR: eglSwapBuffers, %0X\n", eglGetError()); }; wl_egl_window_resize((struct wl_egl_window*)o->egl_window_native, handle->lowlevel->wayland.ww, handle->lowlevel->wayland.wh, 0, 0); - // MwLLForceRender(handle->lowlevel); } #endif } From 0a62467760d794414516de1af6bdfd3d83f13f2a Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 18 Mar 2026 23:01:39 -0700 Subject: [PATCH 76/94] correct mouse clicks --- include/Mw/LowLevel/Wayland.h | 2 ++ src/backend/wayland.c | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index c09f81b1..02488138 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -204,6 +204,8 @@ struct _MwLLWayland { MwLL currentlyHeldWidget; + struct wl_surface* curSurface; + cairo_surface_t* cs; cairo_t* cairo; }; diff --git a/src/backend/wayland.c b/src/backend/wayland.c index c85ca6a2..f15d3d7b 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -377,6 +377,7 @@ static void pointer_enter(void* data, struct wl_pointer* wl_pointer, MwU32 seria MwLL self = data; WAYLAND_EVENT_OP_START(self); + self->wayland.curSurface = surface; self->wayland.pointer_serial = serial; @@ -429,7 +430,11 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri p.point = self->wayland.cur_mouse_pos; - if(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.parent == NULL) { + return; + } + + if(self->wayland.framebuffer.surface == self->wayland.curSurface) { int i; switch(button) { @@ -999,7 +1004,7 @@ static void region_setup(MwLL handle) { if(handle->wayland.type == MWLL_WAYLAND_POPUP) { wl_region_add(handle->wayland.region, 0, 0, handle->wayland.ww + abs(handle->wayland.x), handle->wayland.wh + abs(handle->wayland.y)); } else { - wl_region_add(handle->wayland.region, handle->wayland.x, handle->wayland.y, handle->wayland.ww + abs(handle->wayland.x), handle->wayland.wh + abs(handle->wayland.y)); + wl_region_add(handle->wayland.region, 0, 0, handle->wayland.ww, handle->wayland.wh); } wl_surface_set_input_region(handle->wayland.framebuffer.surface, handle->wayland.region); wl_surface_set_opaque_region(handle->wayland.framebuffer.surface, handle->wayland.region); @@ -1233,6 +1238,7 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { r->wayland.sublevel->subsurface = wl_subcompositor_get_subsurface(r->wayland.sublevel->subcompositor, r->wayland.framebuffer.surface, parent_surface); + wl_subsurface_set_desync(r->wayland.sublevel->subsurface); wl_subsurface_set_position(r->wayland.sublevel->subsurface, x, y); r->wayland.configured = MwTRUE; From 59608238012c36ad7945969887b051653f30b4ff Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 18 Mar 2026 23:07:16 -0700 Subject: [PATCH 77/94] wayland: don't early return from pointer_button, it causes a deadlock --- src/backend/wayland.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index f15d3d7b..e45c367a 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -430,10 +430,6 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri p.point = self->wayland.cur_mouse_pos; - if(self->wayland.parent == NULL) { - return; - } - if(self->wayland.framebuffer.surface == self->wayland.curSurface) { int i; @@ -878,7 +874,7 @@ static void xdg_toplevel_configure(void* data, region_setup(self); MwLLDispatch(self, resize, NULL); - MwLLDispatch(self, draw, NULL); + // MwLLDispatch(self, draw, NULL); MwLLForceRender(self); @@ -1407,7 +1403,7 @@ static void MwLLDestroyImpl(MwLL handle) { struct timeval tv; struct timespec t = { .tv_sec = 0, - .tv_nsec = 100, + .tv_nsec = 0, }; int select_ret; From 91c05b670d1171df71d8d9ea0e2f3fcc9b028019 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 19 Mar 2026 15:57:20 -0700 Subject: [PATCH 78/94] wayland: working viewport, subsurface input region --- include/Mw/LowLevel.h | 2 ++ include/Mw/LowLevel/Wayland.h | 1 + src/backend/wayland.c | 31 +++++++++++++++++++++++++------ src/core.c | 1 + 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index 30d7f310..b7e21afc 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -39,6 +39,8 @@ struct _MwLLCommon { int type; int coordinate_type; + MwBool place_above; + MwLLHandler handler; }; diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 02488138..76a5801c 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -147,6 +147,7 @@ struct _MwLLWayland { struct wl_registry* registry; struct wl_compositor* compositor; struct wl_registry_listener registry_listener; + struct wl_region* o_region; struct wl_region* region; struct wl_output* output; diff --git a/src/backend/wayland.c b/src/backend/wayland.c index e45c367a..f5880388 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -996,14 +996,26 @@ static void region_setup(MwLL handle) { if(!handle->wayland.configured) { return; } + MwLL parent = handle->wayland.parent; + int width = handle->wayland.ww; + int height = handle->wayland.wh; + wl_region_add(handle->wayland.o_region, 0, 0, 1, 1); + wl_surface_set_opaque_region(handle->wayland.framebuffer.surface, handle->wayland.o_region); if(handle->wayland.type == MWLL_WAYLAND_POPUP) { - wl_region_add(handle->wayland.region, 0, 0, handle->wayland.ww + abs(handle->wayland.x), handle->wayland.wh + abs(handle->wayland.y)); + wl_region_add(handle->wayland.region, 0, 0, width + abs(handle->wayland.x), height + abs(handle->wayland.y)); } else { - wl_region_add(handle->wayland.region, 0, 0, handle->wayland.ww, handle->wayland.wh); + if(parent) { + if(width - handle->wayland.x > parent->wayland.ww) { + width = parent->wayland.ww - handle->wayland.x; + } + if(height - handle->wayland.y > parent->wayland.wh) { + height = parent->wayland.wh - handle->wayland.y; + } + } + wl_region_add(handle->wayland.region, 0, 0, width, height); } wl_surface_set_input_region(handle->wayland.framebuffer.surface, handle->wayland.region); - wl_surface_set_opaque_region(handle->wayland.framebuffer.surface, handle->wayland.region); } static wayland_protocol_t* xdg_toplevel_icon_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland) { @@ -1237,6 +1249,10 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { wl_subsurface_set_desync(r->wayland.sublevel->subsurface); wl_subsurface_set_position(r->wayland.sublevel->subsurface, x, y); + if(parent) { + wl_subsurface_place_above(r->wayland.sublevel->subsurface, parent->wayland.framebuffer.surface); + } + r->wayland.configured = MwTRUE; } @@ -1387,7 +1403,8 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { framebuffer_setup(&r->wayland); - r->wayland.region = wl_compositor_create_region(r->wayland.compositor); + r->wayland.region = wl_compositor_create_region(r->wayland.compositor); + r->wayland.o_region = wl_compositor_create_region(r->wayland.compositor); region_setup(r); MwLLForceRender(r); @@ -1514,7 +1531,6 @@ refresh: static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { int i; - cairo_set_source_rgb(handle->wayland.cairo, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); cairo_new_path(handle->wayland.cairo); for(i = 0; i < points_count; i++) { @@ -1525,6 +1541,7 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL } } cairo_close_path(handle->wayland.cairo); + cairo_fill(handle->wayland.cairo); handle->wayland.events_pending = 1; @@ -1660,16 +1677,18 @@ static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { cairo_t* c; cairo_surface_t* cs; + MwLL parent = handle->wayland.parent; cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, rect->width, rect->height); c = cairo_create(cs); cairo_scale(c, (double)rect->width / pixmap->common.width, (double)rect->height / pixmap->common.height); + cairo_set_source_surface(c, pixmap->wayland.cs, 0, 0); cairo_pattern_set_filter(cairo_get_source(c), CAIRO_FILTER_NEAREST); + cairo_paint(c); - cairo_set_source_rgb(handle->wayland.cairo, 1, 1, 1); cairo_set_source_surface(handle->wayland.cairo, cs, rect->x, rect->y); cairo_paint(handle->wayland.cairo); diff --git a/src/core.c b/src/core.c index c3274a15..a8178c7d 100644 --- a/src/core.c +++ b/src/core.c @@ -46,6 +46,7 @@ static void llresizehandler(MwLL handle, void* data) { MwDispatchUserHandler(h, MwNresizeHandler, NULL); for(i = 0; i < arrlen(h->children); i++) { MwDispatch(h->children[i], parent_resize); + MwDispatch(h->children[i], draw); } MwDispatch(h, resize); } From 5f53236c91e2abc2046845c2489bb29b2567a2a6 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 19 Mar 2026 15:59:44 -0700 Subject: [PATCH 79/94] remove unused test parameter added to common lowLevel --- include/Mw/LowLevel.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index b7e21afc..30d7f310 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -39,8 +39,6 @@ struct _MwLLCommon { int type; int coordinate_type; - MwBool place_above; - MwLLHandler handler; }; From 42db5889db2eae5c47031fed9f78e45d5140a32a Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 19 Mar 2026 16:01:32 -0700 Subject: [PATCH 80/94] wayland c89 --- src/backend/wayland.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index f5880388..117a328c 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -993,12 +993,14 @@ static void region_invalidate(MwLL handle) { wl_region_subtract(handle->wayland.region, 0, 0, handle->wayland.ww, handle->wayland.wh); } static void region_setup(MwLL handle) { - if(!handle->wayland.configured) { - return; - } MwLL parent = handle->wayland.parent; int width = handle->wayland.ww; int height = handle->wayland.wh; + + if(!handle->wayland.configured) { + return; + } + wl_region_add(handle->wayland.o_region, 0, 0, 1, 1); wl_surface_set_opaque_region(handle->wayland.framebuffer.surface, handle->wayland.o_region); From 04eb28b6173fdcf52c996b8fd180d529cc92430b Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 19 Mar 2026 16:05:44 -0700 Subject: [PATCH 81/94] revert the removal of MwLLBeginDraw/EndDraw, turns out the newer system still doesn't please weston and likely other compositors --- include/Mw/LowLevel.h | 2 ++ src/backend/call.c | 6 ++++-- src/backend/cocoa.m | 8 ++++++++ src/backend/gdi.c | 8 ++++++++ src/backend/wayland.c | 8 ++++++++ src/backend/x11.c | 11 +++++++++-- src/core.c | 3 +++ src/lowlevel.c | 3 +++ 8 files changed, 45 insertions(+), 4 deletions(-) diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index 30d7f310..9766d052 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -190,6 +190,8 @@ MWDECL void (*MwLLDestroy)(MwLL handle); MWDECL void (*MwLLPolygon)(MwLL handle, MwPoint* points, int points_count, MwLLColor color); MWDECL void (*MwLLLine)(MwLL handle, MwPoint* points, MwLLColor color); +MWDECL void (*MwLLBeginDraw)(MwLL handle); +MWDECL void (*MwLLEndDraw)(MwLL handle); MWDECL MwLLColor (*MwLLAllocColor)(MwLL handle, int r, int g, int b); MWDECL void (*MwLLColorUpdate)(MwLL handle, MwLLColor c, int r, int g, int b); diff --git a/src/backend/call.c b/src/backend/call.c index 2ce5ed23..e2ce934c 100644 --- a/src/backend/call.c +++ b/src/backend/call.c @@ -8,8 +8,10 @@ MwLLCreate = MwLLCreateImpl; \ MwLLDestroy = MwLLDestroyImpl; \ \ - MwLLPolygon = MwLLPolygonImpl; \ - MwLLLine = MwLLLineImpl; \ + MwLLPolygon = MwLLPolygonImpl; \ + MwLLLine = MwLLLineImpl; \ + MwLLBeginDraw = MwLLBeginDrawImpl; \ + MwLLEndDraw = MwLLEndDrawImpl; \ \ MwLLAllocColor = MwLLAllocColorImpl; \ MwLLColorUpdate = MwLLColorUpdateImpl; \ diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 738ab108..725642d3 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -1001,6 +1001,14 @@ static void MwLLDestroyImpl(MwLL 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) { MilskoCocoa* h = handle->cocoa.real; diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 3c286a8e..4601b79d 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -310,6 +310,14 @@ static void MwLLDestroyImpl(MwLL 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) { POINT* p = malloc(sizeof(*p) * points_count); HPEN pen = CreatePen(PS_NULL, 0, RGB(0, 0, 0)); diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 117a328c..be4bc148 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1531,6 +1531,14 @@ refresh: MwLLDispatch(handle, draw, NULL); } +static void MwLLBeginDrawImpl(MwLL handle) { + (void)handle; +} + +static void MwLLEndDrawImpl(MwLL handle) { + update_buffer(&handle->wayland.framebuffer); +} + static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { int i; cairo_set_source_rgb(handle->wayland.cairo, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); diff --git a/src/backend/x11.c b/src/backend/x11.c index 6124ceea..f7c6fe4b 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -261,8 +261,15 @@ static void MwLLDestroyImpl(MwLL handle) { free(handle); } -static void -MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { +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; XPoint* p = malloc(sizeof(*p) * points_count); diff --git a/src/core.c b/src/core.c index a8178c7d..f17fdbfa 100644 --- a/src/core.c +++ b/src/core.c @@ -6,11 +6,14 @@ static void lldrawhandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; (void)data; + MwLLBeginDraw(handle); h->bgcolor = NULL; MwDispatch(h, draw); if(h->draw_inject != NULL) h->draw_inject(h); MwDispatchUserHandler(h, MwNdrawHandler, NULL); + + MwLLEndDraw(handle); } static void lluphandler(MwLL handle, void* data) { diff --git a/src/lowlevel.c b/src/lowlevel.c index eeabaa33..8f8a4d93 100644 --- a/src/lowlevel.c +++ b/src/lowlevel.c @@ -6,6 +6,9 @@ void (*MwLLDestroy)(MwLL handle) = NULL; void (*MwLLPolygon)(MwLL handle, MwPoint* points, int points_count, MwLLColor color) = NULL; void (*MwLLLine)(MwLL handle, MwPoint* points, MwLLColor color) = NULL; +void (*MwLLBeginDraw)(MwLL handle) = NULL; +void (*MwLLEndDraw)(MwLL handle) = NULL; + MwLLColor (*MwLLAllocColor)(MwLL handle, int r, int g, int b) = NULL; void (*MwLLColorUpdate)(MwLL handle, MwLLColor c, int r, int g, int b) = NULL; void (*MwLLFreeColor)(MwLLColor color) = NULL; From f44f98b8aa8d0fd39ca3480d7594d7292189dcc7 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 19 Mar 2026 16:35:56 -0700 Subject: [PATCH 82/94] wayland: don't update buffer if we haven't configured --- src/backend/wayland.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index be4bc148..d4213653 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -2,9 +2,12 @@ #include #include +#include +#include #include #include "../../external/stb_ds.h" +#include "Mw/BaseTypes.h" #include #include @@ -842,7 +845,7 @@ 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) { } -/* `xdg_toplevel.close` callback */ +/* `xdg_toplevel.configure` callback */ static void xdg_toplevel_configure(void* data, struct xdg_toplevel* xdg_toplevel, MwI32 width, MwI32 height, @@ -867,6 +870,7 @@ static void xdg_toplevel_configure(void* data, region_invalidate(self); self->wayland.ww = width; self->wayland.wh = height; + xdg_surface_set_window_geometry(self->wayland.toplevel->xdg_surface, 0, 0, self->wayland.ww, self->wayland.wh); framebuffer_destroy(&self->wayland); @@ -874,7 +878,7 @@ static void xdg_toplevel_configure(void* data, region_setup(self); MwLLDispatch(self, resize, NULL); - // MwLLDispatch(self, draw, NULL); + MwLLDispatch(self, draw, NULL); MwLLForceRender(self); @@ -978,7 +982,7 @@ static void framebuffer_setup(struct _MwLLWayland* wayland) { wayland->cairo = cairo_create(wayland->cs); memset(wayland->framebuffer.buf, 255, wayland->framebuffer.buf_size); - update_buffer(&wayland->framebuffer); + if(wayland->configured) update_buffer(&wayland->framebuffer); }; static void framebuffer_destroy(struct _MwLLWayland* wayland) { buffer_destroy(&wayland->framebuffer); @@ -1212,6 +1216,8 @@ static void destroy_toplevel(MwLL r) { wl_registry_destroy(r->wayland.registry); wl_display_disconnect(r->wayland.display); + + r->wayland.configured = MwFALSE; } /* Sublevel setup function */ @@ -1265,6 +1271,8 @@ static void destroy_sublevel(MwLL r) { wl_subsurface_destroy(r->wayland.sublevel->subsurface); free(r->wayland.sublevel); + + r->wayland.configured = MwFALSE; } static void popup_configure(void* data, @@ -1367,6 +1375,13 @@ static void destroy_popup(MwLL r) { wl_surface_destroy(r->wayland.framebuffer.surface); wl_registry_destroy(r->wayland.registry); + + r->wayland.configured = MwFALSE; +} + +static void wl_logger(const char* fmt, va_list args) { + vprintf(fmt, args); + raise(SIGTRAP); } static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { @@ -1375,6 +1390,8 @@ 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; @@ -1519,8 +1536,9 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { } if(handle->wayland.type == MWLL_WAYLAND_POPUP) { - destroy_popup(handle); - setup_popup(handle, handle->wayland.x, handle->wayland.y); + // destroy_popup(handle); + // wl_flush(handle); + // setup_popup(handle, handle->wayland.x, handle->wayland.y); } refresh: @@ -1536,7 +1554,7 @@ static void MwLLBeginDrawImpl(MwLL handle) { } static void MwLLEndDrawImpl(MwLL handle) { - update_buffer(&handle->wayland.framebuffer); + if(handle->wayland.configured) update_buffer(&handle->wayland.framebuffer); } static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { @@ -1632,7 +1650,7 @@ static void MwLLNextEventImpl(MwLL handle) { handle->wayland.events_pending = 0; } if(handle->wayland.force_render) { - update_buffer(&handle->wayland.framebuffer); + if(handle->wayland.configured) update_buffer(&handle->wayland.framebuffer); handle->wayland.force_render = 0; } } @@ -1739,7 +1757,7 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { handle->wayland.icon->buf[i + 3] = 255; } - update_buffer(handle->wayland.icon); + if(handle->wayland.configured) update_buffer(handle->wayland.icon); xdg_toplevel_icon_v1_add_buffer(icon, handle->wayland.icon->shm_buffer, 1); @@ -1817,6 +1835,8 @@ static void MwLLDetachImpl(MwLL handle, MwPoint* point) { return; } + wl_flush(handle); + switch(handle->wayland.type_to_be) { case MWLL_WAYLAND_POPUP: setup_popup(handle, point->x, point->y); From f78e5e620fe0929d45757844b59d0ed56692ca6e Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 19 Mar 2026 17:05:08 -0700 Subject: [PATCH 83/94] wayland: image clipping attempt --- src/backend/wayland.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index d4213653..c22685fa 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -877,12 +878,11 @@ static void xdg_toplevel_configure(void* data, framebuffer_setup(&self->wayland); region_setup(self); +finish: MwLLDispatch(self, resize, NULL); MwLLDispatch(self, draw, NULL); MwLLForceRender(self); - - return; }; /* Empty function for satisfying zxdg_toplevel's requirements */ @@ -1710,6 +1710,11 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, rect->width, rect->height); c = cairo_create(cs); + if(parent) { + cairo_rectangle(c, 0, 0, parent->wayland.ww + handle->wayland.x, parent->wayland.wh + handle->wayland.y); + cairo_clip(c); + } + cairo_scale(c, (double)rect->width / pixmap->common.width, (double)rect->height / pixmap->common.height); cairo_set_source_surface(c, pixmap->wayland.cs, 0, 0); @@ -1848,6 +1853,15 @@ static void MwLLDetachImpl(MwLL handle, MwPoint* point) { } static void MwLLShowImpl(MwLL handle, int show) { + switch(handle->wayland.type) { + case MWLL_WAYLAND_UNKNOWN: + case MWLL_WAYLAND_TOPLEVEL: + break; + case MWLL_WAYLAND_SUBLEVEL: + break; + case MWLL_WAYLAND_POPUP: + break; + } } static void MwLLMakePopupImpl(MwLL handle, MwLL parent) { From 3eeace0963b4e2551fa18459b58b5dddadd20301 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 19 Mar 2026 17:32:36 -0700 Subject: [PATCH 84/94] don't use wl_dispatch_pending_timeout appearently debian still doesn't ship with it --- src/backend/wayland.c | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index c22685fa..8cc6000a 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -1070,15 +1071,17 @@ static int event_loop(MwLL handle) { } wl_display_prepare_read(handle->wayland.display); - wl_display_read_events(wayland->display); - if((res = wl_display_dispatch_timeout(wayland->display, &timeout)) <= 0) { - if(res < 0) { - wl_display_cancel_read(handle->wayland.display); - } + /* Condition where no events are being sent. */ + if(!poll(&fd, 1, timeout.tv_nsec)) { + wl_display_cancel_read(wayland->display); wl_surface_commit(wayland->framebuffer.surface); return 0; } + wl_display_read_events(wayland->display); + if(wl_display_dispatch_pending(wayland->display) < 0) { + wl_display_cancel_read(wayland->display); + } return 1; } @@ -1615,13 +1618,26 @@ static void MwLLFreeColorImpl(MwLLColor color) { } static int MwLLPendingImpl(MwLL handle) { - MwBool pending = MwFALSE; struct timespec timeout; - timeout.tv_nsec = 1; - timeout.tv_sec = 0; - int i; + struct pollfd fd; + int pending = 0; - pending = wl_display_dispatch_timeout(handle->wayland.display, &timeout); + timeout.tv_nsec = 100; + timeout.tv_sec = 0; + + fd.fd = wl_display_get_fd(handle->wayland.display); + fd.events = POLLOUT; + + 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); + } + } + wl_surface_commit(handle->wayland.framebuffer.surface); if(handle->wayland.always_render) { event_loop(handle); From 22fe52c4a3dd98134dba2f90d77f34c718ca689e Mon Sep 17 00:00:00 2001 From: Nishi Date: Fri, 20 Mar 2026 09:59:07 +0900 Subject: [PATCH 85/94] ugh --- src/backend/wayland.c | 19 ++++++++++++++----- src/core.c | 2 ++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 8cc6000a..9bf9f900 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1382,6 +1382,16 @@ static void destroy_popup(MwLL r) { r->wayland.configured = MwFALSE; } +static void clip(MwLL handle){ + MwLL parent = handle->wayland.parent; + + if(parent && handle->wayland.type == MWLL_WAYLAND_SUBLEVEL) { + cairo_reset_clip(handle->wayland.cairo); + cairo_rectangle(handle->wayland.cairo, 0, 0, parent->wayland.ww + handle->wayland.x, parent->wayland.wh + handle->wayland.y); + cairo_clip(handle->wayland.cairo); + } +} + static void wl_logger(const char* fmt, va_list args) { vprintf(fmt, args); raise(SIGTRAP); @@ -1562,6 +1572,9 @@ static void MwLLEndDrawImpl(MwLL handle) { static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { int i; + + clip(handle); + cairo_set_source_rgb(handle->wayland.cairo, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); cairo_new_path(handle->wayland.cairo); for(i = 0; i < points_count; i++) { @@ -1721,15 +1734,11 @@ static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { cairo_t* c; cairo_surface_t* cs; - MwLL parent = handle->wayland.parent; cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, rect->width, rect->height); c = cairo_create(cs); - if(parent) { - cairo_rectangle(c, 0, 0, parent->wayland.ww + handle->wayland.x, parent->wayland.wh + handle->wayland.y); - cairo_clip(c); - } + clip(handle); cairo_scale(c, (double)rect->width / pixmap->common.width, (double)rect->height / pixmap->common.height); diff --git a/src/core.c b/src/core.c index f17fdbfa..39cae924 100644 --- a/src/core.c +++ b/src/core.c @@ -815,6 +815,8 @@ void MwReparent(MwWidget handle, MwWidget new_parent) { arrput(new_parent->children, handle); MwDispatch(handle->parent, children_update); + + MwForceRender(handle); } MwClass MwGetClass(MwWidget handle) { From 3cf94f66513a5049f913032f0b927a3bc1b2ae31 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Thu, 19 Mar 2026 19:43:57 -0700 Subject: [PATCH 86/94] wayland: malicious compliance with gnome's CSD rule --- .clangd | 2 + include/Mw/LowLevel/Wayland.h | 26 ++++- pl/rules.pl | 1 + src/backend/wayland.c | 183 ++++++++++++++++++++++++---------- 4 files changed, 160 insertions(+), 52 deletions(-) create mode 100644 .clangd diff --git a/.clangd b/.clangd new file mode 100644 index 00000000..c2520c5c --- /dev/null +++ b/.clangd @@ -0,0 +1,2 @@ +Completion: + HeaderInsertion: Never diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 76a5801c..b2927494 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -24,12 +24,21 @@ MWDECL int MwLLWaylandCallInit(void); #ifndef WL_PROTOCOLS_DEFINED #define WL_PROTOCOLS_DEFINED #include "Wayland/xdg-shell-client-protocol.h" +#include "Wayland/viewporter-client-protocol.h" #include "Wayland/xdg-decoration-client-protocol.h" #include "Wayland/cursor-shape-client-protocol.h" #include "Wayland/primary-selection-client-protocol.h" #include "Wayland/xdg-toplevel-icon-client-protocol.h" #endif +#define SSD_BORDER_FRAME_LEFT 5 +#define SSD_BORDER_FRAME_RIGHT 5 +#define SSD_BORDER_FRAME_TOP 24 +#define SSD_BORDER_FRAME_BOTTOM 5 + +#define SSD_LEFT_OFFSET(handle) handle->wayland.has_decorations ? 0 : SSD_BORDER_FRAME_LEFT +#define SSD_TOP_OFFSET(handle) handle->wayland.has_decorations ? 0 : SSD_BORDER_FRAME_TOP + struct _MwLLWayland; typedef struct wayland_protocol { @@ -58,6 +67,9 @@ struct _MwLLWaylandTopLevel { MwBool compositor_created; MwBool xdg_wm_base_created; MwBool xdg_surface_created; + + struct wl_subsurface* ssurface; + struct wl_subcompositor* scompositor; }; struct _MwLLWaylandSublevel { @@ -143,6 +155,9 @@ struct _MwLLWayland { MwBool always_render; + MwBool has_decorations; + char title[255]; + struct wl_display* display; struct wl_registry* registry; struct wl_compositor* compositor; @@ -151,6 +166,8 @@ struct _MwLLWayland { struct wl_region* region; struct wl_output* output; + struct wp_viewport* vp; + /* 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.*/ @@ -192,6 +209,7 @@ struct _MwLLWayland { MwBool did_event_loop_early; struct _MwLLWaylandShmBuffer framebuffer; + struct _MwLLWaylandShmBuffer backbuffer; struct _MwLLWaylandShmBuffer cursor; struct _MwLLWaylandShmBuffer* icon; @@ -203,12 +221,16 @@ struct _MwLLWayland { uint32_t last_time; + MwBool moving; + MwLL currentlyHeldWidget; struct wl_surface* curSurface; - cairo_surface_t* cs; - cairo_t* cairo; + cairo_surface_t* front_cs; + cairo_surface_t* back_cs; + cairo_t* front_cairo; + cairo_t* back_cairo; }; struct _MwLLWaylandColor { diff --git a/pl/rules.pl b/pl/rules.pl index 45bb6daf..a35a6c3e 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -37,6 +37,7 @@ if (grep(/^wayland$/, @backends)) { } 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"); diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 8cc6000a..40dfbc7c 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1,19 +1,9 @@ #include -#include -#include -#include -#include #include -#include -#include +#include #include "../../external/stb_ds.h" -#include "Mw/BaseTypes.h" - -#include -#include -#include /* TODO: * - MwLLMakePopupImpl @@ -49,6 +39,11 @@ static void framebuffer_setup(struct _MwLLWayland* wayland); /* Destroy the framebuffer */ static void framebuffer_destroy(struct _MwLLWayland* handle); +/* Setup the framebuffer with the saved width/height */ +static void backbuffer_setup(struct _MwLLWayland* wayland); +/* Destroy the backbuffer */ +static void backbuffer_destroy(struct _MwLLWayland* handle); + static void buffer_destroy(struct _MwLLWaylandShmBuffer* buffer); static void region_setup(MwLL handle); @@ -435,7 +430,7 @@ 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) { + if(self->wayland.framebuffer.surface == self->wayland.curSurface || self->wayland.backbuffer.surface == self->wayland.curSurface) { int i; switch(button) { @@ -798,7 +793,11 @@ static void wl_compositor_interface_destroy(struct _MwLLWayland* wayland, waylan /* wl_subcompositor setup function */ static wayland_protocol_t* wl_subcompositor_setup(MwU32 name, struct _MwLLWayland* wayland) { - wayland->sublevel->subcompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1); + if(wayland->type == MWLL_WAYLAND_TOPLEVEL) { + wayland->toplevel->scompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1); + } else { + wayland->sublevel->subcompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1); + } return NULL; } @@ -824,6 +823,18 @@ static void xdg_wm_base_interface_destroy(struct _MwLLWayland* wayland, wayland_ free(data->listener); } +/* xdg_wm_base setup function */ +static wayland_protocol_t* wp_viewporter_setup(MwU32 name, struct _MwLLWayland* wayland) { + wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); + proto->context = wl_registry_bind(wayland->registry, name, &wp_viewporter_interface, 1); + + return proto; +} + +static void wp_viewporter_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { + free(data->listener); +} + /* the two decoration manager constructs */ typedef struct zxdg_decoration_manager_v1_context { struct zxdg_decoration_manager_v1* manager; @@ -875,6 +886,9 @@ static void xdg_toplevel_configure(void* data, xdg_surface_set_window_geometry(self->wayland.toplevel->xdg_surface, 0, 0, self->wayland.ww, self->wayland.wh); + backbuffer_destroy(&self->wayland); + backbuffer_setup(&self->wayland); + framebuffer_destroy(&self->wayland); framebuffer_setup(&self->wayland); region_setup(self); @@ -910,6 +924,7 @@ static void xdg_surface_configure( if(self->wayland.configured) { wl_surface_commit(self->wayland.framebuffer.surface); + wl_surface_commit(self->wayland.backbuffer.surface); } self->wayland.configured = MwTRUE; @@ -917,8 +932,8 @@ static void xdg_surface_configure( /* wl_shm setup function */ static wayland_protocol_t* wl_shm_setup(MwU32 name, struct _MwLLWayland* wayland) { - wayland->framebuffer.shm = wl_registry_bind(wayland->registry, name, &wl_shm_interface, 1); + wayland->backbuffer.shm = wl_registry_bind(wayland->registry, name, &wl_shm_interface, 1); wayland->cursor.shm = wl_registry_bind(wayland->registry, name, &wl_shm_interface, 1); return NULL; @@ -979,16 +994,34 @@ static void buffer_destroy(struct _MwLLWaylandShmBuffer* buffer) { static void framebuffer_setup(struct _MwLLWayland* wayland) { buffer_setup(&wayland->framebuffer, wayland->ww, wayland->wh); - wayland->cs = cairo_image_surface_create_for_data(wayland->framebuffer.buf, CAIRO_FORMAT_ARGB32, wayland->ww, wayland->wh, 4 * wayland->ww); - wayland->cairo = cairo_create(wayland->cs); + wayland->front_cs = cairo_image_surface_create_for_data(wayland->framebuffer.buf, CAIRO_FORMAT_ARGB32, wayland->ww, wayland->wh, 4 * wayland->ww); + wayland->front_cairo = cairo_create(wayland->front_cs); memset(wayland->framebuffer.buf, 255, wayland->framebuffer.buf_size); if(wayland->configured) update_buffer(&wayland->framebuffer); }; static void framebuffer_destroy(struct _MwLLWayland* wayland) { buffer_destroy(&wayland->framebuffer); - cairo_destroy(wayland->cairo); - cairo_surface_destroy(wayland->cs); + cairo_destroy(wayland->front_cairo); + cairo_surface_destroy(wayland->front_cs); +}; + +static void backbuffer_setup(struct _MwLLWayland* wayland) { + if(wayland->type != MWLL_WAYLAND_TOPLEVEL) { + return; + } + buffer_setup(&wayland->backbuffer, wayland->ww, wayland->wh); + + wayland->back_cs = cairo_image_surface_create_for_data(wayland->backbuffer.buf, CAIRO_FORMAT_ARGB32, wayland->ww, wayland->wh, 4 * wayland->ww); + wayland->back_cairo = cairo_create(wayland->back_cs); + + memset(wayland->backbuffer.buf, 255, wayland->backbuffer.buf_size); + if(wayland->configured) update_buffer(&wayland->backbuffer); +}; +static void backbuffer_destroy(struct _MwLLWayland* wayland) { + buffer_destroy(&wayland->backbuffer); + cairo_destroy(wayland->back_cairo); + cairo_surface_destroy(wayland->back_cs); }; static void region_invalidate(MwLL handle) { @@ -1007,7 +1040,6 @@ static void region_setup(MwLL handle) { } wl_region_add(handle->wayland.o_region, 0, 0, 1, 1); - wl_surface_set_opaque_region(handle->wayland.framebuffer.surface, handle->wayland.o_region); 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)); @@ -1022,7 +1054,12 @@ static void region_setup(MwLL handle) { } wl_region_add(handle->wayland.region, 0, 0, width, height); } + wl_surface_set_opaque_region(handle->wayland.framebuffer.surface, handle->wayland.region); wl_surface_set_input_region(handle->wayland.framebuffer.surface, handle->wayland.region); + if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { + wl_surface_set_opaque_region(handle->wayland.backbuffer.surface, handle->wayland.region); + wl_surface_set_input_region(handle->wayland.backbuffer.surface, handle->wayland.region); + } } static wayland_protocol_t* xdg_toplevel_icon_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland) { @@ -1076,6 +1113,8 @@ static int event_loop(MwLL handle) { wl_display_cancel_read(wayland->display); wl_surface_commit(wayland->framebuffer.surface); + if(wayland->type == MWLL_WAYLAND_TOPLEVEL) + wl_surface_commit(wayland->backbuffer.surface); return 0; } wl_display_read_events(wayland->display); @@ -1109,8 +1148,10 @@ static void setup_callbacks(struct _MwLLWayland* wayland) { WL_INTERFACE(zwp_primary_selection_device_manager_v1); if(wayland->type == MWLL_WAYLAND_TOPLEVEL) { WL_INTERFACE(xdg_wm_base); + WL_INTERFACE(wp_viewporter); WL_INTERFACE(zxdg_decoration_manager_v1); WL_INTERFACE(xdg_toplevel_icon_manager_v1); + WL_INTERFACE(wl_subcompositor); } else if(wayland->type == MWLL_WAYLAND_POPUP) { WL_INTERFACE(xdg_wm_base); } else { @@ -1138,8 +1179,6 @@ static void setup_toplevel(MwLL r, int x, int y) { return; } - r->wayland.framebuffer.surface = NULL; - /* 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); @@ -1153,9 +1192,11 @@ static void setup_toplevel(MwLL r, int x, int y) { /* Create a wl_surface, a xdg_surface and a xdg_toplevel */ r->wayland.framebuffer.surface = wl_compositor_create_surface(r->wayland.compositor); + r->wayland.backbuffer.surface = wl_compositor_create_surface(r->wayland.compositor); + r->wayland.toplevel->ssurface = wl_subcompositor_get_subsurface(r->wayland.toplevel->scompositor, r->wayland.framebuffer.surface, r->wayland.backbuffer.surface); r->wayland.toplevel->xdg_surface = - xdg_wm_base_get_xdg_surface(WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context, r->wayland.framebuffer.surface); + xdg_wm_base_get_xdg_surface(WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context, r->wayland.backbuffer.surface); r->wayland.toplevel->xdg_top_level = xdg_surface_get_toplevel(r->wayland.toplevel->xdg_surface); /* setup mandatory listeners */ @@ -1172,6 +1213,7 @@ static void setup_toplevel(MwLL r, int x, int y) { xdg_toplevel_set_app_id(r->wayland.toplevel->xdg_top_level, "MilskoWaylandApp"); /* Perform the initial commit and wait for the first configure event */ + wl_surface_commit(r->wayland.backbuffer.surface); wl_surface_commit(r->wayland.framebuffer.surface); while(!r->wayland.configured) { event_loop(r); @@ -1186,8 +1228,18 @@ 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 { - printf("zxdg null\n"); + /* 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 - (SSD_BORDER_FRAME_LEFT + SSD_BORDER_FRAME_RIGHT), r->wayland.wh - (SSD_BORDER_FRAME_TOP + SSD_BORDER_FRAME_BOTTOM)); + r->wayland.has_decorations = MwFALSE; + + wl_subsurface_set_position(r->wayland.toplevel->ssurface, SSD_BORDER_FRAME_LEFT, SSD_BORDER_FRAME_TOP); + wl_subsurface_set_desync(r->wayland.toplevel->ssurface); } } @@ -1269,6 +1321,7 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { /* Sublevel setup function */ static void destroy_sublevel(MwLL r) { + backbuffer_destroy(&r->wayland); framebuffer_destroy(&r->wayland); wl_subsurface_destroy(r->wayland.sublevel->subsurface); @@ -1365,6 +1418,7 @@ static void setup_popup(MwLL r, int x, int y) { // framebuffer_destroy(&r->wayland); framebuffer_setup(&r->wayland); + backbuffer_setup(&r->wayland); } /* Popup destroy function */ @@ -1424,6 +1478,7 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { } framebuffer_setup(&r->wayland); + backbuffer_setup(&r->wayland); r->wayland.region = wl_compositor_create_region(r->wayland.compositor); r->wayland.o_region = wl_compositor_create_region(r->wayland.compositor); @@ -1515,8 +1570,6 @@ static void MwLLSetXYImpl(MwLL handle, int x, int y) { if(handle->wayland.type == MWLL_WAYLAND_SUBLEVEL) { wl_subsurface_set_position(handle->wayland.sublevel->subsurface, x, y); } - if(handle->wayland.type == MWLL_WAYLAND_POPUP) { - } region_setup(handle); MwLLDispatch(handle, draw, NULL); @@ -1531,17 +1584,29 @@ 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 - (SSD_BORDER_FRAME_LEFT + SSD_BORDER_FRAME_RIGHT)) + w = handle->wayland.parent->wayland.ww - (SSD_BORDER_FRAME_LEFT + SSD_BORDER_FRAME_RIGHT); + if(h >= handle->wayland.parent->wayland.wh - (SSD_BORDER_FRAME_TOP + SSD_BORDER_FRAME_BOTTOM)) + h = handle->wayland.parent->wayland.wh - (SSD_BORDER_FRAME_TOP + SSD_BORDER_FRAME_BOTTOM); + } + } handle->wayland.ww = w; handle->wayland.wh = h; + // if(handle->wayland.wh >= (SSD_BORDER_FRAME_TOP + SSD_BORDER_FRAME_BOTTOM)) { + // handle->wayland.wh -= (SSD_BORDER_FRAME_TOP + SSD_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); } if(handle->wayland.type == MWLL_WAYLAND_POPUP) { - // destroy_popup(handle); - // wl_flush(handle); - // setup_popup(handle, handle->wayland.x, handle->wayland.y); + destroy_popup(handle); + wl_flush(handle); + setup_popup(handle, handle->wayland.x, handle->wayland.y); } refresh: @@ -1549,31 +1614,48 @@ refresh: framebuffer_destroy(&handle->wayland); framebuffer_setup(&handle->wayland); + backbuffer_destroy(&handle->wayland); + backbuffer_setup(&handle->wayland); MwLLDispatch(handle, draw, NULL); } static void MwLLBeginDrawImpl(MwLL handle) { - (void)handle; + if(handle->wayland.type != MWLL_WAYLAND_TOPLEVEL) { + return; + } + if(!handle->wayland.has_decorations) { + cairo_set_source_rgb(handle->wayland.back_cairo, 0, 0.25, 0.25); + cairo_rectangle(handle->wayland.back_cairo, 1, 1, handle->wayland.ww - 2, handle->wayland.wh - 2); + cairo_fill_preserve(handle->wayland.back_cairo); + cairo_set_source_rgb(handle->wayland.back_cairo, 1, 1, 1); + cairo_rectangle(handle->wayland.back_cairo, 0, 0, handle->wayland.ww, handle->wayland.wh); + cairo_stroke(handle->wayland.back_cairo); + } } static void MwLLEndDrawImpl(MwLL handle) { - if(handle->wayland.configured) update_buffer(&handle->wayland.framebuffer); + if(handle->wayland.configured) { + update_buffer(&handle->wayland.framebuffer); + if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { + update_buffer(&handle->wayland.backbuffer); + } + } } static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { int i; - cairo_set_source_rgb(handle->wayland.cairo, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); - cairo_new_path(handle->wayland.cairo); + 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); for(i = 0; i < points_count; i++) { if(i == 0) { - cairo_move_to(handle->wayland.cairo, points[i].x, points[i].y); + cairo_move_to(handle->wayland.front_cairo, points[i].x, points[i].y); } else { - cairo_line_to(handle->wayland.cairo, points[i].x, points[i].y); + cairo_line_to(handle->wayland.front_cairo, points[i].x, points[i].y); } } - cairo_close_path(handle->wayland.cairo); + cairo_close_path(handle->wayland.front_cairo); - cairo_fill(handle->wayland.cairo); + cairo_fill(handle->wayland.front_cairo); handle->wayland.events_pending = 1; } @@ -1581,18 +1663,18 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { int i; - cairo_set_line_cap(handle->wayland.cairo, CAIRO_LINE_CAP_SQUARE); - cairo_set_source_rgb(handle->wayland.cairo, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); - cairo_new_path(handle->wayland.cairo); + 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); for(i = 0; i < 2; i++) { if(i == 0) { - cairo_move_to(handle->wayland.cairo, points[i].x, points[i].y); + cairo_move_to(handle->wayland.front_cairo, points[i].x, points[i].y); } else { - cairo_line_to(handle->wayland.cairo, points[i].x, points[i].y); + cairo_line_to(handle->wayland.front_cairo, points[i].x, points[i].y); } } - cairo_close_path(handle->wayland.cairo); - cairo_stroke(handle->wayland.cairo); + cairo_close_path(handle->wayland.front_cairo); + cairo_stroke(handle->wayland.front_cairo); handle->wayland.events_pending = 1; } @@ -1638,6 +1720,9 @@ static int MwLLPendingImpl(MwLL handle) { } } wl_surface_commit(handle->wayland.framebuffer.surface); + if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { + wl_surface_commit(handle->wayland.backbuffer.surface); + } if(handle->wayland.always_render) { event_loop(handle); @@ -1675,6 +1760,9 @@ static void MwLLSetTitleImpl(MwLL handle, const char* title) { if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { xdg_toplevel_set_title(handle->wayland.toplevel->xdg_top_level, title); } + if(!handle->wayland.has_decorations) { + strncpy(handle->wayland.title, title, 255); + } } static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, int width, int height) { @@ -1726,11 +1814,6 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, rect->width, rect->height); c = cairo_create(cs); - if(parent) { - cairo_rectangle(c, 0, 0, parent->wayland.ww + handle->wayland.x, parent->wayland.wh + handle->wayland.y); - cairo_clip(c); - } - cairo_scale(c, (double)rect->width / pixmap->common.width, (double)rect->height / pixmap->common.height); cairo_set_source_surface(c, pixmap->wayland.cs, 0, 0); @@ -1738,8 +1821,8 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { cairo_paint(c); - cairo_set_source_surface(handle->wayland.cairo, cs, rect->x, rect->y); - cairo_paint(handle->wayland.cairo); + cairo_set_source_surface(handle->wayland.front_cairo, cs, rect->x, rect->y); + cairo_paint(handle->wayland.front_cairo); cairo_destroy(c); cairo_surface_destroy(cs); From 52d676e54fc2ad56aa3370f7ca5ccee7a24134bf Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Fri, 20 Mar 2026 19:28:18 -0700 Subject: [PATCH 87/94] csd and clipping --- include/Mw/LowLevel/Wayland.h | 21 +++-- src/backend/wayland.c | 167 ++++++++++++++++++++++++++++------ 2 files changed, 153 insertions(+), 35 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index b2927494..053d0ff9 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -31,13 +31,13 @@ MWDECL int MwLLWaylandCallInit(void); #include "Wayland/xdg-toplevel-icon-client-protocol.h" #endif -#define SSD_BORDER_FRAME_LEFT 5 -#define SSD_BORDER_FRAME_RIGHT 5 -#define SSD_BORDER_FRAME_TOP 24 -#define SSD_BORDER_FRAME_BOTTOM 5 +#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 SSD_LEFT_OFFSET(handle) handle->wayland.has_decorations ? 0 : SSD_BORDER_FRAME_LEFT -#define SSD_TOP_OFFSET(handle) handle->wayland.has_decorations ? 0 : SSD_BORDER_FRAME_TOP +#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; @@ -185,8 +185,10 @@ struct _MwLLWayland { uint32_t clipboard_serial; wl_clipboard_device_context_t** clipboard_devices; - struct wl_pointer* pointer; - MwU32 pointer_serial; + struct wl_pointer* pointer; + MwU32 pointer_serial; + struct wl_seat* pointer_seat; + struct wl_keyboard* keyboard; MwU32 keyboard_serial; @@ -196,6 +198,8 @@ struct _MwLLWayland { MwBool configured; /* Whether or not xdg_toplevel_configure has run once */ + MwBool held_down; + MwI32 x, y; MwI32 ox, oy; MwU32 ww, wh; /* Window position */ @@ -231,6 +235,7 @@ struct _MwLLWayland { cairo_surface_t* back_cs; cairo_t* front_cairo; cairo_t* back_cairo; + cairo_t* selected_cairo; }; struct _MwLLWaylandColor { diff --git a/src/backend/wayland.c b/src/backend/wayland.c index be8b45ac..d6eae3cc 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -391,6 +391,30 @@ static void pointer_leave(void* data, struct wl_pointer* wl_pointer, MwU32 seria struct wl_surface* surface) { }; +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) { + 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) { + 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) { + 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); + } else if(p.point.y <= CSD_BORDER_FRAME_TOP) { + xdg_toplevel_move(self->wayland.toplevel->xdg_top_level, self->wayland.pointer_seat, serial); + } + }; +} + /* `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) { @@ -448,12 +472,15 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri p.button = MwLLMouseRight; break; } + self->wayland.held_down = state == WL_POINTER_BUTTON_STATE_PRESSED; + switch(state) { case WL_POINTER_BUTTON_STATE_PRESSED: MwLLDispatch(self, down, &p); if(self->wayland.parent != NULL) { self->wayland.parent->wayland.currentlyHeldWidget = self; } + break; case WL_POINTER_BUTTON_STATE_RELEASED: if(self->wayland.parent != NULL) { @@ -472,6 +499,10 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri MwLLDispatch(self, draw, NULL); } + if(!self->wayland.has_decorations) { + xdg_borderless_step(self, p, serial); + } + WAYLAND_EVENT_OP_END(self); }; @@ -694,7 +725,8 @@ static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat, wl_keyboard_add_listener(self->wayland.keyboard, &keyboard_listener, data); } if(capabilities & WL_SEAT_CAPABILITY_POINTER) { - self->wayland.pointer = wl_seat_get_pointer(wl_seat); + self->wayland.pointer_seat = wl_seat; + self->wayland.pointer = wl_seat_get_pointer(wl_seat); wl_pointer_add_listener(self->wayland.pointer, &pointer_listener, data); } @@ -893,7 +925,10 @@ static void xdg_toplevel_configure(void* data, framebuffer_setup(&self->wayland); region_setup(self); -finish: + 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)); + } + MwLLDispatch(self, resize, NULL); MwLLDispatch(self, draw, NULL); @@ -997,7 +1032,7 @@ static void framebuffer_setup(struct _MwLLWayland* wayland) { wayland->front_cs = cairo_image_surface_create_for_data(wayland->framebuffer.buf, CAIRO_FORMAT_ARGB32, wayland->ww, wayland->wh, 4 * wayland->ww); wayland->front_cairo = cairo_create(wayland->front_cs); - memset(wayland->framebuffer.buf, 255, wayland->framebuffer.buf_size); + memset(wayland->framebuffer.buf, 0, wayland->framebuffer.buf_size); if(wayland->configured) update_buffer(&wayland->framebuffer); }; static void framebuffer_destroy(struct _MwLLWayland* wayland) { @@ -1015,7 +1050,7 @@ static void backbuffer_setup(struct _MwLLWayland* wayland) { wayland->back_cs = cairo_image_surface_create_for_data(wayland->backbuffer.buf, CAIRO_FORMAT_ARGB32, wayland->ww, wayland->wh, 4 * wayland->ww); wayland->back_cairo = cairo_create(wayland->back_cs); - memset(wayland->backbuffer.buf, 255, wayland->backbuffer.buf_size); + memset(wayland->backbuffer.buf, 0, wayland->backbuffer.buf_size); if(wayland->configured) update_buffer(&wayland->backbuffer); }; static void backbuffer_destroy(struct _MwLLWayland* wayland) { @@ -1054,12 +1089,12 @@ static void region_setup(MwLL handle) { } wl_region_add(handle->wayland.region, 0, 0, width, height); } - wl_surface_set_opaque_region(handle->wayland.framebuffer.surface, handle->wayland.region); - wl_surface_set_input_region(handle->wayland.framebuffer.surface, handle->wayland.region); if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { wl_surface_set_opaque_region(handle->wayland.backbuffer.surface, handle->wayland.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_input_region(handle->wayland.framebuffer.surface, handle->wayland.region); } static wayland_protocol_t* xdg_toplevel_icon_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland) { @@ -1194,6 +1229,7 @@ static void setup_toplevel(MwLL r, int x, int y) { r->wayland.framebuffer.surface = wl_compositor_create_surface(r->wayland.compositor); r->wayland.backbuffer.surface = wl_compositor_create_surface(r->wayland.compositor); r->wayland.toplevel->ssurface = wl_subcompositor_get_subsurface(r->wayland.toplevel->scompositor, r->wayland.framebuffer.surface, r->wayland.backbuffer.surface); + wl_subsurface_set_desync(r->wayland.toplevel->ssurface); r->wayland.toplevel->xdg_surface = xdg_wm_base_get_xdg_surface(WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context, r->wayland.backbuffer.surface); @@ -1235,11 +1271,10 @@ static void setup_toplevel(MwLL r, int x, int y) { 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 - (SSD_BORDER_FRAME_LEFT + SSD_BORDER_FRAME_RIGHT), r->wayland.wh - (SSD_BORDER_FRAME_TOP + SSD_BORDER_FRAME_BOTTOM)); + 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, SSD_BORDER_FRAME_LEFT, SSD_BORDER_FRAME_TOP); - wl_subsurface_set_desync(r->wayland.toplevel->ssurface); + wl_subsurface_set_position(r->wayland.toplevel->ssurface, CSD_BORDER_FRAME_LEFT, CSD_BORDER_FRAME_TOP); } } @@ -1437,11 +1472,16 @@ static void destroy_popup(MwLL r) { } static void clip(MwLL handle) { - MwLL parent = handle->wayland.parent; - - if(parent && handle->wayland.type == MWLL_WAYLAND_SUBLEVEL) { + MwLL topmost = handle->wayland.parent; + if(topmost && 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_rectangle(handle->wayland.front_cairo, 0, 0, (topmost->wayland.ww + handle->wayland.x) - (CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT), (topmost->wayland.wh + handle->wayland.y) - (CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM)); + cairo_clip(handle->wayland.front_cairo); + } + if(topmost && handle->wayland.type == MWLL_WAYLAND_SUBLEVEL) { + while(topmost->wayland.parent) topmost = topmost->wayland.parent; + cairo_reset_clip(handle->wayland.front_cairo); + cairo_rectangle(handle->wayland.front_cairo, 0, 0, (topmost->wayland.ww + handle->wayland.x) - (CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT), (topmost->wayland.wh + handle->wayland.y) - (CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM)); cairo_clip(handle->wayland.front_cairo); } } @@ -1596,17 +1636,17 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { } 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 - (SSD_BORDER_FRAME_LEFT + SSD_BORDER_FRAME_RIGHT)) - w = handle->wayland.parent->wayland.ww - (SSD_BORDER_FRAME_LEFT + SSD_BORDER_FRAME_RIGHT); - if(h >= handle->wayland.parent->wayland.wh - (SSD_BORDER_FRAME_TOP + SSD_BORDER_FRAME_BOTTOM)) - h = handle->wayland.parent->wayland.wh - (SSD_BORDER_FRAME_TOP + SSD_BORDER_FRAME_BOTTOM); + 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; - // if(handle->wayland.wh >= (SSD_BORDER_FRAME_TOP + SSD_BORDER_FRAME_BOTTOM)) { - // handle->wayland.wh -= (SSD_BORDER_FRAME_TOP + SSD_BORDER_FRAME_BOTTOM); + // 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) { @@ -1631,23 +1671,96 @@ refresh: static void MwLLBeginDrawImpl(MwLL handle) { if(handle->wayland.type != MWLL_WAYLAND_TOPLEVEL) { + handle->wayland.selected_cairo = handle->wayland.front_cairo; return; } if(!handle->wayland.has_decorations) { - cairo_set_source_rgb(handle->wayland.back_cairo, 0, 0.25, 0.25); - cairo_rectangle(handle->wayland.back_cairo, 1, 1, handle->wayland.ww - 2, handle->wayland.wh - 2); - cairo_fill_preserve(handle->wayland.back_cairo); - cairo_set_source_rgb(handle->wayland.back_cairo, 1, 1, 1); - cairo_rectangle(handle->wayland.back_cairo, 0, 0, handle->wayland.ww, handle->wayland.wh); + int x, y; + 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; + 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_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_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_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_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_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_stroke(handle->wayland.back_cairo); + + if(strlen(handle->wayland.title) != 0) { + int y, x; + int i = 0, sx = 0, sy = 0; + int tw, th; + unsigned char* px; + MwRect r; + MwLLPixmap p; + tw = strlen(handle->wayland.title) * 7; + th = 14; + px = malloc(tw * th * 4); + assert(px); + + memset(px, 0, tw * th * 4); + + handle->wayland.selected_cairo = handle->wayland.back_cairo; + + while(handle->wayland.title[i]) { + int out; + i += MwUTF8ToUTF32(handle->wayland.title + i, &out); + + if(out > 0xff) { + out = 0; + } + + for(y = 0; y < 14; y++) { + for(x = 0; x < 7; x++) { + unsigned char* ppx = &px[((sy + y) * tw + sx + x) * 4]; + int col = MwFontData[out].data[y] & (1 << ((7 - 1) - x)) ? 255 : 0; + ppx[0] = col; + ppx[1] = col; + ppx[2] = col; + ppx[3] = col; + } + } + sx += 7; + } + + p = MwLLCreatePixmap(handle, px, tw, th); + r.x = 5; + r.y = 5; + r.width = tw; + r.height = th; + + MwLLDrawPixmap(handle, &r, p); + MwLLDestroyPixmap(p); + free(px); + } + update_buffer(&handle->wayland.backbuffer); } + handle->wayland.selected_cairo = handle->wayland.front_cairo; } 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); } } } @@ -1835,8 +1948,8 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { cairo_paint(c); - cairo_set_source_surface(handle->wayland.front_cairo, cs, rect->x, rect->y); - cairo_paint(handle->wayland.front_cairo); + cairo_set_source_surface(handle->wayland.selected_cairo, cs, rect->x, rect->y); + cairo_paint(handle->wayland.selected_cairo); cairo_destroy(c); cairo_surface_destroy(cs); From dee940161e3c72fa2938e9e1182ed7ae5498266e Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Fri, 20 Mar 2026 19:33:12 -0700 Subject: [PATCH 88/94] clip: only apply extra clipping when haves decorations --- src/backend/wayland.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index d6eae3cc..6f7a08ea 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1472,16 +1472,22 @@ static void destroy_popup(MwLL r) { } static void clip(MwLL handle) { - MwLL topmost = handle->wayland.parent; - if(topmost && handle->wayland.type == MWLL_WAYLAND_SUBLEVEL) { + MwLL parent = handle->wayland.parent; + MwLL topmost = parent; + int left_offset = 0; + int top_offset = 0; + + if(parent && handle->wayland.type == MWLL_WAYLAND_SUBLEVEL) { cairo_reset_clip(handle->wayland.front_cairo); - cairo_rectangle(handle->wayland.front_cairo, 0, 0, (topmost->wayland.ww + handle->wayland.x) - (CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT), (topmost->wayland.wh + handle->wayland.y) - (CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM)); + 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) { - while(topmost->wayland.parent) topmost = topmost->wayland.parent; cairo_reset_clip(handle->wayland.front_cairo); - cairo_rectangle(handle->wayland.front_cairo, 0, 0, (topmost->wayland.ww + handle->wayland.x) - (CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT), (topmost->wayland.wh + handle->wayland.y) - (CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM)); + 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); } } From 69076f28930a25c31a579034f3f364be0e444f0f Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Fri, 20 Mar 2026 19:42:30 -0700 Subject: [PATCH 89/94] fix menus on csd --- src/backend/wayland.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 6f7a08ea..17872faa 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1402,6 +1402,10 @@ static void setup_popup(MwLL r, int x, int y) { while(topmost_parent->wayland.type != MWLL_WAYLAND_TOPLEVEL) { topmost_parent = topmost_parent->wayland.parent; } + if(!topmost_parent->wayland.has_decorations) { + r->wayland.x += ceil((float)CSD_BORDER_FRAME_LEFT / 2.); + 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)); @@ -1425,9 +1429,7 @@ static void setup_popup(MwLL r, int x, int y) { xdg_positioner_set_size(r->wayland.popup->xdg_positioner, r->wayland.ww, r->wayland.wh); xdg_positioner_set_anchor_rect( r->wayland.popup->xdg_positioner, - x, y, r->wayland.ww, r->wayland.wh); - xdg_positioner_set_anchor(r->wayland.popup->xdg_positioner, XDG_POSITIONER_ANCHOR_TOP_LEFT); - xdg_positioner_set_gravity(r->wayland.popup->xdg_positioner, XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT); + r->wayland.x, r->wayland.y, r->wayland.ww, r->wayland.wh); xdg_surface = topmost_parent->wayland.toplevel->xdg_surface; @@ -1759,6 +1761,8 @@ static void MwLLBeginDrawImpl(MwLL handle) { free(px); } update_buffer(&handle->wayland.backbuffer); + + wl_surface_commit(handle->wayland.backbuffer.surface); } handle->wayland.selected_cairo = handle->wayland.front_cairo; } @@ -1961,8 +1965,8 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { cairo_surface_destroy(cs); MwLLForceRender(handle); - // update_buffer(&handle->wayland.framebuffer); - // wl_surface_damage(handle->wayland.framebuffer.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); + update_buffer(&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) { if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { From 0527d376b7aa6fc344ecbcf9afa045bfaea3016f Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Fri, 20 Mar 2026 20:23:02 -0700 Subject: [PATCH 90/94] add function for forcing the client to be configured before doing any xdg stuff (in a way Both all compositors like) --- src/backend/wayland.c | 117 ++++++++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 51 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 17872faa..3a5c461a 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -890,6 +890,68 @@ 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) { } +/* Standard Wayland event loop. */ +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; + + if(wayland->display == NULL) { + return 0; + } + fd.fd = wl_display_get_fd(wayland->display); + fd.events = POLLIN; + + /* If an error other than EAGAIN happens, we have likely been disconnected from the Wayland session */ + while(wl_display_flush(wayland->display) == -1) { + if(errno != EAGAIN) { + return MwFALSE; + } + + while(poll(&fd, 1, -1) == -1) { + if(errno != EINTR && errno != EAGAIN) { + wl_display_cancel_read(wayland->display); + + MwLLDispatch(handle, close, NULL); + return 0; + } + } + } + + wl_display_prepare_read(handle->wayland.display); + /* Condition where no events are being sent. */ + if(!poll(&fd, 1, timeout.tv_nsec)) { + wl_display_cancel_read(wayland->display); + + wl_surface_commit(wayland->framebuffer.surface); + if(wayland->type == MWLL_WAYLAND_TOPLEVEL) + wl_surface_commit(wayland->backbuffer.surface); + return 0; + } + wl_display_read_events(wayland->display); + if(wl_display_dispatch_pending(wayland->display) < 0) { + wl_display_cancel_read(wayland->display); + } + return 1; +} + +/* 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"); + raise(SIGTRAP); + return; + } + event_loop(handle); + } +} + /* `xdg_toplevel.configure` callback */ static void xdg_toplevel_configure(void* data, struct xdg_toplevel* xdg_toplevel, @@ -1033,7 +1095,8 @@ static void framebuffer_setup(struct _MwLLWayland* wayland) { wayland->front_cairo = cairo_create(wayland->front_cs); memset(wayland->framebuffer.buf, 0, wayland->framebuffer.buf_size); - if(wayland->configured) update_buffer(&wayland->framebuffer); + hang_until_configured((MwLL)wayland); + update_buffer(&wayland->framebuffer); }; static void framebuffer_destroy(struct _MwLLWayland* wayland) { buffer_destroy(&wayland->framebuffer); @@ -1051,7 +1114,8 @@ static void backbuffer_setup(struct _MwLLWayland* wayland) { wayland->back_cairo = cairo_create(wayland->back_cs); memset(wayland->backbuffer.buf, 0, wayland->backbuffer.buf_size); - if(wayland->configured) update_buffer(&wayland->backbuffer); + hang_until_configured((MwLL)wayland); + update_buffer(&wayland->backbuffer); }; static void backbuffer_destroy(struct _MwLLWayland* wayland) { buffer_destroy(&wayland->backbuffer); @@ -1110,55 +1174,6 @@ static void xdg_toplevel_icon_manager_v1_interface_destroy(struct _MwLLWayland* free(data->listener); } -/* Standard Wayland event loop. */ -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; - - if(wayland->display == NULL) { - return 0; - } - fd.fd = wl_display_get_fd(wayland->display); - fd.events = POLLIN; - - /* If an error other than EAGAIN happens, we have likely been disconnected from the Wayland session */ - while(wl_display_flush(wayland->display) == -1) { - if(errno != EAGAIN) { - return MwFALSE; - } - - while(poll(&fd, 1, -1) == -1) { - if(errno != EINTR && errno != EAGAIN) { - wl_display_cancel_read(wayland->display); - - MwLLDispatch(handle, close, NULL); - return 0; - } - } - } - - wl_display_prepare_read(handle->wayland.display); - /* Condition where no events are being sent. */ - if(!poll(&fd, 1, timeout.tv_nsec)) { - wl_display_cancel_read(wayland->display); - - wl_surface_commit(wayland->framebuffer.surface); - if(wayland->type == MWLL_WAYLAND_TOPLEVEL) - wl_surface_commit(wayland->backbuffer.surface); - return 0; - } - wl_display_read_events(wayland->display); - if(wl_display_dispatch_pending(wayland->display) < 0) { - wl_display_cancel_read(wayland->display); - } - return 1; -} - /* Function for setting up the callbacks/structs that will be registered upon the relevant interfaces being found. */ static void setup_callbacks(struct _MwLLWayland* wayland) { /* Convience macro for adding the interface functions to the setup map */ From 2499f82933e35e8fddc521a6c55a7d6a43518595 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 22 Mar 2026 16:12:54 -0700 Subject: [PATCH 91/94] wayland: fix double free in wp_viewporter_interface_destroy --- 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 3a5c461a..06fdbb01 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -864,7 +864,7 @@ 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); + // free(data->listener); } /* the two decoration manager constructs */ From 09441380b5e07d2a990040c3dfd8c3ec435e3b23 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 22 Mar 2026 16:15:50 -0700 Subject: [PATCH 92/94] wayland: fallback if selected_cairo is null --- include/Mw/LowLevel/Wayland.h | 1 + src/backend/wayland.c | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 053d0ff9..9659ac56 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -235,6 +235,7 @@ struct _MwLLWayland { cairo_surface_t* back_cs; cairo_t* front_cairo; cairo_t* back_cairo; + /* The cairo to actually use for draw operations. Typically is front_cairo, but MwLLBeginDraw can change this to the back_cairo so it can be used to draw window decorations. */ cairo_t* selected_cairo; }; diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 06fdbb01..66889221 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1960,6 +1960,7 @@ static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { cairo_t* c; cairo_surface_t* cs; + cairo_t * selected_cairo = handle->wayland.selected_cairo ? handle->wayland.selected_cairo : handle->wayland.front_cairo; cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, rect->width, rect->height); c = cairo_create(cs); @@ -1973,8 +1974,8 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { cairo_paint(c); - cairo_set_source_surface(handle->wayland.selected_cairo, cs, rect->x, rect->y); - cairo_paint(handle->wayland.selected_cairo); + cairo_set_source_surface(selected_cairo, cs, rect->x, rect->y); + cairo_paint(selected_cairo); cairo_destroy(c); cairo_surface_destroy(cs); From c3d25e6b7d96c9b477aa1d248e3e0d721d63e8ca Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 22 Mar 2026 16:32:36 -0700 Subject: [PATCH 93/94] wayland: don't do draw dispatch on forceRender anymore, merely update the buffer --- src/backend/wayland.c | 29 ++++++++++++++++++----------- src/widget/opengl.c | 7 ++++--- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 66889221..0a21590d 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1861,31 +1861,37 @@ static int MwLLPendingImpl(MwLL handle) { fd.fd = wl_display_get_fd(handle->wayland.display); fd.events = POLLOUT; - wl_display_prepare_read(handle->wayland.display); + 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); } else { - wl_display_read_events(handle->wayland.display); + if(!handle->wayland.always_render) 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) { + // handle->wayland.did_event_loop_early = MwTRUE; + // event_loop(handle); + return pending; + } + wl_surface_commit(handle->wayland.framebuffer.surface); if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { wl_surface_commit(handle->wayland.backbuffer.surface); } - if(handle->wayland.always_render) { + if(handle->wayland.events_pending) { + handle->wayland.did_event_loop_early = MwTRUE; event_loop(handle); - return 0; - } else if(handle->wayland.force_render) { - MwLLDispatch(handle, draw, NULL); return 1; } - if(handle->wayland.events_pending || handle->wayland.force_render) { - handle->wayland.did_event_loop_early = MwTRUE; - return event_loop(handle); - } + + // if(handle->wayland.force_render) { + + // return 1; + // } return pending; } @@ -1902,6 +1908,7 @@ static void MwLLNextEventImpl(MwLL handle) { handle->wayland.events_pending = 0; } if(handle->wayland.force_render) { + // MwLLDispatch(handle, draw, NULL); if(handle->wayland.configured) update_buffer(&handle->wayland.framebuffer); handle->wayland.force_render = 0; } @@ -1960,7 +1967,7 @@ static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { cairo_t* c; cairo_surface_t* cs; - cairo_t * selected_cairo = handle->wayland.selected_cairo ? handle->wayland.selected_cairo : handle->wayland.front_cairo; + cairo_t* selected_cairo = handle->wayland.selected_cairo ? handle->wayland.selected_cairo : handle->wayland.front_cairo; cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, rect->width, rect->height); c = cairo_create(cs); diff --git a/src/widget/opengl.c b/src/widget/opengl.c index 779b17af..6d67344c 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -165,9 +165,10 @@ static int create(MwWidget handle) { 1, EGL_NONE}; EGLDisplay display; - waylandopengl_t* o = r = malloc(sizeof(*o)); - MwLL topmost_parent = handle->lowlevel->wayland.parent; - topmost_parent->wayland.always_render = MwTRUE; + 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; From 9d65e9c6bf37a21c625a95a43410c030af4fc855 Mon Sep 17 00:00:00 2001 From: IoI_xD Date: Mon, 23 Mar 2026 12:05:32 -0700 Subject: [PATCH 94/94] Wayland improvements --- examples/basic/clipboard.c | 1 + examples/vkdemos/vulkan.c | 9 ++- include/Mw/LowLevel/Wayland.h | 7 +- src/backend/wayland.c | 143 ++++++++++++++++++---------------- src/widget/combobox.c | 2 +- src/widget/vulkan.c | 2 +- 6 files changed, 89 insertions(+), 75 deletions(-) diff --git a/examples/basic/clipboard.c b/examples/basic/clipboard.c index 384cbc6f..57d57925 100644 --- a/examples/basic/clipboard.c +++ b/examples/basic/clipboard.c @@ -29,6 +29,7 @@ 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); diff --git a/examples/vkdemos/vulkan.c b/examples/vkdemos/vulkan.c index 0e1842d0..29547ce5 100644 --- a/examples/vkdemos/vulkan.c +++ b/examples/vkdemos/vulkan.c @@ -27,6 +27,8 @@ MwWidget window, vulkan; int ow = 300; int oh = 250; +double timer = 0; + PFN_vkGetInstanceProcAddr _vkGetInstanceProcAddr; VkInstance instance; VkDevice device; @@ -75,9 +77,10 @@ void tick(MwWidget handle, void* user_data, void* call_data) { VkSubmitInfo submitInfo = {}; VkPresentInfoKHR presentInfo = {}; - VkClearValue clearColor = {{{0.0f, 0.0f, 0.0f, 1.0f}}}; + VkClearValue clearColor = {{{sin(timer) / 10., cos(timer) / 10., atan(timer) / 10., 1.0f}}}; uint32_t vertexCount = 3; uint32_t instanceCount = 1; + timer += (float)(rand() % 1000) / 1000.; VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT}; @@ -289,8 +292,8 @@ void vulkan_setup(MwWidget handle) { swapchainCreateInfo.imageExtent = (VkExtent2D){.width = ow, .height = oh}, swapchainCreateInfo.imageArrayLayers = 1, swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | - VK_IMAGE_USAGE_TRANSFER_DST_BIT | - VK_IMAGE_USAGE_SAMPLED_BIT; + VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_SAMPLED_BIT; // th is how we specify no transformation. swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 9659ac56..00556dad 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -141,6 +141,9 @@ struct _MwLLWayland { enum _MwLLWaylandType type; enum _MwLLWaylandType type_to_be; + MwBool detatching; + MwPoint detach_point; + /* Map of Wayland interfaces to their relevant setup functions. */ struct { const char* key; @@ -227,8 +230,6 @@ struct _MwLLWayland { MwBool moving; - MwLL currentlyHeldWidget; - struct wl_surface* curSurface; cairo_surface_t* front_cs; @@ -236,7 +237,7 @@ struct _MwLLWayland { cairo_t* front_cairo; cairo_t* back_cairo; /* The cairo to actually use for draw operations. Typically is front_cairo, but MwLLBeginDraw can change this to the back_cairo so it can be used to draw window decorations. */ - cairo_t* selected_cairo; + cairo_t* selected_cairo; }; struct _MwLLWaylandColor { diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 0a21590d..2e32ceda 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -228,8 +228,12 @@ 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); + + ctx->ll->wayland.events_pending = 1; } static void wl_data_source_listener_target(void* data, @@ -415,6 +419,8 @@ static void xdg_borderless_step(MwLL self, MwLLMouse p, MwU32 serial) { }; } +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) { @@ -428,15 +434,25 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time p.point = self->wayland.cur_mouse_pos; MwLLDispatch(self, move, &p); - if(self->wayland.parent != NULL) { - if(!self->wayland.parent->wayland.currentlyHeldWidget) { - MwLLDispatch(self, down, &p); - } + if(currentlyHeldWidget) { + MwLLDispatch(currentlyHeldWidget, down, &p); } - /* Only draw once every 50 milliseconds */ - if((self->wayland.last_time + 50) <= time) { - MwLLDispatch(self, draw, NULL); - self->wayland.last_time = time; + + /* 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) { + 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) { + MwLLDispatch(self, draw, NULL); + self->wayland.last_time = time; + } } WAYLAND_EVENT_OP_END(self); @@ -477,17 +493,13 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri switch(state) { case WL_POINTER_BUTTON_STATE_PRESSED: MwLLDispatch(self, down, &p); - if(self->wayland.parent != NULL) { - self->wayland.parent->wayland.currentlyHeldWidget = self; - } + currentlyHeldWidget = self; break; case WL_POINTER_BUTTON_STATE_RELEASED: - if(self->wayland.parent != NULL) { - if(self->wayland.parent->wayland.currentlyHeldWidget != NULL) { - MwLLDispatch(self->wayland.parent->wayland.currentlyHeldWidget, up, &p); - self->wayland.parent->wayland.currentlyHeldWidget = NULL; - } + if(currentlyHeldWidget != NULL) { + MwLLDispatch(currentlyHeldWidget, up, &p); + currentlyHeldWidget = NULL; } else { MwLLDispatch(self, up, &p); } @@ -993,8 +1005,6 @@ static void xdg_toplevel_configure(void* data, MwLLDispatch(self, resize, NULL); MwLLDispatch(self, draw, NULL); - - MwLLForceRender(self); }; /* Empty function for satisfying zxdg_toplevel's requirements */ @@ -1851,15 +1861,15 @@ static void MwLLFreeColorImpl(MwLLColor color) { } static int MwLLPendingImpl(MwLL handle) { - struct timespec timeout; - struct pollfd fd; - int pending = 0; - - timeout.tv_nsec = 100; - timeout.tv_sec = 0; - - fd.fd = wl_display_get_fd(handle->wayland.display); - fd.events = POLLOUT; + struct timespec timeout = { + .tv_nsec = 100, + .tv_sec = 0, + }; + struct pollfd fd = { + .fd = wl_display_get_fd(handle->wayland.display), + .events = POLLOUT, + }; + int pending = 0; if(!handle->wayland.always_render) wl_display_prepare_read(handle->wayland.display); if(!poll(&fd, 1, timeout.tv_nsec)) { @@ -1872,8 +1882,8 @@ static int MwLLPendingImpl(MwLL handle) { } if(handle->wayland.always_render) { - // handle->wayland.did_event_loop_early = MwTRUE; - // event_loop(handle); + handle->wayland.did_event_loop_early = MwTRUE; + event_loop(handle); return pending; } @@ -1882,18 +1892,7 @@ static int MwLLPendingImpl(MwLL handle) { wl_surface_commit(handle->wayland.backbuffer.surface); } - if(handle->wayland.events_pending) { - handle->wayland.did_event_loop_early = MwTRUE; - event_loop(handle); - return 1; - } - - // if(handle->wayland.force_render) { - - // return 1; - // } - - return pending; + return handle->wayland.force_render || handle->wayland.events_pending || pending; } static void MwLLNextEventImpl(MwLL handle) { @@ -1904,14 +1903,15 @@ static void MwLLNextEventImpl(MwLL handle) { event_loop(handle); } } - if(handle->wayland.events_pending) { - handle->wayland.events_pending = 0; - } + if(handle->wayland.force_render) { - // 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; } + if(handle->wayland.events_pending) { + handle->wayland.events_pending = 0; + } } static void MwLLSetTitleImpl(MwLL handle, const char* title) { @@ -2034,6 +2034,9 @@ static void MwLLForceRenderImpl(MwLL handle) { wl_surface_damage(handle->wayland.framebuffer.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); handle->wayland.force_render = MwTRUE; + if(handle->wayland.parent) { + handle->wayland.parent->wayland.force_render = MwTRUE; + } } static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { @@ -2087,28 +2090,8 @@ static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { } static void MwLLDetachImpl(MwLL handle, MwPoint* point) { - switch(handle->wayland.type) { - case MWLL_WAYLAND_UNKNOWN: - case MWLL_WAYLAND_TOPLEVEL: - destroy_toplevel(handle); - break; - case MWLL_WAYLAND_SUBLEVEL: - destroy_sublevel(handle); - break; - case MWLL_WAYLAND_POPUP: - return; - } - - wl_flush(handle); - - switch(handle->wayland.type_to_be) { - case MWLL_WAYLAND_POPUP: - setup_popup(handle, point->x, point->y); - break; - default: - setup_toplevel(handle, point->x, point->y); - break; - } + handle->wayland.detatching = MwTRUE; + handle->wayland.detach_point = *point; } static void MwLLShowImpl(MwLL handle, int show) { @@ -2201,6 +2184,32 @@ static void MwLLBeginStateChangeImpl(MwLL handle) { } static void MwLLEndStateChangeImpl(MwLL handle) { + if(handle->wayland.detatching) { + switch(handle->wayland.type) { + case MWLL_WAYLAND_UNKNOWN: + case MWLL_WAYLAND_TOPLEVEL: + destroy_toplevel(handle); + break; + case MWLL_WAYLAND_SUBLEVEL: + destroy_sublevel(handle); + break; + case MWLL_WAYLAND_POPUP: + return; + } + + 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; + } + handle->wayland.detatching = MwFALSE; + } + MwLLShow(handle, 1); } diff --git a/src/widget/combobox.c b/src/widget/combobox.c index 591258f9..6b543733 100644 --- a/src/widget/combobox.c +++ b/src/widget/combobox.c @@ -138,8 +138,8 @@ static void click(MwWidget handle) { p.x = 0; p.y = MwGetInteger(handle, MwNheight); MwLLBeginStateChange(cb->listbox->lowlevel); - MwLLMakeToolWindow(cb->listbox->lowlevel); MwLLDetach(cb->listbox->lowlevel, &p); + MwLLMakeToolWindow(cb->listbox->lowlevel); MwLLEndStateChange(cb->listbox->lowlevel); } else { MwLLSetCursor(handle->lowlevel, &MwCursorDefault, &MwCursorDefaultMask); diff --git a/src/widget/vulkan.c b/src/widget/vulkan.c index b78e7429..e2dfa4c8 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 */ - topmost_parent->wayland.always_render = MwTRUE; + handle->lowlevel->wayland.always_render = MwTRUE; while(topmost_parent->wayland.parent != NULL) { topmost_parent = topmost_parent->wayland.parent;