From fe17eefb215a8d2fb26b6b0599b25619a638a349 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 18:07:34 -0700 Subject: [PATCH 1/7] revert hyprland code --- src/backend/wayland/interfaces.c | 8 +- src/draw.c | 355 +++++++------------------------ 2 files changed, 76 insertions(+), 287 deletions(-) diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index a7245912..84ed4923 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -40,19 +40,15 @@ static void new_protocol(void* data, struct wl_registry* registry, MwLL self = data; (void)version; (void)registry; - wayland_protocol_callback_table_t* cb; WAYLAND_EVENT_OP_START(self); - cb = shget(self->wayland.wl_protocol_setup_map, interface); + wayland_protocol_callback_table_t* cb = shget(self->wayland.wl_protocol_setup_map, interface); if(cb != NULL) { shput(self->wayland.wl_protocol_map, interface, cb->setup(name, data, version)); - } else if(strcmp(interface, "wp_alpha_modifier_v1") == 0) { /* we don't care for adding this protocol, we just use it to know if the compositor will let us have transparent surfaces */ + } else if(strcmp(interface, "wp_alpha_modifier_v1") == 0) { self->common.supports_transparency = MwTRUE; - } else if(strstr(interface, "hyprland") != NULL) { - /* we have nothing to make use of with hyprland, we just want to check if we're running under it. */ - self->wayland.on_hyprland = MwTRUE; } else { // printf("unknown interface %s\n", interface); } diff --git a/src/draw.c b/src/draw.c index 19b4081a..c7869e0f 100644 --- a/src/draw.c +++ b/src/draw.c @@ -53,105 +53,6 @@ static void color_set_disabled_if_disabled(MwWidget handle, MwLLColor rgb) { } }; -/* Whether (x, y) within a w*h rect falls inside a rounded-rect mask of the - * given corner radius. Shared by every raster-based rounded fill below so - * they all cut the same corner shape. */ -static int rounded_rect_contains(int x, int y, int w, int h, int rad) { - int cx = -1; - int cy = -1; - - if(x < rad && y < rad) { - cx = rad; - cy = rad; - } else if(x >= w - rad && y < rad) { - cx = w - rad - 1; - cy = rad; - } else if(x < rad && y >= h - rad) { - cx = rad; - cy = h - rad - 1; - } else if(x >= w - rad && y >= h - rad) { - cx = w - rad - 1; - cy = h - rad - 1; - } - - if(cx < 0) { - return 1; - } - - { - int dx = x - cx; - int dy = y - cy; - return (dx * dx + dy * dy) <= rad * rad; - } -} - -static void fill_rect(MwWidget handle, MwRect* rect, MwLLColor color) { - MwPoint p[4]; - - p[0].x = rect->x; - p[0].y = rect->y; - - p[1].x = rect->x + rect->width; - p[1].y = rect->y; - - p[2].x = rect->x + rect->width; - p[2].y = rect->y + rect->height; - - p[3].x = rect->x; - p[3].y = rect->y + rect->height; - - MwLLPolygon(handle->lowlevel, p, 4, color); -} - -/* Flat-colored rounded-rect fill, for backdrops that need to match a rounded - * border/fill's shape instead of a plain MwDrawRect square. */ -static void fill_rect_rounded(MwWidget handle, MwRect* rect, MwLLColor color, int roundness) { - MwLLPixmap pixmap; - int x, y; - int w = rect->width; - int h = rect->height; - int rad = roundness; - unsigned char* data; - - if(w <= 0 || h <= 0) { - return; - } - - if(rad > w / 2) rad = w / 2; - if(rad > h / 2) rad = h / 2; - - if(rad <= 0) { - fill_rect(handle, rect, color); - return; - } - - data = malloc((unsigned long)w * h * 4); - if(!data) { - return; - } - - memset(data, 0, (unsigned long)w * h * 4); - - for(y = 0; y < h; y++) { - for(x = 0; x < w; x++) { - if(rounded_rect_contains(x, y, w, h, rad)) { - unsigned char* pout = &data[(y * w + x) * 4]; - - pout[0] = (unsigned char)color->common.red; - pout[1] = (unsigned char)color->common.green; - pout[2] = (unsigned char)color->common.blue; - pout[3] = 255; - } - } - } - - pixmap = MwLLCreatePixmap(handle->lowlevel, data, w, h); - MwLLDrawPixmap(handle->lowlevel, rect, pixmap); - MwLLDestroyPixmap(pixmap); - - free(data); -} - void MwParseColorNoAllocate(const char* text, MwRGB* rgb) { if(text[0] == '#' && strlen(text) == 4) { rgb->red = hex(text + 1, 1); @@ -199,104 +100,63 @@ MwLLColor MwLightenColor(MwWidget handle, MwLLColor color, int r, int g, int b) } void MwDrawRect(MwWidget handle, MwRect* rect, MwLLColor color) { - if(MwLLWaylandDoRoundness(handle->lowlevel)) { - fill_rect_rounded(handle, rect, color, MwLLWaylandHyprlandGetRoundness()); - } else { - fill_rect(handle, rect, color); - } + MwPoint p[4]; + + p[0].x = rect->x; + p[0].y = rect->y; + + p[1].x = rect->x + rect->width; + p[1].y = rect->y; + + p[2].x = rect->x + rect->width; + p[2].y = rect->y + rect->height; + + p[3].x = rect->x; + p[3].y = rect->y + rect->height; + + MwLLPolygon(handle->lowlevel, p, 4, color); } void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color) { - MwLLPixmap pixmap; - int y; - double darken = 0.; - int ColorDiff = get_color_diff(handle); - MwRect r = *rect; - int roundness = MwLLWaylandDoRoundness(handle->lowlevel) ? MwLLWaylandHyprlandGetRoundness() : 0; - - if(rect->width <= 0 || rect->height <= 0) { + MwLLPixmap pixmap; + int y; + double darken = 0.; + int ColorDiff = get_color_diff(handle); + double darkenStep = (ColorDiff / 2.) / rect->height; + unsigned long sz = 1 * rect->height * 4; + unsigned char* data = malloc(sz * 2); + MwRect r = *rect; + if(!data) { return; } + if(rect->width <= 0 || rect->height <= 0) { + free(data); + return; + } + memset(data, 0, sz); r.x += 1; r.y += 1; r.width -= 2; r.height -= 2; - if(r.width <= 0 || r.height <= 0) { - return; + for(y = 0; y < rect->height; y++) { + MwLLColor col = MwLightenColor(handle, color, (int)-darken, (int)-darken, (int)-darken); + int idx = y * 4; + color_set_disabled_if_disabled(handle, col); + data[idx] = col->common.red; + data[idx + 1] = col->common.green; + data[idx + 2] = col->common.blue; + data[idx + 3] = 255; + MwLLFreeColor(col); + darken += darkenStep; } - if(roundness <= 0) { - double darkenStep = (ColorDiff / 2.) / rect->height; - unsigned long sz = 1 * rect->height * 4; - unsigned char* data = malloc(sz * 2); - if(!data) { - return; - } - memset(data, 0, sz); + pixmap = MwLLCreatePixmap(handle->lowlevel, data, 1, rect->height); + MwLLDrawPixmap(handle->lowlevel, &r, pixmap); + MwLLDestroyPixmap(pixmap); - for(y = 0; y < rect->height; y++) { - MwLLColor col = MwLightenColor(handle, color, (int)-darken, (int)-darken, (int)-darken); - int idx = y * 4; - color_set_disabled_if_disabled(handle, col); - data[idx] = col->common.red; - data[idx + 1] = col->common.green; - data[idx + 2] = col->common.blue; - data[idx + 3] = 255; - MwLLFreeColor(col); - darken += darkenStep; - } - - pixmap = MwLLCreatePixmap(handle->lowlevel, data, 1, rect->height); - MwLLDrawPixmap(handle->lowlevel, &r, pixmap); - MwLLDestroyPixmap(pixmap); - - free(data); - return; - } else { - int w = r.width; - int h = r.height; - int rad = roundness; - int x; - double darkenStep; - unsigned char* data; - - if(rad > w / 2) rad = w / 2; - if(rad > h / 2) rad = h / 2; - - darkenStep = (ColorDiff / 2.) / h; - data = malloc((unsigned long)w * h * 4); - if(!data) { - return; - } - memset(data, 0, (unsigned long)w * h * 4); - - for(y = 0; y < h; y++) { - MwLLColor col = MwLightenColor(handle, color, (int)-darken, (int)-darken, (int)-darken); - color_set_disabled_if_disabled(handle, col); - - for(x = 0; x < w; x++) { - if(rounded_rect_contains(x, y, w, h, rad)) { - unsigned char* pout = &data[(y * w + x) * 4]; - - pout[0] = (unsigned char)col->common.red; - pout[1] = (unsigned char)col->common.green; - pout[2] = (unsigned char)col->common.blue; - pout[3] = 255; - } - } - - MwLLFreeColor(col); - darken += darkenStep; - } - - pixmap = MwLLCreatePixmap(handle->lowlevel, data, w, h); - MwLLDrawPixmap(handle->lowlevel, &r, pixmap); - MwLLDestroyPixmap(pixmap); - - free(data); - } + free(data); } void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert) { @@ -343,8 +203,7 @@ void MwDrawWidgetBack(MwWidget handle, MwRect* rect, MwLLColor color, int invert MwLLColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground)); if(c != NULL) { - int roundness = MwLLWaylandDoRoundness(handle->lowlevel) ? MwLLWaylandHyprlandGetRoundness() : 0; - fill_rect_rounded(handle, rect, c, MwGetInteger(handle, MwNmodernLook) ? roundness : 0); + MwDrawRect(handle, rect, c); MwLLFreeColor(c); } } @@ -595,113 +454,48 @@ static void MwDrawFrameEx_simple(MwWidget handle, MwRect* rect, MwLLColor color, rect->height -= border * 2; } -#define FRAME_ARC_STEPS 6 - -/* Appends the points of an (up to) quarter-circle arc, sweeping from - * start_deg to end_deg (in degrees, either direction), to `points`. */ -static void frame_border_append_arc(MwPoint* points, int* count, int cx, int cy, int radius, double start_deg, double end_deg, int steps) { - int i; - for(i = 0; i <= steps; i++) { - double deg = start_deg + (end_deg - start_deg) * ((double)i / steps); - double rad = deg * M_PI / 180.0; - points[*count].x = cx + (int)(cos(rad) * radius); - points[*count].y = cy + (int)(sin(rad) * radius); - (*count)++; - } -} - -static void frame_border_complex(MwWidget handle, MwRect* rect, MwLLColor lighter, MwLLColor darker, int invert, int border, int diff, int same, int roundness) { - MwPoint p[36]; - int n; - int x = rect->x; - int y = rect->y; - int w = rect->width; - int h = rect->height; - int r = roundness; - int ib, ir; +static void frame_border_complex(MwWidget handle, MwRect* rect, MwLLColor lighter, MwLLColor darker, int invert, int border, int diff, int same) { + MwPoint p[7]; (void)diff; (void)same; - if(r < 0) r = 0; - if(r > w / 2) r = w / 2; - if(r > h / 2) r = h / 2; + p[0].x = rect->x; + p[0].y = rect->y; - if(r <= 0) { - p[0].x = x; - p[0].y = y; + p[1].x = rect->x + rect->width; + p[1].y = rect->y; - p[1].x = x + w; - p[1].y = y; + p[2].x = rect->x + rect->width - border; + p[2].y = rect->y + border; + p[3].x = rect->x + border; + p[3].y = rect->y + border; - p[2].x = x + w - border; - p[2].y = y + border; - p[3].x = x + border; - p[3].y = y + border; + p[4].x = rect->x + border; + p[4].y = rect->y + rect->height - border; - p[4].x = x + border; - p[4].y = y + h - border; + p[5].x = rect->x; + p[5].y = rect->y + rect->height; + MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker); - p[5].x = x; - p[5].y = y + h; - MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker); + p[0].x = rect->x + rect->width; + p[0].y = rect->y; - p[0].x = x + w; - p[0].y = y; + p[1].x = rect->x + rect->width - border; + p[1].y = rect->y + border; - p[1].x = x + w - border; - p[1].y = y + border; + p[2].x = rect->x + rect->width - border; + p[2].y = rect->y + rect->height - border; - p[2].x = x + w - border; - p[2].y = y + h - border; + p[3].x = rect->x + border; + p[3].y = rect->y + rect->height - border; - p[3].x = x + border; - p[3].y = y + h - border; + p[4].x = rect->x; + p[4].y = rect->y + rect->height; - p[4].x = x; - p[4].y = y + h; - - p[5].x = x + w; - p[5].y = y + h; - MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker); - return; - } - - /* With rounded outer corners, each half still meets the other along - * the same two diagonals as the sharp-cornered version above, except - * the TR and BL corners (shared between both halves) are cut by an - * arc whose midpoint lies on that diagonal, and each half draws - * exactly one side of it. The TL/BR corners belong entirely to one - * half, so they get the full quarter-circle arc. - * - * The inner (border-offset) corners get the same treatment, using the - * same corner centers as the outer arcs but shrunk by the border - * width, so the border ring keeps a uniform thickness all the way - * around the curve instead of jumping to a sharp point. If the border - * is thicker than the roundness, this collapses back to the ordinary - * sharp inner corner (ib == border, ir == 0). */ - ib = (r > border) ? r : border; - ir = (r > border) ? (r - border) : 0; - - /* Top-left half: TL (full), TR (near side), BL (near side). */ - n = 0; - frame_border_append_arc(p, &n, x + r, y + r, r, 180, 270, FRAME_ARC_STEPS); - frame_border_append_arc(p, &n, x + w - r, y + r, r, 270, 315, FRAME_ARC_STEPS / 2); - frame_border_append_arc(p, &n, x + w - ib, y + ib, ir, 315, 270, FRAME_ARC_STEPS / 2); - frame_border_append_arc(p, &n, x + ib, y + ib, ir, 270, 180, FRAME_ARC_STEPS); - frame_border_append_arc(p, &n, x + ib, y + h - ib, ir, 180, 135, FRAME_ARC_STEPS / 2); - frame_border_append_arc(p, &n, x + r, y + h - r, r, 135, 180, FRAME_ARC_STEPS / 2); - MwLLPolygon(handle->lowlevel, p, n, invert ? lighter : darker); - - /* Bottom-right half: TR (far side), BL (far side), BR (full). */ - n = 0; - frame_border_append_arc(p, &n, x + w - r, y + r, r, 360, 315, FRAME_ARC_STEPS / 2); - frame_border_append_arc(p, &n, x + w - ib, y + ib, ir, 315, 360, FRAME_ARC_STEPS / 2); - frame_border_append_arc(p, &n, x + w - ib, y + h - ib, ir, 0, 90, FRAME_ARC_STEPS); - frame_border_append_arc(p, &n, x + ib, y + h - ib, ir, 90, 135, FRAME_ARC_STEPS / 2); - frame_border_append_arc(p, &n, x + r, y + h - r, r, 135, 90, FRAME_ARC_STEPS / 2); - frame_border_append_arc(p, &n, x + w - r, y + h - r, r, 90, 0, FRAME_ARC_STEPS); - MwLLPolygon(handle->lowlevel, p, n, invert ? lighter : darker); + p[5].x = rect->x + rect->width; + p[5].y = rect->y + rect->height; + MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker); } static void MwDrawFrameEx_complex(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border, int diff, int same) { @@ -709,19 +503,18 @@ static void MwDrawFrameEx_complex(MwWidget handle, MwRect* rect, MwLLColor color MwLLColor darker = MwLightenColor(handle, color, -ColorDiff * 3 / 2 + diff, -ColorDiff * 3 / 2 + diff, -ColorDiff * 3 / 2 + diff); MwLLColor lighter = same ? MwLightenColor(handle, darker, 0, 0, 0) : MwLightenColor(handle, color, (ColorDiff / 2) - diff, (ColorDiff / 2) - diff, (ColorDiff / 2) - diff); MwRect r = *rect; - int roundness = MwLLWaylandDoRoundness(handle->lowlevel) ? MwLLWaylandHyprlandGetRoundness() : 0; color_set_disabled_if_disabled(handle, darker); color_set_disabled_if_disabled(handle, lighter); - frame_border_complex(handle, rect, lighter, darker, invert, border == 1 ? 1 : (border / 2), diff, same, roundness); + frame_border_complex(handle, rect, lighter, darker, invert, border == 1 ? 1 : (border / 2), diff, same); if(border > 1) { r.x += border / 2; r.y += border / 2; r.width -= border; r.height -= border; - frame_border_complex(handle, &r, lighter, darker, !invert, border / 2, diff, same, roundness); + frame_border_complex(handle, &r, lighter, darker, !invert, border / 2, diff, same); } MwLLFreeColor(lighter); -- 2.39.5 From 18d397b4f82121383bd1dd5c9d7c9f7fbc25020a Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 19:22:32 -0700 Subject: [PATCH 2/7] wh --- CMakeLists.txt | 1 - include/Mw/LowLevel/Wayland.h | 12 +-- pl/rules.pl | 1 - src/backend/cairo.c | 12 +-- src/backend/wayland/hyprland.c | 60 ----------- src/backend/wayland/interfaces.c | 153 +++++++++++++++++---------- src/backend/wayland/wayland.c | 176 ++++++++++++++++--------------- 7 files changed, 200 insertions(+), 215 deletions(-) delete mode 100644 src/backend/wayland/hyprland.c diff --git a/CMakeLists.txt b/CMakeLists.txt index d072daf3..534614f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -269,7 +269,6 @@ if(MW_USE_WAYLAND) src/backend/cairo.c src/backend/wayland/wayland.c src/backend/wayland/buffer.c - src/backend/wayland/hyprland.c src/backend/wayland/interfaces.c src/backend/wayland/region.c ) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 0f570e32..c42231ca 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -238,8 +238,6 @@ struct _MwLLWaylandTopLevel { }; struct _MwLLWaylandSublevel { - struct wl_subsurface* subsurface; - struct wl_subcompositor* subcompositor; MwLL parent; @@ -488,8 +486,9 @@ int MwLLWaylandHyprlandGetRoundness(void); void MwLLWaylandHangUntilConfigured(MwLL handle); -MwBool MwLLWaylandWidgetIsDestroyed(MwLL self); -void MwLLWaylandWidgetUndestroy(MwLL self); +// MwBool MwLLWaylandWidgetIsDestroyed(MwLL self); +// void MwLLWaylandWidgetUndestroy(MwLL self); +void MwLLWaylandChildrenIterate(MwLL handle, void (*func)(MwLL handle, MwLL child)); /* Function for setting up the callbacks/structs that will be registered upon the relevant interfaces being found. */ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland); @@ -500,10 +499,7 @@ void MwLLWaylandClipboardRead(wl_clipboard_device_context_t* ctx, int clipboard_ void MwLLWaylandFlush(MwLL handle); /* Standard procedure before event callbacks in Wayland */ -#define WAYLAND_EVENT_OP_START(self) \ - if(MwLLWaylandWidgetIsDestroyed(self)) { \ - return; \ - } +#define WAYLAND_EVENT_OP_START(self) /* Footer for WAYLAND_EVENT_OP_START */ #define WAYLAND_EVENT_OP_END(self) diff --git a/pl/rules.pl b/pl/rules.pl index 80f930d9..986ee98c 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -49,7 +49,6 @@ if (grep(/^wayland$/, @backends)) { new_object("src/backend/cairo.c"); new_object("src/backend/wayland/wayland.c"); new_object("src/backend/wayland/buffer.c"); - new_object("src/backend/wayland/hyprland.c"); new_object("src/backend/wayland/interfaces.c"); new_object("src/backend/wayland/region.c"); diff --git a/src/backend/cairo.c b/src/backend/cairo.c index 65380fba..d70de1b9 100644 --- a/src/backend/cairo.c +++ b/src/backend/cairo.c @@ -212,8 +212,8 @@ static void MwLLFreeColorImpl(MwLLColor color) {} static MwBool lmao = MwFALSE; static int MwLLPendingImpl(MwLL handle) { - lmao = !lmao; - return lmao; + lmao = !lmao; + return lmao; } static void MwLLNextEventImpl(MwLL handle) { MwLLDispatch(handle, draw, NULL); @@ -257,10 +257,10 @@ static void MwLLRaiseImpl(MwLL handle) {} static void MwLLClipImpl(MwLL handle, MwRect* rect) {} static void MwLLSetupDragAndDropImpl(MwLL handle) {} static int MwLLCairoCallInitImpl(void) { - if(cairo_load_funcs() != 0) { - return 1; - } - return 0; + if(cairo_load_funcs() != 0) { + return 1; + } + return 0; } #include "call.c" CALL(Cairo); diff --git a/src/backend/wayland/hyprland.c b/src/backend/wayland/hyprland.c deleted file mode 100644 index e6c86790..00000000 --- a/src/backend/wayland/hyprland.c +++ /dev/null @@ -1,60 +0,0 @@ -#include - -int MwLLWaylandDoRoundness(MwLL handle) { - if(handle->common.type == MwLLBackendWayland) { - return handle->wayland.on_hyprland; - } else { - return 0; - }; -}; - -int MwLLWaylandHyprlandGetRoundness(void) { - char* home = getenv("HOME"); - int fallback = 20; - char path[PATH_MAX]; - int roundness = fallback; - char line[512]; - FILE* f = NULL; - - if(home == NULL) { - return fallback; - } - - snprintf(path, sizeof(path), "%s/.config/hypr/hyprland.lua", home); - - f = fopen(path, "r"); - if(f == NULL) { - return fallback; - } - - while(fgets(line, sizeof(line), f) != NULL) { - char* key = strstr(line, "roundness"); - char* eq; - char* end; - long value; - - if(key == NULL) { - continue; - } - - eq = strchr(key, '='); - if(eq == NULL) { - continue; - } - eq++; - - while(*eq != '\0' && isspace((unsigned char)*eq)) { - eq++; - } - - value = strtol(eq, &end, 10); - if(end == eq) { - continue; - } - - roundness = (int)value; - } - - fclose(f); - return roundness; -} diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 84ed4923..caf62ac0 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -531,8 +531,7 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time MwLL self = data; MwLL topmost_parent = self; MwMouse p; - MwBool inArea = MwFALSE; - MwLL currentlyHeldWidget = NULL; + MwBool inArea = MwFALSE; (void)time; (void)wl_pointer; @@ -540,8 +539,6 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time WAYLAND_EVENT_OP_START(self); while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; - currentlyHeldWidget = topmost_parent->wayland.currentlyHeldWidget; - if(self->wayland.framebuffer.surface) { inArea |= self->wayland.framebuffer.surface == curSurface; } @@ -552,30 +549,92 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time self->wayland.cur_mouse_pos.x = wl_fixed_to_int(surface_x); self->wayland.cur_mouse_pos.y = wl_fixed_to_int(surface_y); - if(currentlyHeldWidget != NULL) { - currentlyHeldWidget->wayland.cur_mouse_pos.x = wl_fixed_to_int(surface_x); - currentlyHeldWidget->wayland.cur_mouse_pos.y = wl_fixed_to_int(surface_y); - } if(inArea) { p.point = self->wayland.cur_mouse_pos; MwLLDispatch(self, move, &p); - wl_pointer_set_cursor(self->wayland.pointer, self->wayland.pointer_serial, self->wayland.cursor.surface, 0, 0); - } else if(currentlyHeldWidget == self) { - p.point = currentlyHeldWidget->wayland.cur_mouse_pos; - MwLLDispatch(currentlyHeldWidget, move, &p); } WAYLAND_EVENT_OP_END(self); }; +// static void recursive_dispatch_mouse_down(MwLL handle, MwMouse* p) { +// MwWidget h = (MwWidget)handle->common.user; +// MwLLDispatch(handle, down, p); +// if(h) { +// int i; +// for(i = 0; i < arrlen(h->children); i++) { +// MwLLDispatch(h->children[i]->lowlevel, down, p); +// if(arrlen(h->children[i]->children) > 0) { +// recursive_dispatch_mouse_down(h->children[i]->lowlevel, p); +// } +// } +// } +// }; +// static void recursive_dispatch_mouse_up(MwLL handle, MwMouse* p) { +// MwWidget h = (MwWidget)handle->common.user; +// MwLLDispatch(handle, up, p); +// if(h) { +// int i; +// for(i = 0; i < arrlen(h->children); i++) { +// MwLLDispatch(h->children[i]->lowlevel, up, p); +// if(arrlen(h->children[i]->children) > 0) { +// recursive_dispatch_mouse_up(h->children[i]->lowlevel, p); +// } +// } +// } +// }; + +static void pointer_iterate_master(MwLL handle, MwLL child, MwBool down) { + MwLL topmost_parent = handle; + MwPoint point; + MwPoint relative_pos; + MwPoint absolute_pos; + + absolute_pos.x = child->wayland.x; + absolute_pos.y = child->wayland.y; + + while(topmost_parent->wayland.parent) { + topmost_parent = topmost_parent->wayland.parent; + if(topmost_parent) { + absolute_pos.x += topmost_parent->wayland.x; + absolute_pos.y += topmost_parent->wayland.y; + } + } + + point = topmost_parent->wayland.cur_mouse_pos; + relative_pos.x = point.x - absolute_pos.x; + relative_pos.y = point.y - absolute_pos.y; + + if( + point.x >= absolute_pos.x && point.x <= absolute_pos.x + child->wayland.ww && + point.y >= absolute_pos.y && point.y <= absolute_pos.y + child->wayland.wh) { + MwMouse p; + p.point = relative_pos; + + if(down) { + MwLLDispatch(child, down, &p); + } else { + MwLLDispatch(child, up, &p); + } + + printf("%p %s (%d %d %d %d)\n", child, down ? "DOWN" : "UP", p.point.x, p.point.y, child->wayland.ww, child->wayland.wh); + } +} +static void pointer_iterate_down(MwLL handle, MwLL child) { + pointer_iterate_master(handle, child, MwTRUE); + MwLLWaylandChildrenIterate(child, pointer_iterate_down); +} +static void pointer_iterate_up(MwLL handle, MwLL child) { + pointer_iterate_master(handle, child, MwFALSE); + MwLLWaylandChildrenIterate(child, pointer_iterate_up); +} + /* `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; MwMouse p; - MwBool inArea = MwFALSE; - MwLL topmost_parent = self; (void)wl_pointer; (void)serial; @@ -584,46 +643,29 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri WAYLAND_EVENT_OP_START(self); p.point = self->wayland.cur_mouse_pos; - while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; - if(self->wayland.framebuffer.surface) { - inArea |= self->wayland.framebuffer.surface == curSurface; + switch(button) { + case BTN_LEFT: + p.button = MwMOUSE_LEFT; + break; + case BTN_MIDDLE: + p.button = MwMOUSE_MIDDLE; + break; + case BTN_RIGHT: + p.button = MwMOUSE_RIGHT; + break; } - if(self->wayland.backbuffer.surface) { - inArea |= self->wayland.backbuffer.surface == curSurface; - } - if(inArea) { - switch(button) { - case BTN_LEFT: - p.button = MwMOUSE_LEFT; - break; - case BTN_MIDDLE: - p.button = MwMOUSE_MIDDLE; - break; - case BTN_RIGHT: - p.button = MwMOUSE_RIGHT; - break; - } - self->wayland.held_down = state == WL_POINTER_BUTTON_STATE_PRESSED; + self->wayland.held_down = state == WL_POINTER_BUTTON_STATE_PRESSED; - switch(state) { - case WL_POINTER_BUTTON_STATE_PRESSED: - if(button == BTN_LEFT) { - topmost_parent->wayland.focusedWidget = self; - } - MwLLDispatch(self, down, &p); - topmost_parent->wayland.currentlyHeldWidget = self; - - break; - case WL_POINTER_BUTTON_STATE_RELEASED: - if(topmost_parent->wayland.currentlyHeldWidget != NULL) { - MwLLDispatch(topmost_parent->wayland.currentlyHeldWidget, up, &p); - topmost_parent->wayland.currentlyHeldWidget = NULL; - } else { - MwLLDispatch(self, up, &p); - } - break; - } + switch(state) { + case WL_POINTER_BUTTON_STATE_PRESSED: + MwLLDispatch(self, down, &p); + MwLLWaylandChildrenIterate(self, pointer_iterate_down); + break; + case WL_POINTER_BUTTON_STATE_RELEASED: + MwLLDispatch(self, up, &p); + MwLLWaylandChildrenIterate(self, pointer_iterate_up); + break; } if(!self->wayland.has_decorations && self->wayland.do_csd) { @@ -1056,7 +1098,7 @@ static wayland_protocol_t* wl_subcompositor_setup(MwU32 name, struct _MwLLWaylan if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { wayland->toplevel->scompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1); } else { - wayland->sublevel->subcompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1); + // wayland->sublevel->subcompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1); } return NULL; @@ -1067,7 +1109,7 @@ static void wl_subcompositor_interface_destroy(struct _MwLLWayland* wayland, way if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { wl_subcompositor_destroy(wayland->toplevel->scompositor); } else { - wl_subcompositor_destroy(wayland->sublevel->subcompositor); + // wl_subcompositor_destroy(wayland->sublevel->subcompositor); } } @@ -1201,7 +1243,6 @@ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland) { WL_INTERFACE(wl_shm); WL_INTERFACE(wl_compositor); - WL_INTERFACE(wl_seat); WL_INTERFACE(wl_output); WL_INTERFACE(wl_data_device_manager); WL_INTERFACE(zwp_primary_selection_device_manager_v1); @@ -1214,10 +1255,14 @@ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland) { WL_INTERFACE(zxdg_decoration_manager_v1); WL_INTERFACE(xdg_toplevel_icon_manager_v1); WL_INTERFACE(wl_subcompositor); + WL_INTERFACE(wl_seat); } else if(wayland->type == MwLL_WAYLAND_POPUP) { + WL_INTERFACE(wl_seat); } else if(wayland->type == MwLL_WAYLAND_LAYER_SURFACE) { WL_INTERFACE(wp_viewporter); WL_INTERFACE(wl_subcompositor); + WL_INTERFACE(wl_seat); + WL_INTERFACE(wl_seat); } else { WL_INTERFACE(wl_subcompositor); } diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 82c053ea..22c51371 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -12,37 +12,51 @@ MwBool MwWaylandVulkan = MwFALSE; MwBool MwWaylandCairoOnly = MwFALSE; -static pthread_mutex_t destroyedWidgetsTableMutex; -/* - * So Wayland, bless its soul; it keeps using callbacks LONG after they should not only be destroyed but the widget doesn't even exist anymore. Naturally, this causes use after free. so we fight fire with fire in the worst code i've ever written: by storing the freed pointers here, we disallow wayland from ever using them again. if something else is created that takes this slot, we remove it from the table. - * - * To illustrate how bad this code is: if Israel and Palestine found out I was doing this then the Israel/Palestine conflict would be solved because both world leaders would come to the conclusion that this code is the worst thing ever. - */ -static MwLL* destroyedWidgetsTable; +// static pthread_mutex_t destroyedWidgetsTableMutex; +// /* +// * So Wayland, bless its soul; it keeps using callbacks LONG after they should not only be destroyed but the widget doesn't even exist anymore. Naturally, this causes use after free. so we fight fire with fire in the worst code i've ever written: by storing the freed pointers here, we disallow wayland from ever using them again. if something else is created that takes this slot, we remove it from the table. +// * +// * To illustrate how bad this code is: if Israel and Palestine found out I was doing this then the Israel/Palestine conflict would be solved because both world leaders would come to the conclusion that this code is the worst thing ever. +// */ +// static MwLL* destroyedWidgetsTable; -MwBool MwLLWaylandWidgetIsDestroyed(MwLL self) { - int i; - pthread_mutex_lock(&destroyedWidgetsTableMutex); - for(i = 0; i < arrlen(destroyedWidgetsTable); i++) { - if(self == destroyedWidgetsTable[i]) { - pthread_mutex_unlock(&destroyedWidgetsTableMutex); - return MwTRUE; +// MwBool MwLLWaylandWidgetIsDestroyed(MwLL self) { +// int i; +// pthread_mutex_lock(&destroyedWidgetsTableMutex); +// for(i = 0; i < arrlen(destroyedWidgetsTable); i++) { +// if(self == destroyedWidgetsTable[i]) { +// pthread_mutex_unlock(&destroyedWidgetsTableMutex); +// return MwTRUE; +// } +// } +// pthread_mutex_unlock(&destroyedWidgetsTableMutex); +// return MwFALSE; +// } +// void MwLLWaylandWidgetUndestroy(MwLL self) { +// int i; +// pthread_mutex_lock(&destroyedWidgetsTableMutex); +// for(i = 0; i < arrlen(destroyedWidgetsTable); i++) { +// if(self == destroyedWidgetsTable[i]) { +// arrdel(destroyedWidgetsTable, i); +// break; +// } +// } +// pthread_mutex_unlock(&destroyedWidgetsTableMutex); +// return; +// } +// + +void MwLLWaylandChildrenIterate(MwLL handle, void (*func)(MwLL handle, MwLL child)) { + if(handle->common.user) { + MwWidget w = handle->common.user; + int i; + for(i = 0; i < arrlen(w->children); i++) { + if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { + MwLL child = w->children[i]->lowlevel; + func(handle, child); + } } } - pthread_mutex_unlock(&destroyedWidgetsTableMutex); - return MwFALSE; -} -void MwLLWaylandWidgetUndestroy(MwLL self) { - int i; - pthread_mutex_lock(&destroyedWidgetsTableMutex); - for(i = 0; i < arrlen(destroyedWidgetsTable); i++) { - if(self == destroyedWidgetsTable[i]) { - arrdel(destroyedWidgetsTable, i); - break; - } - } - pthread_mutex_unlock(&destroyedWidgetsTableMutex); - return; } static int event_loop(MwLL handle); @@ -370,18 +384,6 @@ static void destroy_toplevel(MwLL r) { wl_pointer_destroy(r->wayland.pointer); wl_keyboard_destroy(r->wayland.keyboard); - if(r->common.user) { - MwWidget w = r->common.user; - int i; - for(i = 0; i < arrlen(w->children); i++) { - if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { - MwLL child = w->children[i]->lowlevel; - wl_subsurface_destroy(child->wayland.sublevel->subsurface); - child->wayland.sublevel->subsurface = NULL; - } - } - } - wl_surface_destroy(r->wayland.framebuffer.surface); free(r->wayland.toplevel); @@ -421,22 +423,12 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { r->wayland.framebuffer.surface = wl_compositor_create_surface(compositor); - r->wayland.sublevel->subsurface = wl_subcompositor_get_subsurface(r->wayland.sublevel->subcompositor, r->wayland.framebuffer.surface, parent_surface); - - wl_subsurface_set_desync(r->wayland.sublevel->subsurface); - wl_subsurface_set_position(r->wayland.sublevel->subsurface, x, y); - - if(parent) { - wl_subsurface_place_above(r->wayland.sublevel->subsurface, parent->wayland.framebuffer.surface); - } - r->wayland.xkb_keymap = parent->wayland.xkb_keymap; r->wayland.xkb_state = parent->wayland.xkb_state; r->wayland.configured = MwTRUE; MwLLWaylandFramebufferSetup(&r->wayland); - MwLLWaylandBackbufferSetup(&r->wayland); } /* Sublevel setup function */ @@ -444,8 +436,6 @@ static void destroy_sublevel(MwLL r) { MwLLWaylandBackbufferDestroy(&r->wayland); MwLLWaylandFramebufferDestroy(&r->wayland); - wl_subsurface_destroy(r->wayland.sublevel->subsurface); - free(r->wayland.sublevel); r->wayland.configured = MwFALSE; @@ -873,12 +863,7 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh r->wayland.x = x; r->wayland.y = y; r->wayland.parent = parent; - if(MwLLWaylandWidgetIsDestroyed(parent)) { - r->wayland.valid = MwFALSE; - return; - } else { - r->wayland.valid = MwTRUE; - } + r->wayland.valid = MwTRUE; if(ty == MwLL_WAYLAND_UNKNOWN) { if(parent == NULL) { @@ -963,10 +948,6 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { memset(r, 0, sizeof(*r)); MwLLCreateCommon(r); - if(MwLLWaylandWidgetIsDestroyed(r)) { - MwLLWaylandWidgetUndestroy(r); - } - r->wayland.is_toplevel = parent == NULL; r->wayland.is_clipping = 0; @@ -1030,15 +1011,11 @@ static void MwLLDestroyImpl(MwLL handle) { printf("widget invalid\n"); } - pthread_mutex_lock(&destroyedWidgetsTableMutex); - arrput(destroyedWidgetsTable, handle); - pthread_mutex_unlock(&destroyedWidgetsTableMutex); + // pthread_mutex_lock(&destroyedWidgetsTableMutex); + // arrput(destroyedWidgetsTable, handle); + // pthread_mutex_unlock(&destroyedWidgetsTableMutex); free(handle); - - // if(topmost_parent->wayland.currentlyHeldWidget == handle) { - // topmost_parent->wayland.currentlyHeldWidget = NULL; - // } } static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h) { @@ -1066,7 +1043,7 @@ static void MwLLSetXYImpl(MwLL handle, int x, int y) { /* toplevels cannot be moved */ break; case MwLL_WAYLAND_SUBLEVEL: - wl_subsurface_set_position(handle->wayland.sublevel->subsurface, x, y); + /* sublevels are drawn according to their own x/y */ break; case MwLL_WAYLAND_POPUP: xdg_positioner_set_anchor_rect(handle->wayland.popup->xdg_positioner, handle->wayland.parent->wayland.x, handle->wayland.parent->wayland.y, handle->wayland.ww, handle->wayland.wh); @@ -1142,6 +1119,41 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { handle->wayland.events_pending = 1; } +static void draw_child(MwLL handle, MwLL child); +static void draw_children(MwLL handle); + +static void draw_child(MwLL handle, MwLL child) { + cairo_t* c; + cairo_surface_t* cs; + cairo_t* selected_cairo = handle->wayland.cairo.front_cairo; + + wl_surface_commit(child->wayland.framebuffer.surface); + + cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, child->wayland.ww, child->wayland.wh); + c = cairo_create(cs); + + cairo_set_source_surface(c, child->wayland.cairo.front_cs, 0, 0); + cairo_pattern_set_filter(cairo_get_source(c), CAIRO_FILTER_NEAREST); + + cairo_set_operator(handle->wayland.cairo.front_cairo, CAIRO_OPERATOR_OVER); + + cairo_paint(c); + + cairo_set_source_surface(selected_cairo, cs, child->wayland.x, child->wayland.y); + cairo_paint(selected_cairo); + + cairo_destroy(c); + cairo_surface_destroy(cs); + + draw_children(child); +} + +static void draw_children(MwLL handle) { + MwLLWaylandChildrenIterate(handle, draw_child); + + wl_surface_damage(handle->wayland.framebuffer.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); + handle->wayland.force_render = MwTRUE; +} typedef struct { double r, g, b; @@ -1304,6 +1316,8 @@ static void MwLLEndDrawImpl(MwLL handle) { MwLLWaylandBufferUpdate(handle, &handle->wayland.backbuffer); } MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); + + draw_children(handle); } } @@ -1361,10 +1375,6 @@ static int MwLLPendingImpl(MwLL handle) { }; int pending = 0; - if(MwLLWaylandWidgetIsDestroyed(handle) || !handle->wayland.valid) { - return 0; - } - handle->wayland.resizing = 0; if(handle->wayland.setting_wh) { @@ -1670,7 +1680,7 @@ static void MwLLMakeBorderlessImpl(MwLL handle, int toggle) { dec->decoration, toggle ? ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE : ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); } else { handle->wayland.do_csd = !toggle; - wl_subsurface_set_position(handle->wayland.toplevel->ssurface, handle->wayland.do_csd ? CSD_BORDER_FRAME_LEFT : 0, handle->wayland.do_csd ? CSD_BORDER_FRAME_TOP : 0); + // wl_subsurface_set_position(handle->wayland.toplevel->ssurface, handle->wayland.do_csd ? CSD_BORDER_FRAME_LEFT : 0, handle->wayland.do_csd ? CSD_BORDER_FRAME_TOP : 0); } } } @@ -1845,20 +1855,16 @@ static void MwLLEndStateChangeImpl(MwLL handle) { if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { MwLL child = w->children[i]->lowlevel; child->wayland.sublevel->xdg_surface = handle->wayland.popup->xdg_surface; - if(child->wayland.sublevel->subsurface) - wl_subsurface_destroy(child->wayland.sublevel->subsurface); + // if(child->wayland.sublevel->subsurface) + // wl_subsurface_destroy(child->wayland.sublevel->subsurface); MwLLWaylandFlush(handle); - child->wayland.sublevel->subsurface = wl_subcompositor_get_subsurface(child->wayland.sublevel->subcompositor, child->wayland.framebuffer.surface, handle->wayland.framebuffer.surface); - wl_subsurface_set_desync(child->wayland.sublevel->subsurface); - wl_subsurface_set_position(child->wayland.sublevel->subsurface, child->wayland.x, child->wayland.y); + // child->wayland.sublevel->subsurface = wl_subcompositor_get_subsurface(child->wayland.sublevel->subcompositor, child->wayland.framebuffer.surface, handle->wayland.framebuffer.surface); + // wl_subsurface_set_desync(child->wayland.sublevel->subsurface); + // wl_subsurface_set_position(child->wayland.sublevel->subsurface, child->wayland.x, child->wayland.y); - wl_subsurface_place_above(child->wayland.sublevel->subsurface, handle->wayland.framebuffer.surface); + // wl_subsurface_place_above(child->wayland.sublevel->subsurface, handle->wayland.framebuffer.surface); MwLLEndStateChangeImpl(w->children[i]->lowlevel); - - if(topmost_parent) { - topmost_parent->wayland.currentlyHeldWidget = NULL; - } } } } -- 2.39.5 From f25b67652343b83dadf0b7c2a34e70d3caa20126 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 21:00:38 -0700 Subject: [PATCH 3/7] and now to merge --- include/Mw/LowLevel/Wayland.h | 4 +- src/backend/wayland/interfaces.c | 141 ++++++++++++++++--------------- src/backend/wayland/wayland.c | 105 ++++++++++++++--------- 3 files changed, 141 insertions(+), 109 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index c42231ca..0bfe2010 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -424,6 +424,8 @@ struct _MwLLWayland { MwBool force_render; MwBool did_event_loop_early; + MwBool do_cascading_draw; + int cascading_child_num; MwBool dispatching_resize; @@ -452,8 +454,6 @@ struct _MwLLWayland { MwU64 next_elapsed; long start_time; long end_time; - - MwBool on_hyprland; }; struct _MwLLWaylandColor { diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index caf62ac0..43703a9b 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -559,76 +559,79 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time WAYLAND_EVENT_OP_END(self); }; -// static void recursive_dispatch_mouse_down(MwLL handle, MwMouse* p) { -// MwWidget h = (MwWidget)handle->common.user; -// MwLLDispatch(handle, down, p); -// if(h) { -// int i; -// for(i = 0; i < arrlen(h->children); i++) { -// MwLLDispatch(h->children[i]->lowlevel, down, p); -// if(arrlen(h->children[i]->children) > 0) { -// recursive_dispatch_mouse_down(h->children[i]->lowlevel, p); -// } -// } -// } -// }; -// static void recursive_dispatch_mouse_up(MwLL handle, MwMouse* p) { -// MwWidget h = (MwWidget)handle->common.user; -// MwLLDispatch(handle, up, p); -// if(h) { -// int i; -// for(i = 0; i < arrlen(h->children); i++) { -// MwLLDispatch(h->children[i]->lowlevel, up, p); -// if(arrlen(h->children[i]->children) > 0) { -// recursive_dispatch_mouse_up(h->children[i]->lowlevel, p); -// } -// } -// } -// }; - -static void pointer_iterate_master(MwLL handle, MwLL child, MwBool down) { - MwLL topmost_parent = handle; - MwPoint point; - MwPoint relative_pos; - MwPoint absolute_pos; - - absolute_pos.x = child->wayland.x; - absolute_pos.y = child->wayland.y; - - while(topmost_parent->wayland.parent) { - topmost_parent = topmost_parent->wayland.parent; - if(topmost_parent) { - absolute_pos.x += topmost_parent->wayland.x; - absolute_pos.y += topmost_parent->wayland.y; +static void recursive_dispatch_mouse_down(MwLL handle, MwMouse* p) { + MwWidget h = (MwWidget)handle->common.user; + MwLLDispatch(handle, down, p); + if(h) { + int i; + for(i = 0; i < arrlen(h->children); i++) { + MwLLDispatch(h->children[i]->lowlevel, down, p); + if(arrlen(h->children[i]->children) > 0) { + recursive_dispatch_mouse_down(h->children[i]->lowlevel, p); + } } } - - point = topmost_parent->wayland.cur_mouse_pos; - relative_pos.x = point.x - absolute_pos.x; - relative_pos.y = point.y - absolute_pos.y; - - if( - point.x >= absolute_pos.x && point.x <= absolute_pos.x + child->wayland.ww && - point.y >= absolute_pos.y && point.y <= absolute_pos.y + child->wayland.wh) { - MwMouse p; - p.point = relative_pos; - - if(down) { - MwLLDispatch(child, down, &p); - } else { - MwLLDispatch(child, up, &p); +}; +static void recursive_dispatch_mouse_up(MwLL handle, MwMouse* p) { + MwWidget h = (MwWidget)handle->common.user; + MwLLDispatch(handle, up, p); + if(h) { + int i; + for(i = 0; i < arrlen(h->children); i++) { + MwLLDispatch(h->children[i]->lowlevel, up, p); + if(arrlen(h->children[i]->children) > 0) { + recursive_dispatch_mouse_up(h->children[i]->lowlevel, p); + } + } + } +}; + +static void mouse_dispatch(MwLL self, MwMouse p, MwU32 state) { + switch(state) { + case WL_POINTER_BUTTON_STATE_PRESSED: + MwLLDispatch(self, down, &p); + break; + case WL_POINTER_BUTTON_STATE_RELEASED: + MwLLDispatch(self, up, &p); + break; + } + + if(self->common.user) { + MwWidget w = self->common.user; + int i; + for(i = 0; i < arrlen(w->children); i++) { + if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { + MwLL child = w->children[i]->lowlevel; + MwLL topmost_parent = child; + MwPoint point; + MwPoint relative_mouse_pos; + MwPoint absolute_pos; + + absolute_pos.x = child->wayland.x; + absolute_pos.y = child->wayland.y; + while(topmost_parent->wayland.parent) { + topmost_parent = topmost_parent->wayland.parent; + if(topmost_parent) { + absolute_pos.x += topmost_parent->wayland.x; + absolute_pos.y += topmost_parent->wayland.y; + } + } + + point = topmost_parent->wayland.cur_mouse_pos; + relative_mouse_pos.x = point.x - absolute_pos.x; + relative_mouse_pos.y = point.y - absolute_pos.y; + + if( + point.x >= absolute_pos.x && point.x <= absolute_pos.x + child->wayland.ww && + point.y >= absolute_pos.y && point.y <= absolute_pos.y + child->wayland.wh) { + + p.point = relative_mouse_pos; + + mouse_dispatch(child, p, state); + } + } } - - printf("%p %s (%d %d %d %d)\n", child, down ? "DOWN" : "UP", p.point.x, p.point.y, child->wayland.ww, child->wayland.wh); } -} -static void pointer_iterate_down(MwLL handle, MwLL child) { - pointer_iterate_master(handle, child, MwTRUE); - MwLLWaylandChildrenIterate(child, pointer_iterate_down); -} -static void pointer_iterate_up(MwLL handle, MwLL child) { - pointer_iterate_master(handle, child, MwFALSE); - MwLLWaylandChildrenIterate(child, pointer_iterate_up); } /* `wl_pointer.button` callback */ @@ -656,17 +659,15 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri break; } self->wayland.held_down = state == WL_POINTER_BUTTON_STATE_PRESSED; - switch(state) { case WL_POINTER_BUTTON_STATE_PRESSED: MwLLDispatch(self, down, &p); - MwLLWaylandChildrenIterate(self, pointer_iterate_down); break; case WL_POINTER_BUTTON_STATE_RELEASED: MwLLDispatch(self, up, &p); - MwLLWaylandChildrenIterate(self, pointer_iterate_up); break; } + mouse_dispatch(self, p, state); if(!self->wayland.has_decorations && self->wayland.do_csd) { if(state != WL_POINTER_BUTTON_STATE_RELEASED) @@ -675,6 +676,8 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri xdg_borderless_step_mup(self, p, serial); } + MwLLForceRender(self); + WAYLAND_EVENT_OP_END(self); }; diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 22c51371..c8c4b017 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -942,6 +942,60 @@ static void detect_dark_theme(MwLL handle) { } #endif +static void draw_child(MwLL handle, MwLL child); +static void draw_children(MwLL handle); + +static void draw_child(MwLL handle, MwLL child) { + cairo_t* c; + cairo_surface_t* cs; + cairo_t* selected_cairo = handle->wayland.cairo.front_cairo; + + wl_surface_commit(child->wayland.framebuffer.surface); + + cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, child->wayland.ww, child->wayland.wh); + c = cairo_create(cs); + + cairo_set_source_surface(c, child->wayland.cairo.front_cs, 0, 0); + cairo_pattern_set_filter(cairo_get_source(c), CAIRO_FILTER_NEAREST); + + cairo_set_operator(handle->wayland.cairo.front_cairo, CAIRO_OPERATOR_OVER); + + cairo_paint(c); + + cairo_set_source_surface(selected_cairo, cs, child->wayland.x, child->wayland.y); + cairo_paint(selected_cairo); + + cairo_destroy(c); + cairo_surface_destroy(cs); + + draw_children(child); +} + +static void draw_children(MwLL handle) { + wl_surface_damage(handle->wayland.framebuffer.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); + + MwLLWaylandChildrenIterate(handle, draw_child); + + if(handle->wayland.configured) MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); + handle->wayland.events_pending = MwFALSE; +} + +static void cascade_child(MwLL handle, MwLL child) { + child->wayland.do_cascading_draw = 10; +} + +static void count_child(MwLL handle, MwLL child) { + handle->wayland.cascading_child_num++; +} + +static void cascade_children(MwLL handle) { + handle->wayland.cascading_child_num = 0; + MwLLWaylandChildrenIterate(handle, count_child); + + handle->wayland.do_cascading_draw = 10; + MwLLWaylandChildrenIterate(handle, cascade_child); +} + static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { MwLL r; r = malloc(sizeof(*r)); @@ -1035,8 +1089,11 @@ static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsign static void MwLLSetXYImpl(MwLL handle, int x, int y) { WIDGET_CHECK(handle); MwLLWaylandRegionInvalidate(handle); - handle->wayland.x = x; - handle->wayland.y = y; + + if(handle->wayland.type != MwLL_WAYLAND_TOPLEVEL) { + handle->wayland.x = x; + handle->wayland.y = y; + } switch(handle->wayland.type) { case MwLL_WAYLAND_TOPLEVEL: @@ -1119,41 +1176,6 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { handle->wayland.events_pending = 1; } -static void draw_child(MwLL handle, MwLL child); -static void draw_children(MwLL handle); - -static void draw_child(MwLL handle, MwLL child) { - cairo_t* c; - cairo_surface_t* cs; - cairo_t* selected_cairo = handle->wayland.cairo.front_cairo; - - wl_surface_commit(child->wayland.framebuffer.surface); - - cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, child->wayland.ww, child->wayland.wh); - c = cairo_create(cs); - - cairo_set_source_surface(c, child->wayland.cairo.front_cs, 0, 0); - cairo_pattern_set_filter(cairo_get_source(c), CAIRO_FILTER_NEAREST); - - cairo_set_operator(handle->wayland.cairo.front_cairo, CAIRO_OPERATOR_OVER); - - cairo_paint(c); - - cairo_set_source_surface(selected_cairo, cs, child->wayland.x, child->wayland.y); - cairo_paint(selected_cairo); - - cairo_destroy(c); - cairo_surface_destroy(cs); - - draw_children(child); -} - -static void draw_children(MwLL handle) { - MwLLWaylandChildrenIterate(handle, draw_child); - - wl_surface_damage(handle->wayland.framebuffer.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); - handle->wayland.force_render = MwTRUE; -} typedef struct { double r, g, b; @@ -1317,7 +1339,7 @@ static void MwLLEndDrawImpl(MwLL handle) { } MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); - draw_children(handle); + cascade_children(handle); } } @@ -1382,6 +1404,12 @@ static int MwLLPendingImpl(MwLL handle) { handle->wayland.setting_wh = 0; } + if(handle->wayland.do_cascading_draw) { + draw_children(handle); + if(handle->wayland.do_cascading_draw > 0) + handle->wayland.do_cascading_draw--; + } + handle->wayland.end_time = MwTimeGetTick(); if(handle->wayland.holding_key) { @@ -1440,6 +1468,7 @@ static int MwLLPendingImpl(MwLL handle) { static void MwLLNextEventImpl(MwLL handle) { WIDGET_CHECK(handle); + if(!MwWaylandVulkan) { if(handle->wayland.did_event_loop_early) { handle->wayland.did_event_loop_early = MwFALSE; -- 2.39.5 From 5d5170e6cac8ece784b3ac366c86fe9697730620 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 21:23:20 -0700 Subject: [PATCH 4/7] currentlyHeldWidget brought back --- include/Mw/LowLevel/Wayland.h | 15 ++++++--- src/backend/wayland/interfaces.c | 48 +++++++++++++++++++++++++-- src/backend/wayland/wayland.c | 57 ++++++++++++++++---------------- 3 files changed, 83 insertions(+), 37 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 0bfe2010..f7102ce1 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -412,7 +412,7 @@ struct _MwLLWayland { MwI32 ox, oy; MwU32 ww, wh; /* Window position */ MwPoint cur_mouse_pos; /* Currently known mouse position */ - MwLL currentlyHeldWidget; + MwLL* currentlyHeldWidgets; MwLL focusedWidget; int resizing; @@ -486,9 +486,9 @@ int MwLLWaylandHyprlandGetRoundness(void); void MwLLWaylandHangUntilConfigured(MwLL handle); -// MwBool MwLLWaylandWidgetIsDestroyed(MwLL self); -// void MwLLWaylandWidgetUndestroy(MwLL self); -void MwLLWaylandChildrenIterate(MwLL handle, void (*func)(MwLL handle, MwLL child)); +MwBool MwLLWaylandWidgetIsDestroyed(MwLL self); +void MwLLWaylandWidgetUndestroy(MwLL self); +void MwLLWaylandChildrenIterate(MwLL handle, void (*func)(MwLL handle, MwLL child)); /* Function for setting up the callbacks/structs that will be registered upon the relevant interfaces being found. */ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland); @@ -498,8 +498,13 @@ void MwLLWaylandClipboardRead(wl_clipboard_device_context_t* ctx, int clipboard_ /* Flush Wayland events */ void MwLLWaylandFlush(MwLL handle); +void MwLLWaylandCascadeChildren(MwLL handle); + /* Standard procedure before event callbacks in Wayland */ -#define WAYLAND_EVENT_OP_START(self) +#define WAYLAND_EVENT_OP_START(self) \ + if(MwLLWaylandWidgetIsDestroyed(self)) { \ + return; \ + } /* Footer for WAYLAND_EVENT_OP_START */ #define WAYLAND_EVENT_OP_END(self) diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 43703a9b..706318a0 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -531,7 +531,9 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time MwLL self = data; MwLL topmost_parent = self; MwMouse p; - MwBool inArea = MwFALSE; + MwBool inArea = MwFALSE; + MwLL* currentlyHeldWidgets = NULL; + int i; (void)time; (void)wl_pointer; @@ -539,6 +541,8 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time WAYLAND_EVENT_OP_START(self); while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; + currentlyHeldWidgets = topmost_parent->wayland.currentlyHeldWidgets; + if(self->wayland.framebuffer.surface) { inArea |= self->wayland.framebuffer.surface == curSurface; } @@ -555,6 +559,19 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time MwLLDispatch(self, move, &p); wl_pointer_set_cursor(self->wayland.pointer, self->wayland.pointer_serial, self->wayland.cursor.surface, 0, 0); } + for(i = 0; i < arrlen(currentlyHeldWidgets); i++) { + MwLL new_topmost = currentlyHeldWidgets[i]; + p.point = topmost_parent->wayland.cur_mouse_pos; + while(new_topmost->wayland.parent) { + p.point.x -= new_topmost->wayland.x; + p.point.y -= new_topmost->wayland.y; + new_topmost = new_topmost->wayland.parent; + } + + MwLLDispatch(currentlyHeldWidgets[i], move, &p); + } + + MwLLWaylandCascadeChildren(self); WAYLAND_EVENT_OP_END(self); }; @@ -598,7 +615,7 @@ static void mouse_dispatch(MwLL self, MwMouse p, MwU32 state) { if(self->common.user) { MwWidget w = self->common.user; - int i; + int i, n; for(i = 0; i < arrlen(w->children); i++) { if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { MwLL child = w->children[i]->lowlevel; @@ -624,9 +641,27 @@ static void mouse_dispatch(MwLL self, MwMouse p, MwU32 state) { if( point.x >= absolute_pos.x && point.x <= absolute_pos.x + child->wayland.ww && point.y >= absolute_pos.y && point.y <= absolute_pos.y + child->wayland.wh) { - + int idx = -1; + for(n = 0; n < arrlen(topmost_parent->wayland.currentlyHeldWidgets); n++) { + if(topmost_parent->wayland.currentlyHeldWidgets[n] == child) { + idx = n; + } + } p.point = relative_mouse_pos; + switch(state) { + case WL_POINTER_BUTTON_STATE_PRESSED: + if(idx == -1) { + arrpush(topmost_parent->wayland.currentlyHeldWidgets, child); + } + break; + case WL_POINTER_BUTTON_STATE_RELEASED: + if(idx != -1) { + arrdel(topmost_parent->wayland.currentlyHeldWidgets, idx); + } + break; + } + mouse_dispatch(child, p, state); } } @@ -638,12 +673,15 @@ static void mouse_dispatch(MwLL self, MwMouse p, MwU32 state) { static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 serial, MwU32 time, MwU32 button, MwU32 state) { MwLL self = data; MwMouse p; + MwLL topmost_parent = self; + int i; (void)wl_pointer; (void)serial; (void)time; WAYLAND_EVENT_OP_START(self); + while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; p.point = self->wayland.cur_mouse_pos; @@ -667,6 +705,10 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri MwLLDispatch(self, up, &p); break; } + + for(i = 0; i < arrlen(self->wayland.currentlyHeldWidgets); i++) { + arrdel(self->wayland.currentlyHeldWidgets, i); + } mouse_dispatch(self, p, state); if(!self->wayland.has_decorations && self->wayland.do_csd) { diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index c8c4b017..d032e7d6 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -12,39 +12,38 @@ MwBool MwWaylandVulkan = MwFALSE; MwBool MwWaylandCairoOnly = MwFALSE; -// static pthread_mutex_t destroyedWidgetsTableMutex; +static pthread_mutex_t destroyedWidgetsTableMutex; // /* // * So Wayland, bless its soul; it keeps using callbacks LONG after they should not only be destroyed but the widget doesn't even exist anymore. Naturally, this causes use after free. so we fight fire with fire in the worst code i've ever written: by storing the freed pointers here, we disallow wayland from ever using them again. if something else is created that takes this slot, we remove it from the table. // * // * To illustrate how bad this code is: if Israel and Palestine found out I was doing this then the Israel/Palestine conflict would be solved because both world leaders would come to the conclusion that this code is the worst thing ever. // */ -// static MwLL* destroyedWidgetsTable; +static MwLL* destroyedWidgetsTable; -// MwBool MwLLWaylandWidgetIsDestroyed(MwLL self) { -// int i; -// pthread_mutex_lock(&destroyedWidgetsTableMutex); -// for(i = 0; i < arrlen(destroyedWidgetsTable); i++) { -// if(self == destroyedWidgetsTable[i]) { -// pthread_mutex_unlock(&destroyedWidgetsTableMutex); -// return MwTRUE; -// } -// } -// pthread_mutex_unlock(&destroyedWidgetsTableMutex); -// return MwFALSE; -// } -// void MwLLWaylandWidgetUndestroy(MwLL self) { -// int i; -// pthread_mutex_lock(&destroyedWidgetsTableMutex); -// for(i = 0; i < arrlen(destroyedWidgetsTable); i++) { -// if(self == destroyedWidgetsTable[i]) { -// arrdel(destroyedWidgetsTable, i); -// break; -// } -// } -// pthread_mutex_unlock(&destroyedWidgetsTableMutex); -// return; -// } -// +MwBool MwLLWaylandWidgetIsDestroyed(MwLL self) { + int i; + pthread_mutex_lock(&destroyedWidgetsTableMutex); + for(i = 0; i < arrlen(destroyedWidgetsTable); i++) { + if(self == destroyedWidgetsTable[i]) { + pthread_mutex_unlock(&destroyedWidgetsTableMutex); + return MwTRUE; + } + } + pthread_mutex_unlock(&destroyedWidgetsTableMutex); + return MwFALSE; +} +void MwLLWaylandWidgetUndestroy(MwLL self) { + int i; + pthread_mutex_lock(&destroyedWidgetsTableMutex); + for(i = 0; i < arrlen(destroyedWidgetsTable); i++) { + if(self == destroyedWidgetsTable[i]) { + arrdel(destroyedWidgetsTable, i); + break; + } + } + pthread_mutex_unlock(&destroyedWidgetsTableMutex); + return; +} void MwLLWaylandChildrenIterate(MwLL handle, void (*func)(MwLL handle, MwLL child)) { if(handle->common.user) { @@ -988,7 +987,7 @@ static void count_child(MwLL handle, MwLL child) { handle->wayland.cascading_child_num++; } -static void cascade_children(MwLL handle) { +void MwLLWaylandCascadeChildren(MwLL handle) { handle->wayland.cascading_child_num = 0; MwLLWaylandChildrenIterate(handle, count_child); @@ -1339,7 +1338,7 @@ static void MwLLEndDrawImpl(MwLL handle) { } MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); - cascade_children(handle); + MwLLWaylandCascadeChildren(handle); } } -- 2.39.5 From 6f4164da0cf33aafcfdb4606acbe4d84d783f994 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 21:25:13 -0700 Subject: [PATCH 5/7] erm --- src/backend/wayland/wayland.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index d032e7d6..d3fb2016 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -13,11 +13,11 @@ MwBool MwWaylandVulkan = MwFALSE; MwBool MwWaylandCairoOnly = MwFALSE; static pthread_mutex_t destroyedWidgetsTableMutex; -// /* -// * So Wayland, bless its soul; it keeps using callbacks LONG after they should not only be destroyed but the widget doesn't even exist anymore. Naturally, this causes use after free. so we fight fire with fire in the worst code i've ever written: by storing the freed pointers here, we disallow wayland from ever using them again. if something else is created that takes this slot, we remove it from the table. -// * -// * To illustrate how bad this code is: if Israel and Palestine found out I was doing this then the Israel/Palestine conflict would be solved because both world leaders would come to the conclusion that this code is the worst thing ever. -// */ +/* + * So Wayland, bless its soul; it keeps using callbacks LONG after they should not only be destroyed but the widget doesn't even exist anymore. Naturally, this causes use after free. so we fight fire with fire in the worst code i've ever written: by storing the freed pointers here, we disallow wayland from ever using them again. if something else is created that takes this slot, we remove it from the table. + * + * To illustrate how bad this code is: if Israel and Palestine found out I was doing this then the Israel/Palestine conflict would be solved because both world leaders would come to the conclusion that this code is the worst thing ever. + */ static MwLL* destroyedWidgetsTable; MwBool MwLLWaylandWidgetIsDestroyed(MwLL self) { @@ -862,7 +862,12 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh r->wayland.x = x; r->wayland.y = y; r->wayland.parent = parent; - r->wayland.valid = MwTRUE; + if(MwLLWaylandWidgetIsDestroyed(parent)) { + r->wayland.valid = MwFALSE; + return; + } else { + r->wayland.valid = MwTRUE; + } if(ty == MwLL_WAYLAND_UNKNOWN) { if(parent == NULL) { @@ -1064,9 +1069,9 @@ static void MwLLDestroyImpl(MwLL handle) { printf("widget invalid\n"); } - // pthread_mutex_lock(&destroyedWidgetsTableMutex); - // arrput(destroyedWidgetsTable, handle); - // pthread_mutex_unlock(&destroyedWidgetsTableMutex); + pthread_mutex_lock(&destroyedWidgetsTableMutex); + arrput(destroyedWidgetsTable, handle); + pthread_mutex_unlock(&destroyedWidgetsTableMutex); free(handle); } -- 2.39.5 From f835e41fb0bfda7ecdd622f2c2290275f594f88b Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 21:34:58 -0700 Subject: [PATCH 6/7] back --- src/backend/wayland/interfaces.c | 1 + src/backend/wayland/wayland.c | 46 +++++++++++++------------------- 2 files changed, 20 insertions(+), 27 deletions(-) diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 706318a0..0d960c2e 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -681,6 +681,7 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri (void)time; WAYLAND_EVENT_OP_START(self); + while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; p.point = self->wayland.cur_mouse_pos; diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index d3fb2016..4f832dcc 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -242,7 +242,8 @@ static void xdg_surface_configure( xdg_surface_ack_configure(xdg_surface, serial); - MwLLDispatch(self, draw, NULL); + MwLLWaylandCascadeChildren(self); + // MwLLDispatch(self, draw, NULL); if(self->wayland.configured) { MwLLWaylandBufferUpdate(self, &self->wayland.framebuffer); @@ -996,7 +997,7 @@ void MwLLWaylandCascadeChildren(MwLL handle) { handle->wayland.cascading_child_num = 0; MwLLWaylandChildrenIterate(handle, count_child); - handle->wayland.do_cascading_draw = 10; + handle->wayland.do_cascading_draw = handle->wayland.cascading_child_num * 10; MwLLWaylandChildrenIterate(handle, cascade_child); } @@ -1006,6 +1007,10 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { memset(r, 0, sizeof(*r)); MwLLCreateCommon(r); + if(MwLLWaylandWidgetIsDestroyed(r)) { + MwLLWaylandWidgetUndestroy(r); + } + r->wayland.is_toplevel = parent == NULL; r->wayland.is_clipping = 0; @@ -1123,7 +1128,8 @@ static void MwLLSetXYImpl(MwLL handle, int x, int y) { if(handle->wayland.type != MwLL_WAYLAND_TOPLEVEL) recursive_render(handle); - MwLLDispatch(handle, draw, NULL); + MwLLWaylandCascadeChildren(handle); + // MwLLDispatch(handle, draw, NULL); } static void actually_set_wh(MwLL handle) { @@ -1152,7 +1158,8 @@ static void actually_set_wh(MwLL handle) { MwLLWaylandFramebufferSetup(&handle->wayland); MwLLWaylandBackbufferDestroy(&handle->wayland); MwLLWaylandBackbufferSetup(&handle->wayland); - MwLLDispatch(handle, draw, NULL); + MwLLWaylandCascadeChildren(handle); + // MwLLDispatch(handle, draw, NULL); } static void MwLLSetWHImpl(MwLL handle, int w, int h) { @@ -1401,6 +1408,10 @@ static int MwLLPendingImpl(MwLL handle) { }; int pending = 0; + if(MwLLWaylandWidgetIsDestroyed(handle) || !handle->wayland.valid) { + return 0; + } + handle->wayland.resizing = 0; if(handle->wayland.setting_wh) { @@ -1433,7 +1444,8 @@ static int MwLLPendingImpl(MwLL handle) { if(handle->wayland.dark_theme_detection) { handle->wayland.dark_theme_detection = MwFALSE; detect_dark_theme(handle); - MwLLDispatch(handle, draw, NULL); + MwLLWaylandCascadeChildren(handle); + // MwLLDispatch(handle, draw, NULL); } else { MwLLDBusPortalPoll(&wl_call_tbl.dbus, &handle->wayland.dbus, handle, "org.freedesktop.portal.Settings", "org.freedesktop.appearance", "color-scheme", &dark_theme_listener); } @@ -1881,27 +1893,6 @@ static void MwLLEndStateChangeImpl(MwLL handle) { if(!handle->wayland.parent) handle->wayland.dark_theme_detection = MwTRUE; - if(handle->common.user) { - MwWidget w = handle->common.user; - int i; - for(i = 0; i < arrlen(w->children); i++) { - if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { - MwLL child = w->children[i]->lowlevel; - child->wayland.sublevel->xdg_surface = handle->wayland.popup->xdg_surface; - // if(child->wayland.sublevel->subsurface) - // wl_subsurface_destroy(child->wayland.sublevel->subsurface); - MwLLWaylandFlush(handle); - - // child->wayland.sublevel->subsurface = wl_subcompositor_get_subsurface(child->wayland.sublevel->subcompositor, child->wayland.framebuffer.surface, handle->wayland.framebuffer.surface); - // wl_subsurface_set_desync(child->wayland.sublevel->subsurface); - // wl_subsurface_set_position(child->wayland.sublevel->subsurface, child->wayland.x, child->wayland.y); - - // wl_subsurface_place_above(child->wayland.sublevel->subsurface, handle->wayland.framebuffer.surface); - MwLLEndStateChangeImpl(w->children[i]->lowlevel); - } - } - } - recursive_render(handle); handle->wayland.events_pending = 1; @@ -1913,7 +1904,8 @@ static void MwLLSetDarkThemeImpl(MwLL handle, int toggle) { (void)toggle; /* Not Really what's supposed to happen with this function, but take this opprutunity to do the handlers that will force everything to redraw. */ - MwLLDispatch(handle, resize, NULL); + MwLLWaylandCascadeChildren(handle); + // MwLLDispatch(handle, resize, NULL); MwLLDispatch(handle, draw, NULL); } -- 2.39.5 From 4d768455bc6e26929b36bdad64417650f66afcf1 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Fri, 11 Sep 2026 22:29:05 -0700 Subject: [PATCH 7/7] finnish --- CMakeLists.txt | 1 + examples/vkdemos/vulkan.c | 4 +-- include/Mw/LowLevel/Wayland.h | 15 +++++++++ pl/rules.pl | 1 + src/backend/wayland/buffer.c | 34 +++++++++++++++++++ src/backend/wayland/interfaces.c | 56 ++++++++++++++++++++++++++++---- src/backend/wayland/wayland.c | 43 +++++++++++++++++------- src/widget/opengl.c | 6 ++++ src/widget/vulkan.c | 2 ++ 9 files changed, 142 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 534614f0..1ec1ed85 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -261,6 +261,7 @@ if(MW_USE_WAYLAND) scan_wayland_protocol("unstable" "primary-selection" "-unstable-v1") scan_wayland_protocol("unstable" "pointer-constraints" "-unstable-v1") scan_wayland_protocol("unstable" "relative-pointer" "-unstable-v1") + scan_wayland_protocol("staging" "fifo" "-v1") scan_wayland_protocol_from_file("wlr-layer-shell" "wlr-layer-shell-unstable-v1.xml") target_sources( diff --git a/examples/vkdemos/vulkan.c b/examples/vkdemos/vulkan.c index 9060a970..60154152 100644 --- a/examples/vkdemos/vulkan.c +++ b/examples/vkdemos/vulkan.c @@ -257,8 +257,8 @@ void vulkan_setup(MwWidget handle) { swapchainCreateInfo.imageExtent = (VkExtent2D){.width = ow, .height = oh}, swapchainCreateInfo.imageArrayLayers = 1, swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | - VK_IMAGE_USAGE_TRANSFER_DST_BIT | - VK_IMAGE_USAGE_SAMPLED_BIT; + VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_SAMPLED_BIT; // th is how we specify no transformation. swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index f7102ce1..5e43c34d 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -207,6 +207,7 @@ MwInline int wayland_load_funcs() { #include "Wayland/relative-pointer-client-protocol.h" #include "Wayland/xdg-toplevel-icon-client-protocol.h" #include "Wayland/wlr-layer-shell-client-protocol.h" +#include "Wayland/fifo-client-protocol.h" #endif typedef struct wayland_protocol { @@ -266,6 +267,7 @@ struct _MwLLWaylandShmBuffer { struct wl_buffer* shm_buffer_back; struct wl_surface* surface; struct wl_output* output; + struct wp_fifo_v1* fifo; MwU8* buf; MwU8* buf_back; @@ -435,6 +437,8 @@ struct _MwLLWayland { struct _MwLLWaylandShmBuffer backbuffer; struct _MwLLWaylandShmBuffer cursor; struct _MwLLWaylandShmBuffer* icon; + MwBool fifo_wait; + MwBool disable_fifo; MwLLPixmap icon_pixmap; @@ -472,6 +476,17 @@ void MwLLWaylandBackbufferSetup(struct _MwLLWayland* wayland); /* Destroy the backbuffer */ void MwLLWaylandBackbufferDestroy(struct _MwLLWayland* handle); +/* Bind a wp_fifo_v1 object to `buffer`'s surface, if wp_fifo_manager_v1 is available and it doesn't have one already. */ +void MwLLWaylandFifoSurfaceSetup(struct _MwLLWayland* wayland, struct _MwLLWaylandShmBuffer* buffer); +/* Destroy `buffer`'s wp_fifo_v1 object, if any. */ +void MwLLWaylandFifoSurfaceDestroy(struct _MwLLWaylandShmBuffer* buffer); +/* Commit `buffer`'s surface, constraining the update to the next display refresh via wp_fifo_v1 if bound. */ +void MwLLWaylandFifoCommit(struct _MwLLWaylandShmBuffer* buffer); + +#ifdef MW_VULKAN +#warning Wayland backend currently disabled by default when Vulkan enabled. Use with caution (MW_BACKEND=wayland to override). +#endif + void MwLLWaylandBufferSetup(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height); void MwLLWaylandBufferUpdate(MwLL self, struct _MwLLWaylandShmBuffer* buffer); void MwLLWaylandBufferDestroy(struct _MwLLWaylandShmBuffer* buffer); diff --git a/pl/rules.pl b/pl/rules.pl index 986ee98c..6c4df63f 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -66,6 +66,7 @@ if (grep(/^wayland$/, @backends)) { scan_wayland_protocol("unstable", "primary-selection", "-unstable-v1"); scan_wayland_protocol("unstable", "pointer-constraints", "-unstable-v1"); scan_wayland_protocol("unstable", "relative-pointer", "-unstable-v1"); + scan_wayland_protocol("staging", "fifo", "-v1"); scan_wayland_protocol_from_file("wlr-layer-shell", "wlr-layer-shell-unstable-v1.xml"); $gl_libs = "-lGL -lGLU"; diff --git a/src/backend/wayland/buffer.c b/src/backend/wayland/buffer.c index df1de797..3ee5e3ca 100644 --- a/src/backend/wayland/buffer.c +++ b/src/backend/wayland/buffer.c @@ -1,5 +1,39 @@ #include #include +#include "../../../external/stb_ds.h" + +/* Bind a wp_fifo_v1 object to `buffer`'s surface, if wp_fifo_manager_v1 is available and it doesn't have one already. */ +void MwLLWaylandFifoSurfaceSetup(struct _MwLLWayland* wayland, struct _MwLLWaylandShmBuffer* buffer) { + wayland_protocol_t* fifo_manager; + + if(buffer->fifo || !buffer->surface) { + return; + } + + fifo_manager = shget(wayland->wl_protocol_map, wp_fifo_manager_v1_interface.name); + if(!fifo_manager) { + return; + } + + buffer->fifo = wp_fifo_manager_v1_get_fifo(fifo_manager->context, buffer->surface); +} + +/* Destroy `buffer`'s wp_fifo_v1 object, if any. */ +void MwLLWaylandFifoSurfaceDestroy(struct _MwLLWaylandShmBuffer* buffer) { + if(buffer->fifo) { + wp_fifo_v1_destroy(buffer->fifo); + buffer->fifo = NULL; + } +} + +/* Commit `buffer`'s surface, constraining the update to the next display refresh via wp_fifo_v1 if bound. */ +void MwLLWaylandFifoCommit(struct _MwLLWaylandShmBuffer* buffer) { + if(buffer->fifo) { + wp_fifo_v1_set_barrier(buffer->fifo); + wp_fifo_v1_wait_barrier(buffer->fifo); + } + wl_surface_commit(buffer->surface); +} void MwLLWaylandFramebufferSetup(struct _MwLLWayland* wayland) { MwLLWaylandBufferSetup(&wayland->framebuffer, wayland->ww, wayland->wh); diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 0d960c2e..9ce42611 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -19,6 +19,35 @@ static void setup_zwp_clipboard(MwLL self, struct wl_seat* wl_seat); static void destroy_clipboard(MwLL self, struct wl_seat* wl_seat); static void destroy_zwp_clipboard(MwLL self, struct wl_seat* wl_seat); +/* Recursively dispatch a key event to a widget and its children */ +static void recursive_dispatch_key(MwLL handle, int* k) { + MwWidget h = (MwWidget)handle->common.user; + MwLLDispatch(handle, key, k); + if(h) { + int i; + for(i = 0; i < arrlen(h->children); i++) { + MwLLDispatch(h->children[i]->lowlevel, key, k); + if(arrlen(h->children[i]->children) > 0) { + recursive_dispatch_key(h->children[i]->lowlevel, k); + } + } + } +}; +/* Recursively dispatch a key released event to a widget and its children */ +static void recursive_dispatch_key_released(MwLL handle, int* k) { + MwWidget h = (MwWidget)handle->common.user; + MwLLDispatch(handle, key_released, k); + if(h) { + int i; + for(i = 0; i < arrlen(h->children); i++) { + MwLLDispatch(h->children[i]->lowlevel, key_released, k); + if(arrlen(h->children[i]->children) > 0) { + recursive_dispatch_key_released(h->children[i]->lowlevel, k); + } + } + } +}; + /* Recursively dispatch a move event to a widget and its children */ static void recursive_dispatch_move(MwLL handle, MwMouse* p) { MwWidget h = (MwWidget)handle->common.user; @@ -923,15 +952,11 @@ static void keyboard_key(void* data, if(key != -1) { if(state == WL_KEYBOARD_KEY_STATE_PRESSED) { - MwLL topmost_parent = self; - while(topmost_parent->wayland.parent) { - MwLLDispatch(topmost_parent, key, &key); - topmost_parent = topmost_parent->wayland.parent; - } + recursive_dispatch_key(self, &key); self->wayland.holding_key = MwTRUE; self->wayland.last_pressed_key = key; } else { - MwLLDispatch(self, key_released, &key); + recursive_dispatch_key_released(self, &key); self->wayland.holding_key = MwFALSE; } self->wayland.start_time = MwTimeGetTick(); @@ -1193,6 +1218,24 @@ static void wp_viewporter_interface_destroy(struct _MwLLWayland* wayland, waylan (void)data; } +/* wp_fifo_manager_v1 setup function */ +static wayland_protocol_t* wp_fifo_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { + wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); + (void)version; + proto->listener = NULL; + proto->context = wl_registry_bind(wayland->registry, name, &wp_fifo_manager_v1_interface, 1); + + return proto; +} + +static void wp_fifo_manager_v1_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { + (void)wayland; + if(data->context) { + wp_fifo_manager_v1_destroy(data->context); + } + free(data); +} + /* zxdg_decoration_manager_v1 setup function */ static wayland_protocol_t* zxdg_decoration_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); @@ -1295,6 +1338,7 @@ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland) { WL_INTERFACE(zwp_pointer_constraints_v1); WL_INTERFACE(zwp_relative_pointer_manager_v1); WL_INTERFACE(xdg_wm_base); + WL_INTERFACE(wp_fifo_manager_v1); WL_INTERFACE(zwlr_layer_shell_v1); /* Only used for layer surface, but we use it always if it's turned into a tool window */ if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { WL_INTERFACE(wp_viewporter); diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index 4f832dcc..433001b5 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -242,8 +242,7 @@ static void xdg_surface_configure( xdg_surface_ack_configure(xdg_surface, serial); - MwLLWaylandCascadeChildren(self); - // MwLLDispatch(self, draw, NULL); + MwLLDispatch(self, draw, NULL); if(self->wayland.configured) { MwLLWaylandBufferUpdate(self, &self->wayland.framebuffer); @@ -260,7 +259,11 @@ void MwLLWaylandBufferUpdate(MwLL self, struct _MwLLWaylandShmBuffer* buffer) { // Yes this is needed every time, it's how we fix weston. if(self->wayland.configured) wl_surface_attach(buffer->surface, buffer->shm_buffer, 0, 0); - wl_surface_commit(buffer->surface); + if(self->wayland.fifo_wait) { + MwLLWaylandFifoCommit(buffer); + } else { + wl_surface_commit(buffer->surface); + } } } } @@ -309,7 +312,9 @@ static void setup_toplevel(MwLL r, int x, int y) { /* Create a wl_surface, a xdg_surface and a xdg_toplevel */ r->wayland.framebuffer.surface = wl_compositor_create_surface(r->wayland.compositor); r->wayland.backbuffer.surface = wl_compositor_create_surface(r->wayland.compositor); - r->wayland.toplevel->ssurface = wl_subcompositor_get_subsurface(r->wayland.toplevel->scompositor, r->wayland.framebuffer.surface, r->wayland.backbuffer.surface); + MwLLWaylandFifoSurfaceSetup(&r->wayland, &r->wayland.framebuffer); + MwLLWaylandFifoSurfaceSetup(&r->wayland, &r->wayland.backbuffer); + r->wayland.toplevel->ssurface = wl_subcompositor_get_subsurface(r->wayland.toplevel->scompositor, r->wayland.framebuffer.surface, r->wayland.backbuffer.surface); wl_subsurface_set_desync(r->wayland.toplevel->ssurface); r->wayland.toplevel->xdg_surface = @@ -384,6 +389,8 @@ static void destroy_toplevel(MwLL r) { wl_pointer_destroy(r->wayland.pointer); wl_keyboard_destroy(r->wayland.keyboard); + MwLLWaylandFifoSurfaceDestroy(&r->wayland.framebuffer); + MwLLWaylandFifoSurfaceDestroy(&r->wayland.backbuffer); wl_surface_destroy(r->wayland.framebuffer.surface); free(r->wayland.toplevel); @@ -422,6 +429,7 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { } r->wayland.framebuffer.surface = wl_compositor_create_surface(compositor); + MwLLWaylandFifoSurfaceSetup(&r->wayland, &r->wayland.framebuffer); r->wayland.xkb_keymap = parent->wayland.xkb_keymap; r->wayland.xkb_state = parent->wayland.xkb_state; @@ -546,6 +554,7 @@ static void setup_popup(MwLL r, int x, int y, MwLL parent) { r->wayland.xkb_state = topmost_parent->wayland.xkb_state; r->wayland.framebuffer.surface = wl_compositor_create_surface(r->wayland.compositor); + MwLLWaylandFifoSurfaceSetup(&r->wayland, &r->wayland.framebuffer); r->wayland.popup->xdg_surface = xdg_wm_base_get_xdg_surface(WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context, r->wayland.framebuffer.surface); @@ -587,6 +596,8 @@ static void destroy_popup(MwLL r) { xdg_positioner_destroy(r->wayland.popup->xdg_positioner); + MwLLWaylandFifoSurfaceDestroy(&r->wayland.framebuffer); + wl_surface_destroy(r->wayland.framebuffer.surface); wl_registry_destroy(r->wayland.registry); @@ -670,6 +681,7 @@ static void setup_layer_surface(MwLL r, int x, int y, int width, int height) { r->wayland.xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); r->wayland.framebuffer.surface = wl_compositor_create_surface(r->wayland.compositor); + MwLLWaylandFifoSurfaceSetup(&r->wayland, &r->wayland.framebuffer); r->wayland.layer_surface->surface = zwlr_layer_shell_v1_get_layer_surface(layer_shell, r->wayland.framebuffer.surface, NULL, ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, "milsko-surfaces"); @@ -700,6 +712,8 @@ static void destroy_layer_surface(MwLL r) { zxdg_decoration_manager_v1_destroy(dec->manager); } + MwLLWaylandFifoSurfaceDestroy(&r->wayland.framebuffer); + wl_surface_destroy(r->wayland.framebuffer.surface); wl_compositor_destroy(r->wayland.compositor); @@ -1128,8 +1142,7 @@ static void MwLLSetXYImpl(MwLL handle, int x, int y) { if(handle->wayland.type != MwLL_WAYLAND_TOPLEVEL) recursive_render(handle); - MwLLWaylandCascadeChildren(handle); - // MwLLDispatch(handle, draw, NULL); + MwLLDispatch(handle, draw, NULL); } static void actually_set_wh(MwLL handle) { @@ -1158,8 +1171,7 @@ static void actually_set_wh(MwLL handle) { MwLLWaylandFramebufferSetup(&handle->wayland); MwLLWaylandBackbufferDestroy(&handle->wayland); MwLLWaylandBackbufferSetup(&handle->wayland); - MwLLWaylandCascadeChildren(handle); - // MwLLDispatch(handle, draw, NULL); + MwLLDispatch(handle, draw, NULL); } static void MwLLSetWHImpl(MwLL handle, int w, int h) { @@ -1444,8 +1456,7 @@ static int MwLLPendingImpl(MwLL handle) { if(handle->wayland.dark_theme_detection) { handle->wayland.dark_theme_detection = MwFALSE; detect_dark_theme(handle); - MwLLWaylandCascadeChildren(handle); - // MwLLDispatch(handle, draw, NULL); + MwLLDispatch(handle, draw, NULL); } else { MwLLDBusPortalPoll(&wl_call_tbl.dbus, &handle->wayland.dbus, handle, "org.freedesktop.portal.Settings", "org.freedesktop.appearance", "color-scheme", &dark_theme_listener); } @@ -1474,10 +1485,12 @@ static int MwLLPendingImpl(MwLL handle) { return pending; } + if(!handle->wayland.disable_fifo) handle->wayland.fifo_wait = MwTRUE; MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) { MwLLWaylandBufferUpdate(handle, &handle->wayland.backbuffer); } + if(!handle->wayland.disable_fifo) handle->wayland.fifo_wait = MwFALSE; return handle->wayland.force_render || handle->wayland.events_pending || pending; } @@ -1494,9 +1507,11 @@ static void MwLLNextEventImpl(MwLL handle) { } if(handle->wayland.force_render) { + handle->wayland.fifo_wait = MwTRUE; MwLLDispatch(handle, draw, NULL); if(handle->wayland.configured) MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); handle->wayland.force_render = 0; + handle->wayland.fifo_wait = MwFALSE; } if(handle->wayland.events_pending) { handle->wayland.events_pending = 0; @@ -1904,7 +1919,7 @@ static void MwLLSetDarkThemeImpl(MwLL handle, int toggle) { (void)toggle; /* Not Really what's supposed to happen with this function, but take this opprutunity to do the handlers that will force everything to redraw. */ - MwLLWaylandCascadeChildren(handle); + MwLLDispatch(handle, draw, NULL); // MwLLDispatch(handle, resize, NULL); MwLLDispatch(handle, draw, NULL); } @@ -1958,10 +1973,14 @@ static int MwLLWaylandCallInitImpl(void) { } else { loadWayland |= (strcmp(mw_backend_env, "wayland") == 0); } + } - } else if(getenv("WAYLAND_DISPLAY")) { + /* NOTE: when vulkan is enabled, refuse to default to wayland. Remove this if I ever get Vulkan widget working with the new surfaces system. */ +#ifndef MW_VULKAN + else if(getenv("WAYLAND_DISPLAY")) { loadWayland |= (getenv("WAYLAND_DISPLAY") != NULL); } +#endif #ifdef MW_OPENGL if(getenv("WSLENV") || getenv("WSL_DISTRO_NAME")) { diff --git a/src/widget/opengl.c b/src/widget/opengl.c index 30a1cee8..9e1b91e8 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -240,6 +240,12 @@ static int wcreate(MwWidget handle) { waylandopengl_t* o = r = malloc(sizeof(*o)); int gbm_format = 0; EGLConfig egl_configs[1024]; + MwWidget topmost_parent = handle; + + /* Disable fifo waiting when we have an OpenGL widget */ + while(topmost_parent->parent) topmost_parent = topmost_parent->parent; + topmost_parent->lowlevel->wayland.disable_fifo = MwTRUE; + memset(o, 0, sizeof(waylandopengl_t)); o->gllib = MwDynamicOpen("libEGL.so"); diff --git a/src/widget/vulkan.c b/src/widget/vulkan.c index f4c53402..acffda3a 100644 --- a/src/widget/vulkan.c +++ b/src/widget/vulkan.c @@ -240,6 +240,8 @@ static int vulkan_instance_setup(MwWidget handle, vulkan_t* o) { #endif #ifdef USE_WAYLAND if(handle->lowlevel->common.type == MwLLBackendWayland) { + MwWidget topmost_parent = handle; + arrput(o->enabledExtensions, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME); /* take this opprutunity to set the widget to always render */ MwWaylandVulkan = MwTRUE; -- 2.39.5