From 843cc74c4c01375e04d53330f4d45d8ea92e2a24 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sat, 29 Nov 2025 17:56:33 -0700 Subject: [PATCH 01/48] wayland backend init commit --- .gitignore | 3 + include/Mw/LowLevel.h | 16 +- include/Mw/LowLevel/Wayland.h | 84 +++++ include/Mw/LowLevel/Wayland/.gitignore | 1 + include/Mw/LowLevel/Wayland/README.md | 1 + pl/ostype/Linux.pl | 7 +- pl/rules.pl | 13 + pl/utils.pl | 17 + src/backend/.gitignore | 1 + src/backend/wayland.c | 437 +++++++++++++++++++++++++ src/backend/x11.c | 1 - src/core.c | 3 + 12 files changed, 581 insertions(+), 3 deletions(-) create mode 100644 include/Mw/LowLevel/Wayland.h create mode 100644 include/Mw/LowLevel/Wayland/.gitignore create mode 100644 include/Mw/LowLevel/Wayland/README.md create mode 100644 src/backend/.gitignore create mode 100644 src/backend/wayland.c diff --git a/.gitignore b/.gitignore index 7b0e56d..814f7b3 100644 --- a/.gitignore +++ b/.gitignore @@ -3,8 +3,11 @@ examples/* examples/*.exe examples/*/* +examples/*/*.o examples/*/*.exe !examples/*/ !examples/*.* !examples/*/*.* compile_flags.txt +*.a +Makefile diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index cb9c1e6..c3f7fe9 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -26,13 +26,15 @@ typedef void* MwLLPixmap; enum MwLLBackends { MwLLBackendX11 = 0, - MwLLBackendGDI + MwLLBackendGDI, + MwLLBackendWayland, }; struct _MwLLCommon { void* user; int copy_buffer; int type; + int success; MwLLHandler handler; }; @@ -56,6 +58,9 @@ struct _MwLLCommonPixmap { #ifdef USE_GDI #include #endif +#ifdef USE_WAYLAND +#include +#endif union _MwLL { struct _MwLLCommon common; @@ -65,6 +70,9 @@ union _MwLL { #ifdef USE_GDI struct _MwLLGDI gdi; #endif +#ifdef USE_WAYLAND + struct _MwLLWayland wayland; +#endif }; union _MwLLColor { @@ -75,6 +83,9 @@ union _MwLLColor { #ifdef USE_GDI struct _MwLLGDIColor gdi; #endif +#ifdef USE_WAYLAND + struct _MwLLWaylandColor wayland; +#endif }; union _MwLLPixmap { @@ -85,6 +96,9 @@ union _MwLLPixmap { #ifdef USE_GDI struct _MwLLGDIPixmap gdi; #endif +#ifdef USE_WAYLAND + struct _MwLLWaylandPixmap wayland; +#endif }; #endif #include diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h new file mode 100644 index 0000000..5fd1e7a --- /dev/null +++ b/include/Mw/LowLevel/Wayland.h @@ -0,0 +1,84 @@ +/* $Id$ */ +/*! + * @file Mw/LowLevel/Wayland.h + * @brief Wayland Backend + * @warning This is used internally + */ +#ifndef __MW_LOWLEVEL_WAYLAND_H__ +#define __MW_LOWLEVEL_WAYLAND_H__ + +#include +#include +#include + +#include +#include + +MWDECL int MwLLWaylandCallInit(void); + +#ifndef WL_PROTOCOLS_DEFINED +#define WL_PROTOCOLS_DEFINED +#include "Wayland/xdg-shell-client-protocol.h" +#include "Wayland/xdg-decoration-client-protocol.h" +#include "Wayland/cursor-shape-client-protocol.h" +#endif + +typedef struct wayland_protocol { + void* listener; + void* context; +} wayland_protocol_t; + +typedef wayland_protocol_t*(wl_setup_func)(MwU32, struct _MwLLWayland*); + +struct _MwLLWayland { + struct _MwLLCommon common; + + // struct wl_shm* shm; + struct wl_display* display; + struct wl_registry* registry; + // struct wl_compositor* compositor; + // struct wl_seat* seat; + struct wl_surface* surface; + struct xdg_surface* xdg_surface; + // struct xdg_wm_base* xdg_wm_base; + struct xdg_toplevel* xdg_top_level; + + struct wl_registry_listener registry_listener; + + // struct zxdg_decoration_manager_v1* decoration_manager; + // struct zxdg_toplevel_decoration_v1* toplevel_decoration; + + struct xdg_toplevel_listener xdg_toplevel_listener; + // struct xdg_wm_base_listener xdg_wm_base_listener; + struct xdg_surface_listener xdg_surface_listener; + // struct wl_pointer_listener pointer_listener; + // struct wl_seat_listener seat_listener; + // struct wl_keyboard_listener keyboard_listener; + // struct wl_shell_surface_listener shell_surface_listener; + // struct zxdg_toplevel_decoration_v1_listener decoration_listener; + + struct { + const char* key; + wl_setup_func* value; + }* wl_protocol_setup_map; + + struct { + const char* key; + wayland_protocol_t* value; + }* wl_protocol_map; + + struct xkb_context* xkb_context; + + MwBool configured; + MwBool running; +}; + +struct _MwLLWaylandColor { + struct _MwLLCommonColor common; +}; + +struct _MwLLWaylandPixmap { + struct _MwLLCommonPixmap common; +}; + +#endif diff --git a/include/Mw/LowLevel/Wayland/.gitignore b/include/Mw/LowLevel/Wayland/.gitignore new file mode 100644 index 0000000..25a4663 --- /dev/null +++ b/include/Mw/LowLevel/Wayland/.gitignore @@ -0,0 +1 @@ +*protocol.h diff --git a/include/Mw/LowLevel/Wayland/README.md b/include/Mw/LowLevel/Wayland/README.md new file mode 100644 index 0000000..e0c17e8 --- /dev/null +++ b/include/Mw/LowLevel/Wayland/README.md @@ -0,0 +1 @@ +Folder for wayland-scanner to place any of its files. diff --git a/pl/ostype/Linux.pl b/pl/ostype/Linux.pl index 980b119..f3befce 100644 --- a/pl/ostype/Linux.pl +++ b/pl/ostype/Linux.pl @@ -1,4 +1,9 @@ # $Id$ -use_backend("x11"); + +if(system("wayland-scanner -v >/dev/null 2>&1") == 0){ + use_backend("wayland", "x11"); +} else { + use_backend("x11"); +} 1; diff --git a/pl/rules.pl b/pl/rules.pl index 90778b9..e1bd499 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -27,6 +27,19 @@ if (grep(/^gdi$/, @backends)) { $gl_libs = "-lopengl32 -lglu32"; } +if (grep(/^wayland$/, @backends)) { + add_cflags("-DUSE_WAYLAND"); + new_object("src/backend/wayland.c"); + add_libs("-lwayland-client -lxkbcommon"); + + scan_wayland_protocol("stable", "xdg-shell",""); + scan_wayland_protocol("stable", "tablet","-v2"); + scan_wayland_protocol("staging", "cursor-shape","-v1"); + scan_wayland_protocol("unstable", "xdg-decoration","-unstable-v1"); + + $gl_libs = "-lGL -lGLU"; +} + if (param_get("stb-image")) { add_cflags("-DUSE_STB_IMAGE"); } diff --git a/pl/utils.pl b/pl/utils.pl index 218f505..5887e74 100644 --- a/pl/utils.pl +++ b/pl/utils.pl @@ -55,6 +55,23 @@ sub use_backend { } } +sub scan_wayland_protocol { + my $tier = $_[0]; + my $proto = $_[1]; + my $ver = $_[2]; + + my $proto_c = "src/backend/wayland-${proto}-protocol.c"; + + if(system("wayland-scanner private-code /usr/share/wayland-protocols/${tier}/${proto}/${proto}${ver}.xml ${proto_c}") != 0) { + print("^ Error on getting private code for /usr/share/wayland-protocols/${tier}/${proto}/${proto}${ver}.xml\n"); + } else { + new_object($proto_c); + }; + if(system("wayland-scanner client-header /usr/share/wayland-protocols/${tier}/${proto}/${proto}${ver}.xml include/Mw/LowLevel/Wayland/${proto}-client-protocol.h")) { + print("^ Error on getting client header for /usr/share/wayland-protocols/${tier}/${proto}/${proto}${ver}.xml\n"); + }; +} + our %params = (); sub param_set { diff --git a/src/backend/.gitignore b/src/backend/.gitignore new file mode 100644 index 0000000..137387c --- /dev/null +++ b/src/backend/.gitignore @@ -0,0 +1 @@ +wayland*protocol.c diff --git a/src/backend/wayland.c b/src/backend/wayland.c new file mode 100644 index 0000000..f964037 --- /dev/null +++ b/src/backend/wayland.c @@ -0,0 +1,437 @@ +/* $Id$ */ + +/** + TODO: + + - would fit with Milsko's goal to support older compositors using wl_shell. would also suck to test because most compositors outright removed that around 2021... + + */ + +#include + +#include "../../external/stb_ds.h" + +#define WAYLAND_GET_INTERFACE(r, inter) shget(r->wayland.wl_protocol_map, inter##_interface.name) + +// REGISTRY +static void new_protocol(void* data, struct wl_registry* registry, + MwU32 name, const char* interface, + MwU32 version) { + struct _MwLLWayland* wayland = data; + + wl_setup_func* func = shget(wayland->wl_protocol_setup_map, interface); + if(func != NULL) { + shput(wayland->wl_protocol_map, interface, func(name, data)); + } +}; + +static void protocol_removed(void* data, + struct wl_registry* registry, + MwU32 name) { + +}; + +// SEAT +static void wl_seat_name(void* data, struct wl_seat* wl_seat, const char* name) {}; +static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat, + uint32_t capabilities) {}; + +// XDG SHELL +void xdg_wm_base_ping(void* data, + struct xdg_wm_base* xdg_wm_base, + uint32_t serial) { + // The compositor will send us a ping event to check that we're responsive. + // We need to send back a pong request immediately. + xdg_wm_base_pong(xdg_wm_base, serial); +}; + +// XDG SHELL SURFACE +static void wl_shell_surface_ping(void* data, + struct wl_shell_surface* wl_shell_surface, + uint32_t serial) {}; +static void wl_shell_surface_configure(void* data, + struct wl_shell_surface* wl_shell_surface, + uint32_t edges, + int32_t width, + int32_t height) {}; + +static void wl_shell_surface_popup_done(void* data, + struct wl_shell_surface* wl_shell_surface) {}; + +static wayland_protocol_t* wl_shm_setup(MwU32 name, struct _MwLLWayland* wayland) { + wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); + proto->listener = NULL; + proto->context = wl_registry_bind(wayland->registry, name, &wl_shm_interface, 1); + return proto; +} +static wayland_protocol_t* wl_seat_setup(MwU32 name, struct _MwLLWayland* wayland) { + wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); + proto->listener = malloc(sizeof(struct wl_seat_listener)); + + ((struct wl_seat_listener*)proto->listener)->name = wl_seat_name; + ((struct wl_seat_listener*)proto->listener)->capabilities = wl_seat_capabilities; + + proto->context = wl_registry_bind(wayland->registry, name, &wl_seat_interface, 1); + wl_seat_add_listener(proto->context, proto->listener, wayland); + + return proto; +} +static wayland_protocol_t* wl_compositor_setup(MwU32 name, struct _MwLLWayland* wayland) { + wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); + proto->listener = NULL; + proto->context = wl_registry_bind(wayland->registry, name, &wl_compositor_interface, 1); + + return proto; +} +static wayland_protocol_t* xdg_wm_base_setup(MwU32 name, struct _MwLLWayland* wayland) { + wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); + proto->listener = malloc(sizeof(struct xdg_wm_base_listener)); + + ((struct xdg_wm_base_listener*)proto->listener)->ping = xdg_wm_base_ping; + + proto->context = wl_registry_bind(wayland->registry, name, &xdg_wm_base_interface, 1); + xdg_wm_base_add_listener(proto->context, proto->listener, wayland); + + return proto; +} +static wayland_protocol_t* wl_shell_surface_setup(MwU32 name, struct _MwLLWayland* wayland) { + wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); + proto->listener = malloc(sizeof(struct wl_shell_surface_listener)); + + ((struct wl_shell_surface_listener*)proto->listener)->ping = wl_shell_surface_ping; + ((struct wl_shell_surface_listener*)proto->listener)->configure = wl_shell_surface_configure; + ((struct wl_shell_surface_listener*)proto->listener)->popup_done = wl_shell_surface_popup_done; + + proto->context = wl_registry_bind(wayland->registry, name, &wl_shell_surface_interface, 1); + wl_shell_surface_add_listener(proto->context, proto->listener, wayland); + + return proto; +} + +static wayland_protocol_t* wp_cursor_shape_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland) { + wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); + proto->listener = NULL; + + proto->context = wl_registry_bind(wayland->registry, name, &wp_cursor_shape_manager_v1_interface, 1); + + return proto; +} + +typedef struct zxdg_decoration_manager_v1_context { + struct zxdg_decoration_manager_v1* manager; + // struct zxdg_decoration_toplevel_v1* toplevel; + struct zxdg_toplevel_decoration_v1* decoration; +} zxdg_decoration_manager_v1_context_t; + +static wayland_protocol_t* zxdg_decoration_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland) { + wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); + zxdg_decoration_manager_v1_context_t* ctx = malloc(sizeof(zxdg_decoration_manager_v1_context_t)); + proto->listener = NULL; + + ctx->manager = wl_registry_bind(wayland->registry, name, &zxdg_decoration_manager_v1_interface, 1); + ; + + proto->context = ctx; + + return proto; +} + +static void xdg_toplevel_configure(void* data, + struct xdg_toplevel* xdg_toplevel, + int32_t width, int32_t height, + struct wl_array* states) { + struct _MwLLWayland* self = (struct _MwLLWayland*)data; + + wl_surface_commit(self->surface); + + return; +}; + +static void decoration_configure( + void* data, struct zxdg_toplevel_decoration_v1* zxdg_toplevel_decoration_v1, + uint32_t mode) { +} + +static void xdg_toplevel_close( + void* data, struct xdg_toplevel* xdg_toplevel) { + struct _MwLLWayland* self = (struct _MwLLWayland*)data; + // Stop running if the user requests to close the toplevel + self->running = MwFALSE; +}; + +static void xdg_surface_configure( + void* data, struct xdg_surface* xdg_surface, uint32_t serial) { + struct _MwLLWayland* self = (struct _MwLLWayland*)data; + + // The compositor configures our surface, acknowledge the configure event + xdg_surface_ack_configure(xdg_surface, serial); + + if(self->configured) { + // If this isn't the first configure event we've received, we already + // have a buffer attached, so no need to do anything. Commit the + // surface to apply the configure acknowledgement. + wl_surface_commit(self->surface); + } + + self->configured = MwTRUE; +} + +static void shell_surface_ping(void* data, + struct wl_shell_surface* shell_surface, + uint32_t serial) {}; +static void shell_surface_configure( + void* data, struct wl_shell_surface* shell_surface, uint32_t edges, + int32_t width, int32_t height) {}; + +static void shell_surface_popup_done( + void* data, struct wl_shell_surface* shell_surface) {}; + +static void setup_callbacks(struct _MwLLWayland* wayland) { + wayland->registry_listener.global = new_protocol; + wayland->registry_listener.global_remove = protocol_removed; + +#define WL_INTERFACE(interface) \ + shput(wayland->wl_protocol_setup_map, interface##_interface.name, (wl_setup_func*)interface##_setup); + + WL_INTERFACE(wl_shm); + WL_INTERFACE(wl_seat); + WL_INTERFACE(wl_compositor); + WL_INTERFACE(xdg_wm_base); + WL_INTERFACE(wl_shell_surface); + WL_INTERFACE(zxdg_decoration_manager_v1); + WL_INTERFACE(wp_cursor_shape_manager_v1); +} + +static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { + MwLL r; + r = malloc(sizeof(*r)); + MwLLCreateCommon(r); + + r->common.copy_buffer = 1; + r->common.type = MwLLBackendWayland; + + setup_callbacks(&r->wayland); + + // Connect to the Wayland compositor + r->wayland.display = wl_display_connect(NULL); + if(r->wayland.display == NULL) { + printf("wayland: failed to create display\n"); + r->common.success = MwFALSE; + return r; + } + + // Obtain the wl_registry and fetch the list of globals + r->wayland.registry = wl_display_get_registry(r->wayland.display); + wl_registry_add_listener(r->wayland.registry, &r->wayland.registry_listener, r); + if(wl_display_roundtrip(r->wayland.display) == -1) { + printf("roundtrip failed\n"); + r->common.success = MwFALSE; + return r; + } + + // Check that all globals we require are available + if( + WAYLAND_GET_INTERFACE(r, wl_compositor)->context == NULL || + WAYLAND_GET_INTERFACE(r, xdg_wm_base)->context == NULL || + WAYLAND_GET_INTERFACE(r, wl_seat)->context == NULL) { + + printf("no wl_shm, wl_compositor, wl_seat, or xdg_wm_base support\n"); + r->common.success = MwFALSE; + return r; + } + + // wl_log_set_handler_client(_MwLLWayland::logger); + + r->wayland.xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + + // Create a wl_surface, a xdg_surface and a xdg_toplevel + r->wayland.surface = wl_compositor_create_surface(WAYLAND_GET_INTERFACE(r, wl_compositor)->context); + r->wayland.xdg_surface = + xdg_wm_base_get_xdg_surface(WAYLAND_GET_INTERFACE(r, xdg_wm_base)->context, r->wayland.surface); + r->wayland.xdg_top_level = xdg_surface_get_toplevel(r->wayland.xdg_surface); + + // setup mandatory listeners + r->wayland.xdg_surface_listener.configure = xdg_surface_configure; + r->wayland.xdg_toplevel_listener.configure = xdg_toplevel_configure; + r->wayland.xdg_toplevel_listener.close = xdg_toplevel_close; + + xdg_surface_add_listener(r->wayland.xdg_surface, &r->wayland.xdg_surface_listener, r); + xdg_toplevel_add_listener(r->wayland.xdg_top_level, &r->wayland.xdg_toplevel_listener, + r); + + xdg_toplevel_set_title(r->wayland.xdg_top_level, "Milsko Wayland App"); + xdg_toplevel_set_app_id(r->wayland.xdg_top_level, "Milsko Wayland App"); + + // if (!mFlags.windowResizable) { + // xdg_toplevel_set_min_size(mXDGTopLevel, mWidth, mHeight); + // xdg_toplevel_set_max_size(mXDGTopLevel, mWidth, mHeight); + // } + + // Perform the initial commit and wait for the first configure event + wl_surface_commit(r->wayland.surface); + while(wl_display_dispatch(r->wayland.display) != -1 && !r->wayland.configured) { + } + + // setup decorations if we can + if(WAYLAND_GET_INTERFACE(r, zxdg_decoration_manager_v1)->context != NULL) { + zxdg_decoration_manager_v1_context_t* dec = WAYLAND_GET_INTERFACE(r, zxdg_decoration_manager_v1)->context; + + dec->decoration = zxdg_decoration_manager_v1_get_toplevel_decoration( + dec->manager, r->wayland.xdg_top_level); + + // zxdg_toplevel_decoration_v1_add_listener(dec->decoration, + // dec->listener, r); + + zxdg_toplevel_decoration_v1_set_mode( + dec->decoration, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); + } + + wl_surface_commit(r->wayland.surface); + + r->common.success = MwTRUE; + + return r; +} + +static void MwLLDestroyImpl(MwLL handle) { + MwLLDestroyCommon(handle); + + free(handle); +} + +static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { +} + +static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { +} + +static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { + MwLLColor c = malloc(sizeof(*c)); + + c->common.red = r; + c->common.blue = b; + c->common.green = g; + + return c; +} + +static void MwLLColorUpdateImpl(MwLL handle, MwLLColor c, int r, int g, int b) { + c->common.red = r; + c->common.blue = b; + c->common.green = g; +} + +static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h) { + *x = 0; + *y = 0; + *w = 0; + *h = 0; +} + +static void MwLLSetXYImpl(MwLL handle, int x, int y) { +} + +static void MwLLSetWHImpl(MwLL handle, int w, int h) { +} + +static void MwLLFreeColorImpl(MwLLColor color) { +} + +static void MwLLSetBackgroundImpl(MwLL handle, MwLLColor color) { +} + +static int MwLLPendingImpl(MwLL handle) { + return 0; +} + +static void MwLLNextEventImpl(MwLL handle) { +} + +static void MwLLSetTitleImpl(MwLL handle, const char* title) { +} + +static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, int width, int height) { + MwLLPixmap r = malloc(sizeof(*r)); + + r->common.width = width; + r->common.height = height; + r->common.raw = data; + return r; +} + +static void MwLLPixmapUpdateImpl(MwLLPixmap r) { +} + +static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { + free(pixmap); +} + +static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { +} + +static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { +} + +static void MwLLForceRenderImpl(MwLL handle) { +} + +static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { +} + +static void MwLLDetachImpl(MwLL handle, MwPoint* point) { +} + +static void MwLLShowImpl(MwLL handle, int show) { +} + +static void MwLLMakePopupImpl(MwLL handle, MwLL parent) { +} + +static void MwLLSetSizeHintsImpl(MwLL handle, int minx, int miny, int maxx, int maxy) { +} + +static void MwLLMakeBorderlessImpl(MwLL handle, int toggle) { +} + +static void MwLLFocusImpl(MwLL handle) { +} + +static void MwLLGrabPointerImpl(MwLL handle, int toggle) { +} + +static void MwLLSetClipboardImpl(MwLL handle, const char* text) { +} + +static char* MwLLGetClipboardImpl(MwLL handle) { + char* r = NULL; + return r; +} + +static void MwLLMakeToolWindowImpl(MwLL handle) { +} + +static void MwLLGetCursorCoordImpl(MwLL handle, MwPoint* point) { +} + +static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) { +} + +static void MwLLBeginStateChangeImpl(MwLL handle) { + MwLLShow(handle, 0); +} + +static void MwLLEndStateChangeImpl(MwLL handle) { + MwLLShow(handle, 1); +} + +static int MwLLWaylandCallInitImpl(void) { +#ifdef __linux__ + if(strcmp(getenv("XDG_SESSION_TYPE"), "wayland")) { + return 1; + } +#endif + return 0; +} + +#include "call.c" +CALL(Wayland); diff --git a/src/backend/x11.c b/src/backend/x11.c index f75adfb..a7bea2f 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -1019,7 +1019,6 @@ static void MwLLEndStateChangeImpl(MwLL handle) { } static int MwLLX11CallInitImpl(void) { - /* TODO: check properly */ return 0; } diff --git a/src/core.c b/src/core.c index 77c6d9a..6bb4979 100644 --- a/src/core.c +++ b/src/core.c @@ -687,6 +687,9 @@ MwWidget MwGetParent(MwWidget handle) { typedef int (*call_t)(void); int MwLibraryInit(void) { call_t calls[] = { +#ifdef USE_WAYLAND + MwLLWaylandCallInit, +#endif #ifdef USE_X11 MwLLX11CallInit, #endif -- 2.39.5 From 5a9a33e87395753e5b1c09c7c95ea3468050d779 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sat, 29 Nov 2025 20:52:56 -0700 Subject: [PATCH 02/48] wayland: we now have subsurfaces working --- .gitignore | 9 +- include/Mw/LowLevel/Wayland.h | 55 +++--- src/backend/wayland.c | 318 ++++++++++++++++++++++++++-------- 3 files changed, 275 insertions(+), 107 deletions(-) diff --git a/.gitignore b/.gitignore index 814f7b3..06c431e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,8 @@ *.o *.so -examples/* -examples/*.exe examples/*/* -examples/*/*.o -examples/*/*.exe -!examples/*/ -!examples/*.* -!examples/*/*.* +!examples/*/*.c +!examples/*/*.spv compile_flags.txt *.a Makefile diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 5fd1e7a..da610b4 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -30,33 +30,41 @@ typedef struct wayland_protocol { typedef wayland_protocol_t*(wl_setup_func)(MwU32, struct _MwLLWayland*); +struct _MwLLWaylandTopLevel { + struct xdg_surface* xdg_surface; + struct xdg_toplevel* xdg_top_level; + struct xdg_toplevel_listener xdg_toplevel_listener; + struct xdg_surface_listener xdg_surface_listener; + + struct xkb_context* xkb_context; + + MwBool running; + MwBool compositor_created; + MwBool xdg_wm_base_created; + MwBool xdg_surface_created; +}; + struct _MwLLWayland { struct _MwLLCommon common; + union { + struct _MwLLWaylandTopLevel toplevel; + struct wl_subsurface* subsurface; + }; + enum { + MWLL_WAYLAND_TOPLEVEL = 0, + MWLL_WAYLAND_SUBSURFACE = 1, + } type; + MwU32 ww; + MwU32 wh; - // struct wl_shm* shm; - struct wl_display* display; - struct wl_registry* registry; - // struct wl_compositor* compositor; - // struct wl_seat* seat; - struct wl_surface* surface; - struct xdg_surface* xdg_surface; - // struct xdg_wm_base* xdg_wm_base; - struct xdg_toplevel* xdg_top_level; - + struct wl_display* display; + struct wl_registry* registry; + struct wl_compositor* compositor; + struct wl_subcompositor* subcompositor; + struct wl_surface* surface; + struct wl_shm* shm; struct wl_registry_listener registry_listener; - // struct zxdg_decoration_manager_v1* decoration_manager; - // struct zxdg_toplevel_decoration_v1* toplevel_decoration; - - struct xdg_toplevel_listener xdg_toplevel_listener; - // struct xdg_wm_base_listener xdg_wm_base_listener; - struct xdg_surface_listener xdg_surface_listener; - // struct wl_pointer_listener pointer_listener; - // struct wl_seat_listener seat_listener; - // struct wl_keyboard_listener keyboard_listener; - // struct wl_shell_surface_listener shell_surface_listener; - // struct zxdg_toplevel_decoration_v1_listener decoration_listener; - struct { const char* key; wl_setup_func* value; @@ -67,10 +75,7 @@ struct _MwLLWayland { wayland_protocol_t* value; }* wl_protocol_map; - struct xkb_context* xkb_context; - MwBool configured; - MwBool running; }; struct _MwLLWaylandColor { diff --git a/src/backend/wayland.c b/src/backend/wayland.c index f964037..e8e7358 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -9,9 +9,13 @@ #include +#include +#include +#include + #include "../../external/stb_ds.h" -#define WAYLAND_GET_INTERFACE(r, inter) shget(r->wayland.wl_protocol_map, inter##_interface.name) +#define WAYLAND_GET_INTERFACE(r, inter) shget(r.wl_protocol_map, inter##_interface.name) // REGISTRY static void new_protocol(void* data, struct wl_registry* registry, @@ -21,7 +25,10 @@ static void new_protocol(void* data, struct wl_registry* registry, wl_setup_func* func = shget(wayland->wl_protocol_setup_map, interface); if(func != NULL) { + // printf("registering interface %s\n", interface); shput(wayland->wl_protocol_map, interface, func(name, data)); + } else { + // printf("unknown interface %s\n", interface); } }; @@ -34,12 +41,12 @@ static void protocol_removed(void* data, // SEAT static void wl_seat_name(void* data, struct wl_seat* wl_seat, const char* name) {}; static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat, - uint32_t capabilities) {}; + MwU32 capabilities) {}; // XDG SHELL void xdg_wm_base_ping(void* data, struct xdg_wm_base* xdg_wm_base, - uint32_t serial) { + MwU32 serial) { // The compositor will send us a ping event to check that we're responsive. // We need to send back a pong request immediately. xdg_wm_base_pong(xdg_wm_base, serial); @@ -48,22 +55,76 @@ void xdg_wm_base_ping(void* data, // XDG SHELL SURFACE static void wl_shell_surface_ping(void* data, struct wl_shell_surface* wl_shell_surface, - uint32_t serial) {}; + MwU32 serial) {}; static void wl_shell_surface_configure(void* data, struct wl_shell_surface* wl_shell_surface, - uint32_t edges, - int32_t width, - int32_t height) {}; + MwU32 edges, + MwI32 width, + MwI32 height) {}; static void wl_shell_surface_popup_done(void* data, struct wl_shell_surface* wl_shell_surface) {}; static wayland_protocol_t* wl_shm_setup(MwU32 name, struct _MwLLWayland* wayland) { - wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); - proto->listener = NULL; - proto->context = wl_registry_bind(wayland->registry, name, &wl_shm_interface, 1); - return proto; + wayland->shm = wl_registry_bind(wayland->registry, name, &wl_shm_interface, 1); + return NULL; } +static void buffer_setup(struct _MwLLWayland* wayland) { + struct wl_shm_pool* pool; + struct wl_buffer* buffer; + int x, y; + + int fd; + MwU32 size = wayland->ww * wayland->wh * 4; + char temp_name[] = "/tmp/milsko-wl-shm-XXXXXX"; + + fd = mkstemp(temp_name); + + unlink(temp_name); + + if(posix_fallocate(fd, 0, size) != 0) { + printf("failure setting up wl_shm: could not fallocate. %s.\n", strerror(errno)); + close(fd); + return; + } + if(ftruncate(fd, size) != 0) { + printf("failure setting up wl_shm: could not truncate. %s.\n", strerror(errno)); + close(fd); + return; + } + + for(y = 0; y < wayland->wh; y++) { + for(x = 0; x < wayland->ww; x++) { +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) + MwU8 a = 0xFF; + MwU8 r = MIN(((wayland->ww - x) * 0xFF) / wayland->ww, ((wayland->wh - y) * 0xFF) / wayland->wh); + MwU8 g = MIN((x * 0xFF) / wayland->ww, ((wayland->wh - y) * 0xFF) / wayland->wh); + MwU8 b = MIN(((wayland->ww - x) * 0xFF) / wayland->ww, (y * 0xFF) / wayland->wh); + write(fd, &b, 1); + write(fd, &g, 1); + write(fd, &r, 1); + write(fd, &a, 1); +#undef MIN + } + } + + fsync(fd); + + if(!(pool = wl_shm_create_pool(wayland->shm, fd, size))) { + printf("failure setting up wl_shm: could not create pool.\n"); + } + + buffer = wl_shm_pool_create_buffer(pool, 0, wayland->ww, wayland->wh, wayland->ww * 4, WL_SHM_FORMAT_ARGB8888); + + if(wayland->configured) { + wl_surface_attach(wayland->surface, buffer, 0, 0); + wl_surface_commit(wayland->surface); + } + + wl_buffer_destroy(buffer); + close(fd); +} + static wayland_protocol_t* wl_seat_setup(MwU32 name, struct _MwLLWayland* wayland) { wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); proto->listener = malloc(sizeof(struct wl_seat_listener)); @@ -76,13 +137,19 @@ static wayland_protocol_t* wl_seat_setup(MwU32 name, struct _MwLLWayland* waylan return proto; } -static wayland_protocol_t* wl_compositor_setup(MwU32 name, struct _MwLLWayland* wayland) { - wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); - proto->listener = NULL; - proto->context = wl_registry_bind(wayland->registry, name, &wl_compositor_interface, 1); - return proto; +static wayland_protocol_t* wl_compositor_setup(MwU32 name, struct _MwLLWayland* wayland) { + wayland->compositor = wl_registry_bind(wayland->registry, name, &wl_compositor_interface, 1); + + return NULL; } + +static wayland_protocol_t* wl_subcompositor_setup(MwU32 name, struct _MwLLWayland* wayland) { + wayland->subcompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1); + + return NULL; +} + static wayland_protocol_t* xdg_wm_base_setup(MwU32 name, struct _MwLLWayland* wayland) { wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); proto->listener = malloc(sizeof(struct xdg_wm_base_listener)); @@ -138,7 +205,7 @@ static wayland_protocol_t* zxdg_decoration_manager_v1_setup(MwU32 name, struct _ static void xdg_toplevel_configure(void* data, struct xdg_toplevel* xdg_toplevel, - int32_t width, int32_t height, + MwI32 width, MwI32 height, struct wl_array* states) { struct _MwLLWayland* self = (struct _MwLLWayland*)data; @@ -149,18 +216,18 @@ static void xdg_toplevel_configure(void* data, static void decoration_configure( void* data, struct zxdg_toplevel_decoration_v1* zxdg_toplevel_decoration_v1, - uint32_t mode) { + MwU32 mode) { } static void xdg_toplevel_close( void* data, struct xdg_toplevel* xdg_toplevel) { struct _MwLLWayland* self = (struct _MwLLWayland*)data; // Stop running if the user requests to close the toplevel - self->running = MwFALSE; + self->toplevel.running = MwFALSE; }; static void xdg_surface_configure( - void* data, struct xdg_surface* xdg_surface, uint32_t serial) { + void* data, struct xdg_surface* xdg_surface, MwU32 serial) { struct _MwLLWayland* self = (struct _MwLLWayland*)data; // The compositor configures our surface, acknowledge the configure event @@ -170,45 +237,94 @@ static void xdg_surface_configure( // If this isn't the first configure event we've received, we already // have a buffer attached, so no need to do anything. Commit the // surface to apply the configure acknowledgement. + // wl_surface_attach(self->surface, self->buffer, 0, 0); wl_surface_commit(self->surface); } self->configured = MwTRUE; } -static void shell_surface_ping(void* data, - struct wl_shell_surface* shell_surface, - uint32_t serial) {}; -static void shell_surface_configure( - void* data, struct wl_shell_surface* shell_surface, uint32_t edges, - int32_t width, int32_t height) {}; - -static void shell_surface_popup_done( - void* data, struct wl_shell_surface* shell_surface) {}; +#define WL_INTERFACE(interface) \ + shput(wayland->wl_protocol_setup_map, interface##_interface.name, (wl_setup_func*)interface##_setup); static void setup_callbacks(struct _MwLLWayland* wayland) { wayland->registry_listener.global = new_protocol; wayland->registry_listener.global_remove = protocol_removed; -#define WL_INTERFACE(interface) \ - shput(wayland->wl_protocol_setup_map, interface##_interface.name, (wl_setup_func*)interface##_setup); - WL_INTERFACE(wl_shm); - WL_INTERFACE(wl_seat); WL_INTERFACE(wl_compositor); - WL_INTERFACE(xdg_wm_base); - WL_INTERFACE(wl_shell_surface); - WL_INTERFACE(zxdg_decoration_manager_v1); - WL_INTERFACE(wp_cursor_shape_manager_v1); + WL_INTERFACE(wl_subcompositor); + if(wayland->type == MWLL_WAYLAND_TOPLEVEL) { + WL_INTERFACE(wl_seat); + WL_INTERFACE(xdg_wm_base); + WL_INTERFACE(wl_shell_surface); + WL_INTERFACE(zxdg_decoration_manager_v1); + WL_INTERFACE(wp_cursor_shape_manager_v1); + } } -static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { - MwLL r; - r = malloc(sizeof(*r)); - MwLLCreateCommon(r); +#undef WL_INTERFACE - r->common.copy_buffer = 1; - r->common.type = MwLLBackendWayland; +static MwBool flush_display(struct wl_display* display) { + while(wl_display_flush(display) == -1) { + if(errno != EAGAIN) { + return MwFALSE; + } + + struct pollfd fd = {wl_display_get_fd(display), POLL_OUT}; + + while(poll(&fd, 1, -1) == -1) { + if(errno != EINTR && errno != EAGAIN) + return MwFALSE; + } + } + return MwTRUE; +} + +static void event_loop(MwLL handle) { + enum { + DISPLAY_FD, + KEYREPEAT_FD, + CURSOR_FD, + LIBDECOR_FD + }; + if(handle->wayland.display == NULL) { + return; + } + struct pollfd fd = {wl_display_get_fd(handle->wayland.display), POLLIN}; + int timeout = 500; + + while(wl_display_prepare_read(handle->wayland.display) != 0) { + if(wl_display_dispatch_pending(handle->wayland.display) > 0) { + return; + } + } + + // If an error other than EAGAIN happens, we have likely been disconnected + // from the Wayland session + if(!flush_display(handle->wayland.display)) { + wl_display_cancel_read(handle->wayland.display); + + handle->wayland.toplevel.running = MwFALSE; + return; + } + + if(!poll(&fd, 1, timeout)) { + wl_display_cancel_read(handle->wayland.display); + return; + } + + if(fd.revents & POLLIN) { + wl_display_read_events(handle->wayland.display); + if(wl_display_dispatch_pending(handle->wayland.display) > 0) { + } + } else { + wl_display_cancel_read(handle->wayland.display); + } +} + +static void setup_toplevel(MwLL r, int x, int y, int width, int height) { + r->wayland.type = MWLL_WAYLAND_TOPLEVEL; setup_callbacks(&r->wayland); @@ -217,55 +333,48 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { if(r->wayland.display == NULL) { printf("wayland: failed to create display\n"); r->common.success = MwFALSE; - return r; + return; } - // Obtain the wl_registry and fetch the list of globals + // 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); if(wl_display_roundtrip(r->wayland.display) == -1) { printf("roundtrip failed\n"); r->common.success = MwFALSE; - return r; + return; } // Check that all globals we require are available if( - WAYLAND_GET_INTERFACE(r, wl_compositor)->context == NULL || - WAYLAND_GET_INTERFACE(r, xdg_wm_base)->context == NULL || - WAYLAND_GET_INTERFACE(r, wl_seat)->context == NULL) { + r->wayland.compositor == NULL || + WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context == NULL || + WAYLAND_GET_INTERFACE(r->wayland, wl_seat)->context == NULL) { printf("no wl_shm, wl_compositor, wl_seat, or xdg_wm_base support\n"); r->common.success = MwFALSE; - return r; + return; } - // wl_log_set_handler_client(_MwLLWayland::logger); - - r->wayland.xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + r->wayland.toplevel.xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); // Create a wl_surface, a xdg_surface and a xdg_toplevel - r->wayland.surface = wl_compositor_create_surface(WAYLAND_GET_INTERFACE(r, wl_compositor)->context); - r->wayland.xdg_surface = - xdg_wm_base_get_xdg_surface(WAYLAND_GET_INTERFACE(r, xdg_wm_base)->context, r->wayland.surface); - r->wayland.xdg_top_level = xdg_surface_get_toplevel(r->wayland.xdg_surface); + r->wayland.surface = wl_compositor_create_surface(r->wayland.compositor); + r->wayland.toplevel.xdg_surface = + xdg_wm_base_get_xdg_surface(WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context, r->wayland.surface); + r->wayland.toplevel.xdg_top_level = xdg_surface_get_toplevel(r->wayland.toplevel.xdg_surface); // setup mandatory listeners - r->wayland.xdg_surface_listener.configure = xdg_surface_configure; - r->wayland.xdg_toplevel_listener.configure = xdg_toplevel_configure; - r->wayland.xdg_toplevel_listener.close = xdg_toplevel_close; + r->wayland.toplevel.xdg_surface_listener.configure = xdg_surface_configure; + r->wayland.toplevel.xdg_toplevel_listener.configure = xdg_toplevel_configure; + r->wayland.toplevel.xdg_toplevel_listener.close = xdg_toplevel_close; - xdg_surface_add_listener(r->wayland.xdg_surface, &r->wayland.xdg_surface_listener, r); - xdg_toplevel_add_listener(r->wayland.xdg_top_level, &r->wayland.xdg_toplevel_listener, + xdg_surface_add_listener(r->wayland.toplevel.xdg_surface, &r->wayland.toplevel.xdg_surface_listener, r); + xdg_toplevel_add_listener(r->wayland.toplevel.xdg_top_level, &r->wayland.toplevel.xdg_toplevel_listener, r); - xdg_toplevel_set_title(r->wayland.xdg_top_level, "Milsko Wayland App"); - xdg_toplevel_set_app_id(r->wayland.xdg_top_level, "Milsko Wayland App"); - - // if (!mFlags.windowResizable) { - // xdg_toplevel_set_min_size(mXDGTopLevel, mWidth, mHeight); - // xdg_toplevel_set_max_size(mXDGTopLevel, mWidth, mHeight); - // } + xdg_toplevel_set_title(r->wayland.toplevel.xdg_top_level, "Milsko Wayland App"); + 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.surface); @@ -273,23 +382,76 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { } // setup decorations if we can - if(WAYLAND_GET_INTERFACE(r, zxdg_decoration_manager_v1)->context != NULL) { - zxdg_decoration_manager_v1_context_t* dec = WAYLAND_GET_INTERFACE(r, zxdg_decoration_manager_v1)->context; + if(WAYLAND_GET_INTERFACE(r->wayland, zxdg_decoration_manager_v1)->context != NULL) { + zxdg_decoration_manager_v1_context_t* dec = WAYLAND_GET_INTERFACE(r->wayland, zxdg_decoration_manager_v1)->context; dec->decoration = zxdg_decoration_manager_v1_get_toplevel_decoration( - dec->manager, r->wayland.xdg_top_level); - - // zxdg_toplevel_decoration_v1_add_listener(dec->decoration, - // dec->listener, r); + dec->manager, r->wayland.toplevel.xdg_top_level); zxdg_toplevel_decoration_v1_set_mode( dec->decoration, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); + } else { + printf("zxdg null\n"); } + buffer_setup(&r->wayland); + wl_surface_commit(r->wayland.surface); +} + +static void setup_subsurface(MwLL parent, MwLL r, int x, int y, int width, int height) { + struct wl_compositor* compositor = parent->wayland.compositor; + struct wl_subcompositor* subcompositor = parent->wayland.subcompositor; + struct wl_surface* parent_surface = parent->wayland.surface; + + r->wayland.type = MWLL_WAYLAND_SUBSURFACE; + + setup_callbacks(&r->wayland); + + r->wayland.registry = wl_display_get_registry(parent->wayland.display); + r->wayland.display = parent->wayland.display; + + wl_registry_add_listener(r->wayland.registry, &r->wayland.registry_listener, r); + if(wl_display_roundtrip(r->wayland.display) == -1) { + printf("roundtrip failed\n"); + raise(SIGTRAP); + return; + } + r->wayland.display = parent->wayland.display; + + r->wayland.surface = wl_compositor_create_surface(compositor); + + r->wayland.subsurface = wl_subcompositor_get_subsurface(subcompositor, r->wayland.surface, parent_surface); + + wl_subsurface_set_position(r->wayland.subsurface, x, y); + + // printf("position %d %d\n", x, y); + + r->wayland.configured = MwTRUE; + + buffer_setup(&r->wayland); + + wl_surface_commit(parent->wayland.surface); +} +static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { + MwLL r; + r = malloc(sizeof(*r)); + MwLLCreateCommon(r); + + r->common.copy_buffer = 1; + r->common.type = MwLLBackendWayland; + + r->wayland.ww = width; + r->wayland.wh = height; r->common.success = MwTRUE; + if(parent == NULL) { + setup_toplevel(r, x, y, width, height); + } else { + setup_subsurface(parent, r, x, y, width, height); + } + return r; } @@ -341,13 +503,18 @@ static void MwLLSetBackgroundImpl(MwLL handle, MwLLColor color) { } static int MwLLPendingImpl(MwLL handle) { + event_loop(handle); return 0; } static void MwLLNextEventImpl(MwLL handle) { + event_loop(handle); } 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); + } } static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, int width, int height) { @@ -373,6 +540,7 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { } static void MwLLForceRenderImpl(MwLL handle) { + // event_loop(handle); } static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { -- 2.39.5 From 43b0b86a0f9fb4abb2e9169c17055116252bc737 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sat, 29 Nov 2025 21:04:01 -0700 Subject: [PATCH 03/48] changed my mind, removing wl_shell stuff makes the resulting library smaller and i don't actually feel like supporting a feature that's been obsolete since 2013 --- src/backend/wayland.c | 37 ------------------------------------- 1 file changed, 37 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index e8e7358..656ed76 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1,12 +1,5 @@ /* $Id$ */ -/** - TODO: - - - would fit with Milsko's goal to support older compositors using wl_shell. would also suck to test because most compositors outright removed that around 2021... - - */ - #include #include @@ -17,7 +10,6 @@ #define WAYLAND_GET_INTERFACE(r, inter) shget(r.wl_protocol_map, inter##_interface.name) -// REGISTRY static void new_protocol(void* data, struct wl_registry* registry, MwU32 name, const char* interface, MwU32 version) { @@ -38,12 +30,10 @@ static void protocol_removed(void* data, }; -// SEAT static void wl_seat_name(void* data, struct wl_seat* wl_seat, const char* name) {}; static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat, MwU32 capabilities) {}; -// XDG SHELL void xdg_wm_base_ping(void* data, struct xdg_wm_base* xdg_wm_base, MwU32 serial) { @@ -52,19 +42,6 @@ void xdg_wm_base_ping(void* data, xdg_wm_base_pong(xdg_wm_base, serial); }; -// XDG SHELL SURFACE -static void wl_shell_surface_ping(void* data, - struct wl_shell_surface* wl_shell_surface, - MwU32 serial) {}; -static void wl_shell_surface_configure(void* data, - struct wl_shell_surface* wl_shell_surface, - MwU32 edges, - MwI32 width, - MwI32 height) {}; - -static void wl_shell_surface_popup_done(void* data, - struct wl_shell_surface* wl_shell_surface) {}; - static wayland_protocol_t* wl_shm_setup(MwU32 name, struct _MwLLWayland* wayland) { wayland->shm = wl_registry_bind(wayland->registry, name, &wl_shm_interface, 1); return NULL; @@ -161,19 +138,6 @@ static wayland_protocol_t* xdg_wm_base_setup(MwU32 name, struct _MwLLWayland* wa return proto; } -static wayland_protocol_t* wl_shell_surface_setup(MwU32 name, struct _MwLLWayland* wayland) { - wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); - proto->listener = malloc(sizeof(struct wl_shell_surface_listener)); - - ((struct wl_shell_surface_listener*)proto->listener)->ping = wl_shell_surface_ping; - ((struct wl_shell_surface_listener*)proto->listener)->configure = wl_shell_surface_configure; - ((struct wl_shell_surface_listener*)proto->listener)->popup_done = wl_shell_surface_popup_done; - - proto->context = wl_registry_bind(wayland->registry, name, &wl_shell_surface_interface, 1); - wl_shell_surface_add_listener(proto->context, proto->listener, wayland); - - return proto; -} static wayland_protocol_t* wp_cursor_shape_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland) { wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); @@ -257,7 +221,6 @@ static void setup_callbacks(struct _MwLLWayland* wayland) { if(wayland->type == MWLL_WAYLAND_TOPLEVEL) { WL_INTERFACE(wl_seat); WL_INTERFACE(xdg_wm_base); - WL_INTERFACE(wl_shell_surface); WL_INTERFACE(zxdg_decoration_manager_v1); WL_INTERFACE(wp_cursor_shape_manager_v1); } -- 2.39.5 From b2ea14c3540b7def64d911d7bf50fb6c3f77afee Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 1 Dec 2025 11:45:55 -0700 Subject: [PATCH 04/48] handle resizing, turn _MwLLWaylandToplevel into a pointer --- include/Mw/LowLevel/Wayland.h | 7 +- src/backend/wayland.c | 135 ++++++++++++++++++++++------------ 2 files changed, 89 insertions(+), 53 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index da610b4..843c604 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -47,15 +47,13 @@ struct _MwLLWaylandTopLevel { struct _MwLLWayland { struct _MwLLCommon common; union { - struct _MwLLWaylandTopLevel toplevel; - struct wl_subsurface* subsurface; + struct _MwLLWaylandTopLevel* toplevel; + struct wl_subsurface* subsurface; }; enum { MWLL_WAYLAND_TOPLEVEL = 0, MWLL_WAYLAND_SUBSURFACE = 1, } type; - MwU32 ww; - MwU32 wh; struct wl_display* display; struct wl_registry* registry; @@ -76,6 +74,7 @@ struct _MwLLWayland { }* wl_protocol_map; MwBool configured; + MwU32 x, y, ww, wh; }; struct _MwLLWaylandColor { diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 656ed76..17df5cf 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -5,8 +5,14 @@ #include #include #include +#include +#include +#include +#include #include "../../external/stb_ds.h" +#include "Mw/LowLevel.h" +#include "Mw/LowLevel/Wayland/xdg-shell-client-protocol.h" #define WAYLAND_GET_INTERFACE(r, inter) shget(r.wl_protocol_map, inter##_interface.name) @@ -54,6 +60,8 @@ static void buffer_setup(struct _MwLLWayland* wayland) { int fd; MwU32 size = wayland->ww * wayland->wh * 4; char temp_name[] = "/tmp/milsko-wl-shm-XXXXXX"; + void* map; + MwU8 data = 0xFF; fd = mkstemp(temp_name); @@ -70,20 +78,23 @@ static void buffer_setup(struct _MwLLWayland* wayland) { return; } - for(y = 0; y < wayland->wh; y++) { - for(x = 0; x < wayland->ww; x++) { -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) - MwU8 a = 0xFF; - MwU8 r = MIN(((wayland->ww - x) * 0xFF) / wayland->ww, ((wayland->wh - y) * 0xFF) / wayland->wh); - MwU8 g = MIN((x * 0xFF) / wayland->ww, ((wayland->wh - y) * 0xFF) / wayland->wh); - MwU8 b = MIN(((wayland->ww - x) * 0xFF) / wayland->ww, (y * 0xFF) / wayland->wh); - write(fd, &b, 1); - write(fd, &g, 1); - write(fd, &r, 1); - write(fd, &a, 1); -#undef MIN - } - } + map = mmap(NULL, wayland->wh * wayland->ww * 4, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + memset(map, 0xFF, wayland->wh * wayland->ww * 4); + + // for(y = 0; y < wayland->wh; y++) { + // for(x = 0; x < wayland->ww; x++) { + // #define MIN(a, b) (((a) < (b)) ? (a) : (b)) + // MwU8 a = 0xFF; + // MwU8 r = MIN(((wayland->ww - x) * 0xFF) / wayland->ww, ((wayland->wh - y) * 0xFF) / wayland->wh); + // MwU8 g = MIN((x * 0xFF) / wayland->ww, ((wayland->wh - y) * 0xFF) / wayland->wh); + // MwU8 b = MIN(((wayland->ww - x) * 0xFF) / wayland->ww, (y * 0xFF) / wayland->wh); + // write(fd, &b, 1); + // write(fd, &g, 1); + // write(fd, &r, 1); + // write(fd, &a, 1); + // #undef MIN + // } + // } fsync(fd); @@ -171,9 +182,17 @@ static void xdg_toplevel_configure(void* data, struct xdg_toplevel* xdg_toplevel, MwI32 width, MwI32 height, struct wl_array* states) { - struct _MwLLWayland* self = (struct _MwLLWayland*)data; + MwLL self = data; - wl_surface_commit(self->surface); + if(width != 0 && height != 0) { + self->wayland.ww = width; + self->wayland.wh = height; + MwLLDispatch(self, resize, NULL); + xdg_surface_set_window_geometry(self->wayland.toplevel->xdg_surface, self->wayland.x, self->wayland.y, self->wayland.ww, self->wayland.wh); + buffer_setup(&self->wayland); + }; + + wl_surface_commit(self->wayland.surface); return; }; @@ -185,27 +204,28 @@ static void decoration_configure( static void xdg_toplevel_close( void* data, struct xdg_toplevel* xdg_toplevel) { - struct _MwLLWayland* self = (struct _MwLLWayland*)data; + MwLL self = data; + // Stop running if the user requests to close the toplevel - self->toplevel.running = MwFALSE; + self->wayland.toplevel->running = MwFALSE; }; static void xdg_surface_configure( void* data, struct xdg_surface* xdg_surface, MwU32 serial) { - struct _MwLLWayland* self = (struct _MwLLWayland*)data; + MwLL self = data; // The compositor configures our surface, acknowledge the configure event xdg_surface_ack_configure(xdg_surface, serial); - if(self->configured) { + if(self->wayland.configured) { // If this isn't the first configure event we've received, we already // have a buffer attached, so no need to do anything. Commit the // surface to apply the configure acknowledgement. // wl_surface_attach(self->surface, self->buffer, 0, 0); - wl_surface_commit(self->surface); + wl_surface_commit(self->wayland.surface); } - self->configured = MwTRUE; + self->wayland.configured = MwTRUE; } #define WL_INTERFACE(interface) \ @@ -268,7 +288,7 @@ static void event_loop(MwLL handle) { if(!flush_display(handle->wayland.display)) { wl_display_cancel_read(handle->wayland.display); - handle->wayland.toplevel.running = MwFALSE; + handle->wayland.toplevel->running = MwFALSE; return; } @@ -287,7 +307,8 @@ static void event_loop(MwLL handle) { } static void setup_toplevel(MwLL r, int x, int y, int width, int height) { - r->wayland.type = MWLL_WAYLAND_TOPLEVEL; + r->wayland.type = MWLL_WAYLAND_TOPLEVEL; + r->wayland.toplevel = malloc(sizeof(struct _MwLLWaylandTopLevel)); setup_callbacks(&r->wayland); @@ -319,25 +340,25 @@ static void setup_toplevel(MwLL r, int x, int y, int width, int height) { return; } - r->wayland.toplevel.xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + r->wayland.toplevel->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); // Create a wl_surface, a xdg_surface and a xdg_toplevel r->wayland.surface = wl_compositor_create_surface(r->wayland.compositor); - r->wayland.toplevel.xdg_surface = + r->wayland.toplevel->xdg_surface = xdg_wm_base_get_xdg_surface(WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context, r->wayland.surface); - r->wayland.toplevel.xdg_top_level = xdg_surface_get_toplevel(r->wayland.toplevel.xdg_surface); + r->wayland.toplevel->xdg_top_level = xdg_surface_get_toplevel(r->wayland.toplevel->xdg_surface); // setup mandatory listeners - r->wayland.toplevel.xdg_surface_listener.configure = xdg_surface_configure; - r->wayland.toplevel.xdg_toplevel_listener.configure = xdg_toplevel_configure; - r->wayland.toplevel.xdg_toplevel_listener.close = xdg_toplevel_close; + r->wayland.toplevel->xdg_surface_listener.configure = xdg_surface_configure; + r->wayland.toplevel->xdg_toplevel_listener.configure = xdg_toplevel_configure; + r->wayland.toplevel->xdg_toplevel_listener.close = xdg_toplevel_close; - xdg_surface_add_listener(r->wayland.toplevel.xdg_surface, &r->wayland.toplevel.xdg_surface_listener, r); - xdg_toplevel_add_listener(r->wayland.toplevel.xdg_top_level, &r->wayland.toplevel.xdg_toplevel_listener, + xdg_surface_add_listener(r->wayland.toplevel->xdg_surface, &r->wayland.toplevel->xdg_surface_listener, r); + xdg_toplevel_add_listener(r->wayland.toplevel->xdg_top_level, &r->wayland.toplevel->xdg_toplevel_listener, r); - xdg_toplevel_set_title(r->wayland.toplevel.xdg_top_level, "Milsko Wayland App"); - xdg_toplevel_set_app_id(r->wayland.toplevel.xdg_top_level, "MilskoWaylandApp"); + xdg_toplevel_set_title(r->wayland.toplevel->xdg_top_level, "Milsko Wayland App"); + 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.surface); @@ -349,7 +370,7 @@ static void setup_toplevel(MwLL r, int x, int y, int width, int height) { zxdg_decoration_manager_v1_context_t* dec = WAYLAND_GET_INTERFACE(r->wayland, zxdg_decoration_manager_v1)->context; dec->decoration = zxdg_decoration_manager_v1_get_toplevel_decoration( - dec->manager, r->wayland.toplevel.xdg_top_level); + dec->manager, r->wayland.toplevel->xdg_top_level); zxdg_toplevel_decoration_v1_set_mode( dec->decoration, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); @@ -424,6 +445,35 @@ static void MwLLDestroyImpl(MwLL handle) { free(handle); } +static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h) { + *x = handle->wayland.x; + *y = handle->wayland.y; + *w = handle->wayland.ww; + *h = handle->wayland.wh; +} + +static void MwLLSetXYImpl(MwLL handle, int x, int y) { + handle->wayland.x = x; + handle->wayland.y = y; + if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { + xdg_surface_set_window_geometry(handle->wayland.toplevel->xdg_surface, handle->wayland.x, handle->wayland.y, handle->wayland.ww, handle->wayland.wh); + } else { + wl_subsurface_set_position(handle->wayland.subsurface, x, y); + } +} + +static void MwLLSetWHImpl(MwLL handle, int w, int h) { + handle->wayland.ww = w; + handle->wayland.wh = h; + + if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { + xdg_surface_set_window_geometry(handle->wayland.toplevel->xdg_surface, handle->wayland.x, handle->wayland.y, handle->wayland.ww, handle->wayland.wh); + } else { + // setup the buffer again with the new size. + buffer_setup(&handle->wayland); + } +} + static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { } @@ -446,19 +496,6 @@ static void MwLLColorUpdateImpl(MwLL handle, MwLLColor c, int r, int g, int b) { c->common.green = g; } -static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h) { - *x = 0; - *y = 0; - *w = 0; - *h = 0; -} - -static void MwLLSetXYImpl(MwLL handle, int x, int y) { -} - -static void MwLLSetWHImpl(MwLL handle, int w, int h) { -} - static void MwLLFreeColorImpl(MwLLColor color) { } @@ -476,7 +513,7 @@ static void MwLLNextEventImpl(MwLL handle) { 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); + xdg_toplevel_set_title(handle->wayland.toplevel->xdg_top_level, title); } } -- 2.39.5 From 5ad21381c5def03b3f558055be7260b9dc178f08 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 1 Dec 2025 14:19:07 -0700 Subject: [PATCH 05/48] more wayland impls --- src/backend/wayland.c | 80 +++++++++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 33 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 17df5cf..18d4a18 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -2,17 +2,19 @@ #include +#include #include #include #include +#include #include +#include #include -#include #include #include "../../external/stb_ds.h" -#include "Mw/LowLevel.h" -#include "Mw/LowLevel/Wayland/xdg-shell-client-protocol.h" + +#include #define WAYLAND_GET_INTERFACE(r, inter) shget(r.wl_protocol_map, inter##_interface.name) @@ -61,7 +63,6 @@ static void buffer_setup(struct _MwLLWayland* wayland) { MwU32 size = wayland->ww * wayland->wh * 4; char temp_name[] = "/tmp/milsko-wl-shm-XXXXXX"; void* map; - MwU8 data = 0xFF; fd = mkstemp(temp_name); @@ -78,23 +79,9 @@ static void buffer_setup(struct _MwLLWayland* wayland) { return; } - map = mmap(NULL, wayland->wh * wayland->ww * 4, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - memset(map, 0xFF, wayland->wh * wayland->ww * 4); - - // for(y = 0; y < wayland->wh; y++) { - // for(x = 0; x < wayland->ww; x++) { - // #define MIN(a, b) (((a) < (b)) ? (a) : (b)) - // MwU8 a = 0xFF; - // MwU8 r = MIN(((wayland->ww - x) * 0xFF) / wayland->ww, ((wayland->wh - y) * 0xFF) / wayland->wh); - // MwU8 g = MIN((x * 0xFF) / wayland->ww, ((wayland->wh - y) * 0xFF) / wayland->wh); - // MwU8 b = MIN(((wayland->ww - x) * 0xFF) / wayland->ww, (y * 0xFF) / wayland->wh); - // write(fd, &b, 1); - // write(fd, &g, 1); - // write(fd, &r, 1); - // write(fd, &a, 1); - // #undef MIN - // } - // } + lseek(fd, 0, SEEK_SET); + map = mmap(NULL, size, PROT_WRITE, MAP_SHARED, fd, 0); + memset(map, 0xFF, size); fsync(fd); @@ -108,8 +95,8 @@ static void buffer_setup(struct _MwLLWayland* wayland) { wl_surface_attach(wayland->surface, buffer, 0, 0); wl_surface_commit(wayland->surface); } - wl_buffer_destroy(buffer); + wl_shm_pool_destroy(pool); close(fd); } @@ -187,9 +174,9 @@ static void xdg_toplevel_configure(void* data, if(width != 0 && height != 0) { self->wayland.ww = width; self->wayland.wh = height; - MwLLDispatch(self, resize, NULL); xdg_surface_set_window_geometry(self->wayland.toplevel->xdg_surface, self->wayland.x, self->wayland.y, self->wayland.ww, self->wayland.wh); - buffer_setup(&self->wayland); + + MwLLDispatch(self, resize, NULL); }; wl_surface_commit(self->wayland.surface); @@ -234,6 +221,8 @@ static void xdg_surface_configure( static void setup_callbacks(struct _MwLLWayland* wayland) { wayland->registry_listener.global = new_protocol; wayland->registry_listener.global_remove = protocol_removed; + wayland->wl_protocol_setup_map = NULL; + wayland->wl_protocol_map = NULL; WL_INTERFACE(wl_shm); WL_INTERFACE(wl_compositor); @@ -390,6 +379,16 @@ static void setup_subsurface(MwLL parent, MwLL r, int x, int y, int width, int h r->wayland.type = MWLL_WAYLAND_SUBSURFACE; + r->wayland.display = parent->wayland.display; + + r->wayland.surface = wl_compositor_create_surface(compositor); + + r->wayland.subsurface = wl_subcompositor_get_subsurface(subcompositor, r->wayland.surface, parent_surface); + + wl_subsurface_set_position(r->wayland.subsurface, x, y); + + // printf("position %d %d\n", x, y); + setup_callbacks(&r->wayland); r->wayland.registry = wl_display_get_registry(parent->wayland.display); @@ -401,15 +400,6 @@ static void setup_subsurface(MwLL parent, MwLL r, int x, int y, int width, int h raise(SIGTRAP); return; } - r->wayland.display = parent->wayland.display; - - r->wayland.surface = wl_compositor_create_surface(compositor); - - r->wayland.subsurface = wl_subcompositor_get_subsurface(subcompositor, r->wayland.surface, parent_surface); - - wl_subsurface_set_position(r->wayland.subsurface, x, y); - - // printf("position %d %d\n", x, y); r->wayland.configured = MwTRUE; @@ -425,6 +415,9 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r->common.copy_buffer = 1; r->common.type = MwLLBackendWayland; + if(width == 0) width = parent->wayland.ww; + if(height == 0) height = parent->wayland.wh; + r->wayland.ww = width; r->wayland.wh = height; @@ -497,6 +490,7 @@ static void MwLLColorUpdateImpl(MwLL handle, MwLLColor c, int r, int g, int b) { } static void MwLLFreeColorImpl(MwLLColor color) { + free(color); } static void MwLLSetBackgroundImpl(MwLL handle, MwLLColor color) { @@ -541,6 +535,8 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { static void MwLLForceRenderImpl(MwLL handle) { // event_loop(handle); + wl_surface_damage(handle->wayland.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); + wl_surface_commit(handle->wayland.surface); } static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { @@ -556,9 +552,27 @@ static void MwLLMakePopupImpl(MwLL handle, MwLL parent) { } static void MwLLSetSizeHintsImpl(MwLL handle, int minx, int miny, int maxx, int maxy) { + if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { + xdg_toplevel_set_min_size(handle->wayland.toplevel->xdg_top_level, minx, miny); + xdg_toplevel_set_max_size(handle->wayland.toplevel->xdg_top_level, maxx, maxy); + } } static void MwLLMakeBorderlessImpl(MwLL handle, int toggle) { + if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { + if(WAYLAND_GET_INTERFACE(handle->wayland, zxdg_decoration_manager_v1)->context != NULL) { + zxdg_decoration_manager_v1_context_t* dec = WAYLAND_GET_INTERFACE(handle->wayland, zxdg_decoration_manager_v1)->context; + + dec->decoration = zxdg_decoration_manager_v1_get_toplevel_decoration( + dec->manager, handle->wayland.toplevel->xdg_top_level); + + 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"); + } + } } static void MwLLFocusImpl(MwLL handle) { -- 2.39.5 From 37fe636c75528c7c47bef44d507eaf385524430e Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 1 Dec 2025 19:12:49 -0700 Subject: [PATCH 06/48] more wayland work --- examples/basic/rotate.c | 6 +- include/Mw/LowLevel.h | 2 - include/Mw/LowLevel/Wayland.h | 5 + src/backend/call.c | 2 - src/backend/gdi.c | 5 - src/backend/wayland.c | 193 ++++++++++++++++++++++++---------- src/backend/x11.c | 4 - src/core.c | 10 +- src/draw.c | 1 + src/lowlevel.c | 2 - 10 files changed, 152 insertions(+), 78 deletions(-) diff --git a/examples/basic/rotate.c b/examples/basic/rotate.c index c3b85d7..835993d 100644 --- a/examples/basic/rotate.c +++ b/examples/basic/rotate.c @@ -56,13 +56,13 @@ void resize(MwWidget w, void* user, void* client) { int main() { MwWidget window; - int i; + int i; MwLibraryInit(); window = MwVaCreateWidget(MwWindowClass, "window", NULL, MwDEFAULT, MwDEFAULT, (ww = 500), (wh = 500), - MwNtitle, "rotate", - NULL); + MwNtitle, "rotate", + NULL); for(i = 0; i < (int)(sizeof(buttons) / sizeof(buttons[0])); i++) { const char* color = ""; diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index c3f7fe9..49c1cc7 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -198,8 +198,6 @@ MWDECL void (*MwLLMakePopup)(MwLL handle, MwLL parent); MWDECL void (*MwLLBeginStateChange)(MwLL handle); MWDECL void (*MwLLEndStateChange)(MwLL handle); -MWDECL void (*MwLLSetBackground)(MwLL handle, MwLLColor color); - MWDECL void (*MwLLFocus)(MwLL handle); MWDECL void (*MwLLGrabPointer)(MwLL handle, int toggle); diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 843c604..c502a53 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -7,6 +7,7 @@ #ifndef __MW_LOWLEVEL_WAYLAND_H__ #define __MW_LOWLEVEL_WAYLAND_H__ +#include "Mw/BaseTypes.h" #include #include #include @@ -63,6 +64,9 @@ struct _MwLLWayland { struct wl_shm* shm; struct wl_registry_listener registry_listener; + MwU8* mapped_buffer; + int mapped_buffer_size; + struct { const char* key; wl_setup_func* value; @@ -74,6 +78,7 @@ struct _MwLLWayland { }* wl_protocol_map; MwBool configured; + MwBool force_redraw; MwU32 x, y, ww, wh; }; diff --git a/src/backend/call.c b/src/backend/call.c index bace30c..de4b7f0 100644 --- a/src/backend/call.c +++ b/src/backend/call.c @@ -44,8 +44,6 @@ \ MwLLBeginStateChange = MwLLBeginStateChangeImpl; \ MwLLEndStateChange = MwLLEndStateChangeImpl; \ -\ - MwLLSetBackground = MwLLSetBackgroundImpl; \ \ MwLLFocus = MwLLFocusImpl; \ MwLLGrabPointer = MwLLGrabPointerImpl; \ diff --git a/src/backend/gdi.c b/src/backend/gdi.c index f466dfd..d366d6b 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -342,11 +342,6 @@ static void MwLLFreeColorImpl(MwLLColor color) { free(color); } -static void MwLLSetBackgroundImpl(MwLL handle, MwLLColor color) { - (void)handle; - (void)color; -} - static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h) { RECT rc; diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 18d4a18..d14cada 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -13,6 +13,8 @@ #include #include "../../external/stb_ds.h" +#include "Mw/BaseTypes.h" +#include "Mw/LowLevel.h" #include @@ -62,7 +64,6 @@ static void buffer_setup(struct _MwLLWayland* wayland) { int fd; MwU32 size = wayland->ww * wayland->wh * 4; char temp_name[] = "/tmp/milsko-wl-shm-XXXXXX"; - void* map; fd = mkstemp(temp_name); @@ -80,8 +81,9 @@ static void buffer_setup(struct _MwLLWayland* wayland) { } lseek(fd, 0, SEEK_SET); - map = mmap(NULL, size, PROT_WRITE, MAP_SHARED, fd, 0); - memset(map, 0xFF, size); + wayland->mapped_buffer = mmap(NULL, size, PROT_WRITE, MAP_SHARED, fd, 0); + memset(wayland->mapped_buffer, 0xFF, size); + wayland->mapped_buffer_size = size; fsync(fd); @@ -176,10 +178,11 @@ static void xdg_toplevel_configure(void* data, self->wayland.wh = height; xdg_surface_set_window_geometry(self->wayland.toplevel->xdg_surface, self->wayland.x, self->wayland.y, self->wayland.ww, self->wayland.wh); + MwLLSetWH(self, width, height); MwLLDispatch(self, resize, NULL); }; - wl_surface_commit(self->wayland.surface); + MwLLForceRender(self); return; }; @@ -253,48 +256,6 @@ static MwBool flush_display(struct wl_display* display) { return MwTRUE; } -static void event_loop(MwLL handle) { - enum { - DISPLAY_FD, - KEYREPEAT_FD, - CURSOR_FD, - LIBDECOR_FD - }; - if(handle->wayland.display == NULL) { - return; - } - struct pollfd fd = {wl_display_get_fd(handle->wayland.display), POLLIN}; - int timeout = 500; - - while(wl_display_prepare_read(handle->wayland.display) != 0) { - if(wl_display_dispatch_pending(handle->wayland.display) > 0) { - return; - } - } - - // If an error other than EAGAIN happens, we have likely been disconnected - // from the Wayland session - if(!flush_display(handle->wayland.display)) { - wl_display_cancel_read(handle->wayland.display); - - handle->wayland.toplevel->running = MwFALSE; - return; - } - - if(!poll(&fd, 1, timeout)) { - wl_display_cancel_read(handle->wayland.display); - return; - } - - if(fd.revents & POLLIN) { - wl_display_read_events(handle->wayland.display); - if(wl_display_dispatch_pending(handle->wayland.display) > 0) { - } - } else { - wl_display_cancel_read(handle->wayland.display); - } -} - static void setup_toplevel(MwLL r, int x, int y, int width, int height) { r->wayland.type = MWLL_WAYLAND_TOPLEVEL; r->wayland.toplevel = malloc(sizeof(struct _MwLLWaylandTopLevel)); @@ -412,8 +373,8 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r = malloc(sizeof(*r)); MwLLCreateCommon(r); - r->common.copy_buffer = 1; - r->common.type = MwLLBackendWayland; + // r->common.copy_buffer = 1; + r->common.type = MwLLBackendWayland; if(width == 0) width = parent->wayland.ww; if(height == 0) height = parent->wayland.wh; @@ -467,10 +428,76 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { } } +// fractional part of x +static float fpart(float x) { + return x - floor(x); +} +static float rfpart(float x) { + return x - fpart(x); +} + +#define IMAGE_POS_GET(x, y, o) handle->wayland.mapped_buffer[(((y * handle->wayland.ww) + x) * 4) + o] + +#define IMAGE_POS_SET(x, y, o, v) IMAGE_POS_GET(x, y, o) = v; +#define IMAGE_PLOT(x, y, color) \ + IMAGE_POS_SET(x, y, 0, color->common.blue); \ + IMAGE_POS_SET(x, y, 1, color->common.green); \ + IMAGE_POS_SET(x, y, 2, color->common.red); \ + IMAGE_POS_SET(x, y, 3, 255); + +static void +line_draw(MwLL handle, int x0, int y0, int x1, int y1, MwLLColor color) { + int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1; + int dy = -abs(y1 - y0), sy = y0 < y1 ? 1 : -1; + int err = dx + dy, e2; + + for(;;) { + IMAGE_PLOT(x0, y0, color); + if(x0 == x1 && y0 == y1) break; + e2 = 2 * err; + if(e2 >= dy) { + err += dy; + x0 += sx; + } + if(e2 <= dx) { + err += dx; + y0 += sy; + } + } +} + static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { + int i; + int lx = 65536, ly = 65536; + int hx = 0, hy = 0; + int x, y; + + for(i = 0; i < points_count - 1; i++) { + MwPoint p1 = points[i]; + MwPoint p2 = points[i + 1]; + if(p1.x < lx) lx = p1.x; + if(p1.y < ly) ly = p1.y; + if(p1.x > hx) hx = p1.x; + if(p1.y > hy) hy = p1.y; + } + // for(y = ly; y < hy; y++) { + // for(x = lx; x < hx; x++) { + // IMAGE_PLOT(x, y, color); + // } + // } + for(i = 0; i < points_count - 1; i++) { + MwPoint p1 = points[i]; + MwPoint p2 = points[i + 1]; + + line_draw(handle, p1.x, p1.y, p2.x, p2.y, color); + } } static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { + MwPoint p1 = points[0]; + MwPoint p2 = points[1]; + + line_draw(handle, p1.x, p1.y, p2.x, p2.y, color); } static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { @@ -493,16 +520,73 @@ static void MwLLFreeColorImpl(MwLLColor color) { free(color); } -static void MwLLSetBackgroundImpl(MwLL handle, MwLLColor color) { -} - static int MwLLPendingImpl(MwLL handle) { - event_loop(handle); - return 0; + enum { + DISPLAY_FD, + KEYREPEAT_FD, + CURSOR_FD + }; + struct pollfd fd; + int timeout = 1; + + if(handle->wayland.force_redraw) { + return 1; + } + + if(handle->wayland.display == NULL) { + return 0; + } + fd.fd = wl_display_get_fd(handle->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 + if(!flush_display(handle->wayland.display)) { + wl_display_cancel_read(handle->wayland.display); + + handle->wayland.toplevel->running = MwFALSE; + return 0; + } + + // Condition where no events are being sent. + if(!poll(&fd, 1, timeout)) { + wl_display_cancel_read(handle->wayland.display); + // In this case, we need to commit the surface for any animations, etc. + wl_surface_commit(handle->wayland.surface); + return 0; + } + + if(fd.revents & POLLIN) { + wl_display_read_events(handle->wayland.display); + if(wl_display_dispatch_pending(handle->wayland.display) > 0) { + } + } else { + wl_display_cancel_read(handle->wayland.display); + } + + return 1; } static void MwLLNextEventImpl(MwLL handle) { - event_loop(handle); + MwBool render; + + render = handle->wayland.force_redraw; + + if(render) { + int x, y; + unsigned int w, h; + + MwLLGetXYWH(handle, &x, &y, &w, &h); + + MwLLDispatch(handle, draw, NULL); + handle->wayland.force_redraw = MwFALSE; + } } static void MwLLSetTitleImpl(MwLL handle, const char* title) { @@ -537,6 +621,7 @@ static void MwLLForceRenderImpl(MwLL handle) { // event_loop(handle); wl_surface_damage(handle->wayland.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); wl_surface_commit(handle->wayland.surface); + handle->wayland.force_redraw = MwTRUE; } static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { diff --git a/src/backend/x11.c b/src/backend/x11.c index a7bea2f..ec50ad2 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -395,10 +395,6 @@ static void MwLLFreeColorImpl(MwLLColor color) { free(color); } -static void MwLLSetBackgroundImpl(MwLL handle, MwLLColor color) { - XSetWindowBackground(handle->x11.display, handle->x11.window, color->x11.pixel); -} - static int MwLLPendingImpl(MwLL handle) { XEvent ev; if(XCheckTypedWindowEvent(handle->x11.display, handle->x11.window, ClientMessage, &ev) || XCheckWindowEvent(handle->x11.display, handle->x11.window, mask, &ev)) { diff --git a/src/core.c b/src/core.c index 6bb4979..19eaaa8 100644 --- a/src/core.c +++ b/src/core.c @@ -295,7 +295,9 @@ int MwStep(MwWidget handle) { arrfree(widgets); handle->prop_event = 0; - if(handle->lowlevel != NULL && MwLLPending(handle->lowlevel)) MwLLNextEvent(handle->lowlevel); + if(handle->lowlevel != NULL && MwLLPending(handle->lowlevel)) + MwLLNextEvent(handle->lowlevel); + handle->prop_event = 1; clean_destroy_queue(handle); @@ -378,11 +380,7 @@ void MwSetText(MwWidget handle, const char* key, const char* value) { shput(handle->text, key, v); } if(handle->prop_event) MwDispatch3(handle, prop_change, key); - if(strcmp(key, MwNbackground) == 0) { - MwLLColor c = MwParseColor(handle, value); - MwLLSetBackground(handle->lowlevel, c); - MwLLFreeColor(c); - } + if(strcmp(key, MwNbackground) == 0 || strcmp(key, MwNforeground) == 0 || strcmp(key, MwNsubBackground) == 0 || strcmp(key, MwNsubForeground) == 0) { MwForceRender(handle); } diff --git a/src/draw.c b/src/draw.c index fd3541f..deaa7e8 100644 --- a/src/draw.c +++ b/src/draw.c @@ -1,5 +1,6 @@ /* $Id$ */ #include +#include #ifdef USE_STB_IMAGE #include "../external/stb_image.h" diff --git a/src/lowlevel.c b/src/lowlevel.c index 70dd50f..f8a4cca 100644 --- a/src/lowlevel.c +++ b/src/lowlevel.c @@ -40,8 +40,6 @@ void (*MwLLMakePopup)(MwLL handle, MwLL parent); void (*MwLLBeginStateChange)(MwLL handle); void (*MwLLEndStateChange)(MwLL handle); -void (*MwLLSetBackground)(MwLL handle, MwLLColor color); - void (*MwLLFocus)(MwLL handle); void (*MwLLGrabPointer)(MwLL handle, int toggle); -- 2.39.5 From be2eb6483c1d7f4f8f4188a457fa5205758dce08 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 1 Dec 2025 20:05:03 -0700 Subject: [PATCH 07/48] throw in the towel and switch to cairo lmao --- include/Mw/LowLevel/Wayland.h | 5 +- pl/rules.pl | 2 +- src/backend/wayland.c | 92 +++++++++++++---------------------- 3 files changed, 38 insertions(+), 61 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index c502a53..bc2aa25 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -15,6 +15,8 @@ #include #include +#include + MWDECL int MwLLWaylandCallInit(void); #ifndef WL_PROTOCOLS_DEFINED @@ -64,8 +66,9 @@ struct _MwLLWayland { struct wl_shm* shm; struct wl_registry_listener registry_listener; + cairo_surface_t* cairo_surface; + MwU8* mapped_buffer; - int mapped_buffer_size; struct { const char* key; diff --git a/pl/rules.pl b/pl/rules.pl index e1bd499..5f2b0ed 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -30,7 +30,7 @@ if (grep(/^gdi$/, @backends)) { if (grep(/^wayland$/, @backends)) { add_cflags("-DUSE_WAYLAND"); new_object("src/backend/wayland.c"); - add_libs("-lwayland-client -lxkbcommon"); + add_libs("-lcairo -lwayland-client -lxkbcommon"); scan_wayland_protocol("stable", "xdg-shell",""); scan_wayland_protocol("stable", "tablet","-v2"); diff --git a/src/backend/wayland.c b/src/backend/wayland.c index d14cada..589c48d 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -60,6 +60,7 @@ static void buffer_setup(struct _MwLLWayland* wayland) { struct wl_shm_pool* pool; struct wl_buffer* buffer; int x, y; + int stride = wayland->ww * 4; int fd; MwU32 size = wayland->ww * wayland->wh * 4; @@ -80,10 +81,15 @@ static void buffer_setup(struct _MwLLWayland* wayland) { return; } - lseek(fd, 0, SEEK_SET); wayland->mapped_buffer = mmap(NULL, size, PROT_WRITE, MAP_SHARED, fd, 0); memset(wayland->mapped_buffer, 0xFF, size); - wayland->mapped_buffer_size = size; + // wayland->mapped_buffer_size = size; + + wayland->cairo_surface = cairo_image_surface_create_for_data(wayland->mapped_buffer, + CAIRO_FORMAT_ARGB32, + wayland->ww, + wayland->wh, + stride); fsync(fd); @@ -91,7 +97,7 @@ static void buffer_setup(struct _MwLLWayland* wayland) { printf("failure setting up wl_shm: could not create pool.\n"); } - buffer = wl_shm_pool_create_buffer(pool, 0, wayland->ww, wayland->wh, wayland->ww * 4, WL_SHM_FORMAT_ARGB8888); + buffer = wl_shm_pool_create_buffer(pool, 0, wayland->ww, wayland->wh, stride, WL_SHM_FORMAT_ARGB8888); if(wayland->configured) { wl_surface_attach(wayland->surface, buffer, 0, 0); @@ -428,76 +434,41 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { } } -// fractional part of x -static float fpart(float x) { - return x - floor(x); -} -static float rfpart(float x) { - return x - fpart(x); -} - -#define IMAGE_POS_GET(x, y, o) handle->wayland.mapped_buffer[(((y * handle->wayland.ww) + x) * 4) + o] - -#define IMAGE_POS_SET(x, y, o, v) IMAGE_POS_GET(x, y, o) = v; -#define IMAGE_PLOT(x, y, color) \ - IMAGE_POS_SET(x, y, 0, color->common.blue); \ - IMAGE_POS_SET(x, y, 1, color->common.green); \ - IMAGE_POS_SET(x, y, 2, color->common.red); \ - IMAGE_POS_SET(x, y, 3, 255); - -static void -line_draw(MwLL handle, int x0, int y0, int x1, int y1, MwLLColor color) { - int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1; - int dy = -abs(y1 - y0), sy = y0 < y1 ? 1 : -1; - int err = dx + dy, e2; - - for(;;) { - IMAGE_PLOT(x0, y0, color); - if(x0 == x1 && y0 == y1) break; - e2 = 2 * err; - if(e2 >= dy) { - err += dy; - x0 += sx; - } - if(e2 <= dx) { - err += dx; - y0 += sy; - } - } -} - static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { int i; - int lx = 65536, ly = 65536; - int hx = 0, hy = 0; - int x, y; - for(i = 0; i < points_count - 1; i++) { - MwPoint p1 = points[i]; - MwPoint p2 = points[i + 1]; - if(p1.x < lx) lx = p1.x; - if(p1.y < ly) ly = p1.y; - if(p1.x > hx) hx = p1.x; - if(p1.y > hy) hy = p1.y; - } - // for(y = ly; y < hy; y++) { - // for(x = lx; x < hx; x++) { - // IMAGE_PLOT(x, y, color); - // } - // } + cairo_t* cairo = cairo_create(handle->wayland.cairo_surface); + cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); + cairo_set_line_width(cairo, 1); + cairo_set_source_rgb(cairo, color->common.red / 255., color->common.green / 255., color->common.blue / 255.); + cairo_paint(cairo); + for(i = 0; i < points_count - 1; i++) { MwPoint p1 = points[i]; MwPoint p2 = points[i + 1]; - line_draw(handle, p1.x, p1.y, p2.x, p2.y, color); + cairo_move_to(cairo, p1.x, p1.y); + cairo_line_to(cairo, p2.x, p2.y); } + cairo_fill(cairo); + cairo_destroy(cairo); } static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { MwPoint p1 = points[0]; MwPoint p2 = points[1]; + int i; - line_draw(handle, p1.x, p1.y, p2.x, p2.y, color); + cairo_t* cairo = cairo_create(handle->wayland.cairo_surface); + cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); + cairo_set_line_width(cairo, 1); + cairo_set_source_rgb(cairo, color->common.red / 255., color->common.green / 255., color->common.blue / 255.); + cairo_paint(cairo); + + cairo_move_to(cairo, p1.x, p1.y); + cairo_line_to(cairo, p2.x, p2.y); + cairo_fill(cairo); + cairo_destroy(cairo); } static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { @@ -520,6 +491,9 @@ static void MwLLFreeColorImpl(MwLLColor color) { free(color); } +static void MwLLSetBackgroundImpl(MwLL handle, MwLLColor color) { +} + static int MwLLPendingImpl(MwLL handle) { enum { DISPLAY_FD, -- 2.39.5 From 8cbde42de36c50dce40a3a792bd1aed1a9c610c9 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 1 Dec 2025 20:45:21 -0700 Subject: [PATCH 08/48] have cairo fill in lines idk --- include/Mw/LowLevel/Wayland.h | 3 +++ src/backend/wayland.c | 26 +++++++++++++------------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index bc2aa25..d5eb32d 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -66,7 +66,10 @@ struct _MwLLWayland { struct wl_shm* shm; struct wl_registry_listener registry_listener; + int mapped_buffer_size; + cairo_surface_t* cairo_surface; + // cairo_t* cairo; MwU8* mapped_buffer; diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 589c48d..91e46d7 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -433,24 +434,26 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { buffer_setup(&handle->wayland); } } - static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { int i; cairo_t* cairo = cairo_create(handle->wayland.cairo_surface); - cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); - cairo_set_line_width(cairo, 1); cairo_set_source_rgb(cairo, color->common.red / 255., color->common.green / 255., color->common.blue / 255.); - cairo_paint(cairo); + cairo_set_line_width(cairo, 1); + cairo_set_fill_rule(cairo, CAIRO_FILL_RULE_EVEN_ODD); - for(i = 0; i < points_count - 1; i++) { - MwPoint p1 = points[i]; - MwPoint p2 = points[i + 1]; - - cairo_move_to(cairo, p1.x, p1.y); - cairo_line_to(cairo, p2.x, p2.y); + cairo_new_path(cairo); + for(i = 0; i < points_count + 1; i++) { + cairo_line_to(cairo, points[i].x, points[i].y); } + if(points[0].x != points[i].x && points[0].y != points[i].y) { + cairo_line_to(cairo, points[0].x, points[0].y); + } + cairo_close_path(cairo); + + cairo_stroke_preserve(cairo); cairo_fill(cairo); + // cairo_paint(cairo); cairo_destroy(cairo); } @@ -491,9 +494,6 @@ static void MwLLFreeColorImpl(MwLLColor color) { free(color); } -static void MwLLSetBackgroundImpl(MwLL handle, MwLLColor color) { -} - static int MwLLPendingImpl(MwLL handle) { enum { DISPLAY_FD, -- 2.39.5 From c50e9201236e83088a2a6bacbff317d86cd4b27c Mon Sep 17 00:00:00 2001 From: IoIxD Date: Tue, 2 Dec 2025 23:42:55 -0700 Subject: [PATCH 09/48] cairo about to make me give up on the wayland port --- src/backend/wayland.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 91e46d7..abec1b9 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -370,10 +370,6 @@ static void setup_subsurface(MwLL parent, MwLL r, int x, int y, int width, int h } r->wayland.configured = MwTRUE; - - buffer_setup(&r->wayland); - - wl_surface_commit(parent->wayland.surface); } static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { MwLL r; @@ -397,6 +393,8 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { setup_subsurface(parent, r, x, y, width, height); } + buffer_setup(&r->wayland); + return r; } @@ -414,13 +412,6 @@ static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsign } static void MwLLSetXYImpl(MwLL handle, int x, int y) { - handle->wayland.x = x; - handle->wayland.y = y; - if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { - xdg_surface_set_window_geometry(handle->wayland.toplevel->xdg_surface, handle->wayland.x, handle->wayland.y, handle->wayland.ww, handle->wayland.wh); - } else { - wl_subsurface_set_position(handle->wayland.subsurface, x, y); - } } static void MwLLSetWHImpl(MwLL handle, int w, int h) { @@ -431,29 +422,26 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { xdg_surface_set_window_geometry(handle->wayland.toplevel->xdg_surface, handle->wayland.x, handle->wayland.y, handle->wayland.ww, handle->wayland.wh); } else { // setup the buffer again with the new size. - buffer_setup(&handle->wayland); + // buffer_setup(&handle->wayland); } } static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { - int i; + int i = 0; cairo_t* cairo = cairo_create(handle->wayland.cairo_surface); cairo_set_source_rgb(cairo, color->common.red / 255., color->common.green / 255., color->common.blue / 255.); - cairo_set_line_width(cairo, 1); + cairo_set_line_width(cairo, 0.1); cairo_set_fill_rule(cairo, CAIRO_FILL_RULE_EVEN_ODD); cairo_new_path(cairo); - for(i = 0; i < points_count + 1; i++) { + for(; i < points_count; i++) { cairo_line_to(cairo, points[i].x, points[i].y); } - if(points[0].x != points[i].x && points[0].y != points[i].y) { - cairo_line_to(cairo, points[0].x, points[0].y); - } cairo_close_path(cairo); + // cairo_paint(cairo); cairo_stroke_preserve(cairo); cairo_fill(cairo); - // cairo_paint(cairo); cairo_destroy(cairo); } -- 2.39.5 From 0adc98a2a2cdc6ca6d7aa84a848177de55dabd56 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 3 Dec 2025 18:17:27 -0700 Subject: [PATCH 10/48] wayland: give up on cairo and switch to OpenGL --- include/Mw/LowLevel/Wayland.h | 45 ++-- pl/rules.pl | 2 +- src/backend/wayland.c | 376 +++++++++++++++++++++++++--------- src/backend/x11.c | 1 + src/core.c | 3 + src/draw.c | 2 + 6 files changed, 310 insertions(+), 119 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index d5eb32d..c13e9bf 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -12,11 +12,14 @@ #include #include +#include +#include +#include +#include + #include #include -#include - MWDECL int MwLLWaylandCallInit(void); #ifndef WL_PROTOCOLS_DEFINED @@ -58,21 +61,6 @@ struct _MwLLWayland { MWLL_WAYLAND_SUBSURFACE = 1, } type; - struct wl_display* display; - struct wl_registry* registry; - struct wl_compositor* compositor; - struct wl_subcompositor* subcompositor; - struct wl_surface* surface; - struct wl_shm* shm; - struct wl_registry_listener registry_listener; - - int mapped_buffer_size; - - cairo_surface_t* cairo_surface; - // cairo_t* cairo; - - MwU8* mapped_buffer; - struct { const char* key; wl_setup_func* value; @@ -83,9 +71,32 @@ struct _MwLLWayland { wayland_protocol_t* value; }* wl_protocol_map; + /*MwLL* subsurfaces;*/ + + struct wl_display* display; + struct wl_registry* registry; + struct wl_compositor* compositor; + struct wl_subcompositor* subcompositor; + struct wl_surface* surface; + struct wl_shm* shm; + struct wl_registry_listener registry_listener; + // cairo_surface_t* cairo_surface; MwBool configured; MwBool force_redraw; + MwBool do_clear; MwU32 x, y, ww, wh; + + MwLL parent; + + GLuint fbo; + unsigned int fbo_texture; + unsigned int rbo; + + MwBool egl_setup; + EGLNativeWindowType egl_window_native; + EGLDisplay egl_display; + EGLContext egl_context; + EGLSurface egl_surface; }; struct _MwLLWaylandColor { diff --git a/pl/rules.pl b/pl/rules.pl index 5f2b0ed..4927a10 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -30,7 +30,7 @@ if (grep(/^gdi$/, @backends)) { if (grep(/^wayland$/, @backends)) { add_cflags("-DUSE_WAYLAND"); new_object("src/backend/wayland.c"); - add_libs("-lcairo -lwayland-client -lxkbcommon"); + add_libs("-lGL -lEGL -lwayland-egl -lwayland-client -lxkbcommon"); scan_wayland_protocol("stable", "xdg-shell",""); scan_wayland_protocol("stable", "tablet","-v2"); diff --git a/src/backend/wayland.c b/src/backend/wayland.c index abec1b9..b860f7f 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1,5 +1,6 @@ /* $Id$ */ +#include #include #include @@ -18,6 +19,17 @@ #include "Mw/LowLevel.h" #include +#include +#include + +PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers; +PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D; +PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers; +// PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage; +PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer; +PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer; +PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer; +PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatus; #define WAYLAND_GET_INTERFACE(r, inter) shget(r.wl_protocol_map, inter##_interface.name) @@ -57,57 +69,8 @@ static wayland_protocol_t* wl_shm_setup(MwU32 name, struct _MwLLWayland* wayland wayland->shm = wl_registry_bind(wayland->registry, name, &wl_shm_interface, 1); return NULL; } -static void buffer_setup(struct _MwLLWayland* wayland) { - struct wl_shm_pool* pool; - struct wl_buffer* buffer; - int x, y; - int stride = wayland->ww * 4; - - int fd; - MwU32 size = wayland->ww * wayland->wh * 4; - char temp_name[] = "/tmp/milsko-wl-shm-XXXXXX"; - - fd = mkstemp(temp_name); - - unlink(temp_name); - - if(posix_fallocate(fd, 0, size) != 0) { - printf("failure setting up wl_shm: could not fallocate. %s.\n", strerror(errno)); - close(fd); - return; - } - if(ftruncate(fd, size) != 0) { - printf("failure setting up wl_shm: could not truncate. %s.\n", strerror(errno)); - close(fd); - return; - } - - wayland->mapped_buffer = mmap(NULL, size, PROT_WRITE, MAP_SHARED, fd, 0); - memset(wayland->mapped_buffer, 0xFF, size); - // wayland->mapped_buffer_size = size; - - wayland->cairo_surface = cairo_image_surface_create_for_data(wayland->mapped_buffer, - CAIRO_FORMAT_ARGB32, - wayland->ww, - wayland->wh, - stride); - - fsync(fd); - - if(!(pool = wl_shm_create_pool(wayland->shm, fd, size))) { - printf("failure setting up wl_shm: could not create pool.\n"); - } - - buffer = wl_shm_pool_create_buffer(pool, 0, wayland->ww, wayland->wh, stride, WL_SHM_FORMAT_ARGB8888); - - if(wayland->configured) { - wl_surface_attach(wayland->surface, buffer, 0, 0); - wl_surface_commit(wayland->surface); - } - wl_buffer_destroy(buffer); - wl_shm_pool_destroy(pool); - close(fd); -} +// static void buffer_setup(struct _MwLLWayland* wayland) { +// } static wayland_protocol_t* wl_seat_setup(MwU32 name, struct _MwLLWayland* wayland) { wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); @@ -174,20 +137,171 @@ static wayland_protocol_t* zxdg_decoration_manager_v1_setup(MwU32 name, struct _ return proto; } +static MwBool egl_setup(MwLL self, int width, int height) { + int err; + EGLint numConfigs; + EGLint majorVersion; + EGLint minorVersion; + EGLContext context; + EGLSurface surface; + EGLConfig config; + 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_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 = eglGetDisplay(self->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; + } + + // Choose config + if((eglChooseConfig(display, fbAttribs, &config, 1, &numConfigs) != EGL_TRUE) || (numConfigs != 1)) { + printf("ERROR: eglChooseConfig, %0X\n", eglGetError()); + return MwFALSE; + } + + self->wayland.egl_window_native = + wl_egl_window_create(self->wayland.surface, width, height); + if(self->wayland.egl_window_native == EGL_NO_SURFACE) { + printf("ERROR: wl_egl_window_create, EGL_NO_SURFACE\n"); + return MwFALSE; + } + + // Create a surface + surface = eglCreateWindowSurface(display, config, self->wayland.egl_window_native, NULL); + if(surface == EGL_NO_SURFACE) { + printf("ERROR: eglCreateWindowSurface, %0X\n", eglGetError()); + return MwFALSE; + } + + eglBindAPI(EGL_OPENGL_API); + + // Create a GL context + context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs); + if(context == EGL_NO_CONTEXT) { + printf("ERROR: eglCreateContext, %0X\n", eglGetError()); + return MwFALSE; + } + + // Make the context current + if(!eglMakeCurrent(display, surface, surface, context)) { + printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); + return MwFALSE; + } + + glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)eglGetProcAddress("glGenFramebuffers"); + glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)eglGetProcAddress("glFramebufferTexture2D"); + glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)eglGetProcAddress("glGenRenderbuffers"); + // glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)eglGetProcAddress("glRenderbufferStorage"); + glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)eglGetProcAddress("glFramebufferRenderbuffer"); + glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)eglGetProcAddress("glBindRenderbuffer"); + glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)eglGetProcAddress("glBindFramebuffer"); + glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)eglGetProcAddress("glCheckFramebufferStatus"); + + glGenTextures(1, &self->wayland.fbo_texture); + glBindTexture(GL_TEXTURE_2D, self->wayland.fbo_texture); + + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + + glBindTexture(GL_TEXTURE_2D, 0); + + glGenRenderbuffers(1, &self->wayland.rbo); + // glBindRenderbuffer(GL_RENDERBUFFER, self->wayland.rbo)); + // glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 768, 1024); + // glBindRenderbuffer(GL_RENDERBUFFER, 0); + + glGenFramebuffers(1, &self->wayland.fbo); + glBindFramebuffer(GL_FRAMEBUFFER_BINDING, self->wayland.fbo); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self->wayland.fbo_texture, 0); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, self->wayland.rbo); + + if((err = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE) { + printf("Error binding framebuffer: %0X\n", err); + return MwFALSE; + } + + glBindFramebuffer(GL_FRAMEBUFFER_BINDING, 0); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, width, height, -13, -1, 1); + + self->wayland.egl_display = display; + self->wayland.egl_surface = surface; + self->wayland.egl_context = context; + printf("EGL success\n"); + return MwTRUE; +} + static void xdg_toplevel_configure(void* data, struct xdg_toplevel* xdg_toplevel, MwI32 width, MwI32 height, struct wl_array* states) { - MwLL self = data; + MwLL self = data; + PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)eglGetProcAddress("glFramebufferTexture2D"); - if(width != 0 && height != 0) { - self->wayland.ww = width; - self->wayland.wh = height; - xdg_surface_set_window_geometry(self->wayland.toplevel->xdg_surface, self->wayland.x, self->wayland.y, self->wayland.ww, self->wayland.wh); + if(width == 0 && height == 0) { + width = self->wayland.ww; + height = self->wayland.wh; + } + self->wayland.ww = width; + self->wayland.wh = height; + xdg_surface_set_window_geometry(self->wayland.toplevel->xdg_surface, self->wayland.x, self->wayland.y, self->wayland.ww, self->wayland.wh); - MwLLSetWH(self, width, height); - MwLLDispatch(self, resize, NULL); - }; + MwLLSetWH(self, width, height); + MwLLDispatch(self, resize, NULL); + + if(!self->wayland.egl_setup) { + self->wayland.egl_setup = egl_setup(self, width, height); + } else { + wl_egl_window_resize(self->wayland.egl_window_native, width, height, 0, 0); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, width, height, -13, -1, 1); + self->wayland.do_clear = MwTRUE; + + // glDeleteTextures(1, &self->wayland.fbo_texture); + // glGenTextures(1, &self->wayland.fbo_texture); + // glBindTexture(GL_TEXTURE_2D, self->wayland.fbo_texture); + + // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + + // glBindTexture(GL_TEXTURE_2D, 0); + } MwLLForceRender(self); @@ -335,7 +449,7 @@ static void setup_toplevel(MwLL r, int x, int y, int width, int height) { printf("zxdg null\n"); } - buffer_setup(&r->wayland); + // buffer_setup(&r->wayland); wl_surface_commit(r->wayland.surface); } @@ -369,23 +483,34 @@ static void setup_subsurface(MwLL parent, MwLL r, int x, int y, int width, int h return; } + // arrpush(parent->wayland.subsurfaces, r); + r->wayland.configured = MwTRUE; + + r->wayland.egl_context = parent->wayland.egl_context; + r->wayland.egl_display = parent->wayland.egl_display; + r->wayland.egl_surface = parent->wayland.egl_surface; + r->wayland.fbo = parent->wayland.fbo; + r->wayland.fbo_texture = parent->wayland.fbo_texture; + r->wayland.rbo = parent->wayland.rbo; } static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { MwLL r; r = malloc(sizeof(*r)); MwLLCreateCommon(r); - // r->common.copy_buffer = 1; r->common.type = MwLLBackendWayland; - if(width == 0) width = parent->wayland.ww; - if(height == 0) height = parent->wayland.wh; + if(width == 0) width = 1; + if(height == 0) height = 1; - r->wayland.ww = width; - r->wayland.wh = height; + r->wayland.ww = width; + r->wayland.wh = height; + r->wayland.parent = parent; - r->common.success = MwTRUE; + r->wayland.force_redraw = MwFALSE; + r->wayland.do_clear = MwFALSE; + r->common.success = MwTRUE; if(parent == NULL) { setup_toplevel(r, x, y, width, height); @@ -393,7 +518,7 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { setup_subsurface(parent, r, x, y, width, height); } - buffer_setup(&r->wayland); + // buffer_setup(&r->wayland); return r; } @@ -412,6 +537,13 @@ static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsign } static void MwLLSetXYImpl(MwLL handle, int x, int y) { + + if(handle->wayland.type != MWLL_WAYLAND_TOPLEVEL) { + handle->wayland.x = x; + handle->wayland.y = y; + wl_subsurface_set_position(handle->wayland.subsurface, x, y); + MwLLForceRender(handle); + } } static void MwLLSetWHImpl(MwLL handle, int w, int h) { @@ -421,45 +553,82 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { xdg_surface_set_window_geometry(handle->wayland.toplevel->xdg_surface, handle->wayland.x, handle->wayland.y, handle->wayland.ww, handle->wayland.wh); } else { - // setup the buffer again with the new size. - // buffer_setup(&handle->wayland); } } + static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { - int i = 0; + /* + * TODO: this function sucks shit, ioi needs to make it not suck shit :) + */ + int i; + PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)eglGetProcAddress("glBindFramebuffer"); + PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)eglGetProcAddress("glBindRenderbuffer"); + int w, h; - cairo_t* cairo = cairo_create(handle->wayland.cairo_surface); - cairo_set_source_rgb(cairo, color->common.red / 255., color->common.green / 255., color->common.blue / 255.); - cairo_set_line_width(cairo, 0.1); - cairo_set_fill_rule(cairo, CAIRO_FILL_RULE_EVEN_ODD); - - cairo_new_path(cairo); - for(; i < points_count; i++) { - cairo_line_to(cairo, points[i].x, points[i].y); + if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { + w = handle->wayland.ww; + h = handle->wayland.wh; + } else { + MwLL parent = handle->wayland.parent; + while(parent->wayland.type != MWLL_WAYLAND_TOPLEVEL) { + parent = parent->wayland.parent; + } + w = parent->wayland.ww; + h = parent->wayland.wh; } - cairo_close_path(cairo); - // cairo_paint(cairo); - cairo_stroke_preserve(cairo); - cairo_fill(cairo); - cairo_destroy(cairo); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, 0); + glBindFramebuffer(GL_FRAMEBUFFER, handle->wayland.fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, handle->wayland.fbo_texture, 0); + + glBegin(GL_TRIANGLE_FAN); + for(i = 0; i < points_count; i++) { + glColor3f(color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); + glVertex2f( + (handle->wayland.x + points[i].x), + (handle->wayland.y + points[i].y)); + + if((i % 3) == 0 && i != 0) { + glColor3f(color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); + glVertex2f( + (handle->wayland.x + points[i].x), + (handle->wayland.y + points[i].y)); + } + } + glEnd(); + glFinish(); + + glBindTexture(GL_TEXTURE_2D, handle->wayland.fbo_texture); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glClear(GL_COLOR_BUFFER_BIT); + glClearColor(0, 0, 0, 1); + + glColor3f(1.0, 1.0, 1.0); + + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 1); + glVertex2f(0, 0); + glTexCoord2f(1, 1); + glVertex2f(w, 0); + glTexCoord2f(1, 0.0f); + glVertex2f(w, h); + glTexCoord2f(0.0f, 0.0f); + glVertex2f(0, h); + glEnd(); + glFinish(); + + if(!eglSwapBuffers(handle->wayland.egl_display, handle->wayland.egl_surface)) { + printf("error swapping buffers! %0X\n", eglGetError()); + } else { + wl_surface_commit(handle->wayland.surface); + } + glDisable(GL_TEXTURE_2D); + handle->wayland.do_clear = MwFALSE; } static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { - MwPoint p1 = points[0]; - MwPoint p2 = points[1]; - int i; - - cairo_t* cairo = cairo_create(handle->wayland.cairo_surface); - cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); - cairo_set_line_width(cairo, 1); - cairo_set_source_rgb(cairo, color->common.red / 255., color->common.green / 255., color->common.blue / 255.); - cairo_paint(cairo); - - cairo_move_to(cairo, p1.x, p1.y); - cairo_line_to(cairo, p2.x, p2.y); - cairo_fill(cairo); - cairo_destroy(cairo); + // } static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { @@ -536,9 +705,7 @@ static int MwLLPendingImpl(MwLL handle) { } static void MwLLNextEventImpl(MwLL handle) { - MwBool render; - - render = handle->wayland.force_redraw; + MwBool render = handle->wayland.force_redraw; if(render) { int x, y; @@ -580,9 +747,16 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { } static void MwLLForceRenderImpl(MwLL handle) { - // event_loop(handle); wl_surface_damage(handle->wayland.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); + + if(handle->wayland.egl_setup) { + if(!eglSwapBuffers(handle->wayland.egl_display, handle->wayland.egl_surface)) { + printf("error swapping buffers! %0X\n", eglGetError()); + } + } + wl_surface_commit(handle->wayland.surface); + handle->wayland.force_redraw = MwTRUE; } diff --git a/src/backend/x11.c b/src/backend/x11.c index ec50ad2..b6d22c0 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -131,6 +131,7 @@ static XVisualInfo* get_visual_info(Display* display) { } static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { + printf("%d %d\n", width, height); MwLL r; Window p; XVisualInfo* xvi; diff --git a/src/core.c b/src/core.c index 19eaaa8..cb7c6fd 100644 --- a/src/core.c +++ b/src/core.c @@ -1,7 +1,9 @@ /* $Id$ */ #include +#include #include "../external/stb_ds.h" +#include "Mw/LowLevel.h" static void lldrawhandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; @@ -295,6 +297,7 @@ int MwStep(MwWidget handle) { arrfree(widgets); handle->prop_event = 0; + if(handle->lowlevel != NULL && MwLLPending(handle->lowlevel)) MwLLNextEvent(handle->lowlevel); diff --git a/src/draw.c b/src/draw.c index deaa7e8..6229a88 100644 --- a/src/draw.c +++ b/src/draw.c @@ -1,4 +1,5 @@ /* $Id$ */ +#include "Mw/LowLevel.h" #include #include @@ -485,6 +486,7 @@ void MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int invert, p4[2].y = rect->y + s * border; } MwLLPolygon(handle->lowlevel, p4, 3, col); + if(color != col) MwLLFreeColor(col); MwLLFreeColor(lighter); -- 2.39.5 From a932fc00ea3645337a984c9ab3b990fbe623ba56 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 3 Dec 2025 22:26:03 -0700 Subject: [PATCH 11/48] opengl complete --- include/Mw/Core.h | 2 +- include/Mw/LowLevel/Wayland.h | 7 +++--- src/backend/wayland.c | 46 +++++++++++++++-------------------- src/backend/x11.c | 1 - 4 files changed, 25 insertions(+), 31 deletions(-) diff --git a/include/Mw/Core.h b/include/Mw/Core.h index 28df4d4..98812a5 100644 --- a/include/Mw/Core.h +++ b/include/Mw/Core.h @@ -128,7 +128,7 @@ MWDECL void MwLoop(MwWidget handle); */ MWDECL int MwStep(MwWidget handle); -/*! +/*!MwStep( * @brief Check if any event is pending * @param handle Widget * @return `1` if any event is pending diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index c13e9bf..2ed3909 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -71,8 +71,6 @@ struct _MwLLWayland { wayland_protocol_t* value; }* wl_protocol_map; - /*MwLL* subsurfaces;*/ - struct wl_display* display; struct wl_registry* registry; struct wl_compositor* compositor; @@ -80,11 +78,12 @@ struct _MwLLWayland { struct wl_surface* surface; struct wl_shm* shm; struct wl_registry_listener registry_listener; - // cairo_surface_t* cairo_surface; + MwBool configured; MwBool force_redraw; MwBool do_clear; MwU32 x, y, ww, wh; + int z_index; MwLL parent; @@ -97,6 +96,8 @@ struct _MwLLWayland { EGLDisplay egl_display; EGLContext egl_context; EGLSurface egl_surface; + GLuint vertex_buffer; + GLuint vertex_array; }; struct _MwLLWaylandColor { diff --git a/src/backend/wayland.c b/src/backend/wayland.c index b860f7f..bfedd17 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1,5 +1,6 @@ /* $Id$ */ +// #include #include #include @@ -22,10 +23,9 @@ #include #include -PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers; -PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D; -PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers; -// PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage; +PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers; +PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D; +PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers; PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer; PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer; PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer; @@ -254,7 +254,7 @@ static MwBool egl_setup(MwLL self, int width, int height) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glOrtho(0, width, height, -13, -1, 1); + glOrtho(0, width, height, 0, -1, 1); self->wayland.egl_display = display; self->wayland.egl_surface = surface; @@ -283,11 +283,12 @@ static void xdg_toplevel_configure(void* data, if(!self->wayland.egl_setup) { self->wayland.egl_setup = egl_setup(self, width, height); + MwLLForceRender(self); } else { wl_egl_window_resize(self->wayland.egl_window_native, width, height, 0, 0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glOrtho(0, width, height, -13, -1, 1); + glOrtho(0, width, height, 0, -1, 1); self->wayland.do_clear = MwTRUE; // glDeleteTextures(1, &self->wayland.fbo_texture); @@ -303,8 +304,6 @@ static void xdg_toplevel_configure(void* data, // glBindTexture(GL_TEXTURE_2D, 0); } - MwLLForceRender(self); - return; }; @@ -452,6 +451,8 @@ static void setup_toplevel(MwLL r, int x, int y, int width, int height) { // buffer_setup(&r->wayland); wl_surface_commit(r->wayland.surface); + + // glGenBuffers(1, &vertex_buffer); } static void setup_subsurface(MwLL parent, MwLL r, int x, int y, int width, int height) { @@ -518,8 +519,6 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { setup_subsurface(parent, r, x, y, width, height); } - // buffer_setup(&r->wayland); - return r; } @@ -581,20 +580,21 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL glBindTexture(GL_TEXTURE_2D, 0); glBindFramebuffer(GL_FRAMEBUFFER, handle->wayland.fbo); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, handle->wayland.fbo_texture, 0); + glLineWidth(1); + + if(points_count == 3) { + glBegin(GL_TRIANGLES); + } else if(points_count == 4) { + glBegin(GL_QUADS); + } else { + glBegin(GL_QUAD_STRIP); + } - glBegin(GL_TRIANGLE_FAN); for(i = 0; i < points_count; i++) { glColor3f(color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); glVertex2f( - (handle->wayland.x + points[i].x), - (handle->wayland.y + points[i].y)); - - if((i % 3) == 0 && i != 0) { - glColor3f(color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); - glVertex2f( - (handle->wayland.x + points[i].x), - (handle->wayland.y + points[i].y)); - } + ceil(handle->wayland.x) + ceil(points[i].x), + ceil(handle->wayland.y) + ceil(points[i].y)); } glEnd(); glFinish(); @@ -749,12 +749,6 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { static void MwLLForceRenderImpl(MwLL handle) { wl_surface_damage(handle->wayland.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); - if(handle->wayland.egl_setup) { - if(!eglSwapBuffers(handle->wayland.egl_display, handle->wayland.egl_surface)) { - printf("error swapping buffers! %0X\n", eglGetError()); - } - } - wl_surface_commit(handle->wayland.surface); handle->wayland.force_redraw = MwTRUE; diff --git a/src/backend/x11.c b/src/backend/x11.c index b6d22c0..ec50ad2 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -131,7 +131,6 @@ static XVisualInfo* get_visual_info(Display* display) { } static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { - printf("%d %d\n", width, height); MwLL r; Window p; XVisualInfo* xvi; -- 2.39.5 From 247e0b361c6f3a731ba29f5e511a83cbe38c051d Mon Sep 17 00:00:00 2001 From: IoIxD Date: Wed, 3 Dec 2025 23:00:40 -0700 Subject: [PATCH 12/48] introduce MwLLEndDraw, which can be stubbed safely on any platforms and exists purely for wayland to be able to swap buffers at a better time --- include/Mw/LowLevel.h | 1 + src/backend/call.c | 1 + src/backend/gdi.c | 2 ++ src/backend/wayland.c | 49 +++++++++++++++++++------------------------ src/backend/x11.c | 2 ++ src/core.c | 2 ++ src/lowlevel.c | 2 ++ 7 files changed, 31 insertions(+), 28 deletions(-) diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index 49c1cc7..2be5b26 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -164,6 +164,7 @@ 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 (*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 de4b7f0..2c8f399 100644 --- a/src/backend/call.c +++ b/src/backend/call.c @@ -11,6 +11,7 @@ \ MwLLPolygon = MwLLPolygonImpl; \ MwLLLine = MwLLLineImpl; \ + MwLLEndDraw = MwLLEndDrawImpl; \ \ MwLLAllocColor = MwLLAllocColorImpl; \ MwLLColorUpdate = MwLLColorUpdateImpl; \ diff --git a/src/backend/gdi.c b/src/backend/gdi.c index b40c26e..23c2dd3 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -278,6 +278,8 @@ static void MwLLDestroyImpl(MwLL handle) { free(handle); } +static void MwLLEndDrawImpl(MwLL 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 bfedd17..fd8c6bc 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -255,6 +255,7 @@ static MwBool egl_setup(MwLL self, int width, int height) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, width, height, 0, -1, 1); + glEnable(GL_TEXTURE_2D); self->wayland.egl_display = display; self->wayland.egl_surface = surface; @@ -556,31 +557,11 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { } static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { - /* - * TODO: this function sucks shit, ioi needs to make it not suck shit :) - */ - int i; - PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)eglGetProcAddress("glBindFramebuffer"); - PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)eglGetProcAddress("glBindRenderbuffer"); - int w, h; + int i; - if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { - w = handle->wayland.ww; - h = handle->wayland.wh; - } else { - MwLL parent = handle->wayland.parent; - while(parent->wayland.type != MWLL_WAYLAND_TOPLEVEL) { - parent = parent->wayland.parent; - } - w = parent->wayland.ww; - h = parent->wayland.wh; - } - - glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); glBindFramebuffer(GL_FRAMEBUFFER, handle->wayland.fbo); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, handle->wayland.fbo_texture, 0); - glLineWidth(1); if(points_count == 3) { glBegin(GL_TRIANGLES); @@ -598,9 +579,26 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL } glEnd(); glFinish(); + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { + // +} + +static void MwLLEndDrawImpl(MwLL handle) { + int w, h; + + if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { + w = handle->wayland.ww; + h = handle->wayland.wh; + } else { + MwLL parent = handle->wayland.parent; + w = parent->wayland.ww; + h = parent->wayland.wh; + } glBindTexture(GL_TEXTURE_2D, handle->wayland.fbo_texture); - glBindFramebuffer(GL_FRAMEBUFFER, 0); glClear(GL_COLOR_BUFFER_BIT); glClearColor(0, 0, 0, 1); @@ -618,17 +616,12 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL glEnd(); glFinish(); + wl_surface_damage(handle->wayland.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); if(!eglSwapBuffers(handle->wayland.egl_display, handle->wayland.egl_surface)) { printf("error swapping buffers! %0X\n", eglGetError()); } else { wl_surface_commit(handle->wayland.surface); } - glDisable(GL_TEXTURE_2D); - handle->wayland.do_clear = MwFALSE; -} - -static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { - // } static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { diff --git a/src/backend/x11.c b/src/backend/x11.c index ec50ad2..6e2426a 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -256,6 +256,8 @@ static void MwLLDestroyImpl(MwLL handle) { free(handle); } +static void MwLLEndDrawImpl(MwLL 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 cb7c6fd..401600d 100644 --- a/src/core.c +++ b/src/core.c @@ -334,6 +334,8 @@ void MwLoop(MwWidget handle) { } if(v != 0) break; + MwLLEndDraw(handle->lowlevel); + for(i = 0; i < arrlen(handle->tick_list); i++) { MwDispatch(handle->tick_list[i], tick); MwDispatchUserHandler(handle->tick_list[i], MwNtickHandler, NULL); diff --git a/src/lowlevel.c b/src/lowlevel.c index f8a4cca..19445a4 100644 --- a/src/lowlevel.c +++ b/src/lowlevel.c @@ -7,6 +7,8 @@ void (*MwLLDestroy)(MwLL handle); void (*MwLLPolygon)(MwLL handle, MwPoint* points, int points_count, MwLLColor color); void (*MwLLLine)(MwLL handle, MwPoint* points, MwLLColor color); +void (*MwLLEndDraw)(MwLL handle); + MwLLColor (*MwLLAllocColor)(MwLL handle, int r, int g, int b); void (*MwLLColorUpdate)(MwLL handle, MwLLColor c, int r, int g, int b); void (*MwLLFreeColor)(MwLLColor color); -- 2.39.5 From 39f44a56e3128ea4f98d6c1d95847a5fd606dc8e Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 5 Dec 2025 12:40:44 -0700 Subject: [PATCH 13/48] fixed new kde bug where decorations were null --- src/backend/wayland.c | 157 +++++++++++++++++++++++------------------- 1 file changed, 86 insertions(+), 71 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index fd8c6bc..77669f1 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -5,7 +5,6 @@ #include #include -#include #include #include #include @@ -339,6 +338,75 @@ static void xdg_surface_configure( self->wayland.configured = MwTRUE; } +static int event_loop(struct _MwLLWayland* wayland) { + enum { + DISPLAY_FD, + KEYREPEAT_FD, + CURSOR_FD + }; + struct pollfd fd; + int timeout = 100; + + if(wayland->force_redraw) { + return 1; + } + + if(wayland->display == NULL) { + return 0; + } + fd.fd = wl_display_get_fd(wayland->display); + fd.events = POLLIN; + + while(wl_display_prepare_read(wayland->display) != 0) { + if(wl_display_dispatch_pending(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) { + return MwFALSE; + } + + while(poll(&fd, 1, -1) == -1) { + if(errno != EINTR && errno != EAGAIN) { + wl_display_cancel_read(wayland->display); + + wayland->toplevel->running = MwFALSE; + return 0; + } + } + } + + /* + IOI: + I took this from ioilib which I in turn adapted from SDL. I think this is meant to be required? + But doing this on my main machine causes the decorations manager to be null...? This doesn't show up on the project currently using ioilib. + Race condition? Random KDE bug? Who knows, but it seems that not polling for this works anyways (possibly because we already flush events above and then cancel reads when we actually need to close). + */ + /* + + // 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_surface_commit(wayland->surface); + return 0; + } + + */ + + if(fd.revents & POLLIN) { + wl_display_read_events(wayland->display); + if(wl_display_dispatch_pending(wayland->display) > 0) { + } + } else { + wl_display_cancel_read(wayland->display); + } + return 0; +} + #define WL_INTERFACE(interface) \ shput(wayland->wl_protocol_setup_map, interface##_interface.name, (wl_setup_func*)interface##_setup); @@ -361,23 +429,9 @@ static void setup_callbacks(struct _MwLLWayland* wayland) { #undef WL_INTERFACE -static MwBool flush_display(struct wl_display* display) { - while(wl_display_flush(display) == -1) { - if(errno != EAGAIN) { - return MwFALSE; - } - - struct pollfd fd = {wl_display_get_fd(display), POLL_OUT}; - - while(poll(&fd, 1, -1) == -1) { - if(errno != EINTR && errno != EAGAIN) - return MwFALSE; - } - } - return MwTRUE; -} - static void setup_toplevel(MwLL r, int x, int y, int width, int height) { + int i; + r->wayland.type = MWLL_WAYLAND_TOPLEVEL; r->wayland.toplevel = malloc(sizeof(struct _MwLLWaylandTopLevel)); @@ -400,6 +454,16 @@ static void setup_toplevel(MwLL r, int x, int y, int width, int height) { return; } + printf("Found globals: \n"); + for(i = 0; i < shlen(r->wayland.wl_protocol_map); i++) { + wayland_protocol_t* proto = shget(r->wayland.wl_protocol_map, r->wayland.wl_protocol_map[i].key); + if(proto != NULL) { + printf("%s (%p)\n", r->wayland.wl_protocol_map[i].key, r->wayland.wl_protocol_map[i].value); + } else { + printf("%s (proto is null)\n", r->wayland.wl_protocol_map[i].key, r->wayland.wl_protocol_map[i].value); + } + } + // Check that all globals we require are available if( r->wayland.compositor == NULL || @@ -433,11 +497,12 @@ static void setup_toplevel(MwLL r, int x, int y, int width, int height) { // Perform the initial commit and wait for the first configure event wl_surface_commit(r->wayland.surface); - while(wl_display_dispatch(r->wayland.display) != -1 && !r->wayland.configured) { - } + event_loop(&r->wayland); + + printf("%p\n", shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name)); // setup decorations if we can - if(WAYLAND_GET_INTERFACE(r->wayland, zxdg_decoration_manager_v1)->context != NULL) { + if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL) { zxdg_decoration_manager_v1_context_t* dec = WAYLAND_GET_INTERFACE(r->wayland, zxdg_decoration_manager_v1)->context; dec->decoration = zxdg_decoration_manager_v1_get_toplevel_decoration( @@ -537,7 +602,6 @@ static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsign } static void MwLLSetXYImpl(MwLL handle, int x, int y) { - if(handle->wayland.type != MWLL_WAYLAND_TOPLEVEL) { handle->wayland.x = x; handle->wayland.y = y; @@ -645,56 +709,7 @@ static void MwLLFreeColorImpl(MwLLColor color) { } static int MwLLPendingImpl(MwLL handle) { - enum { - DISPLAY_FD, - KEYREPEAT_FD, - CURSOR_FD - }; - struct pollfd fd; - int timeout = 1; - - if(handle->wayland.force_redraw) { - return 1; - } - - if(handle->wayland.display == NULL) { - return 0; - } - fd.fd = wl_display_get_fd(handle->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 - if(!flush_display(handle->wayland.display)) { - wl_display_cancel_read(handle->wayland.display); - - handle->wayland.toplevel->running = MwFALSE; - return 0; - } - - // Condition where no events are being sent. - if(!poll(&fd, 1, timeout)) { - wl_display_cancel_read(handle->wayland.display); - // In this case, we need to commit the surface for any animations, etc. - wl_surface_commit(handle->wayland.surface); - return 0; - } - - if(fd.revents & POLLIN) { - wl_display_read_events(handle->wayland.display); - if(wl_display_dispatch_pending(handle->wayland.display) > 0) { - } - } else { - wl_display_cancel_read(handle->wayland.display); - } - - return 1; + return event_loop(&handle->wayland); } static void MwLLNextEventImpl(MwLL handle) { -- 2.39.5 From 0fc8b099137e3479fd7336f8004f8e42cc067231 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 5 Dec 2025 14:50:04 -0700 Subject: [PATCH 14/48] wayland resize --- include/Mw/LowLevel/Wayland.h | 8 +- src/backend/wayland.c | 249 ++++++++++++++++++++++++---------- 2 files changed, 178 insertions(+), 79 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 2ed3909..786ee07 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -81,7 +81,8 @@ struct _MwLLWayland { MwBool configured; MwBool force_redraw; - MwBool do_clear; + MwBool egl_setup; + MwBool egl_do_resetup; MwU32 x, y, ww, wh; int z_index; @@ -89,15 +90,12 @@ struct _MwLLWayland { GLuint fbo; unsigned int fbo_texture; - unsigned int rbo; - MwBool egl_setup; EGLNativeWindowType egl_window_native; EGLDisplay egl_display; EGLContext egl_context; EGLSurface egl_surface; - GLuint vertex_buffer; - GLuint vertex_array; + EGLConfig egl_config; }; struct _MwLLWaylandColor { diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 77669f1..0566640 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -64,13 +64,6 @@ void xdg_wm_base_ping(void* data, xdg_wm_base_pong(xdg_wm_base, serial); }; -static wayland_protocol_t* wl_shm_setup(MwU32 name, struct _MwLLWayland* wayland) { - wayland->shm = wl_registry_bind(wayland->registry, name, &wl_shm_interface, 1); - return NULL; -} -// static void buffer_setup(struct _MwLLWayland* wayland) { -// } - static wayland_protocol_t* wl_seat_setup(MwU32 name, struct _MwLLWayland* wayland) { wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); proto->listener = malloc(sizeof(struct wl_seat_listener)); @@ -143,7 +136,6 @@ static MwBool egl_setup(MwLL self, int width, int height) { EGLint minorVersion; EGLContext context; EGLSurface surface; - EGLConfig config; EGLint fbAttribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, @@ -178,7 +170,7 @@ static MwBool egl_setup(MwLL self, int width, int height) { } // Choose config - if((eglChooseConfig(display, fbAttribs, &config, 1, &numConfigs) != EGL_TRUE) || (numConfigs != 1)) { + if((eglChooseConfig(display, fbAttribs, &self->wayland.egl_config, 1, &numConfigs) != EGL_TRUE) || (numConfigs != 1)) { printf("ERROR: eglChooseConfig, %0X\n", eglGetError()); return MwFALSE; } @@ -191,7 +183,7 @@ static MwBool egl_setup(MwLL self, int width, int height) { } // Create a surface - surface = eglCreateWindowSurface(display, config, self->wayland.egl_window_native, NULL); + surface = eglCreateWindowSurface(display, self->wayland.egl_config, self->wayland.egl_window_native, NULL); if(surface == EGL_NO_SURFACE) { printf("ERROR: eglCreateWindowSurface, %0X\n", eglGetError()); return MwFALSE; @@ -200,7 +192,7 @@ static MwBool egl_setup(MwLL self, int width, int height) { eglBindAPI(EGL_OPENGL_API); // Create a GL context - context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs); + context = eglCreateContext(display, self->wayland.egl_config, EGL_NO_CONTEXT, contextAttribs); if(context == EGL_NO_CONTEXT) { printf("ERROR: eglCreateContext, %0X\n", eglGetError()); return MwFALSE; @@ -226,24 +218,15 @@ static MwBool egl_setup(MwLL self, int width, int height) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); glBindTexture(GL_TEXTURE_2D, 0); - glGenRenderbuffers(1, &self->wayland.rbo); - // glBindRenderbuffer(GL_RENDERBUFFER, self->wayland.rbo)); - // glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 768, 1024); - // glBindRenderbuffer(GL_RENDERBUFFER, 0); - glGenFramebuffers(1, &self->wayland.fbo); glBindFramebuffer(GL_FRAMEBUFFER_BINDING, self->wayland.fbo); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self->wayland.fbo_texture, 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, self->wayland.rbo); - if((err = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE) { printf("Error binding framebuffer: %0X\n", err); return MwFALSE; @@ -263,6 +246,66 @@ static MwBool egl_setup(MwLL self, int width, int height) { return MwTRUE; } +static void egl_resetup(MwLL handle) { + int err; + + if(!handle->wayland.egl_do_resetup) { + return; + } + + if(!eglMakeCurrent(handle->wayland.egl_display, 0, 0, handle->wayland.egl_context)) { + printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); + return; + } + + if(!eglDestroySurface(handle->wayland.egl_display, handle->wayland.egl_surface)) { + printf("ERROR: eglDestroySurface, %0X\n", eglGetError()); + return; + }; + + handle->wayland.egl_surface = eglCreateWindowSurface(handle->wayland.egl_display, handle->wayland.egl_config, handle->wayland.egl_window_native, NULL); + if(handle->wayland.egl_surface == EGL_NO_SURFACE) { + printf("ERROR: eglCreateWindowSurface, %0X\n", eglGetError()); + return; + } + + if(!eglMakeCurrent(handle->wayland.egl_display, handle->wayland.egl_surface, handle->wayland.egl_surface, handle->wayland.egl_context)) { + printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); + return; + } + + glDeleteTextures(1, &handle->wayland.fbo_texture); + glGenTextures(1, &handle->wayland.fbo_texture); + glBindTexture(GL_TEXTURE_2D, handle->wayland.fbo_texture); + + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, handle->wayland.ww, handle->wayland.wh, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + + glGenFramebuffers(1, &handle->wayland.fbo); + glBindFramebuffer(GL_FRAMEBUFFER_BINDING, handle->wayland.fbo); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, handle->wayland.fbo_texture, 0); + + if((err = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE) { + printf("Error binding framebuffer: %0X\n", err); + return; + } + + glBindFramebuffer(GL_FRAMEBUFFER_BINDING, 0); + + glBindTexture(GL_TEXTURE_2D, 0); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, handle->wayland.ww, handle->wayland.wh, 0, -1, 1); + glViewport(0, 0, handle->wayland.ww, handle->wayland.wh); + + handle->wayland.egl_do_resetup = MwFALSE; +} + static void xdg_toplevel_configure(void* data, struct xdg_toplevel* xdg_toplevel, MwI32 width, MwI32 height, @@ -284,26 +327,12 @@ static void xdg_toplevel_configure(void* data, if(!self->wayland.egl_setup) { self->wayland.egl_setup = egl_setup(self, width, height); MwLLForceRender(self); - } else { - wl_egl_window_resize(self->wayland.egl_window_native, width, height, 0, 0); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, width, height, 0, -1, 1); - self->wayland.do_clear = MwTRUE; - - // glDeleteTextures(1, &self->wayland.fbo_texture); - // glGenTextures(1, &self->wayland.fbo_texture); - // glBindTexture(GL_TEXTURE_2D, self->wayland.fbo_texture); - - // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); - - // glBindTexture(GL_TEXTURE_2D, 0); } + wl_egl_window_resize(self->wayland.egl_window_native, width, height, 0, 0); + self->wayland.egl_do_resetup = MwTRUE; + egl_resetup(self); + return; }; @@ -416,7 +445,6 @@ static void setup_callbacks(struct _MwLLWayland* wayland) { wayland->wl_protocol_setup_map = NULL; wayland->wl_protocol_map = NULL; - WL_INTERFACE(wl_shm); WL_INTERFACE(wl_compositor); WL_INTERFACE(wl_subcompositor); if(wayland->type == MWLL_WAYLAND_TOPLEVEL) { @@ -429,8 +457,9 @@ static void setup_callbacks(struct _MwLLWayland* wayland) { #undef WL_INTERFACE -static void setup_toplevel(MwLL r, int x, int y, int width, int height) { - int i; +static void setup_toplevel(MwLL r, int x, int y) { + int i; + struct wl_region* region; r->wayland.type = MWLL_WAYLAND_TOPLEVEL; r->wayland.toplevel = malloc(sizeof(struct _MwLLWaylandTopLevel)); @@ -484,11 +513,9 @@ static void setup_toplevel(MwLL r, int x, int y, int width, int height) { r->wayland.toplevel->xdg_top_level = xdg_surface_get_toplevel(r->wayland.toplevel->xdg_surface); // setup mandatory listeners - r->wayland.toplevel->xdg_surface_listener.configure = xdg_surface_configure; r->wayland.toplevel->xdg_toplevel_listener.configure = xdg_toplevel_configure; r->wayland.toplevel->xdg_toplevel_listener.close = xdg_toplevel_close; - xdg_surface_add_listener(r->wayland.toplevel->xdg_surface, &r->wayland.toplevel->xdg_surface_listener, r); xdg_toplevel_add_listener(r->wayland.toplevel->xdg_top_level, &r->wayland.toplevel->xdg_toplevel_listener, r); @@ -496,8 +523,12 @@ static void setup_toplevel(MwLL r, int x, int y, int width, int height) { xdg_toplevel_set_app_id(r->wayland.toplevel->xdg_top_level, "MilskoWaylandApp"); // Perform the initial commit and wait for the first configure event + region = wl_compositor_create_region(r->wayland.compositor); + wl_region_add(region, 0, 0, r->wayland.ww, r->wayland.wh); + wl_surface_set_opaque_region(r->wayland.surface, region); wl_surface_commit(r->wayland.surface); event_loop(&r->wayland); + wl_region_destroy(region); printf("%p\n", shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name)); @@ -516,15 +547,19 @@ static void setup_toplevel(MwLL r, int x, int y, int width, int height) { // buffer_setup(&r->wayland); - wl_surface_commit(r->wayland.surface); - // glGenBuffers(1, &vertex_buffer); } -static void setup_subsurface(MwLL parent, MwLL r, int x, int y, int width, int height) { +static void setup_subsurface(MwLL parent, MwLL r, int x, int y) { struct wl_compositor* compositor = parent->wayland.compositor; struct wl_subcompositor* subcompositor = parent->wayland.subcompositor; struct wl_surface* parent_surface = parent->wayland.surface; + MwLL topmost_parent = parent; + struct wl_region* region; + + while(topmost_parent->wayland.type != MWLL_WAYLAND_TOPLEVEL) { + topmost_parent = topmost_parent->wayland.parent; + } r->wayland.type = MWLL_WAYLAND_SUBSURFACE; @@ -532,6 +567,13 @@ static void setup_subsurface(MwLL parent, MwLL r, int x, int y, int width, int h r->wayland.surface = wl_compositor_create_surface(compositor); + region = wl_compositor_create_region(compositor); + wl_region_add(region, 0, 0, r->wayland.ww, r->wayland.wh); + wl_surface_set_opaque_region(r->wayland.surface, region); + wl_surface_commit(r->wayland.surface); + event_loop(&r->wayland); + wl_region_destroy(region); + r->wayland.subsurface = wl_subcompositor_get_subsurface(subcompositor, r->wayland.surface, parent_surface); wl_subsurface_set_position(r->wayland.subsurface, x, y); @@ -540,8 +582,8 @@ static void setup_subsurface(MwLL parent, MwLL r, int x, int y, int width, int h setup_callbacks(&r->wayland); - r->wayland.registry = wl_display_get_registry(parent->wayland.display); - r->wayland.display = parent->wayland.display; + r->wayland.registry = wl_display_get_registry(topmost_parent->wayland.display); + r->wayland.display = topmost_parent->wayland.display; wl_registry_add_listener(r->wayland.registry, &r->wayland.registry_listener, r); if(wl_display_roundtrip(r->wayland.display) == -1) { @@ -554,13 +596,24 @@ static void setup_subsurface(MwLL parent, MwLL r, int x, int y, int width, int h r->wayland.configured = MwTRUE; - r->wayland.egl_context = parent->wayland.egl_context; - r->wayland.egl_display = parent->wayland.egl_display; - r->wayland.egl_surface = parent->wayland.egl_surface; - r->wayland.fbo = parent->wayland.fbo; - r->wayland.fbo_texture = parent->wayland.fbo_texture; - r->wayland.rbo = parent->wayland.rbo; + r->wayland.egl_context = topmost_parent->wayland.egl_context; + r->wayland.egl_display = topmost_parent->wayland.egl_display; + r->wayland.egl_surface = topmost_parent->wayland.egl_surface; + r->wayland.fbo = topmost_parent->wayland.fbo; + r->wayland.fbo_texture = topmost_parent->wayland.fbo_texture; } + +static void framebuffer_action_begin(MwLL handle) { + glBindTexture(GL_TEXTURE_2D, 0); + glBindFramebuffer(GL_FRAMEBUFFER, handle->wayland.fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, handle->wayland.fbo_texture, 0); +} + +static void framebuffer_action_end(MwLL handle) { + glFinish(); + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { MwLL r; r = malloc(sizeof(*r)); @@ -576,13 +629,12 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r->wayland.parent = parent; r->wayland.force_redraw = MwFALSE; - r->wayland.do_clear = MwFALSE; r->common.success = MwTRUE; if(parent == NULL) { - setup_toplevel(r, x, y, width, height); + setup_toplevel(r, x, y); } else { - setup_subsurface(parent, r, x, y, width, height); + setup_subsurface(parent, r, x, y); } return r; @@ -611,6 +663,10 @@ static void MwLLSetXYImpl(MwLL handle, int x, int y) { } static void MwLLSetWHImpl(MwLL handle, int w, int h) { + /* Prevent an integer underflow when the w/h is too low */ + if(w < 10 || h < 10) { + return; + } handle->wayland.ww = w; handle->wayland.wh = h; @@ -621,29 +677,74 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { } static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { - int i; + int i, n; + float maxX = 0, maxY = 0; + float centerX, centerY; - glBindTexture(GL_TEXTURE_2D, 0); - glBindFramebuffer(GL_FRAMEBUFFER, handle->wayland.fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, handle->wayland.fbo_texture, 0); + if(points_count > 3) { + /* To avoid having to do a real triangulation algorithim: + 1.) loop through the points once to determine the bounds of the polygon + 2.) calculate the center of the polygon - if(points_count == 3) { - glBegin(GL_TRIANGLES); - } else if(points_count == 4) { - glBegin(GL_QUADS); - } else { - glBegin(GL_QUAD_STRIP); + */ + for(i = 0; i < points_count; i++) { + float x = round(handle->wayland.x) + round(points[i].x); + float y = round(handle->wayland.y) + round(points[i].y); + if(x >= maxX) { + maxX = x; + } + if(y >= maxY) { + maxY = y; + } + } } + centerX = (handle->wayland.x + maxX / 2); + centerY = (handle->wayland.y + maxY / 2); + /* Efficient? No. But at the end of the day it's still not that many polygons, and if a computer can't handle 12 polygons over 6 then it should not be using Wayland anyways */ + + framebuffer_action_begin(handle); + glBegin(GL_TRIANGLE_FAN); for(i = 0; i < points_count; i++) { + float x = round(handle->wayland.x) + round(points[i].x); + float y = round(handle->wayland.y) + round(points[i].y); + glColor3f(color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); - glVertex2f( - ceil(handle->wayland.x) + ceil(points[i].x), - ceil(handle->wayland.y) + ceil(points[i].y)); + + /* If we have a polygon that's covering the whole screen, we want to do glClear + */ + if(x == 0 && y == 0) { + /* + We determine this by checking if all of the points are at the edge of the screen (and if there's more then 6 points). + Not a pretty solution, but unless the user does something weird like draw a triangle over itself twice, I'm pretty sure this is effective. + */ + if(points_count >= 6) { + MwBool doClear = MwTRUE; + for(n = 0; n < points_count; n++) { + if((points[n].x >= (handle->wayland.ww) - 1 || points[n].x <= 1) && (points[n].y >= (handle->wayland.wh) - 1 || points[n].y <= 1)) { + } else { + doClear = MwFALSE; + break; + } + } + if(doClear) { + glEnd(); + glClear(GL_COLOR_BUFFER_BIT); + glClearColor(color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0, 1); + glBegin(GL_TRIANGLE_FAN); + } + } + } + + glVertex2f(x, y); + if(points_count > 3) { + glVertex2f(maxX, maxY); + glVertex2f(x, y); + } } glEnd(); - glFinish(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + + framebuffer_action_end(handle); } static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { @@ -663,8 +764,8 @@ static void MwLLEndDrawImpl(MwLL handle) { } glBindTexture(GL_TEXTURE_2D, handle->wayland.fbo_texture); - glClear(GL_COLOR_BUFFER_BIT); - glClearColor(0, 0, 0, 1); + // glClear(GL_COLOR_BUFFER_BIT); + // glClearColor(0, 0, 0, 1); glColor3f(1.0, 1.0, 1.0); -- 2.39.5 From 495ea93c7466662b33a02b1420b97d7f596c08fa Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 5 Dec 2025 15:18:21 -0700 Subject: [PATCH 15/48] working pixmap --- include/Mw/LowLevel/Wayland.h | 1 + src/backend/wayland.c | 51 ++++++++++++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 786ee07..ed7dcaf 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -104,6 +104,7 @@ struct _MwLLWaylandColor { struct _MwLLWaylandPixmap { struct _MwLLCommonPixmap common; + GLuint texture; }; #endif diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 0566640..043530d 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -238,6 +238,8 @@ static MwBool egl_setup(MwLL self, int width, int height) { glLoadIdentity(); glOrtho(0, width, height, 0, -1, 1); glEnable(GL_TEXTURE_2D); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); self->wayland.egl_display = display; self->wayland.egl_surface = surface; @@ -513,9 +515,12 @@ static void setup_toplevel(MwLL r, int x, int y) { r->wayland.toplevel->xdg_top_level = xdg_surface_get_toplevel(r->wayland.toplevel->xdg_surface); // setup mandatory listeners + r->wayland.toplevel->xdg_surface_listener.configure = xdg_surface_configure; + r->wayland.toplevel->xdg_toplevel_listener.configure = xdg_toplevel_configure; r->wayland.toplevel->xdg_toplevel_listener.close = xdg_toplevel_close; + xdg_surface_add_listener(r->wayland.toplevel->xdg_surface, &r->wayland.toplevel->xdg_surface_listener, r); xdg_toplevel_add_listener(r->wayland.toplevel->xdg_top_level, &r->wayland.toplevel->xdg_toplevel_listener, r); @@ -604,7 +609,6 @@ static void setup_subsurface(MwLL parent, MwLL r, int x, int y) { } static void framebuffer_action_begin(MwLL handle) { - glBindTexture(GL_TEXTURE_2D, 0); glBindFramebuffer(GL_FRAMEBUFFER, handle->wayland.fbo); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, handle->wayland.fbo_texture, 0); } @@ -836,20 +840,59 @@ static void MwLLSetTitleImpl(MwLL handle, const char* title) { static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, int width, int height) { MwLLPixmap r = malloc(sizeof(*r)); - r->common.width = width; - r->common.height = height; - r->common.raw = data; + r->common.width = width; + r->common.height = height; + r->common.raw = data; + r->wayland.texture = 0; + + glGenTextures(1, &r->wayland.texture); + + glBindTexture(GL_TEXTURE_2D, r->wayland.texture); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glBindTexture(GL_TEXTURE_2D, 0); + + MwLLPixmapUpdate(r); + return r; } static void MwLLPixmapUpdateImpl(MwLLPixmap r) { + glBindTexture(GL_TEXTURE_2D, r->wayland.texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, r->common.width, r->common.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, r->common.raw); + glBindTexture(GL_TEXTURE_2D, 0); } static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { + glDeleteTextures(1, &pixmap->wayland.texture); free(pixmap); } static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { + int x, y; + glColor3f(1.0, 1.0, 1.0); + + x = handle->wayland.x + rect->x; + y = handle->wayland.y + rect->y; + + glBindTexture(GL_TEXTURE_2D, pixmap->wayland.texture); + glActiveTexture(pixmap->wayland.texture); + + framebuffer_action_begin(handle); + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0); + glVertex2f(x, y); + glTexCoord2f(1, 0); + glVertex2f(x + rect->width, y); + glTexCoord2f(1, 1); + glVertex2f(x + rect->width, y + rect->height); + glTexCoord2f(0.0f, 1); + glVertex2f(x, y + rect->height); + glEnd(); + glFinish(); + framebuffer_action_end(handle); } static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { -- 2.39.5 From 39533b3fec614bb1179960a7381e32f2f8e9022f Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 5 Dec 2025 17:16:08 -0700 Subject: [PATCH 16/48] swap buffers in draw handler instead --- .gitignore | 1 - examples/basic/checkbox.c | 6 ++-- include/Mw/LowLevel.h | 1 + include/Mw/LowLevel/Wayland.h | 1 + src/backend/wayland.c | 58 +++++++++++++++++++---------------- src/core.c | 10 ++++-- 6 files changed, 45 insertions(+), 32 deletions(-) diff --git a/.gitignore b/.gitignore index b022af0..a5e12aa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ *.o *.so *.dll -examples/* examples/*.exe examples/*/* !examples/*/*.c diff --git a/examples/basic/checkbox.c b/examples/basic/checkbox.c index 972cb2c..546b7df 100644 --- a/examples/basic/checkbox.c +++ b/examples/basic/checkbox.c @@ -5,10 +5,10 @@ int main() { MwWidget window; MwLibraryInit(); - + window = MwVaCreateWidget(MwWindowClass, "test", NULL, MwDEFAULT, MwDEFAULT, 8 + 16 + 8 + 16 * 10 + 8, 8 + 16 + 8 + 16 + 8, - MwNtitle, "checkbox", - NULL); + MwNtitle, "checkbox", + NULL); MwVaCreateWidget(MwCheckBoxClass, "cb1", window, 8, 8, 16, 16, NULL); diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index 2be5b26..e8721dd 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -35,6 +35,7 @@ struct _MwLLCommon { int copy_buffer; int type; int success; + int do_redraw; MwLLHandler handler; }; diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index ed7dcaf..ba042a6 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -82,6 +82,7 @@ struct _MwLLWayland { MwBool configured; MwBool force_redraw; MwBool egl_setup; + MwBool drawn_once; MwBool egl_do_resetup; MwU32 x, y, ww, wh; int z_index; diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 043530d..e4bd5e3 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -315,13 +315,17 @@ static void xdg_toplevel_configure(void* data, MwLL self = data; PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)eglGetProcAddress("glFramebufferTexture2D"); - if(width == 0 && height == 0) { + if(width == 0 || height == 0) { width = self->wayland.ww; height = self->wayland.wh; + // if it's still 0 then bail + if(width == 0 || height == 0) { + return; + } } self->wayland.ww = width; self->wayland.wh = height; - xdg_surface_set_window_geometry(self->wayland.toplevel->xdg_surface, self->wayland.x, self->wayland.y, self->wayland.ww, self->wayland.wh); + xdg_surface_set_window_geometry(self->wayland.toplevel->xdg_surface, 0, 0, self->wayland.ww, self->wayland.wh); MwLLSetWH(self, width, height); MwLLDispatch(self, resize, NULL); @@ -369,18 +373,15 @@ static void xdg_surface_configure( self->wayland.configured = MwTRUE; } -static int event_loop(struct _MwLLWayland* wayland) { +static int event_loop(MwLL handle) { enum { DISPLAY_FD, KEYREPEAT_FD, CURSOR_FD }; - struct pollfd fd; - int timeout = 100; - - if(wayland->force_redraw) { - return 1; - } + struct pollfd fd; + int timeout = 100; + struct _MwLLWayland* wayland = &handle->wayland; if(wayland->display == NULL) { return 0; @@ -388,12 +389,6 @@ static int event_loop(struct _MwLLWayland* wayland) { fd.fd = wl_display_get_fd(wayland->display); fd.events = POLLIN; - while(wl_display_prepare_read(wayland->display) != 0) { - if(wl_display_dispatch_pending(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) { @@ -433,8 +428,11 @@ static int event_loop(struct _MwLLWayland* wayland) { if(wl_display_dispatch_pending(wayland->display) > 0) { } } else { - wl_display_cancel_read(wayland->display); + if(wl_display_dispatch_pending(wayland->display) == 0) { + MwLLDispatch(handle, draw, NULL); + } } + return 0; } @@ -532,11 +530,9 @@ static void setup_toplevel(MwLL r, int x, int y) { wl_region_add(region, 0, 0, r->wayland.ww, r->wayland.wh); wl_surface_set_opaque_region(r->wayland.surface, region); wl_surface_commit(r->wayland.surface); - event_loop(&r->wayland); + event_loop(r); wl_region_destroy(region); - printf("%p\n", shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name)); - // setup decorations if we can if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL) { zxdg_decoration_manager_v1_context_t* dec = WAYLAND_GET_INTERFACE(r->wayland, zxdg_decoration_manager_v1)->context; @@ -576,7 +572,7 @@ static void setup_subsurface(MwLL parent, MwLL r, int x, int y) { wl_region_add(region, 0, 0, r->wayland.ww, r->wayland.wh); wl_surface_set_opaque_region(r->wayland.surface, region); wl_surface_commit(r->wayland.surface); - event_loop(&r->wayland); + event_loop(r); wl_region_destroy(region); r->wayland.subsurface = wl_subcompositor_get_subsurface(subcompositor, r->wayland.surface, parent_surface); @@ -628,13 +624,18 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { if(width == 0) width = 1; if(height == 0) height = 1; - r->wayland.ww = width; - r->wayland.wh = height; + r->wayland.ww = width; + r->wayland.wh = height; + printf("%d %d\n", x, y); + r->wayland.parent = parent; r->wayland.force_redraw = MwFALSE; r->common.success = MwTRUE; + r->wayland.drawn_once = MwFALSE; + r->wayland.x = x; + r->wayland.y = y; if(parent == NULL) { setup_toplevel(r, x, y); } else { @@ -668,14 +669,16 @@ static void MwLLSetXYImpl(MwLL handle, int x, int y) { static void MwLLSetWHImpl(MwLL handle, int w, int h) { /* Prevent an integer underflow when the w/h is too low */ - if(w < 10 || h < 10) { + if((w < 10 || h < 10)) { + handle->wayland.ww = 10; + handle->wayland.wh = 10; return; } handle->wayland.ww = w; handle->wayland.wh = h; if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { - xdg_surface_set_window_geometry(handle->wayland.toplevel->xdg_surface, handle->wayland.x, handle->wayland.y, handle->wayland.ww, handle->wayland.wh); + xdg_surface_set_window_geometry(handle->wayland.toplevel->xdg_surface, 0, 0, handle->wayland.ww, handle->wayland.wh); } else { } } @@ -769,7 +772,7 @@ static void MwLLEndDrawImpl(MwLL handle) { glBindTexture(GL_TEXTURE_2D, handle->wayland.fbo_texture); // glClear(GL_COLOR_BUFFER_BIT); - // glClearColor(0, 0, 0, 1); + // glClearColor(1.0, 0, 0, 1); glColor3f(1.0, 1.0, 1.0); @@ -790,6 +793,7 @@ static void MwLLEndDrawImpl(MwLL handle) { printf("error swapping buffers! %0X\n", eglGetError()); } else { wl_surface_commit(handle->wayland.surface); + handle->wayland.drawn_once = MwTRUE; } } @@ -814,7 +818,9 @@ static void MwLLFreeColorImpl(MwLLColor color) { } static int MwLLPendingImpl(MwLL handle) { - return event_loop(&handle->wayland); + if(wl_display_dispatch_pending(handle->wayland.display) == 0) { + } + return event_loop(handle) || handle->wayland.force_redraw; } static void MwLLNextEventImpl(MwLL handle) { diff --git a/src/core.c b/src/core.c index 401600d..4df7fe7 100644 --- a/src/core.c +++ b/src/core.c @@ -7,6 +7,7 @@ static void lldrawhandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; + int ind; (void)data; @@ -14,6 +15,13 @@ static void lldrawhandler(MwLL handle, void* data) { MwDispatch(h, draw); if(h->draw_inject != NULL) h->draw_inject(h); MwDispatchUserHandler(h, MwNdrawHandler, NULL); + + handle->common.do_redraw = MwTRUE; + if(h->parent == NULL) { + MwLLEndDraw(h->lowlevel); + } else if(h->parent->lowlevel == NULL) { + MwLLEndDraw(h->lowlevel); + } } static void lluphandler(MwLL handle, void* data) { @@ -334,8 +342,6 @@ void MwLoop(MwWidget handle) { } if(v != 0) break; - MwLLEndDraw(handle->lowlevel); - for(i = 0; i < arrlen(handle->tick_list); i++) { MwDispatch(handle->tick_list[i], tick); MwDispatchUserHandler(handle->tick_list[i], MwNtickHandler, NULL); -- 2.39.5 From c1c969859cf8840c22aa72e6a17d071aa93d2934 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 5 Dec 2025 18:53:15 -0700 Subject: [PATCH 17/48] undo the ugly clear color hack thing --- src/backend/wayland.c | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index e4bd5e3..15f9724 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -718,31 +718,6 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL glColor3f(color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); - /* If we have a polygon that's covering the whole screen, we want to do glClear - */ - if(x == 0 && y == 0) { - /* - We determine this by checking if all of the points are at the edge of the screen (and if there's more then 6 points). - Not a pretty solution, but unless the user does something weird like draw a triangle over itself twice, I'm pretty sure this is effective. - */ - if(points_count >= 6) { - MwBool doClear = MwTRUE; - for(n = 0; n < points_count; n++) { - if((points[n].x >= (handle->wayland.ww) - 1 || points[n].x <= 1) && (points[n].y >= (handle->wayland.wh) - 1 || points[n].y <= 1)) { - } else { - doClear = MwFALSE; - break; - } - } - if(doClear) { - glEnd(); - glClear(GL_COLOR_BUFFER_BIT); - glClearColor(color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0, 1); - glBegin(GL_TRIANGLE_FAN); - } - } - } - glVertex2f(x, y); if(points_count > 3) { glVertex2f(maxX, maxY); -- 2.39.5 From 31e419a134b7a026552c09d10ee239d3d1635682 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 5 Dec 2025 18:53:49 -0700 Subject: [PATCH 18/48] context doesn't need to be recreated on resize --- src/backend/wayland.c | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 15f9724..b588f04 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -251,31 +251,6 @@ static MwBool egl_setup(MwLL self, int width, int height) { static void egl_resetup(MwLL handle) { int err; - if(!handle->wayland.egl_do_resetup) { - return; - } - - if(!eglMakeCurrent(handle->wayland.egl_display, 0, 0, handle->wayland.egl_context)) { - printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); - return; - } - - if(!eglDestroySurface(handle->wayland.egl_display, handle->wayland.egl_surface)) { - printf("ERROR: eglDestroySurface, %0X\n", eglGetError()); - return; - }; - - handle->wayland.egl_surface = eglCreateWindowSurface(handle->wayland.egl_display, handle->wayland.egl_config, handle->wayland.egl_window_native, NULL); - if(handle->wayland.egl_surface == EGL_NO_SURFACE) { - printf("ERROR: eglCreateWindowSurface, %0X\n", eglGetError()); - return; - } - - if(!eglMakeCurrent(handle->wayland.egl_display, handle->wayland.egl_surface, handle->wayland.egl_surface, handle->wayland.egl_context)) { - printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); - return; - } - glDeleteTextures(1, &handle->wayland.fbo_texture); glGenTextures(1, &handle->wayland.fbo_texture); glBindTexture(GL_TEXTURE_2D, handle->wayland.fbo_texture); -- 2.39.5 From ba6466a642a37eab25a4bce892161a35f8f323ae Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 5 Dec 2025 19:18:11 -0700 Subject: [PATCH 19/48] everything gets drawn --- include/Mw/LowLevel/Wayland.h | 2 ++ src/backend/wayland.c | 44 ++++++++++++++++++++--------------- src/core.c | 8 +------ 3 files changed, 28 insertions(+), 26 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index ba042a6..7c4eb32 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -79,6 +79,8 @@ struct _MwLLWayland { struct wl_shm* shm; struct wl_registry_listener registry_listener; + MwLL* subwidgets; + MwBool configured; MwBool force_redraw; MwBool egl_setup; diff --git a/src/backend/wayland.c b/src/backend/wayland.c index b588f04..99b9fd9 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -308,12 +308,12 @@ static void xdg_toplevel_configure(void* data, if(!self->wayland.egl_setup) { self->wayland.egl_setup = egl_setup(self, width, height); MwLLForceRender(self); + } else { + wl_egl_window_resize(self->wayland.egl_window_native, width, height, 0, 0); + self->wayland.egl_do_resetup = MwTRUE; + egl_resetup(self); } - wl_egl_window_resize(self->wayland.egl_window_native, width, height, 0, 0); - self->wayland.egl_do_resetup = MwTRUE; - egl_resetup(self); - return; }; @@ -355,8 +355,9 @@ static int event_loop(MwLL handle) { CURSOR_FD }; struct pollfd fd; - int timeout = 100; - struct _MwLLWayland* wayland = &handle->wayland; + int timeout = 100; + struct _MwLLWayland* wayland = &handle->wayland; + MwLL topmost_parent = handle->wayland.parent; if(wayland->display == NULL) { return 0; @@ -404,7 +405,11 @@ static int event_loop(MwLL handle) { } } else { if(wl_display_dispatch_pending(wayland->display) == 0) { + int i; MwLLDispatch(handle, draw, NULL); + for(i = 0; i < arrlen(handle->wayland.subwidgets); i++) { + MwLLDispatch(handle->wayland.subwidgets[i], draw, NULL); + } } } @@ -577,6 +582,8 @@ static void setup_subsurface(MwLL parent, MwLL r, int x, int y) { r->wayland.egl_surface = topmost_parent->wayland.egl_surface; r->wayland.fbo = topmost_parent->wayland.fbo; r->wayland.fbo_texture = topmost_parent->wayland.fbo_texture; + + arrpush(parent->wayland.subwidgets, r); } static void framebuffer_action_begin(MwLL handle) { @@ -599,8 +606,18 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { if(width == 0) width = 1; if(height == 0) height = 1; + if(x == MwDEFAULT) { + x = 0; + } + if(y == MwDEFAULT) { + y = 0; + } + r->wayland.ww = width; r->wayland.wh = height; + r->wayland.x = x; + r->wayland.y = y; + printf("%d %d\n", x, y); r->wayland.parent = parent; @@ -609,9 +626,8 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r->common.success = MwTRUE; r->wayland.drawn_once = MwFALSE; - r->wayland.x = x; - r->wayland.y = y; if(parent == NULL) { + printf("toplevel %d %d\n", x, y); setup_toplevel(r, x, y); } else { setup_subsurface(parent, r, x, y); @@ -774,17 +790,7 @@ static int MwLLPendingImpl(MwLL handle) { } static void MwLLNextEventImpl(MwLL handle) { - MwBool render = handle->wayland.force_redraw; - - if(render) { - int x, y; - unsigned int w, h; - - MwLLGetXYWH(handle, &x, &y, &w, &h); - - MwLLDispatch(handle, draw, NULL); - handle->wayland.force_redraw = MwFALSE; - } + // MwBool render = handle->wayland.force_redraw; } static void MwLLSetTitleImpl(MwLL handle, const char* title) { diff --git a/src/core.c b/src/core.c index 4df7fe7..9d9337e 100644 --- a/src/core.c +++ b/src/core.c @@ -15,13 +15,6 @@ static void lldrawhandler(MwLL handle, void* data) { MwDispatch(h, draw); if(h->draw_inject != NULL) h->draw_inject(h); MwDispatchUserHandler(h, MwNdrawHandler, NULL); - - handle->common.do_redraw = MwTRUE; - if(h->parent == NULL) { - MwLLEndDraw(h->lowlevel); - } else if(h->parent->lowlevel == NULL) { - MwLLEndDraw(h->lowlevel); - } } static void lluphandler(MwLL handle, void* data) { @@ -339,6 +332,7 @@ void MwLoop(MwWidget handle) { long more; while(MwPending(handle)) { if((v = MwStep(handle)) != 0) break; + MwLLEndDraw(handle->lowlevel); } if(v != 0) break; -- 2.39.5 From 620b6c7fc37aeec3d34103e47d736b0c9135c3cd Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 5 Dec 2025 19:27:49 -0700 Subject: [PATCH 20/48] revive nextevent --- src/backend/wayland.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 99b9fd9..83d0b73 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -790,7 +790,12 @@ static int MwLLPendingImpl(MwLL handle) { } static void MwLLNextEventImpl(MwLL handle) { - // MwBool render = handle->wayland.force_redraw; + MwBool render = handle->wayland.force_redraw; + + if(render) { + MwLLDispatch(handle, draw, NULL); + handle->wayland.force_redraw = MwFALSE; + } } static void MwLLSetTitleImpl(MwLL handle, const char* title) { -- 2.39.5 From d308c83fc2f009d280e22766a9424d65a6387272 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 5 Dec 2025 20:25:23 -0700 Subject: [PATCH 21/48] recursive updating --- include/Mw/LowLevel/Wayland.h | 1 - src/backend/wayland.c | 85 +++++++++++++++++++++++------------ src/core.c | 2 +- 3 files changed, 58 insertions(+), 30 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 7c4eb32..dbc9417 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -84,7 +84,6 @@ struct _MwLLWayland { MwBool configured; MwBool force_redraw; MwBool egl_setup; - MwBool drawn_once; MwBool egl_do_resetup; MwU32 x, y, ww, wh; int z_index; diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 83d0b73..e0b0e39 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include "../../external/stb_ds.h" @@ -244,7 +245,6 @@ static MwBool egl_setup(MwLL self, int width, int height) { self->wayland.egl_display = display; self->wayland.egl_surface = surface; self->wayland.egl_context = context; - printf("EGL success\n"); return MwTRUE; } @@ -283,6 +283,26 @@ static void egl_resetup(MwLL handle) { handle->wayland.egl_do_resetup = MwFALSE; } +static void recursive_draw(MwLL handle) { + int i; + if(handle->wayland.subwidgets != NULL) { + for(i = 0; i < arrlen(handle->wayland.subwidgets); i++) { + MwLLDispatch(handle->wayland.subwidgets[i], draw, NULL); + recursive_draw(handle->wayland.subwidgets[i]); + } + } +} + +static void recursive_resize(MwLL handle) { + int i; + if(handle->wayland.subwidgets != NULL) { + for(i = 0; i < arrlen(handle->wayland.subwidgets); i++) { + MwLLDispatch(handle->wayland.subwidgets[i], resize, NULL); + recursive_resize(handle->wayland.subwidgets[i]); + } + } +} + static void xdg_toplevel_configure(void* data, struct xdg_toplevel* xdg_toplevel, MwI32 width, MwI32 height, @@ -304,6 +324,7 @@ static void xdg_toplevel_configure(void* data, MwLLSetWH(self, width, height); MwLLDispatch(self, resize, NULL); + recursive_resize(self); if(!self->wayland.egl_setup) { self->wayland.egl_setup = egl_setup(self, width, height); @@ -405,11 +426,8 @@ static int event_loop(MwLL handle) { } } else { if(wl_display_dispatch_pending(wayland->display) == 0) { - int i; MwLLDispatch(handle, draw, NULL); - for(i = 0; i < arrlen(handle->wayland.subwidgets); i++) { - MwLLDispatch(handle->wayland.subwidgets[i], draw, NULL); - } + recursive_draw(handle); } } @@ -463,16 +481,6 @@ static void setup_toplevel(MwLL r, int x, int y) { return; } - printf("Found globals: \n"); - for(i = 0; i < shlen(r->wayland.wl_protocol_map); i++) { - wayland_protocol_t* proto = shget(r->wayland.wl_protocol_map, r->wayland.wl_protocol_map[i].key); - if(proto != NULL) { - printf("%s (%p)\n", r->wayland.wl_protocol_map[i].key, r->wayland.wl_protocol_map[i].value); - } else { - printf("%s (proto is null)\n", r->wayland.wl_protocol_map[i].key, r->wayland.wl_protocol_map[i].value); - } - } - // Check that all globals we require are available if( r->wayland.compositor == NULL || @@ -506,12 +514,8 @@ 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 - region = wl_compositor_create_region(r->wayland.compositor); - wl_region_add(region, 0, 0, r->wayland.ww, r->wayland.wh); - wl_surface_set_opaque_region(r->wayland.surface, region); wl_surface_commit(r->wayland.surface); event_loop(r); - wl_region_destroy(region); // setup decorations if we can if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL) { @@ -618,16 +622,13 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r->wayland.x = x; r->wayland.y = y; - printf("%d %d\n", x, y); - r->wayland.parent = parent; r->wayland.force_redraw = MwFALSE; r->common.success = MwTRUE; - r->wayland.drawn_once = MwFALSE; + r->wayland.subwidgets = NULL; if(parent == NULL) { - printf("toplevel %d %d\n", x, y); setup_toplevel(r, x, y); } else { setup_subsurface(parent, r, x, y); @@ -678,6 +679,7 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL int i, n; float maxX = 0, maxY = 0; float centerX, centerY; + int doLoopback = MwFALSE; if(points_count > 3) { /* To avoid having to do a real triangulation algorithim: @@ -702,7 +704,16 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL /* Efficient? No. But at the end of the day it's still not that many polygons, and if a computer can't handle 12 polygons over 6 then it should not be using Wayland anyways */ framebuffer_action_begin(handle); - glBegin(GL_TRIANGLE_FAN); + + if(points_count == 3) { + glBegin(GL_TRIANGLES); + } else if((points_count % 3) == 0) { + glBegin(GL_POLYGON); + } else { + glBegin(GL_TRIANGLE_FAN); + doLoopback = MwTRUE; + } + for(i = 0; i < points_count; i++) { float x = round(handle->wayland.x) + round(points[i].x); float y = round(handle->wayland.y) + round(points[i].y); @@ -710,18 +721,37 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL glColor3f(color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); glVertex2f(x, y); - if(points_count > 3) { + if(doLoopback) { glVertex2f(maxX, maxY); glVertex2f(x, y); } } glEnd(); + glColor3f(0, 0, 0); framebuffer_action_end(handle); } static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { - // + int i; + + glLineWidth(1); + + framebuffer_action_begin(handle); + glBegin(GL_LINES); + for(i = 0; i < 2; i++) { + float x = round(handle->wayland.x) + round(points[i].x); + float y = round(handle->wayland.y) + round(points[i].y); + + glColor3f(color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); + + glVertex2f(x, y); + } + + glEnd(); + glColor3f(0, 0, 0); + + framebuffer_action_end(handle); } static void MwLLEndDrawImpl(MwLL handle) { @@ -759,7 +789,6 @@ static void MwLLEndDrawImpl(MwLL handle) { printf("error swapping buffers! %0X\n", eglGetError()); } else { wl_surface_commit(handle->wayland.surface); - handle->wayland.drawn_once = MwTRUE; } } @@ -793,7 +822,7 @@ static void MwLLNextEventImpl(MwLL handle) { MwBool render = handle->wayland.force_redraw; if(render) { - MwLLDispatch(handle, draw, NULL); + recursive_draw(handle); handle->wayland.force_redraw = MwFALSE; } } diff --git a/src/core.c b/src/core.c index 9d9337e..489a6d1 100644 --- a/src/core.c +++ b/src/core.c @@ -332,8 +332,8 @@ void MwLoop(MwWidget handle) { long more; while(MwPending(handle)) { if((v = MwStep(handle)) != 0) break; - MwLLEndDraw(handle->lowlevel); } + MwLLEndDraw(handle->lowlevel); if(v != 0) break; for(i = 0; i < arrlen(handle->tick_list); i++) { -- 2.39.5 From f2c05762ae763f9b3855d7ecdea848bc654dc67e Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 5 Dec 2025 20:27:27 -0700 Subject: [PATCH 22/48] wayland: default title shouldn't mention wayland --- 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 e0b0e39..ba36212 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -510,7 +510,7 @@ static void setup_toplevel(MwLL r, int x, int y) { xdg_toplevel_add_listener(r->wayland.toplevel->xdg_top_level, &r->wayland.toplevel->xdg_toplevel_listener, r); - xdg_toplevel_set_title(r->wayland.toplevel->xdg_top_level, "Milsko Wayland App"); + xdg_toplevel_set_title(r->wayland.toplevel->xdg_top_level, "Milsko App"); xdg_toplevel_set_app_id(r->wayland.toplevel->xdg_top_level, "MilskoWaylandApp"); // Perform the initial commit and wait for the first configure event -- 2.39.5 From 71aac9987c18022aad39fc2e77ada04f41e8b773 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 5 Dec 2025 22:48:02 -0700 Subject: [PATCH 23/48] revert some leaks into other code files --- examples/basic/checkbox.c | 6 +++--- examples/basic/rotate.c | 6 +++--- include/Mw/LowLevel.h | 2 -- src/backend/wayland.c | 8 ++++---- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/examples/basic/checkbox.c b/examples/basic/checkbox.c index 546b7df..972cb2c 100644 --- a/examples/basic/checkbox.c +++ b/examples/basic/checkbox.c @@ -5,10 +5,10 @@ int main() { MwWidget window; MwLibraryInit(); - + window = MwVaCreateWidget(MwWindowClass, "test", NULL, MwDEFAULT, MwDEFAULT, 8 + 16 + 8 + 16 * 10 + 8, 8 + 16 + 8 + 16 + 8, - MwNtitle, "checkbox", - NULL); + MwNtitle, "checkbox", + NULL); MwVaCreateWidget(MwCheckBoxClass, "cb1", window, 8, 8, 16, 16, NULL); diff --git a/examples/basic/rotate.c b/examples/basic/rotate.c index 835993d..c3b85d7 100644 --- a/examples/basic/rotate.c +++ b/examples/basic/rotate.c @@ -56,13 +56,13 @@ void resize(MwWidget w, void* user, void* client) { int main() { MwWidget window; - int i; + int i; MwLibraryInit(); window = MwVaCreateWidget(MwWindowClass, "window", NULL, MwDEFAULT, MwDEFAULT, (ww = 500), (wh = 500), - MwNtitle, "rotate", - NULL); + MwNtitle, "rotate", + NULL); for(i = 0; i < (int)(sizeof(buttons) / sizeof(buttons[0])); i++) { const char* color = ""; diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index e8721dd..47f367a 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -34,8 +34,6 @@ struct _MwLLCommon { void* user; int copy_buffer; int type; - int success; - int do_redraw; MwLLHandler handler; }; diff --git a/src/backend/wayland.c b/src/backend/wayland.c index ba36212..53b4483 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -468,7 +469,7 @@ static void setup_toplevel(MwLL r, int x, int y) { r->wayland.display = wl_display_connect(NULL); if(r->wayland.display == NULL) { printf("wayland: failed to create display\n"); - r->common.success = MwFALSE; + raise(SIGTRAP); return; } @@ -477,7 +478,7 @@ static void setup_toplevel(MwLL r, int x, int y) { wl_registry_add_listener(r->wayland.registry, &r->wayland.registry_listener, r); if(wl_display_roundtrip(r->wayland.display) == -1) { printf("roundtrip failed\n"); - r->common.success = MwFALSE; + raise(SIGTRAP); return; } @@ -488,7 +489,7 @@ static void setup_toplevel(MwLL r, int x, int y) { WAYLAND_GET_INTERFACE(r->wayland, wl_seat)->context == NULL) { printf("no wl_shm, wl_compositor, wl_seat, or xdg_wm_base support\n"); - r->common.success = MwFALSE; + raise(SIGTRAP); return; } @@ -625,7 +626,6 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r->wayland.parent = parent; r->wayland.force_redraw = MwFALSE; - r->common.success = MwTRUE; r->wayland.subwidgets = NULL; if(parent == NULL) { -- 2.39.5 From 320c3c2b2634edfba79d02b0e06a96562dea6592 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 5 Dec 2025 22:48:59 -0700 Subject: [PATCH 24/48] correct accidental paste in Core.h --- include/Mw/Core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/Mw/Core.h b/include/Mw/Core.h index 98812a5..28df4d4 100644 --- a/include/Mw/Core.h +++ b/include/Mw/Core.h @@ -128,7 +128,7 @@ MWDECL void MwLoop(MwWidget handle); */ MWDECL int MwStep(MwWidget handle); -/*!MwStep( +/*! * @brief Check if any event is pending * @param handle Widget * @return `1` if any event is pending -- 2.39.5 From cbeb239cb759aafb984d24a3e82e0af1ab0d1743 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 5 Dec 2025 22:58:37 -0700 Subject: [PATCH 25/48] merge push --- test | 1 + 1 file changed, 1 insertion(+) create mode 100644 test diff --git a/test b/test new file mode 100644 index 0000000..b478595 --- /dev/null +++ b/test @@ -0,0 +1 @@ +s -- 2.39.5 From 7836b0abcd4e4facaba71f09e984dd489cd1e15e Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 5 Dec 2025 23:07:50 -0700 Subject: [PATCH 26/48] remove accidental test file --- test | 1 - 1 file changed, 1 deletion(-) delete mode 100644 test diff --git a/test b/test deleted file mode 100644 index b478595..0000000 --- a/test +++ /dev/null @@ -1 +0,0 @@ -s -- 2.39.5 From 6433322cda399a2cf0dfe7edc19e323bb2027092 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 7 Dec 2025 17:25:16 -0700 Subject: [PATCH 27/48] wayland: pointer listener --- include/Mw/LowLevel/Wayland.h | 19 +++--- src/backend/wayland.c | 105 ++++++++++++++++++++++++++++------ src/core.c | 5 +- 3 files changed, 104 insertions(+), 25 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index dbc9417..75f208b 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -1,4 +1,3 @@ -/* $Id$ */ /*! * @file Mw/LowLevel/Wayland.h * @brief Wayland Backend @@ -12,6 +11,7 @@ #include #include +#include #include #include #include @@ -44,7 +44,6 @@ struct _MwLLWaylandTopLevel { struct xkb_context* xkb_context; - MwBool running; MwBool compositor_created; MwBool xdg_wm_base_created; MwBool xdg_surface_created; @@ -79,14 +78,18 @@ struct _MwLLWayland { struct wl_shm* shm; struct wl_registry_listener registry_listener; + struct wl_pointer* pointer; + MwLL* subwidgets; - MwBool configured; - MwBool force_redraw; - MwBool egl_setup; - MwBool egl_do_resetup; - MwU32 x, y, ww, wh; - int z_index; + MwBool configured; + MwBool force_redraw; + MwBool egl_setup; + MwBool egl_do_resetup; + MwU32 x, y, ww, wh; + MwPoint cur_mouse_pos; + + int last_serial; MwLL parent; diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 53b4483..32f5c0b 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1,12 +1,9 @@ -/* $Id$ */ - -// #include -#include #include #include #include #include +#include #include #include #include @@ -24,6 +21,9 @@ #include #include +/* TODO: find out what FreeBSD and such wants us to include */ +#include + PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers; PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D; PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers; @@ -32,6 +32,16 @@ PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer; PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer; PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatus; +/* + callback todo: + void (*up)(MwLL handle, void* data); + void (*down)(MwLL handle, void* data); + void (*key)(MwLL handle, void* data); + void (*key_released)(MwLL handle, void* data); + void (*focus_in)(MwLL handle, void* data); + void (*focus_out)(MwLL handle, void* data); +*/ + #define WAYLAND_GET_INTERFACE(r, inter) shget(r.wl_protocol_map, inter##_interface.name) static void new_protocol(void* data, struct wl_registry* registry, @@ -54,9 +64,73 @@ static void protocol_removed(void* data, }; -static void wl_seat_name(void* data, struct wl_seat* wl_seat, const char* name) {}; +static void pointer_enter(void* data, struct wl_pointer* wl_pointer, uint32_t serial, + struct wl_surface* surface, wl_fixed_t surface_x, + wl_fixed_t surface_y) {}; +static void pointer_leave(void* data, struct wl_pointer* wl_pointer, uint32_t serial, + struct wl_surface* surface) {}; +static void pointer_motion(void* data, struct wl_pointer* wl_pointer, uint32_t time, + wl_fixed_t surface_x, wl_fixed_t surface_y) { + MwLL self = data; + MwLLMouse p; + + 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; + MwLLDispatch(self, move, &p); +}; +static void pointer_button(void* data, struct wl_pointer* wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { + MwLL self = data; + MwLLMouse p; + 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) { + switch(button) { + case BTN_LEFT: + p.button = MwLLMouseLeft; + break; + case BTN_MIDDLE: + p.button = MwLLMouseMiddle; + break; + case BTN_RIGHT: + p.button = MwLLMouseRight; + break; + } + switch(state) { + case WL_POINTER_BUTTON_STATE_PRESSED: + MwLLDispatch(self, down, &p); + break; + case WL_POINTER_BUTTON_STATE_RELEASED: + MwLLDispatch(self, up, &p); + break; + } + } +}; +static void pointer_axis(void* data, struct wl_pointer* wl_pointer, uint32_t time, + uint32_t axis, wl_fixed_t value) {}; + +struct wl_pointer_listener pointer_listener = { + .enter = pointer_enter, + .leave = pointer_leave, + .motion = pointer_motion, + .button = pointer_button, + .axis = pointer_axis, +}; + +static void + wl_seat_name(void* data, struct wl_seat* wl_seat, const char* name) {}; static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat, - MwU32 capabilities) {}; + MwU32 capabilities) { + MwLL self = data; + if(capabilities & WL_SEAT_CAPABILITY_KEYBOARD) { + struct wl_keyboard* keyboard = wl_seat_get_keyboard(wl_seat); + // wl_keyboard_add_listener(keyboard, const struct wl_keyboard_listener* listener, data); + } + if(capabilities & WL_SEAT_CAPABILITY_POINTER && !self->wayland.pointer) { + self->wayland.pointer = wl_seat_get_pointer(wl_seat); + wl_pointer_add_listener(self->wayland.pointer, &pointer_listener, data); + return; + } +}; void xdg_wm_base_ping(void* data, struct xdg_wm_base* xdg_wm_base, @@ -66,15 +140,15 @@ void xdg_wm_base_ping(void* data, xdg_wm_base_pong(xdg_wm_base, serial); }; -static wayland_protocol_t* wl_seat_setup(MwU32 name, struct _MwLLWayland* wayland) { +static wayland_protocol_t* wl_seat_setup(MwU32 name, MwLL ll) { wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); proto->listener = malloc(sizeof(struct wl_seat_listener)); ((struct wl_seat_listener*)proto->listener)->name = wl_seat_name; ((struct wl_seat_listener*)proto->listener)->capabilities = wl_seat_capabilities; - proto->context = wl_registry_bind(wayland->registry, name, &wl_seat_interface, 1); - wl_seat_add_listener(proto->context, proto->listener, wayland); + proto->context = wl_registry_bind(ll->wayland.registry, name, &wl_seat_interface, 1); + wl_seat_add_listener(proto->context, proto->listener, ll); return proto; } @@ -347,9 +421,7 @@ static void decoration_configure( static void xdg_toplevel_close( void* data, struct xdg_toplevel* xdg_toplevel) { MwLL self = data; - - // Stop running if the user requests to close the toplevel - self->wayland.toplevel->running = MwFALSE; + MwLLDispatch(self, close, NULL); }; static void xdg_surface_configure( @@ -397,7 +469,7 @@ static int event_loop(MwLL handle) { if(errno != EINTR && errno != EAGAIN) { wl_display_cancel_read(wayland->display); - wayland->toplevel->running = MwFALSE; + MwLLDispatch(handle, close, NULL); return 0; } } @@ -446,8 +518,8 @@ static void setup_callbacks(struct _MwLLWayland* wayland) { WL_INTERFACE(wl_compositor); WL_INTERFACE(wl_subcompositor); + WL_INTERFACE(wl_seat); if(wayland->type == MWLL_WAYLAND_TOPLEVEL) { - WL_INTERFACE(wl_seat); WL_INTERFACE(xdg_wm_base); WL_INTERFACE(zxdg_decoration_manager_v1); WL_INTERFACE(wp_cursor_shape_manager_v1); @@ -627,7 +699,7 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r->wayland.force_redraw = MwFALSE; r->wayland.subwidgets = NULL; - + r->wayland.pointer = NULL; if(parent == NULL) { setup_toplevel(r, x, y); } else { @@ -766,6 +838,8 @@ static void MwLLEndDrawImpl(MwLL handle) { h = parent->wayland.wh; } + recursive_draw(handle); + glBindTexture(GL_TEXTURE_2D, handle->wayland.fbo_texture); // glClear(GL_COLOR_BUFFER_BIT); // glClearColor(1.0, 0, 0, 1); @@ -822,7 +896,6 @@ static void MwLLNextEventImpl(MwLL handle) { MwBool render = handle->wayland.force_redraw; if(render) { - recursive_draw(handle); handle->wayland.force_redraw = MwFALSE; } } diff --git a/src/core.c b/src/core.c index 83de5c1..696ed42 100644 --- a/src/core.c +++ b/src/core.c @@ -14,6 +14,10 @@ static void lldrawhandler(MwLL handle, void* data) { MwDispatch(h, draw); if(h->draw_inject != NULL) h->draw_inject(h); MwDispatchUserHandler(h, MwNdrawHandler, NULL); + + if(handle->wayland.parent == NULL) { + MwLLEndDraw(handle); + } } static void lluphandler(MwLL handle, void* data) { @@ -332,7 +336,6 @@ void MwLoop(MwWidget handle) { while(MwPending(handle)) { if((v = MwStep(handle)) != 0) break; } - MwLLEndDraw(handle->lowlevel); if(v != 0) break; for(i = 0; i < arrlen(handle->tick_list); i++) { -- 2.39.5 From 89ff065a718cc18f7d19a07da53f6d43c9879bc0 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 7 Dec 2025 18:52:49 -0700 Subject: [PATCH 28/48] seperate opengl contexts --- include/Mw/LowLevel.h | 1 + src/backend/call.c | 7 ++++--- src/backend/gdi.c | 1 + src/backend/wayland.c | 26 +++++++++++++------------- src/backend/x11.c | 13 +++++++------ src/core.c | 5 +++-- src/lowlevel.c | 1 + 7 files changed, 30 insertions(+), 24 deletions(-) diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index 516b815..167785a 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -162,6 +162,7 @@ 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); diff --git a/src/backend/call.c b/src/backend/call.c index e97e28b..e2ce934 100644 --- a/src/backend/call.c +++ b/src/backend/call.c @@ -8,9 +8,10 @@ MwLLCreate = MwLLCreateImpl; \ MwLLDestroy = MwLLDestroyImpl; \ \ - MwLLPolygon = MwLLPolygonImpl; \ - MwLLLine = MwLLLineImpl; \ - MwLLEndDraw = MwLLEndDrawImpl; \ + MwLLPolygon = MwLLPolygonImpl; \ + MwLLLine = MwLLLineImpl; \ + MwLLBeginDraw = MwLLBeginDrawImpl; \ + MwLLEndDraw = MwLLEndDrawImpl; \ \ MwLLAllocColor = MwLLAllocColorImpl; \ MwLLColorUpdate = MwLLColorUpdateImpl; \ diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 9d25fae..a527e09 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -277,6 +277,7 @@ static void MwLLDestroyImpl(MwLL handle) { free(handle); } +static void MwLLBeginDrawImpl(MwLL handle) {} static void MwLLEndDrawImpl(MwLL handle) {} static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 32f5c0b..cfd30f2 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -274,12 +274,6 @@ static MwBool egl_setup(MwLL self, int width, int height) { return MwFALSE; } - // Make the context current - if(!eglMakeCurrent(display, surface, surface, context)) { - printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); - return MwFALSE; - } - glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)eglGetProcAddress("glGenFramebuffers"); glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)eglGetProcAddress("glFramebufferTexture2D"); glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)eglGetProcAddress("glGenRenderbuffers"); @@ -305,7 +299,7 @@ static MwBool egl_setup(MwLL self, int width, int height) { if((err = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE) { printf("Error binding framebuffer: %0X\n", err); - return MwFALSE; + // return MwFALSE; } glBindFramebuffer(GL_FRAMEBUFFER_BINDING, 0); @@ -653,12 +647,10 @@ static void setup_subsurface(MwLL parent, MwLL r, int x, int y) { // arrpush(parent->wayland.subsurfaces, r); r->wayland.configured = MwTRUE; - - r->wayland.egl_context = topmost_parent->wayland.egl_context; - r->wayland.egl_display = topmost_parent->wayland.egl_display; - r->wayland.egl_surface = topmost_parent->wayland.egl_surface; - r->wayland.fbo = topmost_parent->wayland.fbo; - r->wayland.fbo_texture = topmost_parent->wayland.fbo_texture; + if(!r->wayland.egl_setup) { + r->wayland.egl_setup = egl_setup(r, r->wayland.ww, r->wayland.wh); + MwLLForceRender(r); + }; arrpush(parent->wayland.subwidgets, r); } @@ -826,6 +818,13 @@ static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { framebuffer_action_end(handle); } +static void MwLLBeginDrawImpl(MwLL handle) { + if(!eglMakeCurrent(handle->wayland.egl_display, handle->wayland.egl_surface, handle->wayland.egl_surface, handle->wayland.egl_context)) { + printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); + return; + } +} + static void MwLLEndDrawImpl(MwLL handle) { int w, h; @@ -859,6 +858,7 @@ static void MwLLEndDrawImpl(MwLL handle) { glFinish(); wl_surface_damage(handle->wayland.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); + if(!eglSwapBuffers(handle->wayland.egl_display, handle->wayland.egl_surface)) { printf("error swapping buffers! %0X\n", eglGetError()); } else { diff --git a/src/backend/x11.c b/src/backend/x11.c index 44da549..3c54155 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -148,14 +148,14 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { if(height < 2) height = 2; if(parent == NULL) { - r->x11.display = XOpenDisplay(NULL); - p = XRootWindow(r->x11.display, XDefaultScreen(r->x11.display)); - r->x11.top = 1; + r->x11.display = XOpenDisplay(NULL); + p = XRootWindow(r->x11.display, XDefaultScreen(r->x11.display)); + r->x11.top = 1; r->x11.toplevel = 1; } else { - r->x11.display = parent->x11.display; - p = parent->x11.window; - r->x11.top = 0; + r->x11.display = parent->x11.display; + p = parent->x11.window; + r->x11.top = 0; r->x11.toplevel = 0; } r->x11.window = XCreateSimpleWindow(r->x11.display, p, px, py, width, height, 0, 0, WhitePixel(r->x11.display, DefaultScreen(r->x11.display))); @@ -259,6 +259,7 @@ static void MwLLDestroyImpl(MwLL handle) { free(handle); } +static void MwLLBeginDrawImpl(MwLL handle) {} static void MwLLEndDrawImpl(MwLL handle) {} static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { diff --git a/src/core.c b/src/core.c index 696ed42..a734655 100644 --- a/src/core.c +++ b/src/core.c @@ -9,15 +9,16 @@ static void lldrawhandler(MwLL handle, void* data) { int ind; (void)data; + if(handle->wayland.parent == NULL) + MwLLBeginDraw(handle); h->bgcolor = NULL; MwDispatch(h, draw); if(h->draw_inject != NULL) h->draw_inject(h); MwDispatchUserHandler(h, MwNdrawHandler, NULL); - if(handle->wayland.parent == NULL) { + if(handle->wayland.parent == NULL) MwLLEndDraw(handle); - } } static void lluphandler(MwLL handle, void* data) { diff --git a/src/lowlevel.c b/src/lowlevel.c index 8e94790..96f6196 100644 --- a/src/lowlevel.c +++ b/src/lowlevel.c @@ -6,6 +6,7 @@ void (*MwLLDestroy)(MwLL handle); void (*MwLLPolygon)(MwLL handle, MwPoint* points, int points_count, MwLLColor color); void (*MwLLLine)(MwLL handle, MwPoint* points, MwLLColor color); +void (*MwLLBeginDraw)(MwLL handle); void (*MwLLEndDraw)(MwLL handle); MwLLColor (*MwLLAllocColor)(MwLL handle, int r, int g, int b); -- 2.39.5 From 6f1716151d2197772a87142b454ea6430973dd9a Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 7 Dec 2025 19:04:59 -0700 Subject: [PATCH 29/48] finished seperating opengl contexts, apply nishi patch --- include/Mw/BaseTypes.h | 4 ++-- include/Mw/LowLevel/Wayland.h | 3 ++- include/Mw/MachDep.h | 2 ++ pl/ostype/Linux.pl | 5 +++-- pl/rules.pl | 22 ++++++++++++++++------ pl/utils.pl | 33 ++++++++++++++++++++++++--------- src/backend/gdi.c | 9 +++++++-- src/backend/wayland.c | 34 +++++++++++++++++++++++----------- src/backend/x11.c | 9 +++++++-- src/core.c | 1 - src/widget/opengl.c | 3 ++- src/widget/scrollbar.c | 8 ++++---- 12 files changed, 92 insertions(+), 41 deletions(-) diff --git a/include/Mw/BaseTypes.h b/include/Mw/BaseTypes.h index e44c3bc..7b92c93 100644 --- a/include/Mw/BaseTypes.h +++ b/include/Mw/BaseTypes.h @@ -58,8 +58,8 @@ typedef unsigned long MwU64; #ifdef OTHER_TYPES_DEFINED #undef OTHER_TYPES_DEFINED #else -typedef int MwI32; -typedef unsigned int MwU32; +typedef int MwI32; +typedef unsigned int MwU32; typedef short MwI16; typedef unsigned short MwU16; diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 75f208b..6ce73fb 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -6,7 +6,6 @@ #ifndef __MW_LOWLEVEL_WAYLAND_H__ #define __MW_LOWLEVEL_WAYLAND_H__ -#include "Mw/BaseTypes.h" #include #include #include @@ -29,6 +28,8 @@ MWDECL int MwLLWaylandCallInit(void); #include "Wayland/cursor-shape-client-protocol.h" #endif +struct _MwLLWayland; + typedef struct wayland_protocol { void* listener; void* context; diff --git a/include/Mw/MachDep.h b/include/Mw/MachDep.h index cbc8bcd..6eb37be 100644 --- a/include/Mw/MachDep.h +++ b/include/Mw/MachDep.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,7 @@ #include #include #include +#include #endif #ifndef M_PI diff --git a/pl/ostype/Linux.pl b/pl/ostype/Linux.pl index d79d182..42b6397 100644 --- a/pl/ostype/Linux.pl +++ b/pl/ostype/Linux.pl @@ -1,6 +1,7 @@ -if(system("wayland-scanner -v >/dev/null 2>&1") == 0){ +if (system("wayland-scanner -v >/dev/null 2>&1") == 0) { use_backend("wayland", "x11"); -} else { +} +else { use_backend("x11"); } diff --git a/pl/rules.pl b/pl/rules.pl index 8ba2206..ab5521b 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -29,12 +29,19 @@ if (grep(/^gdi$/, @backends)) { if (grep(/^wayland$/, @backends)) { add_cflags("-DUSE_WAYLAND"); new_object("src/backend/wayland.c"); - add_libs("-lGL -lEGL -lwayland-egl -lwayland-client -lxkbcommon"); + if ($cross) { + add_libs("-lGL -lEGL -lwayland-egl -lwayland-client -lxkbcommon"); + } + else { + add_libs("-lGL -lEGL"); + add_cflags(`pkg-config --cflags wayland-egl wayland-client xkbcommon`); + add_libs(`pkg-config --libs wayland-egl wayland-client xkbcommon`); + } - scan_wayland_protocol("stable", "xdg-shell",""); - scan_wayland_protocol("stable", "tablet","-v2"); - scan_wayland_protocol("staging", "cursor-shape","-v1"); - scan_wayland_protocol("unstable", "xdg-decoration","-unstable-v1"); + scan_wayland_protocol("stable", "xdg-shell", ""); + scan_wayland_protocol("stable", "tablet", "-v2"); + scan_wayland_protocol("staging", "cursor-shape", "-v1"); + scan_wayland_protocol("unstable", "xdg-decoration", "-unstable-v1"); $gl_libs = "-lGL -lGLU"; } @@ -47,7 +54,10 @@ if (param_get("stb-truetype")) { } if (param_get("freetype2")) { add_cflags("-DUSE_FREETYPE2"); - if (not($cross)) { + if ($cross) { + add_libs("-lfreetype"); + } + else { add_cflags(`pkg-config --cflags freetype2`); add_libs(`pkg-config --libs freetype2`); } diff --git a/pl/utils.pl b/pl/utils.pl index 4b1b517..971c196 100644 --- a/pl/utils.pl +++ b/pl/utils.pl @@ -55,20 +55,35 @@ sub use_backend { } sub scan_wayland_protocol { - my $tier = $_[0]; + my $tier = $_[0]; my $proto = $_[1]; - my $ver = $_[2]; + my $ver = $_[2]; my $proto_c = "src/backend/wayland-${proto}-protocol.c"; - if(system("wayland-scanner private-code /usr/share/wayland-protocols/${tier}/${proto}/${proto}${ver}.xml ${proto_c}") != 0) { - print("^ Error on getting private code for /usr/share/wayland-protocols/${tier}/${proto}/${proto}${ver}.xml\n"); - } else { + if ( + system( +"wayland-scanner private-code /usr/share/wayland-protocols/${tier}/${proto}/${proto}${ver}.xml ${proto_c}" + ) != 0 + ) + { + print( +"^ Error on getting private code for /usr/share/wayland-protocols/${tier}/${proto}/${proto}${ver}.xml\n" + ); + } + else { new_object($proto_c); - }; - if(system("wayland-scanner client-header /usr/share/wayland-protocols/${tier}/${proto}/${proto}${ver}.xml include/Mw/LowLevel/Wayland/${proto}-client-protocol.h")) { - print("^ Error on getting client header for /usr/share/wayland-protocols/${tier}/${proto}/${proto}${ver}.xml\n"); - }; + } + if ( + system( +"wayland-scanner client-header /usr/share/wayland-protocols/${tier}/${proto}/${proto}${ver}.xml include/Mw/LowLevel/Wayland/${proto}-client-protocol.h" + ) + ) + { + print( +"^ Error on getting client header for /usr/share/wayland-protocols/${tier}/${proto}/${proto}${ver}.xml\n" + ); + } } our %params = (); diff --git a/src/backend/gdi.c b/src/backend/gdi.c index a527e09..ad6d338 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -277,8 +277,13 @@ static void MwLLDestroyImpl(MwLL handle) { free(handle); } -static void MwLLBeginDrawImpl(MwLL handle) {} -static void MwLLEndDrawImpl(MwLL 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); diff --git a/src/backend/wayland.c b/src/backend/wayland.c index cfd30f2..974a36e 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -227,12 +227,12 @@ static MwBool egl_setup(MwLL self, int width, int height) { EGL_CONTEXT_MINOR_VERSION, 1, EGL_NONE}; - EGLDisplay display = eglGetDisplay(self->wayland.display); + EGLDisplay display; + display = eglGetDisplay(self->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()); @@ -274,6 +274,11 @@ static MwBool egl_setup(MwLL self, int width, int height) { return MwFALSE; } + if(!eglMakeCurrent(display, surface, surface, context)) { + printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); + return MwFALSE; + } + glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)eglGetProcAddress("glGenFramebuffers"); glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)eglGetProcAddress("glFramebufferTexture2D"); glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)eglGetProcAddress("glGenRenderbuffers"); @@ -320,6 +325,11 @@ static MwBool egl_setup(MwLL self, int width, int height) { static void egl_resetup(MwLL handle) { int err; + if(!eglMakeCurrent(handle->wayland.egl_display, handle->wayland.egl_surface, handle->wayland.egl_surface, handle->wayland.egl_context)) { + printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); + return; + } + glDeleteTextures(1, &handle->wayland.fbo_texture); glGenTextures(1, &handle->wayland.fbo_texture); glBindTexture(GL_TEXTURE_2D, handle->wayland.fbo_texture); @@ -819,10 +829,11 @@ static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { } static void MwLLBeginDrawImpl(MwLL handle) { - if(!eglMakeCurrent(handle->wayland.egl_display, handle->wayland.egl_surface, handle->wayland.egl_surface, handle->wayland.egl_context)) { - printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); - return; - } + if(handle->wayland.parent == NULL) + if(!eglMakeCurrent(handle->wayland.egl_display, handle->wayland.egl_surface, handle->wayland.egl_surface, handle->wayland.egl_context)) { + printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); + return; + } } static void MwLLEndDrawImpl(MwLL handle) { @@ -859,11 +870,12 @@ static void MwLLEndDrawImpl(MwLL handle) { wl_surface_damage(handle->wayland.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); - if(!eglSwapBuffers(handle->wayland.egl_display, handle->wayland.egl_surface)) { - printf("error swapping buffers! %0X\n", eglGetError()); - } else { - wl_surface_commit(handle->wayland.surface); - } + if(handle->wayland.parent == NULL) + if(!eglSwapBuffers(handle->wayland.egl_display, handle->wayland.egl_surface)) { + printf("error swapping buffers! %0X\n", eglGetError()); + } else { + wl_surface_commit(handle->wayland.surface); + } } static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { diff --git a/src/backend/x11.c b/src/backend/x11.c index 3c54155..dcecf11 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -259,8 +259,13 @@ static void MwLLDestroyImpl(MwLL handle) { free(handle); } -static void MwLLBeginDrawImpl(MwLL handle) {} -static void MwLLEndDrawImpl(MwLL handle) {} +static void MwLLBeginDrawImpl(MwLL handle) { + (void)handle; +} + +static void MwLLEndDrawImpl(MwLL handle) { + (void)handle; +} static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) { int i; diff --git a/src/core.c b/src/core.c index a734655..bd6faed 100644 --- a/src/core.c +++ b/src/core.c @@ -6,7 +6,6 @@ static void lldrawhandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; - int ind; (void)data; if(handle->wayland.parent == NULL) diff --git a/src/widget/opengl.c b/src/widget/opengl.c index 552105a..05257e3 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -89,7 +89,8 @@ static int create(MwWidget handle) { 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"); diff --git a/src/widget/scrollbar.c b/src/widget/scrollbar.c index 6490b06..ebfcb40 100644 --- a/src/widget/scrollbar.c +++ b/src/widget/scrollbar.c @@ -142,7 +142,7 @@ static void draw(MwWidget handle) { } static void mouse_move(MwWidget handle) { - int or = MwGetInteger(handle, MwNorientation); + int or = MwGetInteger(handle, MwNorientation); scrollbar_t* scr = handle->internal; if(!handle->pressed) return; @@ -170,9 +170,9 @@ static void mouse_move(MwWidget handle) { } static void mouse_down(MwWidget handle, void* ptr) { - int ww = MwGetInteger(handle, MwNwidth); - int wh = MwGetInteger(handle, MwNheight); - int or = MwGetInteger(handle, MwNorientation); + int ww = MwGetInteger(handle, MwNwidth); + int wh = MwGetInteger(handle, MwNheight); + int or = MwGetInteger(handle, MwNorientation); scrollbar_t* scr = handle->internal; MwLLMouse* m = ptr; -- 2.39.5 From 631579642cac45ab2f5b1e24b6ebd77a405fe4b5 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 7 Dec 2025 19:08:29 -0700 Subject: [PATCH 30/48] we only need xdg_wm_base support --- src/backend/wayland.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 974a36e..b1a1a81 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -561,10 +561,9 @@ static void setup_toplevel(MwLL r, int x, int y) { // Check that all globals we require are available if( r->wayland.compositor == NULL || - WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context == NULL || - WAYLAND_GET_INTERFACE(r->wayland, wl_seat)->context == NULL) { + WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context == NULL) { - printf("no wl_shm, wl_compositor, wl_seat, or xdg_wm_base support\n"); + printf("no xdg_wm_base support\n"); raise(SIGTRAP); return; } -- 2.39.5 From b441f236b405cc3daf873059fd18fda04276a522 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 7 Dec 2025 19:12:59 -0700 Subject: [PATCH 31/48] have children swap buffers on the playground --- src/backend/wayland.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index b1a1a81..a7819d2 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -828,11 +828,10 @@ static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { } static void MwLLBeginDrawImpl(MwLL handle) { - if(handle->wayland.parent == NULL) - if(!eglMakeCurrent(handle->wayland.egl_display, handle->wayland.egl_surface, handle->wayland.egl_surface, handle->wayland.egl_context)) { - printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); - return; - } + if(!eglMakeCurrent(handle->wayland.egl_display, handle->wayland.egl_surface, handle->wayland.egl_surface, handle->wayland.egl_context)) { + printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); + return; + } } static void MwLLEndDrawImpl(MwLL handle) { @@ -869,12 +868,11 @@ static void MwLLEndDrawImpl(MwLL handle) { wl_surface_damage(handle->wayland.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); - if(handle->wayland.parent == NULL) - if(!eglSwapBuffers(handle->wayland.egl_display, handle->wayland.egl_surface)) { - printf("error swapping buffers! %0X\n", eglGetError()); - } else { - wl_surface_commit(handle->wayland.surface); - } + if(!eglSwapBuffers(handle->wayland.egl_display, handle->wayland.egl_surface)) { + printf("error swapping buffers! %0X\n", eglGetError()); + } else { + wl_surface_commit(handle->wayland.surface); + } } static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { -- 2.39.5 From 718548f1b88f4bfe38832a2ceb6b1e6541de88da Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 7 Dec 2025 19:20:29 -0700 Subject: [PATCH 32/48] remove some scattered includes --- src/core.c | 1 - src/draw.c | 1 - 2 files changed, 2 deletions(-) diff --git a/src/core.c b/src/core.c index bd6faed..6f2f041 100644 --- a/src/core.c +++ b/src/core.c @@ -1,5 +1,4 @@ #include -#include #include "../external/stb_ds.h" #include "Mw/LowLevel.h" diff --git a/src/draw.c b/src/draw.c index 871cf11..7be59be 100644 --- a/src/draw.c +++ b/src/draw.c @@ -1,5 +1,4 @@ #include -#include #ifdef USE_STB_IMAGE #include "../external/stb_image.h" -- 2.39.5 From 3305756af8c646efc0842cfb6a1d74f8e6872318 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 7 Dec 2025 19:29:00 -0700 Subject: [PATCH 33/48] more scattered include removal --- src/backend/wayland.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index a7819d2..d30a5d4 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1,28 +1,21 @@ #include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include #include #include "../../external/stb_ds.h" -#include "Mw/BaseTypes.h" -#include "Mw/LowLevel.h" #include #include #include /* TODO: find out what FreeBSD and such wants us to include */ +#ifdef __FreeBSD__ +/* XXX: Untested (nishi) */ +#include +#else #include +#endif PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers; PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D; -- 2.39.5 From 1e5ff44d792125cecf8eb17f6771a82d495f5ff6 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 7 Dec 2025 19:33:16 -0700 Subject: [PATCH 34/48] swap buffers on all children --- .clangd | 1 + src/backend/wayland.c | 20 +++++++++++--------- src/core.c | 6 ++---- 3 files changed, 14 insertions(+), 13 deletions(-) create mode 100644 .clangd diff --git a/.clangd b/.clangd new file mode 100644 index 0000000..7abd528 --- /dev/null +++ b/.clangd @@ -0,0 +1 @@ +header-insertion: never diff --git a/src/backend/wayland.c b/src/backend/wayland.c index d30a5d4..d1130e6 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -821,10 +821,11 @@ static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { } static void MwLLBeginDrawImpl(MwLL handle) { - if(!eglMakeCurrent(handle->wayland.egl_display, handle->wayland.egl_surface, handle->wayland.egl_surface, handle->wayland.egl_context)) { - printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); - return; - } + if(handle->wayland.parent == NULL) + if(!eglMakeCurrent(handle->wayland.egl_display, handle->wayland.egl_surface, handle->wayland.egl_surface, handle->wayland.egl_context)) { + printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); + return; + } } static void MwLLEndDrawImpl(MwLL handle) { @@ -861,11 +862,12 @@ static void MwLLEndDrawImpl(MwLL handle) { wl_surface_damage(handle->wayland.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); - if(!eglSwapBuffers(handle->wayland.egl_display, handle->wayland.egl_surface)) { - printf("error swapping buffers! %0X\n", eglGetError()); - } else { - wl_surface_commit(handle->wayland.surface); - } + if(handle->wayland.parent == NULL) + if(!eglSwapBuffers(handle->wayland.egl_display, handle->wayland.egl_surface)) { + printf("error swapping buffers! %0X\n", eglGetError()); + } else { + wl_surface_commit(handle->wayland.surface); + } } static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { diff --git a/src/core.c b/src/core.c index 6f2f041..792dd30 100644 --- a/src/core.c +++ b/src/core.c @@ -7,16 +7,14 @@ static void lldrawhandler(MwLL handle, void* data) { MwWidget h = (MwWidget)handle->common.user; (void)data; - if(handle->wayland.parent == NULL) - MwLLBeginDraw(handle); + MwLLBeginDraw(handle); h->bgcolor = NULL; MwDispatch(h, draw); if(h->draw_inject != NULL) h->draw_inject(h); MwDispatchUserHandler(h, MwNdrawHandler, NULL); - if(handle->wayland.parent == NULL) - MwLLEndDraw(handle); + MwLLEndDraw(handle); } static void lluphandler(MwLL handle, void* data) { -- 2.39.5 From fd39a0aa1c5072de99f17fe5fd9b0cbaaffdb4e3 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 7 Dec 2025 20:29:51 -0700 Subject: [PATCH 35/48] no more framebuffer --- src/backend/wayland.c | 170 ++---------------------------------------- 1 file changed, 6 insertions(+), 164 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index d1130e6..e242672 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -16,15 +16,6 @@ #else #include #endif - -PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers; -PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D; -PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers; -PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer; -PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer; -PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer; -PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatus; - /* callback todo: void (*up)(MwLL handle, void* data); @@ -272,36 +263,6 @@ static MwBool egl_setup(MwLL self, int width, int height) { return MwFALSE; } - glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)eglGetProcAddress("glGenFramebuffers"); - glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)eglGetProcAddress("glFramebufferTexture2D"); - glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)eglGetProcAddress("glGenRenderbuffers"); - // glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)eglGetProcAddress("glRenderbufferStorage"); - glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)eglGetProcAddress("glFramebufferRenderbuffer"); - glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)eglGetProcAddress("glBindRenderbuffer"); - glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)eglGetProcAddress("glBindFramebuffer"); - glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)eglGetProcAddress("glCheckFramebufferStatus"); - - glGenTextures(1, &self->wayland.fbo_texture); - glBindTexture(GL_TEXTURE_2D, self->wayland.fbo_texture); - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); - - glBindTexture(GL_TEXTURE_2D, 0); - - glGenFramebuffers(1, &self->wayland.fbo); - glBindFramebuffer(GL_FRAMEBUFFER_BINDING, self->wayland.fbo); - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self->wayland.fbo_texture, 0); - - if((err = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE) { - printf("Error binding framebuffer: %0X\n", err); - // return MwFALSE; - } - - glBindFramebuffer(GL_FRAMEBUFFER_BINDING, 0); - glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, width, height, 0, -1, 1); @@ -323,30 +284,6 @@ static void egl_resetup(MwLL handle) { return; } - glDeleteTextures(1, &handle->wayland.fbo_texture); - glGenTextures(1, &handle->wayland.fbo_texture); - glBindTexture(GL_TEXTURE_2D, handle->wayland.fbo_texture); - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, handle->wayland.ww, handle->wayland.wh, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); - - glGenFramebuffers(1, &handle->wayland.fbo); - glBindFramebuffer(GL_FRAMEBUFFER_BINDING, handle->wayland.fbo); - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, handle->wayland.fbo_texture, 0); - - if((err = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE) { - printf("Error binding framebuffer: %0X\n", err); - return; - } - - glBindFramebuffer(GL_FRAMEBUFFER_BINDING, 0); - - glBindTexture(GL_TEXTURE_2D, 0); - glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, handle->wayland.ww, handle->wayland.wh, 0, -1, 1); @@ -379,8 +316,7 @@ static void xdg_toplevel_configure(void* data, struct xdg_toplevel* xdg_toplevel, MwI32 width, MwI32 height, struct wl_array* states) { - MwLL self = data; - PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)eglGetProcAddress("glFramebufferTexture2D"); + MwLL self = data; if(width == 0 || height == 0) { width = self->wayland.ww; @@ -472,24 +408,6 @@ static int event_loop(MwLL handle) { } } - /* - IOI: - I took this from ioilib which I in turn adapted from SDL. I think this is meant to be required? - But doing this on my main machine causes the decorations manager to be null...? This doesn't show up on the project currently using ioilib. - Race condition? Random KDE bug? Who knows, but it seems that not polling for this works anyways (possibly because we already flush events above and then cancel reads when we actually need to close). - */ - /* - - // 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_surface_commit(wayland->surface); - return 0; - } - - */ - if(fd.revents & POLLIN) { wl_display_read_events(wayland->display); if(wl_display_dispatch_pending(wayland->display) > 0) { @@ -657,16 +575,6 @@ static void setup_subsurface(MwLL parent, MwLL r, int x, int y) { arrpush(parent->wayland.subwidgets, r); } -static void framebuffer_action_begin(MwLL handle) { - glBindFramebuffer(GL_FRAMEBUFFER, handle->wayland.fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, handle->wayland.fbo_texture, 0); -} - -static void framebuffer_action_end(MwLL handle) { - glFinish(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); -} - static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { MwLL r; r = malloc(sizeof(*r)); @@ -745,40 +653,8 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL int i, n; float maxX = 0, maxY = 0; float centerX, centerY; - int doLoopback = MwFALSE; - if(points_count > 3) { - /* To avoid having to do a real triangulation algorithim: - 1.) loop through the points once to determine the bounds of the polygon - 2.) calculate the center of the polygon - - */ - for(i = 0; i < points_count; i++) { - float x = round(handle->wayland.x) + round(points[i].x); - float y = round(handle->wayland.y) + round(points[i].y); - if(x >= maxX) { - maxX = x; - } - if(y >= maxY) { - maxY = y; - } - } - } - centerX = (handle->wayland.x + maxX / 2); - centerY = (handle->wayland.y + maxY / 2); - - /* Efficient? No. But at the end of the day it's still not that many polygons, and if a computer can't handle 12 polygons over 6 then it should not be using Wayland anyways */ - - framebuffer_action_begin(handle); - - if(points_count == 3) { - glBegin(GL_TRIANGLES); - } else if((points_count % 3) == 0) { - glBegin(GL_POLYGON); - } else { - glBegin(GL_TRIANGLE_FAN); - doLoopback = MwTRUE; - } + glBegin(GL_POLYGON); for(i = 0; i < points_count; i++) { float x = round(handle->wayland.x) + round(points[i].x); @@ -787,15 +663,9 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL glColor3f(color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); glVertex2f(x, y); - if(doLoopback) { - glVertex2f(maxX, maxY); - glVertex2f(x, y); - } } glEnd(); glColor3f(0, 0, 0); - - framebuffer_action_end(handle); } static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { @@ -803,29 +673,17 @@ static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { glLineWidth(1); - framebuffer_action_begin(handle); - glBegin(GL_LINES); - for(i = 0; i < 2; i++) { - float x = round(handle->wayland.x) + round(points[i].x); - float y = round(handle->wayland.y) + round(points[i].y); - - glColor3f(color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); - - glVertex2f(x, y); - } - glEnd(); glColor3f(0, 0, 0); - - framebuffer_action_end(handle); } static void MwLLBeginDrawImpl(MwLL handle) { - if(handle->wayland.parent == NULL) + if(handle->wayland.parent == NULL) { if(!eglMakeCurrent(handle->wayland.egl_display, handle->wayland.egl_surface, handle->wayland.egl_surface, handle->wayland.egl_context)) { printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); return; } + } } static void MwLLEndDrawImpl(MwLL handle) { @@ -842,32 +700,18 @@ static void MwLLEndDrawImpl(MwLL handle) { recursive_draw(handle); - glBindTexture(GL_TEXTURE_2D, handle->wayland.fbo_texture); // glClear(GL_COLOR_BUFFER_BIT); // glClearColor(1.0, 0, 0, 1); - glColor3f(1.0, 1.0, 1.0); - - glBegin(GL_QUADS); - glTexCoord2f(0.0f, 1); - glVertex2f(0, 0); - glTexCoord2f(1, 1); - glVertex2f(w, 0); - glTexCoord2f(1, 0.0f); - glVertex2f(w, h); - glTexCoord2f(0.0f, 0.0f); - glVertex2f(0, h); - glEnd(); - glFinish(); - wl_surface_damage(handle->wayland.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); - if(handle->wayland.parent == NULL) + if(handle->wayland.parent == NULL) { if(!eglSwapBuffers(handle->wayland.egl_display, handle->wayland.egl_surface)) { printf("error swapping buffers! %0X\n", eglGetError()); } else { wl_surface_commit(handle->wayland.surface); } + } } static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { @@ -953,7 +797,6 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { glBindTexture(GL_TEXTURE_2D, pixmap->wayland.texture); glActiveTexture(pixmap->wayland.texture); - framebuffer_action_begin(handle); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0); glVertex2f(x, y); @@ -965,7 +808,6 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { glVertex2f(x, y + rect->height); glEnd(); glFinish(); - framebuffer_action_end(handle); } static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { -- 2.39.5 From 87d7157291e0865cfc9728ad09e78e8586ff9e99 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 7 Dec 2025 20:41:37 -0700 Subject: [PATCH 36/48] subsurfaces have been useless for awhile, remove them and name the sub-widgets sublevels --- include/Mw/LowLevel/Wayland.h | 12 ++++-------- src/backend/wayland.c | 14 +++++++------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 6ce73fb..ed40bfe 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -52,13 +52,11 @@ struct _MwLLWaylandTopLevel { struct _MwLLWayland { struct _MwLLCommon common; - union { - struct _MwLLWaylandTopLevel* toplevel; - struct wl_subsurface* subsurface; - }; + // data that's only loaded if it's a toplevel + struct _MwLLWaylandTopLevel* toplevel; enum { - MWLL_WAYLAND_TOPLEVEL = 0, - MWLL_WAYLAND_SUBSURFACE = 1, + MWLL_WAYLAND_TOPLEVEL = 0, + MWLL_WAYLAND_SUBLEVEL = 1, } type; struct { @@ -90,8 +88,6 @@ struct _MwLLWayland { MwU32 x, y, ww, wh; MwPoint cur_mouse_pos; - int last_serial; - MwLL parent; GLuint fbo; diff --git a/src/backend/wayland.c b/src/backend/wayland.c index e242672..c8f2c90 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -522,7 +522,7 @@ static void setup_toplevel(MwLL r, int x, int y) { // glGenBuffers(1, &vertex_buffer); } -static void setup_subsurface(MwLL parent, MwLL r, int x, int y) { +static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { struct wl_compositor* compositor = parent->wayland.compositor; struct wl_subcompositor* subcompositor = parent->wayland.subcompositor; struct wl_surface* parent_surface = parent->wayland.surface; @@ -533,7 +533,7 @@ static void setup_subsurface(MwLL parent, MwLL r, int x, int y) { topmost_parent = topmost_parent->wayland.parent; } - r->wayland.type = MWLL_WAYLAND_SUBSURFACE; + r->wayland.type = MWLL_WAYLAND_SUBLEVEL; r->wayland.display = parent->wayland.display; @@ -546,9 +546,9 @@ static void setup_subsurface(MwLL parent, MwLL r, int x, int y) { event_loop(r); wl_region_destroy(region); - r->wayland.subsurface = wl_subcompositor_get_subsurface(subcompositor, r->wayland.surface, parent_surface); + // r->wayland.sublevel = wl_subcompositor_get_sublevel(subcompositor, r->wayland.surface, parent_surface); - wl_subsurface_set_position(r->wayland.subsurface, x, y); + // wl_sublevel_set_position(r->wayland.sublevel, x, y); // printf("position %d %d\n", x, y); @@ -564,7 +564,7 @@ static void setup_subsurface(MwLL parent, MwLL r, int x, int y) { return; } - // arrpush(parent->wayland.subsurfaces, r); + // arrpush(parent->wayland.sublevels, r); r->wayland.configured = MwTRUE; if(!r->wayland.egl_setup) { @@ -605,7 +605,7 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { if(parent == NULL) { setup_toplevel(r, x, y); } else { - setup_subsurface(parent, r, x, y); + setup_sublevel(parent, r, x, y); } return r; @@ -628,7 +628,7 @@ static void MwLLSetXYImpl(MwLL handle, int x, int y) { if(handle->wayland.type != MWLL_WAYLAND_TOPLEVEL) { handle->wayland.x = x; handle->wayland.y = y; - wl_subsurface_set_position(handle->wayland.subsurface, x, y); + // wl_sublevel_set_position(handle->wayland.sublevel, x, y); MwLLForceRender(handle); } } -- 2.39.5 From 6ecc3fc708a289dc2cac9d9b07e61808b79ceb6b Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 7 Dec 2025 20:43:24 -0700 Subject: [PATCH 37/48] remove some extranous gl stuff --- src/backend/wayland.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index c8f2c90..6f34ab8 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -654,14 +654,14 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL float maxX = 0, maxY = 0; float centerX, centerY; + glColor3f(color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); + glBegin(GL_POLYGON); for(i = 0; i < points_count; i++) { float x = round(handle->wayland.x) + round(points[i].x); float y = round(handle->wayland.y) + round(points[i].y); - glColor3f(color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); - glVertex2f(x, y); } glEnd(); @@ -672,7 +672,15 @@ static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { int i; glLineWidth(1); + glColor3f(color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); + glBegin(GL_LINES); + for(i = 0; i < 2; i++) { + float x = round(handle->wayland.x) + round(points[i].x); + float y = round(handle->wayland.y) + round(points[i].y); + + glVertex2f(x, y); + } glEnd(); glColor3f(0, 0, 0); } @@ -807,7 +815,6 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { glTexCoord2f(0.0f, 1); glVertex2f(x, y + rect->height); glEnd(); - glFinish(); } static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { -- 2.39.5 From df43752fa74754c7550d5a3b02d1e0c825955f35 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 8 Dec 2025 15:28:20 -0700 Subject: [PATCH 38/48] wayland: properly pump the events system, only drawing when necessary --- include/Mw/LowLevel/Wayland.h | 14 +++- src/backend/wayland.c | 131 +++++++++++++++++++++++----------- 2 files changed, 100 insertions(+), 45 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index ed40bfe..de63469 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -76,18 +76,25 @@ struct _MwLLWayland { struct wl_surface* surface; struct wl_shm* shm; struct wl_registry_listener registry_listener; + struct wl_event_queue* event_queue; struct wl_pointer* pointer; MwLL* subwidgets; - MwBool configured; - MwBool force_redraw; + MwBool configured; + MwBool force_redraw; + MwBool egl_setup; - MwBool egl_do_resetup; + MwBool has_set_xy; MwU32 x, y, ww, wh; MwPoint cur_mouse_pos; + struct timeval timer; + + MwU64 cooldown_timer; + MwU64 cooldown_timer_epoch; + MwLL parent; GLuint fbo; @@ -107,6 +114,7 @@ struct _MwLLWaylandColor { struct _MwLLWaylandPixmap { struct _MwLLCommonPixmap common; GLuint texture; + MwBool texture_deleted; }; #endif diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 6f34ab8..d461c5c 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -26,6 +26,8 @@ void (*focus_out)(MwLL handle, void* data); */ +static void timed_redraw(MwLL handle, MwU32 time, int cooldown, MwU64* cooldown_timer); + #define WAYLAND_GET_INTERFACE(r, inter) shget(r.wl_protocol_map, inter##_interface.name) static void new_protocol(void* data, struct wl_registry* registry, @@ -48,12 +50,12 @@ static void protocol_removed(void* data, }; -static void pointer_enter(void* data, struct wl_pointer* wl_pointer, uint32_t serial, +static void pointer_enter(void* data, struct wl_pointer* wl_pointer, MwU32 serial, struct wl_surface* surface, wl_fixed_t surface_x, wl_fixed_t surface_y) {}; -static void pointer_leave(void* data, struct wl_pointer* wl_pointer, uint32_t serial, +static void pointer_leave(void* data, struct wl_pointer* wl_pointer, MwU32 serial, struct wl_surface* surface) {}; -static void pointer_motion(void* data, struct wl_pointer* wl_pointer, uint32_t time, +static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time, wl_fixed_t surface_x, wl_fixed_t surface_y) { MwLL self = data; MwLLMouse p; @@ -62,8 +64,10 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, uint32_t t self->wayland.cur_mouse_pos.y = wl_fixed_to_double(surface_y); p.point = self->wayland.cur_mouse_pos; MwLLDispatch(self, move, &p); + + timed_redraw(self, time, 50, &self->wayland.cooldown_timer); }; -static void pointer_button(void* data, struct wl_pointer* wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { +static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 serial, MwU32 time, MwU32 button, MwU32 state) { MwLL self = data; MwLLMouse p; p.point = self->wayland.cur_mouse_pos; @@ -88,9 +92,11 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, uint32_t s break; } } + + timed_redraw(self, time, 50, &self->wayland.cooldown_timer); }; -static void pointer_axis(void* data, struct wl_pointer* wl_pointer, uint32_t time, - uint32_t axis, wl_fixed_t value) {}; +static void pointer_axis(void* data, struct wl_pointer* wl_pointer, MwU32 time, + MwU32 axis, wl_fixed_t value) {}; struct wl_pointer_listener pointer_listener = { .enter = pointer_enter, @@ -112,7 +118,6 @@ static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat, if(capabilities & WL_SEAT_CAPABILITY_POINTER && !self->wayland.pointer) { self->wayland.pointer = wl_seat_get_pointer(wl_seat); wl_pointer_add_listener(self->wayland.pointer, &pointer_listener, data); - return; } }; @@ -258,9 +263,14 @@ static MwBool egl_setup(MwLL self, int width, int height) { return MwFALSE; } - if(!eglMakeCurrent(display, surface, surface, context)) { - printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); - return MwFALSE; + self->wayland.egl_display = display; + self->wayland.egl_surface = surface; + self->wayland.egl_context = context; + + if(self->wayland.parent == NULL) { + if(!eglMakeCurrent(self->wayland.egl_display, self->wayland.egl_surface, self->wayland.egl_surface, self->wayland.egl_context)) { + printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); + } } glMatrixMode(GL_PROJECTION); @@ -270,26 +280,21 @@ static MwBool egl_setup(MwLL self, int width, int height) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - self->wayland.egl_display = display; - self->wayland.egl_surface = surface; - self->wayland.egl_context = context; return MwTRUE; } static void egl_resetup(MwLL handle) { int err; - if(!eglMakeCurrent(handle->wayland.egl_display, handle->wayland.egl_surface, handle->wayland.egl_surface, handle->wayland.egl_context)) { - printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); - return; - } + // if(!eglMakeCurrent(handle->wayland.egl_display, handle->wayland.egl_surface, handle->wayland.egl_surface, handle->wayland.egl_context)) { + // printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); + // return; + // } glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, handle->wayland.ww, handle->wayland.wh, 0, -1, 1); glViewport(0, 0, handle->wayland.ww, handle->wayland.wh); - - handle->wayland.egl_do_resetup = MwFALSE; } static void recursive_draw(MwLL handle) { @@ -302,16 +307,25 @@ static void recursive_draw(MwLL handle) { } } -static void recursive_resize(MwLL handle) { - int i; - if(handle->wayland.subwidgets != NULL) { - for(i = 0; i < arrlen(handle->wayland.subwidgets); i++) { - MwLLDispatch(handle->wayland.subwidgets[i], resize, NULL); - recursive_resize(handle->wayland.subwidgets[i]); +static void timed_redraw(MwLL handle, MwU32 time, int cooldown, MwU64* cooldown_timer) { + if(handle->wayland.parent == NULL) { + if(time >= (*cooldown_timer + cooldown)) { + egl_resetup(handle); + MwLLDispatch(handle, draw, NULL); + // recursive_draw(handle); + *cooldown_timer = time; } } } +static void timed_redraw_by_epoch(MwLL handle, int cooldown) { + gettimeofday(&handle->wayland.timer, NULL); + unsigned long long time = + (unsigned long long)(handle->wayland.timer.tv_sec) * 1000 + + (unsigned long long)(handle->wayland.timer.tv_usec) / 1000; + timed_redraw(handle, time, cooldown, &handle->wayland.cooldown_timer_epoch); +} + static void xdg_toplevel_configure(void* data, struct xdg_toplevel* xdg_toplevel, MwI32 width, MwI32 height, @@ -326,20 +340,17 @@ static void xdg_toplevel_configure(void* data, return; } } + 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); - MwLLSetWH(self, width, height); MwLLDispatch(self, resize, NULL); - recursive_resize(self); if(!self->wayland.egl_setup) { self->wayland.egl_setup = egl_setup(self, width, height); - MwLLForceRender(self); } else { wl_egl_window_resize(self->wayland.egl_window_native, width, height, 0, 0); - self->wayland.egl_do_resetup = MwTRUE; egl_resetup(self); } @@ -413,9 +424,13 @@ static int event_loop(MwLL handle) { if(wl_display_dispatch_pending(wayland->display) > 0) { } } else { + /* Condition for no events being sent */ if(wl_display_dispatch_pending(wayland->display) == 0) { - MwLLDispatch(handle, draw, NULL); - recursive_draw(handle); + if(wayland->event_queue != NULL) { + if(wl_display_roundtrip_queue(wayland->display, wayland->event_queue) < 0) { + printf("error\n"); + }; + } } } @@ -444,8 +459,7 @@ static void setup_callbacks(struct _MwLLWayland* wayland) { #undef WL_INTERFACE static void setup_toplevel(MwLL r, int x, int y) { - int i; - struct wl_region* region; + int i; r->wayland.type = MWLL_WAYLAND_TOPLEVEL; r->wayland.toplevel = malloc(sizeof(struct _MwLLWaylandTopLevel)); @@ -517,6 +531,10 @@ static void setup_toplevel(MwLL r, int x, int y) { printf("zxdg null\n"); } + r->wayland.event_queue = wl_display_create_queue(r->wayland.display); + + MwLLForceRender(r); + // buffer_setup(&r->wayland); // glGenBuffers(1, &vertex_buffer); @@ -526,8 +544,8 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { struct wl_compositor* compositor = parent->wayland.compositor; struct wl_subcompositor* subcompositor = parent->wayland.subcompositor; struct wl_surface* parent_surface = parent->wayland.surface; - MwLL topmost_parent = parent; struct wl_region* region; + MwLL topmost_parent = parent; while(topmost_parent->wayland.type != MWLL_WAYLAND_TOPLEVEL) { topmost_parent = topmost_parent->wayland.parent; @@ -572,7 +590,15 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { MwLLForceRender(r); }; + r->wayland.event_queue = parent->wayland.event_queue; + arrpush(parent->wayland.subwidgets, r); + + wl_surface_damage(parent->wayland.surface, 0, 0, parent->wayland.ww, parent->wayland.wh); + + egl_resetup(topmost_parent); + MwLLDispatch(topmost_parent, draw, NULL); + recursive_draw(topmost_parent); } static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { @@ -599,6 +625,9 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r->wayland.parent = parent; + r->wayland.cooldown_timer = 0; + r->wayland.has_set_xy = MwFALSE; + r->wayland.force_redraw = MwFALSE; r->wayland.subwidgets = NULL; r->wayland.pointer = NULL; @@ -626,10 +655,20 @@ static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsign static void MwLLSetXYImpl(MwLL handle, int x, int y) { if(handle->wayland.type != MWLL_WAYLAND_TOPLEVEL) { + MwLL topmost_parent = handle->wayland.parent; + + while(topmost_parent->wayland.type != MWLL_WAYLAND_TOPLEVEL) { + topmost_parent = topmost_parent->wayland.parent; + } + handle->wayland.x = x; handle->wayland.y = y; - // wl_sublevel_set_position(handle->wayland.sublevel, x, y); - MwLLForceRender(handle); + if(handle->wayland.has_set_xy) { + timed_redraw_by_epoch(topmost_parent, 25); + recursive_draw(topmost_parent); + } else if(x != 0 && y != 0) { + handle->wayland.has_set_xy = MwTRUE; + } } } @@ -646,6 +685,13 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { xdg_surface_set_window_geometry(handle->wayland.toplevel->xdg_surface, 0, 0, handle->wayland.ww, handle->wayland.wh); } else { + MwLL topmost_parent = handle->wayland.parent; + + while(topmost_parent->wayland.type != MWLL_WAYLAND_TOPLEVEL) { + topmost_parent = topmost_parent->wayland.parent; + } + timed_redraw_by_epoch(topmost_parent, 25); + recursive_draw(topmost_parent); } } @@ -692,6 +738,8 @@ static void MwLLBeginDrawImpl(MwLL handle) { return; } } + // glClear(GL_COLOR_BUFFER_BIT); + // glClearColor(1.0, 0, 0, 1); } static void MwLLEndDrawImpl(MwLL handle) { @@ -711,8 +759,6 @@ static void MwLLEndDrawImpl(MwLL handle) { // glClear(GL_COLOR_BUFFER_BIT); // glClearColor(1.0, 0, 0, 1); - wl_surface_damage(handle->wayland.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); - if(handle->wayland.parent == NULL) { if(!eglSwapBuffers(handle->wayland.egl_display, handle->wayland.egl_surface)) { printf("error swapping buffers! %0X\n", eglGetError()); @@ -745,7 +791,7 @@ static void MwLLFreeColorImpl(MwLLColor color) { static int MwLLPendingImpl(MwLL handle) { if(wl_display_dispatch_pending(handle->wayland.display) == 0) { } - return event_loop(handle) || handle->wayland.force_redraw; + return event_loop(handle); } static void MwLLNextEventImpl(MwLL handle) { @@ -815,16 +861,17 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { glTexCoord2f(0.0f, 1); glVertex2f(x, y + rect->height); glEnd(); + glFinish(); } - static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { } static void MwLLForceRenderImpl(MwLL handle) { wl_surface_damage(handle->wayland.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); - wl_surface_commit(handle->wayland.surface); - + if(handle->wayland.egl_setup) { + timed_redraw_by_epoch(handle, 25); + } handle->wayland.force_redraw = MwTRUE; } -- 2.39.5 From c796ed617d2632d42818f40d9fed519865d0aa00 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 8 Dec 2025 15:33:57 -0700 Subject: [PATCH 39/48] we don't need timed_redraw for resizing anymoreg --- src/backend/wayland.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index d461c5c..f6a0fe4 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -18,8 +18,6 @@ #endif /* callback todo: - void (*up)(MwLL handle, void* data); - void (*down)(MwLL handle, void* data); void (*key)(MwLL handle, void* data); void (*key_released)(MwLL handle, void* data); void (*focus_in)(MwLL handle, void* data); @@ -92,8 +90,7 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri break; } } - - timed_redraw(self, time, 50, &self->wayland.cooldown_timer); + MwLLDispatch(self, draw, NULL); }; static void pointer_axis(void* data, struct wl_pointer* wl_pointer, MwU32 time, MwU32 axis, wl_fixed_t value) {}; @@ -533,7 +530,9 @@ static void setup_toplevel(MwLL r, int x, int y) { r->wayland.event_queue = wl_display_create_queue(r->wayland.display); - MwLLForceRender(r); + egl_resetup(r); + MwLLDispatch(r, draw, NULL); + recursive_draw(r); // buffer_setup(&r->wayland); @@ -587,7 +586,9 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { r->wayland.configured = MwTRUE; if(!r->wayland.egl_setup) { r->wayland.egl_setup = egl_setup(r, r->wayland.ww, r->wayland.wh); - MwLLForceRender(r); + egl_resetup(r); + MwLLDispatch(r, draw, NULL); + recursive_draw(r); }; r->wayland.event_queue = parent->wayland.event_queue; -- 2.39.5 From cb0998605343e1cb2a2485a2a258182c06ab3838 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 8 Dec 2025 16:37:59 -0700 Subject: [PATCH 40/48] fix resizing --- include/Mw/LowLevel/Wayland.h | 9 ++++-- src/backend/wayland.c | 57 ++++++++++++++++++----------------- 2 files changed, 37 insertions(+), 29 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index de63469..454de5c 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -87,7 +87,10 @@ struct _MwLLWayland { MwBool egl_setup; MwBool has_set_xy; - MwU32 x, y, ww, wh; + int resize_counter; + MwU32 x, y; + MwU32 ww, wh; + MwU32 lw, lh; MwPoint cur_mouse_pos; struct timeval timer; @@ -95,7 +98,9 @@ struct _MwLLWayland { MwU64 cooldown_timer; MwU64 cooldown_timer_epoch; - MwLL parent; + MwLL parent; + MwLL topmost_parent; + MwBool draw_recursively; GLuint fbo; unsigned int fbo_texture; diff --git a/src/backend/wayland.c b/src/backend/wayland.c index f6a0fe4..14cd116 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -428,6 +428,16 @@ static int event_loop(MwLL handle) { printf("error\n"); }; } + /* HACK: If the last known size is different, force a redraw */ + if(wayland->lw != wayland->ww || wayland->lh != wayland->wh) { + MwLLDispatch(handle, draw, 0); + wayland->resize_counter++; + if(wayland->resize_counter >= 5) { + wayland->lw = wayland->ww; + wayland->lh = wayland->wh; + wayland->resize_counter = 0; + } + } } } @@ -544,10 +554,13 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { struct wl_subcompositor* subcompositor = parent->wayland.subcompositor; struct wl_surface* parent_surface = parent->wayland.surface; struct wl_region* region; - MwLL topmost_parent = parent; + { + MwLL topmost_parent = parent; - while(topmost_parent->wayland.type != MWLL_WAYLAND_TOPLEVEL) { - topmost_parent = topmost_parent->wayland.parent; + while(topmost_parent->wayland.type != MWLL_WAYLAND_TOPLEVEL) { + topmost_parent = topmost_parent->wayland.parent; + } + r->wayland.topmost_parent = topmost_parent; } r->wayland.type = MWLL_WAYLAND_SUBLEVEL; @@ -571,8 +584,8 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { setup_callbacks(&r->wayland); - r->wayland.registry = wl_display_get_registry(topmost_parent->wayland.display); - r->wayland.display = topmost_parent->wayland.display; + r->wayland.registry = wl_display_get_registry(r->wayland.topmost_parent->wayland.display); + r->wayland.display = r->wayland.topmost_parent->wayland.display; wl_registry_add_listener(r->wayland.registry, &r->wayland.registry_listener, r); if(wl_display_roundtrip(r->wayland.display) == -1) { @@ -597,9 +610,9 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { wl_surface_damage(parent->wayland.surface, 0, 0, parent->wayland.ww, parent->wayland.wh); - egl_resetup(topmost_parent); - MwLLDispatch(topmost_parent, draw, NULL); - recursive_draw(topmost_parent); + egl_resetup(r->wayland.topmost_parent); + MwLLDispatch(r->wayland.topmost_parent, draw, NULL); + recursive_draw(r->wayland.topmost_parent); } static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { @@ -628,6 +641,7 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r->wayland.cooldown_timer = 0; r->wayland.has_set_xy = MwFALSE; + r->wayland.resize_counter = 0; r->wayland.force_redraw = MwFALSE; r->wayland.subwidgets = NULL; @@ -656,17 +670,11 @@ static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsign static void MwLLSetXYImpl(MwLL handle, int x, int y) { if(handle->wayland.type != MWLL_WAYLAND_TOPLEVEL) { - MwLL topmost_parent = handle->wayland.parent; - - while(topmost_parent->wayland.type != MWLL_WAYLAND_TOPLEVEL) { - topmost_parent = topmost_parent->wayland.parent; - } - handle->wayland.x = x; handle->wayland.y = y; if(handle->wayland.has_set_xy) { - timed_redraw_by_epoch(topmost_parent, 25); - recursive_draw(topmost_parent); + timed_redraw_by_epoch(handle->wayland.topmost_parent, 25); + recursive_draw(handle->wayland.topmost_parent); } else if(x != 0 && y != 0) { handle->wayland.has_set_xy = MwTRUE; } @@ -676,23 +684,18 @@ static void MwLLSetXYImpl(MwLL handle, int x, int y) { static void MwLLSetWHImpl(MwLL handle, int w, int h) { /* Prevent an integer underflow when the w/h is too low */ if((w < 10 || h < 10)) { - handle->wayland.ww = 10; - handle->wayland.wh = 10; + handle->wayland.ww = handle->wayland.lw = 10; + handle->wayland.wh = handle->wayland.lh = 10; return; } - handle->wayland.ww = w; - handle->wayland.wh = h; + handle->wayland.ww = handle->wayland.lw = w; + handle->wayland.wh = handle->wayland.lh = h; if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { xdg_surface_set_window_geometry(handle->wayland.toplevel->xdg_surface, 0, 0, handle->wayland.ww, handle->wayland.wh); } else { - MwLL topmost_parent = handle->wayland.parent; - - while(topmost_parent->wayland.type != MWLL_WAYLAND_TOPLEVEL) { - topmost_parent = topmost_parent->wayland.parent; - } - timed_redraw_by_epoch(topmost_parent, 25); - recursive_draw(topmost_parent); + timed_redraw_by_epoch(handle->wayland.topmost_parent, 25); + recursive_draw(handle->wayland.topmost_parent); } } -- 2.39.5 From 36ed559da1cf94cda7b17ef5e8fa8304303f1c1e Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 8 Dec 2025 17:11:42 -0700 Subject: [PATCH 41/48] untested keyboard support --- include/Mw/LowLevel/Wayland.h | 2 + src/backend/wayland.c | 125 ++++++++++++++++++++++++++++------ 2 files changed, 108 insertions(+), 19 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 454de5c..a3b5ad0 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -44,6 +44,8 @@ struct _MwLLWaylandTopLevel { struct xdg_surface_listener xdg_surface_listener; struct xkb_context* xkb_context; + struct xkb_keymap* xkb_keymap; + struct xkb_state* xkb_state; MwBool compositor_created; MwBool xdg_wm_base_created; diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 14cd116..ee2770f 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -16,13 +16,12 @@ #else #include #endif + /* - callback todo: - void (*key)(MwLL handle, void* data); - void (*key_released)(MwLL handle, void* data); - void (*focus_in)(MwLL handle, void* data); - void (*focus_out)(MwLL handle, void* data); -*/ + * GENERAL TODO: + * comment the file lmao + * make sure MwLLDestroy is finished (+ handle dropdown bug that results from it) + */ static void timed_redraw(MwLL handle, MwU32 time, int cooldown, MwU64* cooldown_timer); @@ -50,9 +49,11 @@ static void protocol_removed(void* data, static void pointer_enter(void* data, struct wl_pointer* wl_pointer, MwU32 serial, struct wl_surface* surface, wl_fixed_t surface_x, - wl_fixed_t surface_y) {}; + wl_fixed_t surface_y) { +}; static void pointer_leave(void* data, struct wl_pointer* wl_pointer, MwU32 serial, - struct wl_surface* surface) {}; + struct wl_surface* surface) { +}; static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time, wl_fixed_t surface_x, wl_fixed_t surface_y) { MwLL self = data; @@ -103,6 +104,102 @@ struct wl_pointer_listener pointer_listener = { .axis = pointer_axis, }; +static void keyboard_keymap(void* data, + struct wl_keyboard* wl_keyboard, + uint32_t format, + int32_t fd, + uint32_t size) { + MwLL self = data; + if(self->wayland.type == MWLL_WAYLAND_TOPLEVEL) { + struct _MwLLWaylandTopLevel* wayland = self->wayland.toplevel; + assert(format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1); + + char* map_shm = (char*)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + assert(map_shm != MAP_FAILED); + + struct xkb_keymap* xkb_keymap = xkb_keymap_new_from_string( + wayland->xkb_context, map_shm, XKB_KEYMAP_FORMAT_TEXT_V1, + XKB_KEYMAP_COMPILE_NO_FLAGS); + munmap(map_shm, size); + close(fd); + + struct xkb_state* xkb_state = xkb_state_new(xkb_keymap); + xkb_keymap_unref(wayland->xkb_keymap); + xkb_state_unref(wayland->xkb_state); + + wayland->xkb_keymap = xkb_keymap; + wayland->xkb_state = xkb_state; + } +}; +static void keyboard_enter(void* data, + struct wl_keyboard* wl_keyboard, + uint32_t serial, + struct wl_surface* surface, + struct wl_array* keys) { + MwLL self = data; + MwLLDispatch(self, focus_in, NULL); +}; +static void keyboard_leave(void* data, + struct wl_keyboard* wl_keyboard, + uint32_t serial, + struct wl_surface* surface) { + MwLL self = data; + MwLLDispatch(self, focus_out, NULL); +}; +static void keyboard_key(void* data, + struct wl_keyboard* wl_keyboard, + uint32_t serial, + uint32_t time, + uint32_t key, + uint32_t state) { + MwLL self = data; + if(self->wayland.type == MWLL_WAYLAND_TOPLEVEL) { + struct _MwLLWaylandTopLevel* wayland = self->wayland.toplevel; + xkb_layout_index_t layout; + xkb_level_index_t level; + const xkb_keysym_t* syms_out; + MwU32 keycode = key + 8; + MwU64 syms_num; + int i; + + if(!wayland->xkb_keymap) { + return; + } + + layout = xkb_state_key_get_layout(wayland->xkb_state, keycode); + level = + xkb_keymap_num_levels_for_key(wayland->xkb_keymap, keycode, layout) - 1; + syms_num = xkb_keymap_key_get_syms_by_level(wayland->xkb_keymap, keycode, layout, level, &syms_out); + if(syms_out == NULL) { + return; + } + + for(i = 0; i < syms_num; i++) { + int sym = syms_out[i]; + if(state == WL_KEYBOARD_KEY_STATE_PRESSED) { + MwLLDispatch(self, key, &sym); + } else { + MwLLDispatch(self, key_released, &sym); + } + } + } +}; +static void keyboard_modifiers(void* data, + struct wl_keyboard* wl_keyboard, + uint32_t serial, + uint32_t mods_depressed, + uint32_t mods_latched, + uint32_t mods_locked, + uint32_t group) {}; + +struct wl_keyboard_listener keyboard_listener = { + .keymap = keyboard_keymap, + .enter = keyboard_enter, + .leave = keyboard_leave, + .key = keyboard_key, + .modifiers = keyboard_modifiers, +}; + static void wl_seat_name(void* data, struct wl_seat* wl_seat, const char* name) {}; static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat, @@ -110,7 +207,7 @@ static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat, MwLL self = data; if(capabilities & WL_SEAT_CAPABILITY_KEYBOARD) { struct wl_keyboard* keyboard = wl_seat_get_keyboard(wl_seat); - // wl_keyboard_add_listener(keyboard, const struct wl_keyboard_listener* listener, data); + wl_keyboard_add_listener(keyboard, &keyboard_listener, data); } if(capabilities & WL_SEAT_CAPABILITY_POINTER && !self->wayland.pointer) { self->wayland.pointer = wl_seat_get_pointer(wl_seat); @@ -490,16 +587,6 @@ static void setup_toplevel(MwLL r, int x, int y) { return; } - // Check that all globals we require are available - if( - r->wayland.compositor == NULL || - WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context == NULL) { - - printf("no xdg_wm_base support\n"); - raise(SIGTRAP); - return; - } - r->wayland.toplevel->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); // Create a wl_surface, a xdg_surface and a xdg_toplevel -- 2.39.5 From d9f543e2cc61d9d748d4ee0406153f2a1e7817d4 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 8 Dec 2025 23:05:25 -0700 Subject: [PATCH 42/48] opengl support --- include/Mw/LowLevel/Wayland.h | 1 + src/backend/wayland.c | 91 ++++++++++++++++++++--------------- src/widget/opengl.c | 39 ++++++++++++++- 3 files changed, 90 insertions(+), 41 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index a3b5ad0..5da10ae 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -103,6 +103,7 @@ struct _MwLLWayland { MwLL parent; MwLL topmost_parent; MwBool draw_recursively; + MwBool no_viewport; GLuint fbo; unsigned int fbo_texture; diff --git a/src/backend/wayland.c b/src/backend/wayland.c index ee2770f..b87eea4 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -288,7 +288,7 @@ static wayland_protocol_t* zxdg_decoration_manager_v1_setup(MwU32 name, struct _ return proto; } -static MwBool egl_setup(MwLL self, int width, int height) { +static MwBool egl_setup(MwLL self, int x, int y, int width, int height) { int err; EGLint numConfigs; EGLint majorVersion; @@ -367,28 +367,18 @@ static MwBool egl_setup(MwLL self, int width, int height) { } } - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, width, height, 0, -1, 1); glEnable(GL_TEXTURE_2D); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); + glViewport(x, y, width, height); return MwTRUE; } static void egl_resetup(MwLL handle) { int err; - - // if(!eglMakeCurrent(handle->wayland.egl_display, handle->wayland.egl_surface, handle->wayland.egl_surface, handle->wayland.egl_context)) { - // printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); - // return; - // } - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, handle->wayland.ww, handle->wayland.wh, 0, -1, 1); - glViewport(0, 0, handle->wayland.ww, handle->wayland.wh); + glViewport(handle->wayland.x, handle->wayland.y, handle->wayland.ww, handle->wayland.wh); + glScissor(handle->wayland.x, handle->wayland.y, handle->wayland.ww, handle->wayland.wh); } static void recursive_draw(MwLL handle) { @@ -442,7 +432,7 @@ static void xdg_toplevel_configure(void* data, MwLLDispatch(self, resize, NULL); if(!self->wayland.egl_setup) { - self->wayland.egl_setup = egl_setup(self, width, height); + self->wayland.egl_setup = egl_setup(self, self->wayland.x, self->wayland.y, width, height); } else { wl_egl_window_resize(self->wayland.egl_window_native, width, height, 0, 0); egl_resetup(self); @@ -532,6 +522,7 @@ static int event_loop(MwLL handle) { if(wayland->resize_counter >= 5) { wayland->lw = wayland->ww; wayland->lh = wayland->wh; + wayland->lh = wayland->wh; wayland->resize_counter = 0; } } @@ -685,7 +676,7 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { r->wayland.configured = MwTRUE; if(!r->wayland.egl_setup) { - r->wayland.egl_setup = egl_setup(r, r->wayland.ww, r->wayland.wh); + r->wayland.egl_setup = egl_setup(r, r->wayland.x, r->wayland.y, r->wayland.ww, r->wayland.wh); egl_resetup(r); MwLLDispatch(r, draw, NULL); recursive_draw(r); @@ -733,6 +724,9 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r->wayland.force_redraw = MwFALSE; r->wayland.subwidgets = NULL; r->wayland.pointer = NULL; + + r->wayland.no_viewport = MwTRUE; + if(parent == NULL) { setup_toplevel(r, x, y); } else { @@ -760,7 +754,7 @@ static void MwLLSetXYImpl(MwLL handle, int x, int y) { handle->wayland.x = x; handle->wayland.y = y; if(handle->wayland.has_set_xy) { - timed_redraw_by_epoch(handle->wayland.topmost_parent, 25); + timed_redraw_by_epoch(handle->wayland.topmost_parent, 15); recursive_draw(handle->wayland.topmost_parent); } else if(x != 0 && y != 0) { handle->wayland.has_set_xy = MwTRUE; @@ -781,7 +775,7 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { xdg_surface_set_window_geometry(handle->wayland.toplevel->xdg_surface, 0, 0, handle->wayland.ww, handle->wayland.wh); } else { - timed_redraw_by_epoch(handle->wayland.topmost_parent, 25); + timed_redraw_by_epoch(handle->wayland.topmost_parent, 15); recursive_draw(handle->wayland.topmost_parent); } } @@ -790,14 +784,23 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL int i, n; float maxX = 0, maxY = 0; float centerX, centerY; + float w, h; + + if(handle->wayland.parent == NULL) { + w = handle->wayland.ww; + h = handle->wayland.wh; + } else { + w = handle->wayland.parent->wayland.ww; + h = handle->wayland.parent->wayland.wh; + } glColor3f(color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); glBegin(GL_POLYGON); for(i = 0; i < points_count; i++) { - float x = round(handle->wayland.x) + round(points[i].x); - float y = round(handle->wayland.y) + round(points[i].y); + float x = ((float)(handle->wayland.x + points[i].x) / (w / 2)) - 1.0; + float y = 1.0 - ((float)(handle->wayland.y + points[i].y) / (h / 2)); glVertex2f(x, y); } @@ -806,15 +809,24 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL } static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { - int i; + int i; + float w, h; + + if(handle->wayland.parent == NULL) { + w = handle->wayland.ww; + h = handle->wayland.wh; + } else { + w = handle->wayland.parent->wayland.ww; + h = handle->wayland.parent->wayland.wh; + } glLineWidth(1); glColor3f(color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); glBegin(GL_LINES); for(i = 0; i < 2; i++) { - float x = round(handle->wayland.x) + round(points[i].x); - float y = round(handle->wayland.y) + round(points[i].y); + float x = ((float)(handle->wayland.x + points[i].x) / (w / 2)) - 1.0; + float y = 1.0 - ((float)(handle->wayland.y + points[i].y) / (h / 2)); glVertex2f(x, y); } @@ -823,6 +835,7 @@ static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { } static void MwLLBeginDrawImpl(MwLL handle) { + egl_resetup(handle); if(handle->wayland.parent == NULL) { if(!eglMakeCurrent(handle->wayland.egl_display, handle->wayland.egl_surface, handle->wayland.egl_surface, handle->wayland.egl_context)) { printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); @@ -836,15 +849,6 @@ static void MwLLBeginDrawImpl(MwLL handle) { static void MwLLEndDrawImpl(MwLL handle) { int w, h; - if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { - w = handle->wayland.ww; - h = handle->wayland.wh; - } else { - MwLL parent = handle->wayland.parent; - w = parent->wayland.ww; - h = parent->wayland.wh; - } - recursive_draw(handle); // glClear(GL_COLOR_BUFFER_BIT); @@ -933,11 +937,20 @@ static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { } static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { - int x, y; - glColor3f(1.0, 1.0, 1.0); + float x, y, w, h; - x = handle->wayland.x + rect->x; - y = handle->wayland.y + rect->y; + if(handle->wayland.parent == NULL) { + w = handle->wayland.ww; + h = handle->wayland.wh; + } else { + w = handle->wayland.parent->wayland.ww; + h = handle->wayland.parent->wayland.wh; + } + + x = ((float)(handle->wayland.x + rect->x) / (w / 2)) - 1.0; + y = 1.0 - ((float)(handle->wayland.y + rect->y) / (h / 2)); + + glColor3f(1.0, 1.0, 1.0); glBindTexture(GL_TEXTURE_2D, pixmap->wayland.texture); glActiveTexture(pixmap->wayland.texture); @@ -946,11 +959,11 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { glTexCoord2f(0.0f, 0); glVertex2f(x, y); glTexCoord2f(1, 0); - glVertex2f(x + rect->width, y); + glVertex2f(x + (rect->width / (w / 2)), y); glTexCoord2f(1, 1); - glVertex2f(x + rect->width, y + rect->height); + glVertex2f(x + (rect->width / (w / 2)), y - (rect->height / (h / 2))); glTexCoord2f(0.0f, 1); - glVertex2f(x, y + rect->height); + glVertex2f(x, y - (rect->height / (h / 2))); glEnd(); glFinish(); } diff --git a/src/widget/opengl.c b/src/widget/opengl.c index 05257e3..1e07ddd 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -1,6 +1,12 @@ #include #include +#ifdef USE_WAYLAND +#include +#include +#include +#endif + #ifdef USE_GDI typedef HGLRC(WINAPI* MWwglCreateContext)(HDC); typedef BOOL(WINAPI* MWwglMakeCurrent)(HDC, HGLRC); @@ -89,8 +95,7 @@ static int create(MwWidget handle) { 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"); @@ -104,6 +109,13 @@ static int create(MwWidget handle) { o->gl = o->glXCreateContext(handle->lowlevel->x11.display, o->visual, NULL, GL_TRUE); } #endif +#ifdef USE_WAYLAND + /* Wayland uses OpenGL as its backend so its already initialized */ + if(handle->lowlevel->common.type == MwLLBackendWayland) { + handle->lowlevel->wayland.no_viewport = MwTRUE; + } +#endif + handle->internal = r; handle->lowlevel->common.copy_buffer = 0; @@ -134,6 +146,10 @@ static void destroy(MwWidget handle) { MwDynamicClose(o->lib); } #endif +#ifdef USE_WAYLAND +/* Wayland uses OpenGL as its backend so its destroyed accordingly */ +#endif + free(handle->internal); } @@ -152,6 +168,10 @@ static void mwOpenGLMakeCurrentImpl(MwWidget handle) { o->glXMakeCurrent(handle->lowlevel->x11.display, handle->lowlevel->x11.window, o->gl); } #endif +#ifdef USE_WAYLAND + if(handle->lowlevel->common.type == MwLLBackendWayland) { + } +#endif } static void mwOpenGLSwapBufferImpl(MwWidget handle) { @@ -169,6 +189,16 @@ static void mwOpenGLSwapBufferImpl(MwWidget handle) { o->glXSwapBuffers(handle->lowlevel->x11.display, handle->lowlevel->x11.window); } #endif +#ifdef USE_WAYLAND +#define tp handle->lowlevel->wayland.topmost_parent->wayland + if(handle->lowlevel->common.type == MwLLBackendWayland) { + if(!eglSwapBuffers( + tp.egl_display, tp.egl_surface)) { + printf("Userland error: eglSwapBuffers, %0X\n", eglGetError()); + } + } +#undef topmost_parent +#endif } static void* mwOpenGLGetProcAddressImpl(MwWidget handle, const char* name) { @@ -185,6 +215,11 @@ static void* mwOpenGLGetProcAddressImpl(MwWidget handle, const char* name) { return o->glXGetProcAddress((const GLubyte*)name); } +#endif +#ifdef USE_WAYLAND + if(handle->lowlevel->common.type == MwLLBackendWayland) { + return eglGetProcAddress(name); + } #endif return NULL; } -- 2.39.5 From 4513475528535783536b5cca0eb2987a2b5946fd Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 8 Dec 2025 23:53:00 -0700 Subject: [PATCH 43/48] opengl support --- src/backend/wayland.c | 45 +++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/src/backend/wayland.c b/src/backend/wayland.c index b87eea4..ea00809 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -370,15 +370,22 @@ static MwBool egl_setup(MwLL self, int x, int y, int width, int height) { glEnable(GL_TEXTURE_2D); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - glViewport(x, y, width, height); return MwTRUE; } static void egl_resetup(MwLL handle) { - int err; - glViewport(handle->wayland.x, handle->wayland.y, handle->wayland.ww, handle->wayland.wh); - glScissor(handle->wayland.x, handle->wayland.y, handle->wayland.ww, handle->wayland.wh); + float w, h; + + if(handle->wayland.parent == NULL) { + w = handle->wayland.ww; + h = handle->wayland.wh; + } else { + w = handle->wayland.parent->wayland.ww; + h = handle->wayland.parent->wayland.wh; + } + + glViewport(handle->wayland.x, handle->wayland.y, w, h); } static void recursive_draw(MwLL handle) { @@ -556,8 +563,9 @@ static void setup_callbacks(struct _MwLLWayland* wayland) { static void setup_toplevel(MwLL r, int x, int y) { int i; - r->wayland.type = MWLL_WAYLAND_TOPLEVEL; - r->wayland.toplevel = malloc(sizeof(struct _MwLLWaylandTopLevel)); + r->wayland.type = MWLL_WAYLAND_TOPLEVEL; + r->wayland.toplevel = malloc(sizeof(struct _MwLLWaylandTopLevel)); + r->wayland.topmost_parent = NULL; setup_callbacks(&r->wayland); @@ -754,8 +762,8 @@ static void MwLLSetXYImpl(MwLL handle, int x, int y) { handle->wayland.x = x; handle->wayland.y = y; if(handle->wayland.has_set_xy) { - timed_redraw_by_epoch(handle->wayland.topmost_parent, 15); - recursive_draw(handle->wayland.topmost_parent); + timed_redraw_by_epoch(handle->wayland.topmost_parent, 25); + // recursive_draw(handle->wayland.topmost_parent); } else if(x != 0 && y != 0) { handle->wayland.has_set_xy = MwTRUE; } @@ -775,8 +783,8 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { xdg_surface_set_window_geometry(handle->wayland.toplevel->xdg_surface, 0, 0, handle->wayland.ww, handle->wayland.wh); } else { - timed_redraw_by_epoch(handle->wayland.topmost_parent, 15); - recursive_draw(handle->wayland.topmost_parent); + timed_redraw_by_epoch(handle->wayland.topmost_parent, 25); + // recursive_draw(handle->wayland.topmost_parent); } } @@ -790,8 +798,8 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL w = handle->wayland.ww; h = handle->wayland.wh; } else { - w = handle->wayland.parent->wayland.ww; - h = handle->wayland.parent->wayland.wh; + w = handle->wayland.topmost_parent->wayland.ww; + h = handle->wayland.topmost_parent->wayland.wh; } glColor3f(color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0); @@ -812,12 +820,12 @@ static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { int i; float w, h; - if(handle->wayland.parent == NULL) { + if(handle->wayland.topmost_parent == NULL) { w = handle->wayland.ww; h = handle->wayland.wh; } else { - w = handle->wayland.parent->wayland.ww; - h = handle->wayland.parent->wayland.wh; + w = handle->wayland.topmost_parent->wayland.ww; + h = handle->wayland.topmost_parent->wayland.wh; } glLineWidth(1); @@ -835,7 +843,6 @@ static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { } static void MwLLBeginDrawImpl(MwLL handle) { - egl_resetup(handle); if(handle->wayland.parent == NULL) { if(!eglMakeCurrent(handle->wayland.egl_display, handle->wayland.egl_surface, handle->wayland.egl_surface, handle->wayland.egl_context)) { printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); @@ -939,12 +946,12 @@ static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) { static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { float x, y, w, h; - if(handle->wayland.parent == NULL) { + if(handle->wayland.topmost_parent == NULL) { w = handle->wayland.ww; h = handle->wayland.wh; } else { - w = handle->wayland.parent->wayland.ww; - h = handle->wayland.parent->wayland.wh; + w = handle->wayland.topmost_parent->wayland.ww; + h = handle->wayland.topmost_parent->wayland.wh; } x = ((float)(handle->wayland.x + rect->x) / (w / 2)) - 1.0; -- 2.39.5 From ccdde06389360e9f439dbca2acb0702f9c2b9c5b Mon Sep 17 00:00:00 2001 From: IoIxD Date: Tue, 9 Dec 2025 00:23:11 -0700 Subject: [PATCH 44/48] don't compile with wayland by default --- pl/ostype/Linux.pl | 7 +--- src/backend/wayland.c | 97 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 81 insertions(+), 23 deletions(-) diff --git a/pl/ostype/Linux.pl b/pl/ostype/Linux.pl index 42b6397..f695e4f 100644 --- a/pl/ostype/Linux.pl +++ b/pl/ostype/Linux.pl @@ -1,8 +1,3 @@ -if (system("wayland-scanner -v >/dev/null 2>&1") == 0) { - use_backend("wayland", "x11"); -} -else { - use_backend("x11"); -} +use_backend("x11"); 1; diff --git a/src/backend/wayland.c b/src/backend/wayland.c index ea00809..2354e59 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -15,6 +15,7 @@ #include #else #include +#include #endif /* @@ -104,11 +105,31 @@ struct wl_pointer_listener pointer_listener = { .axis = pointer_axis, }; +static void recursive_key(MwLL handle, void* ud) { + int i; + if(handle->wayland.subwidgets != NULL) { + for(i = 0; i < arrlen(handle->wayland.subwidgets); i++) { + MwLLDispatch(handle->wayland.subwidgets[i], key, ud); + recursive_key(handle->wayland.subwidgets[i], ud); + } + } +} + +static void recursive_key_released(MwLL handle, void* ud) { + int i; + if(handle->wayland.subwidgets != NULL) { + for(i = 0; i < arrlen(handle->wayland.subwidgets); i++) { + MwLLDispatch(handle->wayland.subwidgets[i], key_released, ud); + recursive_key(handle->wayland.subwidgets[i], ud); + } + } +} + static void keyboard_keymap(void* data, struct wl_keyboard* wl_keyboard, - uint32_t format, + MwU32 format, int32_t fd, - uint32_t size) { + MwU32 size) { MwLL self = data; if(self->wayland.type == MWLL_WAYLAND_TOPLEVEL) { struct _MwLLWaylandTopLevel* wayland = self->wayland.toplevel; @@ -133,7 +154,7 @@ static void keyboard_keymap(void* data, }; static void keyboard_enter(void* data, struct wl_keyboard* wl_keyboard, - uint32_t serial, + MwU32 serial, struct wl_surface* surface, struct wl_array* keys) { MwLL self = data; @@ -141,17 +162,17 @@ static void keyboard_enter(void* data, }; static void keyboard_leave(void* data, struct wl_keyboard* wl_keyboard, - uint32_t serial, + MwU32 serial, struct wl_surface* surface) { MwLL self = data; MwLLDispatch(self, focus_out, NULL); }; static void keyboard_key(void* data, struct wl_keyboard* wl_keyboard, - uint32_t serial, - uint32_t time, - uint32_t key, - uint32_t state) { + MwU32 serial, + MwU32 time, + MwU32 key, + MwU32 state) { MwLL self = data; if(self->wayland.type == MWLL_WAYLAND_TOPLEVEL) { struct _MwLLWaylandTopLevel* wayland = self->wayland.toplevel; @@ -176,21 +197,63 @@ static void keyboard_key(void* data, for(i = 0; i < syms_num; i++) { int sym = syms_out[i]; + int key; + switch(sym) { + case XKB_KEY_BackSpace: + key = MwLLKeyBackSpace; + break; + case XKB_KEY_Left: + key = MwLLKeyLeft; + break; + case XKB_KEY_Right: + key = MwLLKeyRight; + break; + case XKB_KEY_Up: + key = MwLLKeyUp; + break; + case XKB_KEY_Down: + key = MwLLKeyDown; + break; + case XKB_KEY_Return: + key = MwLLKeyEnter; + break; + case XKB_KEY_Escape: + key = MwLLKeyEscape; + break; + case XKB_KEY_Shift_L: + key = MwLLKeyLeftShift; + break; + case XKB_KEY_Shift_R: + key = MwLLKeyRightShift; + break; + case XKB_KEY_Alt_L: + case XKB_KEY_Alt_R: + key = MwLLKeyAlt; + break; + case XKB_KEY_Control_L: + case XKB_KEY_Control_R: + key = MwLLKeyControl; + break; + default: + key = sym; + } if(state == WL_KEYBOARD_KEY_STATE_PRESSED) { - MwLLDispatch(self, key, &sym); + MwLLDispatch(self, key, &key); + recursive_key(self, &key); } else { - MwLLDispatch(self, key_released, &sym); + MwLLDispatch(self, key_released, &key); + recursive_key_released(self, &key); } } } }; static void keyboard_modifiers(void* data, struct wl_keyboard* wl_keyboard, - uint32_t serial, - uint32_t mods_depressed, - uint32_t mods_latched, - uint32_t mods_locked, - uint32_t group) {}; + MwU32 serial, + MwU32 mods_depressed, + MwU32 mods_latched, + MwU32 mods_locked, + MwU32 group) {}; struct wl_keyboard_listener keyboard_listener = { .keymap = keyboard_keymap, @@ -370,6 +433,7 @@ static MwBool egl_setup(MwLL self, int x, int y, int width, int height) { glEnable(GL_TEXTURE_2D); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); + glEnable(GL_SCISSOR_TEST); return MwTRUE; } @@ -386,6 +450,7 @@ static void egl_resetup(MwLL handle) { } glViewport(handle->wayland.x, handle->wayland.y, w, h); + glScissor(handle->wayland.x, handle->wayland.y, w, h); } static void recursive_draw(MwLL handle) { @@ -849,8 +914,6 @@ static void MwLLBeginDrawImpl(MwLL handle) { return; } } - // glClear(GL_COLOR_BUFFER_BIT); - // glClearColor(1.0, 0, 0, 1); } static void MwLLEndDrawImpl(MwLL handle) { -- 2.39.5 From e7f0d8a2628fc8cfcf4041e07e339595b54a4bc1 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Tue, 9 Dec 2025 00:46:54 -0700 Subject: [PATCH 45/48] comment and organize the file --- include/Mw/LowLevel/Wayland.h | 54 +++++----- src/backend/wayland.c | 185 +++++++++++++++++++--------------- src/widget/opengl.c | 1 - 3 files changed, 126 insertions(+), 114 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 5da10ae..575fcbe 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -54,18 +54,22 @@ struct _MwLLWaylandTopLevel { struct _MwLLWayland { struct _MwLLCommon common; - // data that's only loaded if it's a toplevel + + /* Pointer for data that's only loaded if the widget is a toplevel */ struct _MwLLWaylandTopLevel* toplevel; + enum { MWLL_WAYLAND_TOPLEVEL = 0, - MWLL_WAYLAND_SUBLEVEL = 1, + MWLL_WAYLAND_SUBLEVEL = 1, /* Sublevels are surfaces that have the toplevel as a parent. They could be implemented as subsurfaces if we ever switch away from OpenGL. Some parts of the code also call them subwidgets. */ } type; + /* Map of Wayland interfaces to their relevant setup functions. */ struct { const char* key; wl_setup_func* value; }* wl_protocol_setup_map; + /* Map of Wayland interfaces to any information we keep about them once we've registered them. */ struct { const char* key; wayland_protocol_t* value; @@ -76,43 +80,31 @@ struct _MwLLWayland { struct wl_compositor* compositor; struct wl_subcompositor* subcompositor; struct wl_surface* surface; - struct wl_shm* shm; struct wl_registry_listener registry_listener; struct wl_event_queue* event_queue; - struct wl_pointer* pointer; - - MwLL* subwidgets; - - MwBool configured; - MwBool force_redraw; - - MwBool egl_setup; - MwBool has_set_xy; - int resize_counter; - MwU32 x, y; - MwU32 ww, wh; - MwU32 lw, lh; - MwPoint cur_mouse_pos; - - struct timeval timer; - - MwU64 cooldown_timer; - MwU64 cooldown_timer_epoch; - - MwLL parent; - MwLL topmost_parent; - MwBool draw_recursively; - MwBool no_viewport; - - GLuint fbo; - unsigned int fbo_texture; - EGLNativeWindowType egl_window_native; EGLDisplay egl_display; EGLContext egl_context; EGLSurface egl_surface; EGLConfig egl_config; + + MwLL* sublevels; /* stb_ds managed array of any sublevels */ + MwBool configured; /* Whether or not xdg_toplevel_configure has run once */ + MwBool egl_setup; /* Whether or not EGL has been set up */ + MwBool has_set_xy /* Whether or not MwSetXY has been called */; + + int resize_counter; /* Counter that's for a hack in event_loop */ + MwU32 x, y, ww, wh; /* Window position */ + MwU32 lw, lh; /* Last known window position */ + MwPoint cur_mouse_pos; /* Currently known mouse position */ + + struct timeval timer; + MwU64 cooldown_timer; + MwU64 cooldown_timer_epoch; + + MwLL parent; + MwLL topmost_parent; /* The parent at the top of all the other parents. Usually a toplevel. */ }; struct _MwLLWaylandColor { diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 2354e59..307e1ee 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -19,15 +19,22 @@ #endif /* - * GENERAL TODO: - * comment the file lmao + * TODO: * make sure MwLLDestroy is finished (+ handle dropdown bug that results from it) + * GNOME doesn't want to support zxdg_decoration_protocol so we're gonna design some Windows 95 ass ui just for that window manager. + * finish the rest of the owl */ +/* + * Redraw `handle` if the given cooldown hasn't expired (`time` >= `cooldown_timer` + `cooldown)). + * Used for pointer callbacks, resize callbacks, etc. to ensure we only resize every x milliseconds + */ static void timed_redraw(MwLL handle, MwU32 time, int cooldown, MwU64* cooldown_timer); -#define WAYLAND_GET_INTERFACE(r, inter) shget(r.wl_protocol_map, inter##_interface.name) +/* Get the registered interface from r, or NULL if it doesn't currently have it. */ +#define WAYLAND_GET_INTERFACE(handle, inter) shget(handle.wl_protocol_map, inter##_interface.name) +/* `wl_registry.global` callback */ static void new_protocol(void* data, struct wl_registry* registry, MwU32 name, const char* interface, MwU32 version) { @@ -35,26 +42,32 @@ static void new_protocol(void* data, struct wl_registry* registry, wl_setup_func* func = shget(wayland->wl_protocol_setup_map, interface); if(func != NULL) { - // printf("registering interface %s\n", interface); + /* printf("registering interface %s\n", interface); */ shput(wayland->wl_protocol_map, interface, func(name, data)); } else { - // printf("unknown interface %s\n", interface); + /* printf("unknown interface %s\n", interface); */ } }; +/* `wl_registry.global_remove` callback */ static void protocol_removed(void* data, struct wl_registry* registry, MwU32 name) { }; +/* `wl_pointer.enter` callback */ static void pointer_enter(void* data, struct wl_pointer* wl_pointer, MwU32 serial, struct wl_surface* surface, wl_fixed_t surface_x, wl_fixed_t surface_y) { }; + +/* `wl_pointer.leave` callback */ static void pointer_leave(void* data, struct wl_pointer* wl_pointer, MwU32 serial, struct wl_surface* surface) { }; + +/* `wl_pointer.motion` callback */ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time, wl_fixed_t surface_x, wl_fixed_t surface_y) { MwLL self = data; @@ -67,6 +80,8 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time timed_redraw(self, time, 50, &self->wayland.cooldown_timer); }; + +/* `wl_pointer.button` callback */ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 serial, MwU32 time, MwU32 button, MwU32 state) { MwLL self = data; MwLLMouse p; @@ -94,6 +109,8 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri } MwLLDispatch(self, draw, NULL); }; + +/* `wl_pointer.axis` callback */ static void pointer_axis(void* data, struct wl_pointer* wl_pointer, MwU32 time, MwU32 axis, wl_fixed_t value) {}; @@ -105,26 +122,40 @@ struct wl_pointer_listener pointer_listener = { .axis = pointer_axis, }; +/* Recursively dispatch the key event to `handle` and its children */ static void recursive_key(MwLL handle, void* ud) { int i; - if(handle->wayland.subwidgets != NULL) { - for(i = 0; i < arrlen(handle->wayland.subwidgets); i++) { - MwLLDispatch(handle->wayland.subwidgets[i], key, ud); - recursive_key(handle->wayland.subwidgets[i], ud); + if(handle->wayland.sublevels != NULL) { + for(i = 0; i < arrlen(handle->wayland.sublevels); i++) { + MwLLDispatch(handle->wayland.sublevels[i], key, ud); + recursive_key(handle->wayland.sublevels[i], ud); } } } +/* Recursively dispatch the key_released event to `handle` and its children */ static void recursive_key_released(MwLL handle, void* ud) { int i; - if(handle->wayland.subwidgets != NULL) { - for(i = 0; i < arrlen(handle->wayland.subwidgets); i++) { - MwLLDispatch(handle->wayland.subwidgets[i], key_released, ud); - recursive_key(handle->wayland.subwidgets[i], ud); + if(handle->wayland.sublevels != NULL) { + for(i = 0; i < arrlen(handle->wayland.sublevels); i++) { + MwLLDispatch(handle->wayland.sublevels[i], key_released, ud); + recursive_key(handle->wayland.sublevels[i], ud); } } } +/* Recursively dispatch the draw event to `handle` and its children */ +static void recursive_draw(MwLL handle) { + int i; + if(handle->wayland.sublevels != NULL) { + for(i = 0; i < arrlen(handle->wayland.sublevels); i++) { + MwLLDispatch(handle->wayland.sublevels[i], draw, NULL); + recursive_draw(handle->wayland.sublevels[i]); + } + } +} + +/* `wl_keyboard.keymap` callback */ static void keyboard_keymap(void* data, struct wl_keyboard* wl_keyboard, MwU32 format, @@ -152,6 +183,8 @@ static void keyboard_keymap(void* data, wayland->xkb_state = xkb_state; } }; + +/* `wl_keyboard.enter` callback */ static void keyboard_enter(void* data, struct wl_keyboard* wl_keyboard, MwU32 serial, @@ -160,6 +193,8 @@ static void keyboard_enter(void* data, MwLL self = data; MwLLDispatch(self, focus_in, NULL); }; + +/* `wl_keyboard.leave` callback */ static void keyboard_leave(void* data, struct wl_keyboard* wl_keyboard, MwU32 serial, @@ -167,6 +202,8 @@ static void keyboard_leave(void* data, MwLL self = data; MwLLDispatch(self, focus_out, NULL); }; + +/* `wl_keyboard.key` callback */ static void keyboard_key(void* data, struct wl_keyboard* wl_keyboard, MwU32 serial, @@ -247,6 +284,8 @@ static void keyboard_key(void* data, } } }; + +/* `wl_keyboard.modifiers` callback */ static void keyboard_modifiers(void* data, struct wl_keyboard* wl_keyboard, MwU32 serial, @@ -263,8 +302,11 @@ struct wl_keyboard_listener keyboard_listener = { .modifiers = keyboard_modifiers, }; +/* `wl_seat.name` callback */ static void - wl_seat_name(void* data, struct wl_seat* wl_seat, const char* name) {}; +wl_seat_name(void* data, struct wl_seat* wl_seat, const char* name) {}; + +/* `wl_seat.capabilities` callback */ static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat, MwU32 capabilities) { MwLL self = data; @@ -272,20 +314,20 @@ static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat, struct wl_keyboard* keyboard = wl_seat_get_keyboard(wl_seat); wl_keyboard_add_listener(keyboard, &keyboard_listener, data); } - if(capabilities & WL_SEAT_CAPABILITY_POINTER && !self->wayland.pointer) { - self->wayland.pointer = wl_seat_get_pointer(wl_seat); - wl_pointer_add_listener(self->wayland.pointer, &pointer_listener, data); + if(capabilities & WL_SEAT_CAPABILITY_POINTER) { + struct wl_pointer* pointer = wl_seat_get_pointer(wl_seat); + wl_pointer_add_listener(pointer, &pointer_listener, data); } }; +/* `xdg_wm_base.ping` callback */ void xdg_wm_base_ping(void* data, struct xdg_wm_base* xdg_wm_base, MwU32 serial) { - // The compositor will send us a ping event to check that we're responsive. - // We need to send back a pong request immediately. xdg_wm_base_pong(xdg_wm_base, serial); }; +/* wl_seat setup function */ static wayland_protocol_t* wl_seat_setup(MwU32 name, MwLL ll) { wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); proto->listener = malloc(sizeof(struct wl_seat_listener)); @@ -299,18 +341,21 @@ static wayland_protocol_t* wl_seat_setup(MwU32 name, MwLL ll) { return proto; } +/* wl_compositor setup function */ static wayland_protocol_t* wl_compositor_setup(MwU32 name, struct _MwLLWayland* wayland) { wayland->compositor = wl_registry_bind(wayland->registry, name, &wl_compositor_interface, 1); return NULL; } +/* wl_subcompositor setup function */ static wayland_protocol_t* wl_subcompositor_setup(MwU32 name, struct _MwLLWayland* wayland) { wayland->subcompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1); return NULL; } +/* xdg_wm_base setup function */ static wayland_protocol_t* xdg_wm_base_setup(MwU32 name, struct _MwLLWayland* wayland) { wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); proto->listener = malloc(sizeof(struct xdg_wm_base_listener)); @@ -323,6 +368,7 @@ static wayland_protocol_t* xdg_wm_base_setup(MwU32 name, struct _MwLLWayland* wa return proto; } +/* wp_cursor_shape_manager setup function */ static wayland_protocol_t* wp_cursor_shape_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland) { wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); proto->listener = NULL; @@ -332,12 +378,13 @@ static wayland_protocol_t* wp_cursor_shape_manager_v1_setup(MwU32 name, struct _ return proto; } +/* the two decoration manager constructs */ typedef struct zxdg_decoration_manager_v1_context { - struct zxdg_decoration_manager_v1* manager; - // struct zxdg_decoration_toplevel_v1* toplevel; + struct zxdg_decoration_manager_v1* manager; struct zxdg_toplevel_decoration_v1* decoration; } zxdg_decoration_manager_v1_context_t; +/* zxdg_decoration_manager_v1 setup function */ static wayland_protocol_t* zxdg_decoration_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland) { wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); zxdg_decoration_manager_v1_context_t* ctx = malloc(sizeof(zxdg_decoration_manager_v1_context_t)); @@ -351,6 +398,7 @@ static wayland_protocol_t* zxdg_decoration_manager_v1_setup(MwU32 name, struct _ return proto; } +/* EGL Setup function */ static MwBool egl_setup(MwLL self, int x, int y, int width, int height) { int err; EGLint numConfigs; @@ -379,19 +427,19 @@ static MwBool egl_setup(MwLL self, int x, int y, int width, int height) { printf("ERROR: eglGetDisplay, %0X\n", eglGetError()); return MwFALSE; } - // Initialize EGL + /* Initialize EGL */ if(!eglInitialize(display, &majorVersion, &minorVersion)) { printf("ERROR: eglInitialize, %0X\n", eglGetError()); return MwFALSE; } - // Get configs + /* Get configs */ if((eglGetConfigs(display, NULL, 0, &numConfigs) != EGL_TRUE) || (numConfigs == 0)) { printf("ERROR: eglGetConfigs, %0X\n", eglGetError()); return MwFALSE; } - // Choose config + /* Choose config */ if((eglChooseConfig(display, fbAttribs, &self->wayland.egl_config, 1, &numConfigs) != EGL_TRUE) || (numConfigs != 1)) { printf("ERROR: eglChooseConfig, %0X\n", eglGetError()); return MwFALSE; @@ -404,7 +452,7 @@ static MwBool egl_setup(MwLL self, int x, int y, int width, int height) { return MwFALSE; } - // Create a surface + /* Create a surface */ surface = eglCreateWindowSurface(display, self->wayland.egl_config, self->wayland.egl_window_native, NULL); if(surface == EGL_NO_SURFACE) { printf("ERROR: eglCreateWindowSurface, %0X\n", eglGetError()); @@ -413,7 +461,7 @@ static MwBool egl_setup(MwLL self, int x, int y, int width, int height) { eglBindAPI(EGL_OPENGL_API); - // Create a GL context + /* Create a GL context */ context = eglCreateContext(display, self->wayland.egl_config, EGL_NO_CONTEXT, contextAttribs); if(context == EGL_NO_CONTEXT) { printf("ERROR: eglCreateContext, %0X\n", eglGetError()); @@ -438,6 +486,7 @@ static MwBool egl_setup(MwLL self, int x, int y, int width, int height) { return MwTRUE; } +/* EGL reconfiguration function for resizes */ static void egl_resetup(MwLL handle) { float w, h; @@ -453,27 +502,17 @@ static void egl_resetup(MwLL handle) { glScissor(handle->wayland.x, handle->wayland.y, w, h); } -static void recursive_draw(MwLL handle) { - int i; - if(handle->wayland.subwidgets != NULL) { - for(i = 0; i < arrlen(handle->wayland.subwidgets); i++) { - MwLLDispatch(handle->wayland.subwidgets[i], draw, NULL); - recursive_draw(handle->wayland.subwidgets[i]); - } - } -} - static void timed_redraw(MwLL handle, MwU32 time, int cooldown, MwU64* cooldown_timer) { if(handle->wayland.parent == NULL) { if(time >= (*cooldown_timer + cooldown)) { egl_resetup(handle); MwLLDispatch(handle, draw, NULL); - // recursive_draw(handle); *cooldown_timer = time; } } } +/* Same as timed_redraw but it uses the unix epoch as the cooldown timer. */ static void timed_redraw_by_epoch(MwLL handle, int cooldown) { gettimeofday(&handle->wayland.timer, NULL); unsigned long long time = @@ -482,6 +521,7 @@ static void timed_redraw_by_epoch(MwLL handle, int cooldown) { timed_redraw(handle, time, cooldown, &handle->wayland.cooldown_timer_epoch); } +/* `xdg_toplevel.close` callback */ static void xdg_toplevel_configure(void* data, struct xdg_toplevel* xdg_toplevel, MwI32 width, MwI32 height, @@ -491,7 +531,7 @@ static void xdg_toplevel_configure(void* data, if(width == 0 || height == 0) { width = self->wayland.ww; height = self->wayland.wh; - // if it's still 0 then bail + /* if it's still 0 then bail */ if(width == 0 || height == 0) { return; } @@ -513,35 +553,34 @@ static void xdg_toplevel_configure(void* data, return; }; +/* Empty function for satisfying zxdg_toplevel's requirements */ static void decoration_configure( void* data, struct zxdg_toplevel_decoration_v1* zxdg_toplevel_decoration_v1, MwU32 mode) { } +/* `xdg_surface.close` callback */ static void xdg_toplevel_close( void* data, struct xdg_toplevel* xdg_toplevel) { MwLL self = data; MwLLDispatch(self, close, NULL); }; +/* `xdg_surface.configure` callback */ static void xdg_surface_configure( void* data, struct xdg_surface* xdg_surface, MwU32 serial) { MwLL self = data; - // The compositor configures our surface, acknowledge the configure event xdg_surface_ack_configure(xdg_surface, serial); if(self->wayland.configured) { - // If this isn't the first configure event we've received, we already - // have a buffer attached, so no need to do anything. Commit the - // surface to apply the configure acknowledgement. - // wl_surface_attach(self->surface, self->buffer, 0, 0); wl_surface_commit(self->wayland.surface); } self->wayland.configured = MwTRUE; } +/* Standard Wayland event loop. */ static int event_loop(MwLL handle) { enum { DISPLAY_FD, @@ -604,10 +643,13 @@ static int event_loop(MwLL handle) { return 0; } +/* 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 */ #define WL_INTERFACE(interface) \ shput(wayland->wl_protocol_setup_map, interface##_interface.name, (wl_setup_func*)interface##_setup); -static void setup_callbacks(struct _MwLLWayland* wayland) { wayland->registry_listener.global = new_protocol; wayland->registry_listener.global_remove = protocol_removed; wayland->wl_protocol_setup_map = NULL; @@ -621,10 +663,10 @@ static void setup_callbacks(struct _MwLLWayland* wayland) { WL_INTERFACE(zxdg_decoration_manager_v1); WL_INTERFACE(wp_cursor_shape_manager_v1); } +#undef WL_INTERFACE } -#undef WL_INTERFACE - +/* Toplevel setup function */ static void setup_toplevel(MwLL r, int x, int y) { int i; @@ -634,7 +676,7 @@ static void setup_toplevel(MwLL r, int x, int y) { setup_callbacks(&r->wayland); - // Connect to the Wayland compositor + /* Connect to the Wayland compositor */ r->wayland.display = wl_display_connect(NULL); if(r->wayland.display == NULL) { printf("wayland: failed to create display\n"); @@ -642,7 +684,7 @@ static void setup_toplevel(MwLL r, int x, int y) { return; } - // Do a roundtrip to ensure all interfaces are setup. + /* 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); if(wl_display_roundtrip(r->wayland.display) == -1) { @@ -653,13 +695,13 @@ static void setup_toplevel(MwLL r, int x, int y) { r->wayland.toplevel->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - // Create a wl_surface, a xdg_surface and a xdg_toplevel + /* Create a wl_surface, a xdg_surface and a xdg_toplevel */ r->wayland.surface = wl_compositor_create_surface(r->wayland.compositor); r->wayland.toplevel->xdg_surface = xdg_wm_base_get_xdg_surface(WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context, r->wayland.surface); r->wayland.toplevel->xdg_top_level = xdg_surface_get_toplevel(r->wayland.toplevel->xdg_surface); - // setup mandatory listeners + /* setup mandatory listeners */ r->wayland.toplevel->xdg_surface_listener.configure = xdg_surface_configure; r->wayland.toplevel->xdg_toplevel_listener.configure = xdg_toplevel_configure; @@ -672,11 +714,11 @@ static void setup_toplevel(MwLL r, int x, int y) { xdg_toplevel_set_title(r->wayland.toplevel->xdg_top_level, "Milsko App"); xdg_toplevel_set_app_id(r->wayland.toplevel->xdg_top_level, "MilskoWaylandApp"); - // Perform the initial commit and wait for the first configure event + /* Perform the initial commit and wait for the first configure event */ wl_surface_commit(r->wayland.surface); event_loop(r); - // setup decorations if we can + /* setup decorations if we can */ if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL) { zxdg_decoration_manager_v1_context_t* dec = WAYLAND_GET_INTERFACE(r->wayland, zxdg_decoration_manager_v1)->context; @@ -694,12 +736,9 @@ static void setup_toplevel(MwLL r, int x, int y) { egl_resetup(r); MwLLDispatch(r, draw, NULL); recursive_draw(r); - - // buffer_setup(&r->wayland); - - // glGenBuffers(1, &vertex_buffer); } +/* Sublevel setup function */ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { struct wl_compositor* compositor = parent->wayland.compositor; struct wl_subcompositor* subcompositor = parent->wayland.subcompositor; @@ -727,12 +766,6 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { event_loop(r); wl_region_destroy(region); - // r->wayland.sublevel = wl_subcompositor_get_sublevel(subcompositor, r->wayland.surface, parent_surface); - - // wl_sublevel_set_position(r->wayland.sublevel, x, y); - - // printf("position %d %d\n", x, y); - setup_callbacks(&r->wayland); r->wayland.registry = wl_display_get_registry(r->wayland.topmost_parent->wayland.display); @@ -745,8 +778,6 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { return; } - // arrpush(parent->wayland.sublevels, r); - r->wayland.configured = MwTRUE; if(!r->wayland.egl_setup) { r->wayland.egl_setup = egl_setup(r, r->wayland.x, r->wayland.y, r->wayland.ww, r->wayland.wh); @@ -757,7 +788,7 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { r->wayland.event_queue = parent->wayland.event_queue; - arrpush(parent->wayland.subwidgets, r); + arrpush(parent->wayland.sublevels, r); wl_surface_damage(parent->wayland.surface, 0, 0, parent->wayland.ww, parent->wayland.wh); @@ -794,11 +825,7 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r->wayland.has_set_xy = MwFALSE; r->wayland.resize_counter = 0; - r->wayland.force_redraw = MwFALSE; - r->wayland.subwidgets = NULL; - r->wayland.pointer = NULL; - - r->wayland.no_viewport = MwTRUE; + r->wayland.sublevels = NULL; if(parent == NULL) { setup_toplevel(r, x, y); @@ -828,7 +855,7 @@ static void MwLLSetXYImpl(MwLL handle, int x, int y) { handle->wayland.y = y; if(handle->wayland.has_set_xy) { timed_redraw_by_epoch(handle->wayland.topmost_parent, 25); - // recursive_draw(handle->wayland.topmost_parent); + /* recursive_draw(handle->wayland.topmost_parent); */ } else if(x != 0 && y != 0) { handle->wayland.has_set_xy = MwTRUE; } @@ -849,7 +876,7 @@ 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); } else { timed_redraw_by_epoch(handle->wayland.topmost_parent, 25); - // recursive_draw(handle->wayland.topmost_parent); + /* recursive_draw(handle->wayland.topmost_parent); */ } } @@ -921,8 +948,8 @@ static void MwLLEndDrawImpl(MwLL handle) { recursive_draw(handle); - // glClear(GL_COLOR_BUFFER_BIT); - // glClearColor(1.0, 0, 0, 1); + /* glClear(GL_COLOR_BUFFER_BIT); */ + /* glClearColor(1.0, 0, 0, 1); */ if(handle->wayland.parent == NULL) { if(!eglSwapBuffers(handle->wayland.egl_display, handle->wayland.egl_surface)) { @@ -960,11 +987,6 @@ static int MwLLPendingImpl(MwLL handle) { } static void MwLLNextEventImpl(MwLL handle) { - MwBool render = handle->wayland.force_redraw; - - if(render) { - handle->wayland.force_redraw = MwFALSE; - } } static void MwLLSetTitleImpl(MwLL handle, const char* title) { @@ -1046,7 +1068,6 @@ static void MwLLForceRenderImpl(MwLL handle) { if(handle->wayland.egl_setup) { timed_redraw_by_epoch(handle, 25); } - handle->wayland.force_redraw = MwTRUE; } static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { @@ -1070,7 +1091,7 @@ static void MwLLSetSizeHintsImpl(MwLL handle, int minx, int miny, int maxx, int static void MwLLMakeBorderlessImpl(MwLL handle, int toggle) { if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { - if(WAYLAND_GET_INTERFACE(handle->wayland, zxdg_decoration_manager_v1)->context != NULL) { + if(WAYLAND_GET_INTERFACE(handle->wayland, zxdg_decoration_manager_v1) != NULL) { zxdg_decoration_manager_v1_context_t* dec = WAYLAND_GET_INTERFACE(handle->wayland, zxdg_decoration_manager_v1)->context; dec->decoration = zxdg_decoration_manager_v1_get_toplevel_decoration( @@ -1079,7 +1100,7 @@ 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. + /* TODO: hide our custom window decorations when we have them. */ printf("zxdg null\n"); } } diff --git a/src/widget/opengl.c b/src/widget/opengl.c index 1e07ddd..f6cc369 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -112,7 +112,6 @@ static int create(MwWidget handle) { #ifdef USE_WAYLAND /* Wayland uses OpenGL as its backend so its already initialized */ if(handle->lowlevel->common.type == MwLLBackendWayland) { - handle->lowlevel->wayland.no_viewport = MwTRUE; } #endif -- 2.39.5 From 61d8a7202677937e36a1cd1bfc143a05835c7d54 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Tue, 9 Dec 2025 00:48:38 -0700 Subject: [PATCH 46/48] merge gitignore --- .gitignore | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index a5e12aa..005ebea 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,14 @@ +examples/* +examples/*.exe +examples/*/* +examples/*/*.exe +!examples/*/ +!examples/*.* +!examples/*/*.* *.o *.so *.dll -examples/*.exe -examples/*/* -!examples/*/*.c -!examples/*/*.spv -compile_flags.txt +*.lib *.a -Makefile +/Makefile +compile_flags.txt -- 2.39.5 From afff0e9eb086685796ecb7b84b848dbe2b662bb3 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Tue, 9 Dec 2025 01:00:18 -0700 Subject: [PATCH 47/48] remove nonfuncxtional clangd --- .clangd | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .clangd diff --git a/.clangd b/.clangd deleted file mode 100644 index 7abd528..0000000 --- a/.clangd +++ /dev/null @@ -1 +0,0 @@ -header-insertion: never -- 2.39.5 From 2fd445b80f6ccb14ff19d14c10928834359e9040 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Tue, 9 Dec 2025 01:03:05 -0700 Subject: [PATCH 48/48] Wayland.h warning clarifying this is disabled by default --- include/Mw/LowLevel/Wayland.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 575fcbe..af80f47 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -1,7 +1,8 @@ /*! * @file Mw/LowLevel/Wayland.h - * @brief Wayland Backend - * @warning This is used internally + * @brief Work in progress Wayland Backend + * @warning This is used internally. + * @warning This is disabled by default. */ #ifndef __MW_LOWLEVEL_WAYLAND_H__ #define __MW_LOWLEVEL_WAYLAND_H__ -- 2.39.5