This commit is contained in:
parent
f835e41fb0
commit
4d768455bc
9 changed files with 142 additions and 20 deletions
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -1,5 +1,39 @@
|
|||
#include <Mw/Milsko.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) {
|
||||
MwLLWaylandBufferSetup(&wayland->framebuffer, wayland->ww, wayland->wh);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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")) {
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue