Compare commits

...

7 commits

Author SHA1 Message Date
4d768455bc finnish
Some checks are pending
pyrite-dev/milsko/pipeline/head Build started...
2026-09-11 22:29:05 -07:00
f835e41fb0 back
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
2026-09-11 21:34:58 -07:00
6f4164da0c erm
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
2026-09-11 21:25:13 -07:00
5d5170e6ca currentlyHeldWidget brought back
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
2026-09-11 21:23:20 -07:00
f25b676523 and now to merge
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
2026-09-11 21:00:38 -07:00
18d397b4f8 wh 2026-09-11 19:22:32 -07:00
fe17eefb21 revert hyprland code
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
2026-09-11 18:07:34 -07:00
12 changed files with 451 additions and 479 deletions

View file

@ -261,6 +261,7 @@ if(MW_USE_WAYLAND)
scan_wayland_protocol("unstable" "primary-selection" "-unstable-v1") scan_wayland_protocol("unstable" "primary-selection" "-unstable-v1")
scan_wayland_protocol("unstable" "pointer-constraints" "-unstable-v1") scan_wayland_protocol("unstable" "pointer-constraints" "-unstable-v1")
scan_wayland_protocol("unstable" "relative-pointer" "-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") scan_wayland_protocol_from_file("wlr-layer-shell" "wlr-layer-shell-unstable-v1.xml")
target_sources( target_sources(
@ -269,7 +270,6 @@ if(MW_USE_WAYLAND)
src/backend/cairo.c src/backend/cairo.c
src/backend/wayland/wayland.c src/backend/wayland/wayland.c
src/backend/wayland/buffer.c src/backend/wayland/buffer.c
src/backend/wayland/hyprland.c
src/backend/wayland/interfaces.c src/backend/wayland/interfaces.c
src/backend/wayland/region.c src/backend/wayland/region.c
) )

View file

@ -257,8 +257,8 @@ void vulkan_setup(MwWidget handle) {
swapchainCreateInfo.imageExtent = (VkExtent2D){.width = ow, .height = oh}, swapchainCreateInfo.imageExtent = (VkExtent2D){.width = ow, .height = oh},
swapchainCreateInfo.imageArrayLayers = 1, swapchainCreateInfo.imageArrayLayers = 1,
swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT; VK_IMAGE_USAGE_SAMPLED_BIT;
// th is how we specify no transformation. // th is how we specify no transformation.
swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;

View file

@ -207,6 +207,7 @@ MwInline int wayland_load_funcs() {
#include "Wayland/relative-pointer-client-protocol.h" #include "Wayland/relative-pointer-client-protocol.h"
#include "Wayland/xdg-toplevel-icon-client-protocol.h" #include "Wayland/xdg-toplevel-icon-client-protocol.h"
#include "Wayland/wlr-layer-shell-client-protocol.h" #include "Wayland/wlr-layer-shell-client-protocol.h"
#include "Wayland/fifo-client-protocol.h"
#endif #endif
typedef struct wayland_protocol { typedef struct wayland_protocol {
@ -238,8 +239,6 @@ struct _MwLLWaylandTopLevel {
}; };
struct _MwLLWaylandSublevel { struct _MwLLWaylandSublevel {
struct wl_subsurface* subsurface;
struct wl_subcompositor* subcompositor;
MwLL parent; MwLL parent;
@ -268,6 +267,7 @@ struct _MwLLWaylandShmBuffer {
struct wl_buffer* shm_buffer_back; struct wl_buffer* shm_buffer_back;
struct wl_surface* surface; struct wl_surface* surface;
struct wl_output* output; struct wl_output* output;
struct wp_fifo_v1* fifo;
MwU8* buf; MwU8* buf;
MwU8* buf_back; MwU8* buf_back;
@ -414,7 +414,7 @@ struct _MwLLWayland {
MwI32 ox, oy; MwI32 ox, oy;
MwU32 ww, wh; /* Window position */ MwU32 ww, wh; /* Window position */
MwPoint cur_mouse_pos; /* Currently known mouse position */ MwPoint cur_mouse_pos; /* Currently known mouse position */
MwLL currentlyHeldWidget; MwLL* currentlyHeldWidgets;
MwLL focusedWidget; MwLL focusedWidget;
int resizing; int resizing;
@ -426,6 +426,8 @@ struct _MwLLWayland {
MwBool force_render; MwBool force_render;
MwBool did_event_loop_early; MwBool did_event_loop_early;
MwBool do_cascading_draw;
int cascading_child_num;
MwBool dispatching_resize; MwBool dispatching_resize;
@ -435,6 +437,8 @@ struct _MwLLWayland {
struct _MwLLWaylandShmBuffer backbuffer; struct _MwLLWaylandShmBuffer backbuffer;
struct _MwLLWaylandShmBuffer cursor; struct _MwLLWaylandShmBuffer cursor;
struct _MwLLWaylandShmBuffer* icon; struct _MwLLWaylandShmBuffer* icon;
MwBool fifo_wait;
MwBool disable_fifo;
MwLLPixmap icon_pixmap; MwLLPixmap icon_pixmap;
@ -454,8 +458,6 @@ struct _MwLLWayland {
MwU64 next_elapsed; MwU64 next_elapsed;
long start_time; long start_time;
long end_time; long end_time;
MwBool on_hyprland;
}; };
struct _MwLLWaylandColor { struct _MwLLWaylandColor {
@ -474,6 +476,17 @@ void MwLLWaylandBackbufferSetup(struct _MwLLWayland* wayland);
/* Destroy the backbuffer */ /* Destroy the backbuffer */
void MwLLWaylandBackbufferDestroy(struct _MwLLWayland* handle); 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 MwLLWaylandBufferSetup(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height);
void MwLLWaylandBufferUpdate(MwLL self, struct _MwLLWaylandShmBuffer* buffer); void MwLLWaylandBufferUpdate(MwLL self, struct _MwLLWaylandShmBuffer* buffer);
void MwLLWaylandBufferDestroy(struct _MwLLWaylandShmBuffer* buffer); void MwLLWaylandBufferDestroy(struct _MwLLWaylandShmBuffer* buffer);
@ -490,6 +503,7 @@ void MwLLWaylandHangUntilConfigured(MwLL handle);
MwBool MwLLWaylandWidgetIsDestroyed(MwLL self); MwBool MwLLWaylandWidgetIsDestroyed(MwLL self);
void MwLLWaylandWidgetUndestroy(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. */ /* Function for setting up the callbacks/structs that will be registered upon the relevant interfaces being found. */
void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland); void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland);
@ -499,6 +513,8 @@ void MwLLWaylandClipboardRead(wl_clipboard_device_context_t* ctx, int clipboard_
/* Flush Wayland events */ /* Flush Wayland events */
void MwLLWaylandFlush(MwLL handle); void MwLLWaylandFlush(MwLL handle);
void MwLLWaylandCascadeChildren(MwLL handle);
/* Standard procedure before event callbacks in Wayland */ /* Standard procedure before event callbacks in Wayland */
#define WAYLAND_EVENT_OP_START(self) \ #define WAYLAND_EVENT_OP_START(self) \
if(MwLLWaylandWidgetIsDestroyed(self)) { \ if(MwLLWaylandWidgetIsDestroyed(self)) { \

View file

@ -49,7 +49,6 @@ if (grep(/^wayland$/, @backends)) {
new_object("src/backend/cairo.c"); new_object("src/backend/cairo.c");
new_object("src/backend/wayland/wayland.c"); new_object("src/backend/wayland/wayland.c");
new_object("src/backend/wayland/buffer.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/interfaces.c");
new_object("src/backend/wayland/region.c"); new_object("src/backend/wayland/region.c");
@ -67,6 +66,7 @@ if (grep(/^wayland$/, @backends)) {
scan_wayland_protocol("unstable", "primary-selection", "-unstable-v1"); scan_wayland_protocol("unstable", "primary-selection", "-unstable-v1");
scan_wayland_protocol("unstable", "pointer-constraints", "-unstable-v1"); scan_wayland_protocol("unstable", "pointer-constraints", "-unstable-v1");
scan_wayland_protocol("unstable", "relative-pointer", "-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"); scan_wayland_protocol_from_file("wlr-layer-shell", "wlr-layer-shell-unstable-v1.xml");
$gl_libs = "-lGL -lGLU"; $gl_libs = "-lGL -lGLU";

View file

@ -212,8 +212,8 @@ static void MwLLFreeColorImpl(MwLLColor color) {}
static MwBool lmao = MwFALSE; static MwBool lmao = MwFALSE;
static int MwLLPendingImpl(MwLL handle) { static int MwLLPendingImpl(MwLL handle) {
lmao = !lmao; lmao = !lmao;
return lmao; return lmao;
} }
static void MwLLNextEventImpl(MwLL handle) { static void MwLLNextEventImpl(MwLL handle) {
MwLLDispatch(handle, draw, NULL); MwLLDispatch(handle, draw, NULL);
@ -257,10 +257,10 @@ static void MwLLRaiseImpl(MwLL handle) {}
static void MwLLClipImpl(MwLL handle, MwRect* rect) {} static void MwLLClipImpl(MwLL handle, MwRect* rect) {}
static void MwLLSetupDragAndDropImpl(MwLL handle) {} static void MwLLSetupDragAndDropImpl(MwLL handle) {}
static int MwLLCairoCallInitImpl(void) { static int MwLLCairoCallInitImpl(void) {
if(cairo_load_funcs() != 0) { if(cairo_load_funcs() != 0) {
return 1; return 1;
} }
return 0; return 0;
} }
#include "call.c" #include "call.c"
CALL(Cairo); CALL(Cairo);

View file

@ -1,5 +1,39 @@
#include <Mw/Milsko.h> #include <Mw/Milsko.h>
#include <sys/mman.h> #include <sys/mman.h>
#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) { void MwLLWaylandFramebufferSetup(struct _MwLLWayland* wayland) {
MwLLWaylandBufferSetup(&wayland->framebuffer, wayland->ww, wayland->wh); MwLLWaylandBufferSetup(&wayland->framebuffer, wayland->ww, wayland->wh);

View file

@ -1,60 +0,0 @@
#include <Mw/Milsko.h>
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;
}

View file

@ -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_clipboard(MwLL self, struct wl_seat* wl_seat);
static void destroy_zwp_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 */ /* Recursively dispatch a move event to a widget and its children */
static void recursive_dispatch_move(MwLL handle, MwMouse* p) { static void recursive_dispatch_move(MwLL handle, MwMouse* p) {
MwWidget h = (MwWidget)handle->common.user; MwWidget h = (MwWidget)handle->common.user;
@ -40,19 +69,15 @@ static void new_protocol(void* data, struct wl_registry* registry,
MwLL self = data; MwLL self = data;
(void)version; (void)version;
(void)registry; (void)registry;
wayland_protocol_callback_table_t* cb;
WAYLAND_EVENT_OP_START(self); 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) { if(cb != NULL) {
shput(self->wayland.wl_protocol_map, interface, cb->setup(name, data, version)); 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 */ /* 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; 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 { } else {
// printf("unknown interface %s\n", interface); // printf("unknown interface %s\n", interface);
} }
@ -535,8 +560,9 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time
MwLL self = data; MwLL self = data;
MwLL topmost_parent = self; MwLL topmost_parent = self;
MwMouse p; MwMouse p;
MwBool inArea = MwFALSE; MwBool inArea = MwFALSE;
MwLL currentlyHeldWidget = NULL; MwLL* currentlyHeldWidgets = NULL;
int i;
(void)time; (void)time;
(void)wl_pointer; (void)wl_pointer;
@ -544,7 +570,7 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time
WAYLAND_EVENT_OP_START(self); WAYLAND_EVENT_OP_START(self);
while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent;
currentlyHeldWidget = topmost_parent->wayland.currentlyHeldWidget; currentlyHeldWidgets = topmost_parent->wayland.currentlyHeldWidgets;
if(self->wayland.framebuffer.surface) { if(self->wayland.framebuffer.surface) {
inArea |= self->wayland.framebuffer.surface == curSurface; inArea |= self->wayland.framebuffer.surface == curSurface;
@ -556,30 +582,128 @@ 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.x = wl_fixed_to_int(surface_x);
self->wayland.cur_mouse_pos.y = wl_fixed_to_int(surface_y); 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) { if(inArea) {
p.point = self->wayland.cur_mouse_pos; p.point = self->wayland.cur_mouse_pos;
MwLLDispatch(self, move, &p); MwLLDispatch(self, move, &p);
wl_pointer_set_cursor(self->wayland.pointer, self->wayland.pointer_serial, self->wayland.cursor.surface, 0, 0); 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);
} }
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); 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 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, 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;
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) {
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);
}
}
}
}
}
/* `wl_pointer.button` callback */ /* `wl_pointer.button` callback */
static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 serial, MwU32 time, MwU32 button, MwU32 state) { static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 serial, MwU32 time, MwU32 button, MwU32 state) {
MwLL self = data; MwLL self = data;
MwMouse p; MwMouse p;
MwBool inArea = MwFALSE;
MwLL topmost_parent = self; MwLL topmost_parent = self;
int i;
(void)wl_pointer; (void)wl_pointer;
(void)serial; (void)serial;
@ -587,48 +711,35 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri
WAYLAND_EVENT_OP_START(self); WAYLAND_EVENT_OP_START(self);
p.point = self->wayland.cur_mouse_pos;
while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent; while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent;
if(self->wayland.framebuffer.surface) { p.point = self->wayland.cur_mouse_pos;
inArea |= self->wayland.framebuffer.surface == curSurface;
}
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;
switch(state) { switch(button) {
case WL_POINTER_BUTTON_STATE_PRESSED: case BTN_LEFT:
if(button == BTN_LEFT) { p.button = MwMOUSE_LEFT;
topmost_parent->wayland.focusedWidget = self; break;
} case BTN_MIDDLE:
MwLLDispatch(self, down, &p); p.button = MwMOUSE_MIDDLE;
topmost_parent->wayland.currentlyHeldWidget = self; break;
case BTN_RIGHT:
break; p.button = MwMOUSE_RIGHT;
case WL_POINTER_BUTTON_STATE_RELEASED: break;
if(topmost_parent->wayland.currentlyHeldWidget != NULL) {
MwLLDispatch(topmost_parent->wayland.currentlyHeldWidget, up, &p);
topmost_parent->wayland.currentlyHeldWidget = NULL;
} else {
MwLLDispatch(self, up, &p);
}
break;
}
} }
self->wayland.held_down = state == WL_POINTER_BUTTON_STATE_PRESSED;
switch(state) {
case WL_POINTER_BUTTON_STATE_PRESSED:
MwLLDispatch(self, down, &p);
break;
case WL_POINTER_BUTTON_STATE_RELEASED:
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) { if(!self->wayland.has_decorations && self->wayland.do_csd) {
if(state != WL_POINTER_BUTTON_STATE_RELEASED) if(state != WL_POINTER_BUTTON_STATE_RELEASED)
@ -637,6 +748,8 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri
xdg_borderless_step_mup(self, p, serial); xdg_borderless_step_mup(self, p, serial);
} }
MwLLForceRender(self);
WAYLAND_EVENT_OP_END(self); WAYLAND_EVENT_OP_END(self);
}; };
@ -839,15 +952,11 @@ static void keyboard_key(void* data,
if(key != -1) { if(key != -1) {
if(state == WL_KEYBOARD_KEY_STATE_PRESSED) { if(state == WL_KEYBOARD_KEY_STATE_PRESSED) {
MwLL topmost_parent = self; recursive_dispatch_key(self, &key);
while(topmost_parent->wayland.parent) {
MwLLDispatch(topmost_parent, key, &key);
topmost_parent = topmost_parent->wayland.parent;
}
self->wayland.holding_key = MwTRUE; self->wayland.holding_key = MwTRUE;
self->wayland.last_pressed_key = key; self->wayland.last_pressed_key = key;
} else { } else {
MwLLDispatch(self, key_released, &key); recursive_dispatch_key_released(self, &key);
self->wayland.holding_key = MwFALSE; self->wayland.holding_key = MwFALSE;
} }
self->wayland.start_time = MwTimeGetTick(); self->wayland.start_time = MwTimeGetTick();
@ -1060,7 +1169,7 @@ static wayland_protocol_t* wl_subcompositor_setup(MwU32 name, struct _MwLLWaylan
if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { if(wayland->type == MwLL_WAYLAND_TOPLEVEL) {
wayland->toplevel->scompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1); wayland->toplevel->scompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1);
} else { } 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; return NULL;
@ -1071,7 +1180,7 @@ static void wl_subcompositor_interface_destroy(struct _MwLLWayland* wayland, way
if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { if(wayland->type == MwLL_WAYLAND_TOPLEVEL) {
wl_subcompositor_destroy(wayland->toplevel->scompositor); wl_subcompositor_destroy(wayland->toplevel->scompositor);
} else { } else {
wl_subcompositor_destroy(wayland->sublevel->subcompositor); // wl_subcompositor_destroy(wayland->sublevel->subcompositor);
} }
} }
@ -1109,6 +1218,24 @@ static void wp_viewporter_interface_destroy(struct _MwLLWayland* wayland, waylan
(void)data; (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 */ /* zxdg_decoration_manager_v1 setup function */
static wayland_protocol_t* zxdg_decoration_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) { 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)); wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t));
@ -1205,23 +1332,27 @@ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland) {
WL_INTERFACE(wl_shm); WL_INTERFACE(wl_shm);
WL_INTERFACE(wl_compositor); WL_INTERFACE(wl_compositor);
WL_INTERFACE(wl_seat);
WL_INTERFACE(wl_output); WL_INTERFACE(wl_output);
WL_INTERFACE(wl_data_device_manager); WL_INTERFACE(wl_data_device_manager);
WL_INTERFACE(zwp_primary_selection_device_manager_v1); WL_INTERFACE(zwp_primary_selection_device_manager_v1);
WL_INTERFACE(zwp_pointer_constraints_v1); WL_INTERFACE(zwp_pointer_constraints_v1);
WL_INTERFACE(zwp_relative_pointer_manager_v1); WL_INTERFACE(zwp_relative_pointer_manager_v1);
WL_INTERFACE(xdg_wm_base); 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 */ 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) { if(wayland->type == MwLL_WAYLAND_TOPLEVEL) {
WL_INTERFACE(wp_viewporter); WL_INTERFACE(wp_viewporter);
WL_INTERFACE(zxdg_decoration_manager_v1); WL_INTERFACE(zxdg_decoration_manager_v1);
WL_INTERFACE(xdg_toplevel_icon_manager_v1); WL_INTERFACE(xdg_toplevel_icon_manager_v1);
WL_INTERFACE(wl_subcompositor); WL_INTERFACE(wl_subcompositor);
WL_INTERFACE(wl_seat);
} else if(wayland->type == MwLL_WAYLAND_POPUP) { } else if(wayland->type == MwLL_WAYLAND_POPUP) {
WL_INTERFACE(wl_seat);
} else if(wayland->type == MwLL_WAYLAND_LAYER_SURFACE) { } else if(wayland->type == MwLL_WAYLAND_LAYER_SURFACE) {
WL_INTERFACE(wp_viewporter); WL_INTERFACE(wp_viewporter);
WL_INTERFACE(wl_subcompositor); WL_INTERFACE(wl_subcompositor);
WL_INTERFACE(wl_seat);
WL_INTERFACE(wl_seat);
} else { } else {
WL_INTERFACE(wl_subcompositor); WL_INTERFACE(wl_subcompositor);
} }

View file

@ -45,6 +45,19 @@ void MwLLWaylandWidgetUndestroy(MwLL self) {
return; 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);
}
}
}
}
static int event_loop(MwLL handle); static int event_loop(MwLL handle);
/* Recursively dispatch a resize event to a widget and its children */ /* Recursively dispatch a resize event to a widget and its children */
@ -246,7 +259,11 @@ void MwLLWaylandBufferUpdate(MwLL self, struct _MwLLWaylandShmBuffer* buffer) {
// Yes this is needed every time, it's how we fix weston. // Yes this is needed every time, it's how we fix weston.
if(self->wayland.configured) if(self->wayland.configured)
wl_surface_attach(buffer->surface, buffer->shm_buffer, 0, 0); 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);
}
} }
} }
} }
@ -295,7 +312,9 @@ static void setup_toplevel(MwLL r, int x, int y) {
/* Create a wl_surface, a xdg_surface and a xdg_toplevel */ /* Create a wl_surface, a xdg_surface and a xdg_toplevel */
r->wayland.framebuffer.surface = wl_compositor_create_surface(r->wayland.compositor); r->wayland.framebuffer.surface = wl_compositor_create_surface(r->wayland.compositor);
r->wayland.backbuffer.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); wl_subsurface_set_desync(r->wayland.toplevel->ssurface);
r->wayland.toplevel->xdg_surface = r->wayland.toplevel->xdg_surface =
@ -370,18 +389,8 @@ static void destroy_toplevel(MwLL r) {
wl_pointer_destroy(r->wayland.pointer); wl_pointer_destroy(r->wayland.pointer);
wl_keyboard_destroy(r->wayland.keyboard); wl_keyboard_destroy(r->wayland.keyboard);
if(r->common.user) { MwLLWaylandFifoSurfaceDestroy(&r->wayland.framebuffer);
MwWidget w = r->common.user; MwLLWaylandFifoSurfaceDestroy(&r->wayland.backbuffer);
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); wl_surface_destroy(r->wayland.framebuffer.surface);
free(r->wayland.toplevel); free(r->wayland.toplevel);
@ -420,15 +429,7 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) {
} }
r->wayland.framebuffer.surface = wl_compositor_create_surface(compositor); r->wayland.framebuffer.surface = wl_compositor_create_surface(compositor);
MwLLWaylandFifoSurfaceSetup(&r->wayland, &r->wayland.framebuffer);
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_keymap = parent->wayland.xkb_keymap;
r->wayland.xkb_state = parent->wayland.xkb_state; r->wayland.xkb_state = parent->wayland.xkb_state;
@ -436,7 +437,6 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) {
r->wayland.configured = MwTRUE; r->wayland.configured = MwTRUE;
MwLLWaylandFramebufferSetup(&r->wayland); MwLLWaylandFramebufferSetup(&r->wayland);
MwLLWaylandBackbufferSetup(&r->wayland);
} }
/* Sublevel setup function */ /* Sublevel setup function */
@ -444,8 +444,6 @@ static void destroy_sublevel(MwLL r) {
MwLLWaylandBackbufferDestroy(&r->wayland); MwLLWaylandBackbufferDestroy(&r->wayland);
MwLLWaylandFramebufferDestroy(&r->wayland); MwLLWaylandFramebufferDestroy(&r->wayland);
wl_subsurface_destroy(r->wayland.sublevel->subsurface);
free(r->wayland.sublevel); free(r->wayland.sublevel);
r->wayland.configured = MwFALSE; r->wayland.configured = MwFALSE;
@ -556,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.xkb_state = topmost_parent->wayland.xkb_state;
r->wayland.framebuffer.surface = wl_compositor_create_surface(r->wayland.compositor); r->wayland.framebuffer.surface = wl_compositor_create_surface(r->wayland.compositor);
MwLLWaylandFifoSurfaceSetup(&r->wayland, &r->wayland.framebuffer);
r->wayland.popup->xdg_surface = r->wayland.popup->xdg_surface =
xdg_wm_base_get_xdg_surface(WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context, r->wayland.framebuffer.surface); xdg_wm_base_get_xdg_surface(WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context, r->wayland.framebuffer.surface);
@ -597,6 +596,8 @@ static void destroy_popup(MwLL r) {
xdg_positioner_destroy(r->wayland.popup->xdg_positioner); xdg_positioner_destroy(r->wayland.popup->xdg_positioner);
MwLLWaylandFifoSurfaceDestroy(&r->wayland.framebuffer);
wl_surface_destroy(r->wayland.framebuffer.surface); wl_surface_destroy(r->wayland.framebuffer.surface);
wl_registry_destroy(r->wayland.registry); wl_registry_destroy(r->wayland.registry);
@ -680,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.xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
r->wayland.framebuffer.surface = wl_compositor_create_surface(r->wayland.compositor); 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"); 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");
@ -710,6 +712,8 @@ static void destroy_layer_surface(MwLL r) {
zxdg_decoration_manager_v1_destroy(dec->manager); zxdg_decoration_manager_v1_destroy(dec->manager);
} }
MwLLWaylandFifoSurfaceDestroy(&r->wayland.framebuffer);
wl_surface_destroy(r->wayland.framebuffer.surface); wl_surface_destroy(r->wayland.framebuffer.surface);
wl_compositor_destroy(r->wayland.compositor); wl_compositor_destroy(r->wayland.compositor);
@ -957,6 +961,60 @@ static void detect_dark_theme(MwLL handle) {
} }
#endif #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++;
}
void MwLLWaylandCascadeChildren(MwLL handle) {
handle->wayland.cascading_child_num = 0;
MwLLWaylandChildrenIterate(handle, count_child);
handle->wayland.do_cascading_draw = handle->wayland.cascading_child_num * 10;
MwLLWaylandChildrenIterate(handle, cascade_child);
}
static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) {
MwLL r; MwLL r;
r = malloc(sizeof(*r)); r = malloc(sizeof(*r));
@ -1035,10 +1093,6 @@ static void MwLLDestroyImpl(MwLL handle) {
pthread_mutex_unlock(&destroyedWidgetsTableMutex); pthread_mutex_unlock(&destroyedWidgetsTableMutex);
free(handle); 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) { static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h) {
@ -1058,15 +1112,18 @@ static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsign
static void MwLLSetXYImpl(MwLL handle, int x, int y) { static void MwLLSetXYImpl(MwLL handle, int x, int y) {
WIDGET_CHECK(handle); WIDGET_CHECK(handle);
MwLLWaylandRegionInvalidate(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) { switch(handle->wayland.type) {
case MwLL_WAYLAND_TOPLEVEL: case MwLL_WAYLAND_TOPLEVEL:
/* toplevels cannot be moved */ /* toplevels cannot be moved */
break; break;
case MwLL_WAYLAND_SUBLEVEL: case MwLL_WAYLAND_SUBLEVEL:
wl_subsurface_set_position(handle->wayland.sublevel->subsurface, x, y); /* sublevels are drawn according to their own x/y */
break; break;
case MwLL_WAYLAND_POPUP: 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); 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);
@ -1304,6 +1361,8 @@ static void MwLLEndDrawImpl(MwLL handle) {
MwLLWaylandBufferUpdate(handle, &handle->wayland.backbuffer); MwLLWaylandBufferUpdate(handle, &handle->wayland.backbuffer);
} }
MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer);
MwLLWaylandCascadeChildren(handle);
} }
} }
@ -1372,6 +1431,12 @@ static int MwLLPendingImpl(MwLL handle) {
handle->wayland.setting_wh = 0; 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(); handle->wayland.end_time = MwTimeGetTick();
if(handle->wayland.holding_key) { if(handle->wayland.holding_key) {
@ -1420,16 +1485,19 @@ static int MwLLPendingImpl(MwLL handle) {
return pending; return pending;
} }
if(!handle->wayland.disable_fifo) handle->wayland.fifo_wait = MwTRUE;
MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer);
if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) { if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) {
MwLLWaylandBufferUpdate(handle, &handle->wayland.backbuffer); 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; return handle->wayland.force_render || handle->wayland.events_pending || pending;
} }
static void MwLLNextEventImpl(MwLL handle) { static void MwLLNextEventImpl(MwLL handle) {
WIDGET_CHECK(handle); WIDGET_CHECK(handle);
if(!MwWaylandVulkan) { if(!MwWaylandVulkan) {
if(handle->wayland.did_event_loop_early) { if(handle->wayland.did_event_loop_early) {
handle->wayland.did_event_loop_early = MwFALSE; handle->wayland.did_event_loop_early = MwFALSE;
@ -1439,9 +1507,11 @@ static void MwLLNextEventImpl(MwLL handle) {
} }
if(handle->wayland.force_render) { if(handle->wayland.force_render) {
handle->wayland.fifo_wait = MwTRUE;
MwLLDispatch(handle, draw, NULL); MwLLDispatch(handle, draw, NULL);
if(handle->wayland.configured) MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer); if(handle->wayland.configured) MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer);
handle->wayland.force_render = 0; handle->wayland.force_render = 0;
handle->wayland.fifo_wait = MwFALSE;
} }
if(handle->wayland.events_pending) { if(handle->wayland.events_pending) {
handle->wayland.events_pending = 0; handle->wayland.events_pending = 0;
@ -1670,7 +1740,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); dec->decoration, toggle ? ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE : ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
} else { } else {
handle->wayland.do_csd = !toggle; 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);
} }
} }
} }
@ -1838,31 +1908,6 @@ static void MwLLEndStateChangeImpl(MwLL handle) {
if(!handle->wayland.parent) if(!handle->wayland.parent)
handle->wayland.dark_theme_detection = MwTRUE; 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);
if(topmost_parent) {
topmost_parent->wayland.currentlyHeldWidget = NULL;
}
}
}
}
recursive_render(handle); recursive_render(handle);
handle->wayland.events_pending = 1; handle->wayland.events_pending = 1;
@ -1874,7 +1919,8 @@ static void MwLLSetDarkThemeImpl(MwLL handle, int toggle) {
(void)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. */ /* 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); MwLLDispatch(handle, draw, NULL);
// MwLLDispatch(handle, resize, NULL);
MwLLDispatch(handle, draw, NULL); MwLLDispatch(handle, draw, NULL);
} }
@ -1927,10 +1973,14 @@ static int MwLLWaylandCallInitImpl(void) {
} else { } else {
loadWayland |= (strcmp(mw_backend_env, "wayland") == 0); 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); loadWayland |= (getenv("WAYLAND_DISPLAY") != NULL);
} }
#endif
#ifdef MW_OPENGL #ifdef MW_OPENGL
if(getenv("WSLENV") || getenv("WSL_DISTRO_NAME")) { if(getenv("WSLENV") || getenv("WSL_DISTRO_NAME")) {

View file

@ -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) { void MwParseColorNoAllocate(const char* text, MwRGB* rgb) {
if(text[0] == '#' && strlen(text) == 4) { if(text[0] == '#' && strlen(text) == 4) {
rgb->red = hex(text + 1, 1); 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) { void MwDrawRect(MwWidget handle, MwRect* rect, MwLLColor color) {
if(MwLLWaylandDoRoundness(handle->lowlevel)) { MwPoint p[4];
fill_rect_rounded(handle, rect, color, MwLLWaylandHyprlandGetRoundness());
} else { p[0].x = rect->x;
fill_rect(handle, rect, color); 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) { void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color) {
MwLLPixmap pixmap; MwLLPixmap pixmap;
int y; int y;
double darken = 0.; double darken = 0.;
int ColorDiff = get_color_diff(handle); int ColorDiff = get_color_diff(handle);
MwRect r = *rect; double darkenStep = (ColorDiff / 2.) / rect->height;
int roundness = MwLLWaylandDoRoundness(handle->lowlevel) ? MwLLWaylandHyprlandGetRoundness() : 0; unsigned long sz = 1 * rect->height * 4;
unsigned char* data = malloc(sz * 2);
if(rect->width <= 0 || rect->height <= 0) { MwRect r = *rect;
if(!data) {
return; return;
} }
if(rect->width <= 0 || rect->height <= 0) {
free(data);
return;
}
memset(data, 0, sz);
r.x += 1; r.x += 1;
r.y += 1; r.y += 1;
r.width -= 2; r.width -= 2;
r.height -= 2; r.height -= 2;
if(r.width <= 0 || r.height <= 0) { for(y = 0; y < rect->height; y++) {
return; 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) { pixmap = MwLLCreatePixmap(handle->lowlevel, data, 1, rect->height);
double darkenStep = (ColorDiff / 2.) / rect->height; MwLLDrawPixmap(handle->lowlevel, &r, pixmap);
unsigned long sz = 1 * rect->height * 4; MwLLDestroyPixmap(pixmap);
unsigned char* data = malloc(sz * 2);
if(!data) {
return;
}
memset(data, 0, sz);
for(y = 0; y < rect->height; y++) { free(data);
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);
}
} }
void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert) { 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)); MwLLColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground));
if(c != NULL) { if(c != NULL) {
int roundness = MwLLWaylandDoRoundness(handle->lowlevel) ? MwLLWaylandHyprlandGetRoundness() : 0; MwDrawRect(handle, rect, c);
fill_rect_rounded(handle, rect, c, MwGetInteger(handle, MwNmodernLook) ? roundness : 0);
MwLLFreeColor(c); MwLLFreeColor(c);
} }
} }
@ -595,113 +454,48 @@ static void MwDrawFrameEx_simple(MwWidget handle, MwRect* rect, MwLLColor color,
rect->height -= border * 2; rect->height -= border * 2;
} }
#define FRAME_ARC_STEPS 6 static void frame_border_complex(MwWidget handle, MwRect* rect, MwLLColor lighter, MwLLColor darker, int invert, int border, int diff, int same) {
MwPoint p[7];
/* 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;
(void)diff; (void)diff;
(void)same; (void)same;
if(r < 0) r = 0; p[0].x = rect->x;
if(r > w / 2) r = w / 2; p[0].y = rect->y;
if(r > h / 2) r = h / 2;
if(r <= 0) { p[1].x = rect->x + rect->width;
p[0].x = x; p[1].y = rect->y;
p[0].y = y;
p[1].x = x + w; p[2].x = rect->x + rect->width - border;
p[1].y = y; 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[4].x = rect->x + border;
p[2].y = y + border; p[4].y = rect->y + rect->height - border;
p[3].x = x + border;
p[3].y = y + border;
p[4].x = x + border; p[5].x = rect->x;
p[4].y = y + h - border; p[5].y = rect->y + rect->height;
MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker);
p[5].x = x; p[0].x = rect->x + rect->width;
p[5].y = y + h; p[0].y = rect->y;
MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker);
p[0].x = x + w; p[1].x = rect->x + rect->width - border;
p[0].y = y; p[1].y = rect->y + border;
p[1].x = x + w - border; p[2].x = rect->x + rect->width - border;
p[1].y = y + border; p[2].y = rect->y + rect->height - border;
p[2].x = x + w - border; p[3].x = rect->x + border;
p[2].y = y + h - border; p[3].y = rect->y + rect->height - border;
p[3].x = x + border; p[4].x = rect->x;
p[3].y = y + h - border; p[4].y = rect->y + rect->height;
p[4].x = x; p[5].x = rect->x + rect->width;
p[4].y = y + h; p[5].y = rect->y + rect->height;
MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker);
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);
} }
static void MwDrawFrameEx_complex(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border, int diff, int same) { 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 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); MwLLColor lighter = same ? MwLightenColor(handle, darker, 0, 0, 0) : MwLightenColor(handle, color, (ColorDiff / 2) - diff, (ColorDiff / 2) - diff, (ColorDiff / 2) - diff);
MwRect r = *rect; MwRect r = *rect;
int roundness = MwLLWaylandDoRoundness(handle->lowlevel) ? MwLLWaylandHyprlandGetRoundness() : 0;
color_set_disabled_if_disabled(handle, darker); color_set_disabled_if_disabled(handle, darker);
color_set_disabled_if_disabled(handle, lighter); 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) { if(border > 1) {
r.x += border / 2; r.x += border / 2;
r.y += border / 2; r.y += border / 2;
r.width -= border; r.width -= border;
r.height -= 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); MwLLFreeColor(lighter);

View file

@ -240,6 +240,12 @@ static int wcreate(MwWidget handle) {
waylandopengl_t* o = r = malloc(sizeof(*o)); waylandopengl_t* o = r = malloc(sizeof(*o));
int gbm_format = 0; int gbm_format = 0;
EGLConfig egl_configs[1024]; 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)); memset(o, 0, sizeof(waylandopengl_t));
o->gllib = MwDynamicOpen("libEGL.so"); o->gllib = MwDynamicOpen("libEGL.so");

View file

@ -240,6 +240,8 @@ static int vulkan_instance_setup(MwWidget handle, vulkan_t* o) {
#endif #endif
#ifdef USE_WAYLAND #ifdef USE_WAYLAND
if(handle->lowlevel->common.type == MwLLBackendWayland) { if(handle->lowlevel->common.type == MwLLBackendWayland) {
MwWidget topmost_parent = handle;
arrput(o->enabledExtensions, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME); arrput(o->enabledExtensions, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
/* take this opprutunity to set the widget to always render */ /* take this opprutunity to set the widget to always render */
MwWaylandVulkan = MwTRUE; MwWaylandVulkan = MwTRUE;