From 0606f398aeda1a22649ca2099aa98cf2dc53720b Mon Sep 17 00:00:00 2001 From: Nishi Date: Mon, 20 Apr 2026 12:36:01 +0900 Subject: [PATCH] working clipping with wayland --- include/Mw/LowLevel/Wayland.h | 7 ++++++ src/backend/wayland.c | 40 ++++++++++++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 410e8a4..02b59ef 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -118,6 +118,8 @@ typedef struct wayland_call_table { void (*cairo_paint)(cairo_t* cr); void (*cairo_surface_flush)(cairo_surface_t* surface); void (*cairo_clip)(cairo_t* cr); + void (*cairo_save)(cairo_t* cr); + void (*cairo_restore)(cairo_t* cr); void (*cairo_surface_mark_dirty)(cairo_surface_t* surface); void (*cairo_stroke)(cairo_t* cr); void (*cairo_set_source_surface)(cairo_t* cr, @@ -224,6 +226,8 @@ MwInline int wayland_load_funcs() { CAIRO_FUNC(cairo_paint); CAIRO_FUNC(cairo_surface_flush); CAIRO_FUNC(cairo_clip); + CAIRO_FUNC(cairo_save); + CAIRO_FUNC(cairo_restore); CAIRO_FUNC(cairo_surface_mark_dirty); CAIRO_FUNC(cairo_stroke); CAIRO_FUNC(cairo_set_source_surface); @@ -288,6 +292,8 @@ MwInline int wayland_load_funcs() { #define cairo_paint wl_call_tbl.cairo_paint #define cairo_surface_flush wl_call_tbl.cairo_surface_flush #define cairo_clip wl_call_tbl.cairo_clip +#define cairo_save wl_call_tbl.cairo_save +#define cairo_restore wl_call_tbl.cairo_restore #define cairo_surface_mark_dirty wl_call_tbl.cairo_surface_mark_dirty #define cairo_stroke wl_call_tbl.cairo_stroke #define cairo_set_source_surface wl_call_tbl.cairo_set_source_surface @@ -499,6 +505,7 @@ struct _MwLLWayland { MwU32 mw, mh; /* Monitor width and height as advertised by wl_output.mode */ MwLL parent; + MwLL* children; MwBool force_render; MwBool did_event_loop_early; diff --git a/src/backend/wayland.c b/src/backend/wayland.c index dfd560d..99a6280 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1721,9 +1721,9 @@ static void clip(MwLL handle) { MwLL toplevel = handle->wayland.parent; MwLL* ws = NULL; - arrpush(ws, handle); + arrput(ws, handle); while(toplevel) { - arrpush(ws, toplevel); + arrput(ws, toplevel); if(!toplevel->wayland.parent) { break; } @@ -1741,7 +1741,6 @@ static void clip(MwLL handle) { // # ws is traversed result // # ws[ws.length - 1] is ignored bc it's toplevel for(i = arrlen(ws) - 2; i >= 0; i--) { - ; x += ws[i]->wayland.x; y += ws[i]->wayland.y; cx = cx - ws[i]->wayland.x; @@ -1752,11 +1751,14 @@ static void clip(MwLL handle) { cx = MAX(cx, 0); cy = MAX(cy, 0); + arrfree(ws); + handle->wayland.clipping_rect.x = cx; handle->wayland.clipping_rect.y = cy; handle->wayland.clipping_rect.width = w; handle->wayland.clipping_rect.height = h; region_setup(handle); + cairo_reset_clip(handle->wayland.front_cairo); cairo_rectangle(handle->wayland.front_cairo, cx, cy, w, h); cairo_clip(handle->wayland.front_cairo); @@ -1866,6 +1868,10 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { } #endif + if(parent != NULL){ + arrput(parent->wayland.children, r); + } + return r; } @@ -1943,6 +1949,17 @@ static void MwLLDestroyImpl(MwLL handle) { wl_flush(handle); + if(handle->wayland.parent != NULL){ + for(i = 0; i < arrlen(handle->wayland.parent->wayland.children); i++){ + if(handle->wayland.parent->wayland.children[i] == handle){ + arrdel(handle->wayland.parent->wayland.children, i); + break; + } + } + } + + arrfree(handle->wayland.children); + // free(handle); if(currentlyHeldWidget == handle) { @@ -1957,6 +1974,14 @@ static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsign *h = handle->wayland.wh; } +static void recursive_render(MwLL handle){ + int i; + + for(i = 0; i < arrlen(handle->wayland.children); i++) recursive_render(handle->wayland.children[i]); + + MwLLForceRender(handle); +} + static void MwLLSetXYImpl(MwLL handle, int x, int y) { region_invalidate(handle); handle->wayland.x = x; @@ -1966,6 +1991,8 @@ static void MwLLSetXYImpl(MwLL handle, int x, int y) { } region_setup(handle); + recursive_render(handle); + MwLLDispatch(handle, draw, NULL); } @@ -2008,6 +2035,13 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { } static void MwLLBeginDrawImpl(MwLL handle) { + cairo_save(handle->wayland.front_cairo); + cairo_set_source_rgba(handle->wayland.front_cairo, 0, 0, 0, 0); + cairo_set_operator(handle->wayland.front_cairo, CAIRO_OPERATOR_SOURCE); + cairo_rectangle(handle->wayland.front_cairo, 0, 0, handle->wayland.ww, handle->wayland.wh); + cairo_fill(handle->wayland.front_cairo); + cairo_restore(handle->wayland.front_cairo); + if(handle->wayland.type != MWLL_WAYLAND_TOPLEVEL) { handle->wayland.selected_cairo = handle->wayland.front_cairo; return;