Compare commits

...
Sign in to create a new pull request.

8 commits

Author SHA1 Message Date
0181a61a3d add libdecor cflags to perl
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
2026-05-20 13:56:20 -07:00
4c331ad2da wayland: undo the 'has_decorations' override
Some checks failed
pyrite-dev/milsko/pipeline/head There was a failure building this commit
2026-05-20 13:53:32 -07:00
6e2b0ff097 wayland: shitdecor fixes
Some checks failed
pyrite-dev/milsko/pipeline/head There was a failure building this commit
2026-05-20 13:52:11 -07:00
7aad2af609 wayland: merge libdecor
Some checks failed
pyrite-dev/milsko/pipeline/head There was a failure building this commit
2026-05-20 13:45:35 -07:00
70147b2716 works for me
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
2026-05-21 05:22:35 +09:00
ad7db9dcec maybe
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
2026-05-21 04:55:00 +09:00
8fe9a1c168 wayland: clean up destroyedWidgetsTableMutex remenants
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
2026-05-20 12:50:08 -07:00
14915e082a remove wayland's widget-checking stuff in an effort to remove one of the last hacks from the wayland backend
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
2026-05-20 12:46:52 -07:00
5 changed files with 223 additions and 223 deletions

View file

@ -14,7 +14,13 @@
#include <xkbcommon/xkbcommon.h>
#include <cairo/cairo.h>
#include <pthread.h>
#include <dbus/dbus.h>
/* libdecor is included later on so that it's covered by the wayland dynloading. */
struct libdecor_frame;
struct libdecor_interface;
struct libdecor_configuration;
struct libdecor_frame_interface;
enum libdecor_window_state;
struct wl_surface;
#ifdef __cplusplus
extern "C" {
@ -44,6 +50,8 @@ typedef struct wayland_call_table {
void* lib;
void* xkb_lib;
void* cairo_lib;
void* libdecor_lib;
#ifdef USE_DBUS
MwLLDBusFuncTable dbus;
MwBool has_dbus;
@ -141,6 +149,20 @@ typedef struct wayland_call_table {
void (*cairo_set_antialias)(cairo_t*, cairo_antialias_t);
void (*cairo_set_operator)(cairo_t* cr, cairo_operator_t op);
MwBool has_libdecor;
struct libdecor* (*libdecor_new)(struct wl_display* display, struct libdecor_interface* iface);
struct libdecor_state* (*libdecor_state_new)(int width, int height);
void (*libdecor_frame_commit)(struct libdecor_frame* frame, struct libdecor_state* state, struct libdecor_configuration* configuration);
void (*libdecor_state_free)(struct libdecor_state* state);
struct libdecor_frame* (*libdecor_decorate)(struct libdecor* context, struct wl_surface* surface, struct libdecor_frame_interface* iface, void* user_data);
void (*libdecor_frame_set_app_id)(struct libdecor_frame* frame, const char* app_id);
void (*libdecor_frame_set_title)(struct libdecor_frame* frame, const char* title);
void (*libdecor_frame_map)(struct libdecor_frame* frame);
MwBool (*libdecor_configuration_get_content_size)(struct libdecor_configuration* configuration, struct libdecor_frame* frame, int* width, int* height);
MwBool (*libdecor_configuration_get_window_state)(struct libdecor_configuration* configuration, enum libdecor_window_state* window_state);
struct xdg_surface* (*libdecor_frame_get_xdg_surface)(struct libdecor_frame* frame);
int (*libdecor_dispatch)(struct libdecor* context, int timeout);
void (*libdecor_frame_translate_coordinate)(struct libdecor_frame* frame, int surface_x, int surface_y, int* frame_x, int* frame_y);
} wayland_call_table_t;
extern wayland_call_table_t wl_call_tbl;
@ -186,6 +208,17 @@ MwInline int wayland_load_funcs() {
return 1; \
};
/* i mean i pray if somebody is using thr wayland backend over apple/ios that actual decorations are supported. */
#ifdef __APPLE__
wl_call_tbl.libdecor_lib = MwDynamicOpen("libdecor-0.dylib");
#else
wl_call_tbl.libdecor_lib = MwDynamicOpen("libdecor-0.so");
#endif
wl_call_tbl.has_libdecor = (wl_call_tbl.libdecor_lib != NULL);
if(!wl_call_tbl.libdecor_lib) {
printf("(libdecor not found, window will not have any decorations.)\n");
}
WAYLAND_FUNC(wl_display_dispatch)
WAYLAND_FUNC(wl_display_dispatch_pending)
WAYLAND_FUNC(wl_display_disconnect)
@ -267,6 +300,28 @@ MwInline int wayland_load_funcs() {
wl_call_tbl.has_dbus = MwLLDBusFuncSetup(&wl_call_tbl.dbus);
#endif
if(wl_call_tbl.has_libdecor) {
#define LIBDECOR_FUNC(x) \
wl_call_tbl.x = MwDynamicSymbol(wl_call_tbl.libdecor_lib, #x); \
if(!wl_call_tbl.x) { \
printf("WARNING: Can't use libdecor because libdecor-1 doesn't export " #x ".\n"); \
wl_call_tbl.has_libdecor = MwFALSE; \
};
LIBDECOR_FUNC(libdecor_new);
LIBDECOR_FUNC(libdecor_state_new);
LIBDECOR_FUNC(libdecor_frame_commit);
LIBDECOR_FUNC(libdecor_state_free);
LIBDECOR_FUNC(libdecor_decorate);
LIBDECOR_FUNC(libdecor_frame_set_app_id);
LIBDECOR_FUNC(libdecor_frame_set_title);
LIBDECOR_FUNC(libdecor_frame_map);
LIBDECOR_FUNC(libdecor_configuration_get_content_size);
LIBDECOR_FUNC(libdecor_configuration_get_window_state);
LIBDECOR_FUNC(libdecor_frame_get_xdg_surface);
LIBDECOR_FUNC(libdecor_dispatch);
}
return 0;
}
@ -342,6 +397,8 @@ MwInline int wayland_load_funcs() {
#include "Wayland/xdg-toplevel-icon-client-protocol.h"
#endif
#include <libdecor.h>
typedef struct wayland_protocol {
void* listener;
void* context;
@ -495,6 +552,11 @@ struct _MwLLWayland {
MwLLDBusContext dbus;
#endif
struct libdecor* decor;
struct libdecor_frame* decor_frame;
struct libdecor_interface* decor_interface;
enum libdecor_window_state decor_state;
MwBool dark_theme_detection;
MwU32 dark_theme;
@ -568,8 +630,6 @@ struct _MwLLWayland {
cairo_surface_t* back_cs;
cairo_t* front_cairo;
cairo_t* back_cairo;
/* The cairo to actually use for draw operations. Typically is front_cairo, but MwLLBeginDraw can change this to the back_cairo so it can be used to draw window decorations. */
cairo_t* selected_cairo;
};
struct _MwLLWaylandColor {
@ -601,9 +661,6 @@ void MwLLWaylandRegionInvalidate(MwLL handle);
void MwLLWaylandHangUntilConfigured(MwLL handle);
MwBool MwLLWaylandWidgetIsDestroyed(MwLL self);
void MwLLWaylandWidgetUndestroy(MwLL self);
/* Function for setting up the callbacks/structs that will be registered upon the relevant interfaces being found. */
void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland);
@ -613,19 +670,11 @@ 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)
#define WIDGET_CHECK(handle) \
if(!handle->wayland.valid) { \
return; \
}
/* the two decoration manager constructs */
typedef struct zxdg_decoration_manager_v1_context {
struct zxdg_decoration_manager_v1* manager;

View file

@ -2,6 +2,7 @@ my @enabled_backends = ();
if (param_get("wayland") && not(param_get("tiny"))) {
push(@enabled_backends, "wayland");
add_cflags(`pkg-config --cflags libdecor-0`);
}
if (param_get("x11")) {
push(@enabled_backends, "x11");
@ -9,6 +10,7 @@ if (param_get("x11")) {
add_cflags("-DUSE_DBUS");
use_backend(@enabled_backends);
1;

View file

@ -12,7 +12,7 @@ void MwLLWaylandFramebufferSetup(struct _MwLLWayland* wayland) {
wl_surface_attach(wayland->framebuffer.surface, wayland->framebuffer.shm_buffer, 0, 0);
wl_surface_commit(wayland->framebuffer.surface);
MwLLWaylandHangUntilConfigured((MwLL)wayland);
// MwLLWaylandHangUntilConfigured((MwLL)wayland);
MwLLWaylandBufferUpdate((MwLL)wayland, &wayland->framebuffer);
};
void MwLLWaylandFramebufferDestroy(struct _MwLLWayland* wayland) {

View file

@ -10,39 +10,6 @@ wayland_call_table_t wl_call_tbl;
MwBool MwWaylandVulkan = MwFALSE;
#endif
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.
*
* TODO(IOI): FUCKING NO???? FIX THIS.
*/
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;
}
static int event_loop(MwLL handle);
/* Recursively dispatch a resize event to a widget and its children */
@ -61,7 +28,6 @@ static void recursive_dispatch_resize(MwLL handle) {
static void recursive_render(MwLL handle) {
int i;
WIDGET_CHECK(handle);
for(i = 0; i < arrlen(((MwWidget)handle->common.user)->children); i++) recursive_render(((MwWidget)handle->common.user)->children[i]->lowlevel);
@ -235,6 +201,96 @@ void MwLLWaylandBufferUpdate(MwLL self, struct _MwLLWaylandShmBuffer* buffer) {
}
}
/* shitdecor */
static void libdecor_error(struct libdecor* context,
enum libdecor_error error,
const char* message) {
printf("libdecor error (%d): %s\n", error, message);
}
static void
handle_configure(struct libdecor_frame* frame,
struct libdecor_configuration* configuration,
void* user_data) {
MwLL self = user_data;
int width, height;
enum libdecor_window_state window_state;
struct libdecor_state* state;
if(!wl_call_tbl.libdecor_configuration_get_content_size(configuration, frame,
&width, &height)) {
width = self->wayland.ww;
height = self->wayland.wh;
}
width = (width == 0) ? 1 : width;
height = (height == 0) ? 1 : height;
// region_invalidate(self);
self->wayland.ww = width;
self->wayland.wh = height;
if(self->wayland.resizing == 0) {
MwLLWaylandFramebufferDestroy(&self->wayland);
MwLLWaylandFramebufferSetup(&self->wayland);
MwLLWaylandRegionSetup(self);
MwLLDispatch(self, resize, NULL);
recursive_dispatch_resize(self);
if(self->wayland.pointer_constrained) {
zwp_locked_pointer_v1_set_cursor_position_hint(self->wayland.locked_pointer, 0, CSD_BORDER_FRAME_TOP);
wl_surface_commit(self->wayland.framebuffer.surface);
}
self->wayland.resizing = 1;
}
MwLLDispatch(self, draw, NULL);
if(!wl_call_tbl.libdecor_configuration_get_window_state(configuration,
&window_state))
window_state = LIBDECOR_WINDOW_STATE_NONE;
self->wayland.decor_state = window_state;
state = wl_call_tbl.libdecor_state_new(width, height);
wl_call_tbl.libdecor_frame_commit(frame, state, configuration);
wl_call_tbl.libdecor_state_free(state);
self->wayland.configured = MwTRUE;
}
static void
handle_close(struct libdecor_frame* frame,
void* user_data) {
MwLL self = user_data;
MwLLDispatch(self, close, NULL);
}
static void
handle_commit(struct libdecor_frame* frame,
void* user_data) {
MwLL self = user_data;
wl_surface_commit(self->wayland.framebuffer.surface);
}
static void
handle_dismiss_popup(struct libdecor_frame* frame,
const char* seat_name,
void* user_data) {
}
static struct libdecor_frame_interface libdecor_frame_iface = {
handle_configure,
handle_close,
handle_commit,
handle_dismiss_popup,
};
static struct libdecor_interface libdecor_interface = {
libdecor_error};
/* Toplevel setup function */
static void setup_toplevel(MwLL r, int x, int y) {
r->wayland.type = MwLL_WAYLAND_TOPLEVEL;
@ -268,15 +324,14 @@ static void setup_toplevel(MwLL r, int x, int y) {
r->wayland.xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
/* 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);
wl_subsurface_set_desync(r->wayland.toplevel->ssurface);
if(r->wayland.has_decorations) {
r->wayland.toplevel->xdg_surface =
xdg_wm_base_get_xdg_surface(WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context, r->wayland.backbuffer.surface);
xdg_wm_base_get_xdg_surface(WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context, r->wayland.framebuffer.surface);
r->wayland.toplevel->xdg_top_level = xdg_surface_get_toplevel(r->wayland.toplevel->xdg_surface);
}
/* setup mandatory listeners */
r->wayland.toplevel->xdg_surface_listener.configure = xdg_surface_configure;
@ -284,16 +339,26 @@ static void setup_toplevel(MwLL r, int x, int y) {
r->wayland.toplevel->xdg_toplevel_listener.configure = xdg_toplevel_configure;
r->wayland.toplevel->xdg_toplevel_listener.close = xdg_toplevel_close;
if(r->wayland.has_decorations) {
xdg_surface_add_listener(r->wayland.toplevel->xdg_surface, &r->wayland.toplevel->xdg_surface_listener, r);
xdg_toplevel_add_listener(r->wayland.toplevel->xdg_top_level, &r->wayland.toplevel->xdg_toplevel_listener,
r);
xdg_toplevel_set_title(r->wayland.toplevel->xdg_top_level, "Milsko App");
xdg_toplevel_set_app_id(r->wayland.toplevel->xdg_top_level, "MilskoWaylandApp");
} else {
r->wayland.decor = wl_call_tbl.libdecor_new(r->wayland.display, &libdecor_interface);
r->wayland.decor_frame = wl_call_tbl.libdecor_decorate(r->wayland.decor, r->wayland.framebuffer.surface,
&libdecor_frame_iface, r);
wl_call_tbl.libdecor_frame_set_app_id(r->wayland.decor_frame, "milsko-app");
wl_call_tbl.libdecor_frame_set_title(r->wayland.decor_frame, "Milsko App");
wl_call_tbl.libdecor_frame_map(r->wayland.decor_frame);
}
/* Perform the initial commit and wait for the first configure event */
wl_surface_commit(r->wayland.backbuffer.surface);
wl_surface_commit(r->wayland.framebuffer.surface);
wl_surface_commit(r->wayland.backbuffer.surface);
while(!r->wayland.configured) {
event_loop(r);
}
@ -307,8 +372,6 @@ static void setup_toplevel(MwLL r, int x, int y) {
zxdg_toplevel_decoration_v1_set_mode(
dec->decoration, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
} else {
wl_subsurface_set_position(r->wayland.toplevel->ssurface, CSD_BORDER_FRAME_LEFT, CSD_BORDER_FRAME_TOP);
}
}
@ -323,9 +386,10 @@ static void destroy_toplevel(MwLL r) {
wl_compositor_destroy(r->wayland.compositor);
if(r->wayland.has_decorations) {
xdg_surface_destroy(r->wayland.toplevel->xdg_surface);
xdg_toplevel_destroy(r->wayland.toplevel->xdg_top_level);
}
xkb_keymap_unref(r->wayland.xkb_keymap);
@ -440,6 +504,7 @@ struct xdg_popup_listener popup_listener = {
/* Popup setup function */
static void setup_popup(MwLL r, int x, int y, MwLL parent) {
struct xdg_surface* xdg_surface;
struct xdg_surface* parent_xdg_surface;
MwLL topmost_parent = r->wayland.parent;
r->wayland.type = MwLL_WAYLAND_POPUP;
@ -489,16 +554,20 @@ static void setup_popup(MwLL r, int x, int y, MwLL parent) {
r->wayland.framebuffer.surface = wl_compositor_create_surface(r->wayland.compositor);
if(r->wayland.has_decorations) {
parent_xdg_surface = topmost_parent->wayland.toplevel->xdg_surface;
} else {
parent_xdg_surface = wl_call_tbl.libdecor_frame_get_xdg_surface(topmost_parent->wayland.decor_frame);
}
r->wayland.popup->xdg_surface =
xdg_wm_base_get_xdg_surface(WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context, r->wayland.framebuffer.surface);
r->wayland.popup->xdg_popup = xdg_surface_get_popup(
r->wayland.popup->xdg_surface,
xdg_surface,
parent_xdg_surface,
r->wayland.popup->xdg_positioner);
uint32_t ver = wl_proxy_get_version((struct wl_proxy*)r->wayland.popup->xdg_popup);
xdg_popup_add_listener(r->wayland.popup->xdg_popup, &popup_listener, r);
r->wayland.popup->xdg_surface_listener.configure = xdg_surface_configure;
@ -628,12 +697,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;
}
if(ty == MwLL_WAYLAND_UNKNOWN) {
if(parent == NULL) {
@ -657,8 +721,6 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh
}
}
WIDGET_CHECK(r);
MwLLWaylandFramebufferSetup(&r->wayland);
MwLLWaylandBackbufferSetup(&r->wayland);
@ -702,10 +764,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;
@ -786,15 +844,7 @@ static void MwLLDestroyImpl(MwLL handle) {
MwLLWaylandFlush(handle);
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) {
@ -812,7 +862,6 @@ 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;
@ -837,7 +886,11 @@ static void actually_set_wh(MwLL handle) {
MwLLWaylandRegionInvalidate(handle);
if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL && handle->wayland.configured) {
if(handle->wayland.has_decorations) {
xdg_surface_set_window_geometry(handle->wayland.toplevel->xdg_surface, 0, 0, handle->wayland.ww, handle->wayland.wh);
} else {
xdg_surface_set_window_geometry(wl_call_tbl.libdecor_frame_get_xdg_surface(handle->wayland.decor_frame), 0, 0, handle->wayland.ww, handle->wayland.wh);
}
}
if(handle->wayland.type == MwLL_WAYLAND_SUBLEVEL && handle->wayland.configured && !handle->wayland.dispatching_resize) {
@ -863,7 +916,6 @@ static void actually_set_wh(MwLL handle) {
}
static void MwLLSetWHImpl(MwLL handle, int w, int h) {
WIDGET_CHECK(handle);
if(handle->wayland.ww == w && handle->wayland.wh == h) {
return;
@ -886,102 +938,6 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) {
}
static void MwLLBeginDrawImpl(MwLL handle) {
WIDGET_CHECK(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;
}
if(!handle->wayland.has_decorations) {
int x;
MwU32 w = handle->wayland.ww + CSD_BORDER_FRAME_LEFT + CSD_BORDER_FRAME_RIGHT;
MwU32 h = handle->wayland.wh + CSD_BORDER_FRAME_TOP + CSD_BORDER_FRAME_BOTTOM;
cairo_set_line_width(handle->wayland.back_cairo, 4.0);
for(x = 0; x < w; x++) {
float placeholder = (float)x / (float)w;
cairo_set_source_rgb(handle->wayland.back_cairo, placeholder, 0.25, 0.25);
cairo_move_to(handle->wayland.back_cairo, w - x, 0);
cairo_line_to(handle->wayland.back_cairo, w - x, CSD_BORDER_FRAME_TOP);
cairo_stroke(handle->wayland.back_cairo);
cairo_move_to(handle->wayland.back_cairo, x, CSD_BORDER_FRAME_TOP);
cairo_line_to(handle->wayland.back_cairo, x, h);
cairo_stroke(handle->wayland.back_cairo);
}
cairo_set_source_rgba(handle->wayland.back_cairo, 1, 1, 1, 0.5);
cairo_move_to(handle->wayland.back_cairo, 0, 0);
cairo_line_to(handle->wayland.back_cairo, 0, h);
cairo_stroke(handle->wayland.back_cairo);
cairo_move_to(handle->wayland.back_cairo, 0, 0);
cairo_line_to(handle->wayland.back_cairo, w, 0);
cairo_stroke(handle->wayland.back_cairo);
cairo_set_source_rgba(handle->wayland.back_cairo, 0, 0, 0, 0.5);
cairo_move_to(handle->wayland.back_cairo, 0, h);
cairo_line_to(handle->wayland.back_cairo, w, h);
cairo_stroke(handle->wayland.back_cairo);
cairo_move_to(handle->wayland.back_cairo, w, 0);
cairo_line_to(handle->wayland.back_cairo, w, h);
cairo_stroke(handle->wayland.back_cairo);
if(strlen(handle->wayland.title) != 0) {
int y, x;
int i = 0, sx = 0, sy = 0;
int tw, th;
unsigned char* px;
MwRect r;
MwLLPixmap p;
tw = strlen(handle->wayland.title) * 7;
th = 14;
px = malloc(tw * th * 4);
assert(px);
memset(px, 0, tw * th * 4);
handle->wayland.selected_cairo = handle->wayland.back_cairo;
while(handle->wayland.title[i]) {
int out;
i += MwUTF8ToUTF32(handle->wayland.title + i, &out);
if(out > 0xff) {
out = 0;
}
for(y = 0; y < 14; y++) {
for(x = 0; x < 7; x++) {
unsigned char* ppx = &px[((sy + y) * tw + sx + x) * 4];
int col = MwFontData[out].data[y] & (1 << ((7 - 1) - x)) ? 255 : 0;
ppx[0] = col;
ppx[1] = col;
ppx[2] = col;
ppx[3] = col;
}
}
sx += 7;
}
p = MwLLCreatePixmap(handle, px, tw, th);
r.x = 5;
r.y = 5;
r.width = tw;
r.height = th;
MwLLDrawPixmap(handle, &r, p);
MwLLDestroyPixmap(p);
free(px);
}
MwLLWaylandBufferUpdate(handle, &handle->wayland.backbuffer);
}
handle->wayland.selected_cairo = handle->wayland.front_cairo;
}
static void MwLLEndDrawImpl(MwLL handle) {
@ -995,7 +951,6 @@ static void MwLLEndDrawImpl(MwLL handle) {
static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) {
int i;
WIDGET_CHECK(handle);
clip(handle);
@ -1019,7 +974,6 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL
static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) {
int i;
WIDGET_CHECK(handle);
clip(handle);
@ -1073,10 +1027,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) {
@ -1128,7 +1078,6 @@ 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;
@ -1137,6 +1086,10 @@ static void MwLLNextEventImpl(MwLL handle) {
}
}
if(handle->wayland.decor) {
// wl_call_tbl.libdecor_dispatch(handle->wayland.decor, 0);
}
if(handle->wayland.force_render) {
MwLLDispatch(handle, draw, NULL);
if(handle->wayland.configured) MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer);
@ -1148,9 +1101,12 @@ static void MwLLNextEventImpl(MwLL handle) {
}
static void MwLLSetTitleImpl(MwLL handle, const char* title) {
WIDGET_CHECK(handle);
if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) {
if(handle->wayland.has_decorations) {
xdg_toplevel_set_title(handle->wayland.toplevel->xdg_top_level, title);
} else {
wl_call_tbl.libdecor_frame_set_title(handle->wayland.decor_frame, title);
}
}
if(!handle->wayland.has_decorations) {
strncpy(handle->wayland.title, title, 255);
@ -1207,14 +1163,11 @@ static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) {
static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) {
cairo_t* c;
cairo_surface_t* cs;
cairo_t* selected_cairo = handle->wayland.selected_cairo ? handle->wayland.selected_cairo : handle->wayland.front_cairo;
if(rect->width <= 0 || rect->height <= 0 || pixmap->common.width <= 0 || pixmap->common.height <= 0) return;
if(rect->width >= INT16_MAX) rect->width = INT16_MAX;
if(rect->height >= INT16_MAX) rect->height = INT16_MAX;
WIDGET_CHECK(handle);
cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, rect->width, rect->height);
c = cairo_create(cs);
@ -1229,8 +1182,8 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) {
cairo_paint(c);
cairo_set_source_surface(selected_cairo, cs, rect->x, rect->y);
cairo_paint(selected_cairo);
cairo_set_source_surface(handle->wayland.front_cairo, cs, rect->x, rect->y);
cairo_paint(handle->wayland.front_cairo);
cairo_destroy(c);
cairo_surface_destroy(cs);
@ -1239,7 +1192,6 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) {
wl_surface_damage(handle->wayland.framebuffer.surface, 0, 0, handle->wayland.ww, handle->wayland.wh);
}
static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) {
WIDGET_CHECK(handle);
if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) {
if(WAYLAND_GET_INTERFACE(handle->wayland, xdg_toplevel_icon_manager_v1) != NULL) {
struct xdg_toplevel_icon_manager_v1* icon_manager = WAYLAND_GET_INTERFACE(handle->wayland, xdg_toplevel_icon_manager_v1)->context;
@ -1282,7 +1234,6 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) {
}
static void MwLLForceRenderImpl(MwLL handle) {
WIDGET_CHECK(handle);
wl_surface_damage(handle->wayland.framebuffer.surface, 0, 0, handle->wayland.ww, handle->wayland.wh);
handle->wayland.force_render = MwTRUE;
@ -1294,8 +1245,6 @@ static void MwLLForceRenderImpl(MwLL handle) {
static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) {
int x, y, xs, ys;
WIDGET_CHECK(handle);
if(handle->wayland.cursor.setup) {
MwLLWaylandBufferDestroy(&handle->wayland.cursor);
wl_surface_destroy(handle->wayland.cursor.surface);
@ -1346,7 +1295,6 @@ static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) {
static void MwLLDetachImpl(MwLL handle, MwPoint* point) {
MwLL p = handle->wayland.parent;
int x = 0, y = 0;
WIDGET_CHECK(handle);
while(p != NULL) {
x += p->wayland.x;
y += p->wayland.y;
@ -1363,7 +1311,6 @@ static void MwLLShowImpl(MwLL handle, int show) {
if(!handle->wayland.configured) {
return;
}
WIDGET_CHECK(handle);
/* Some guy on a mailing list said that "abusing" wl_surface_attach for this purpose is bad? This is documented behavior so please I beg of you let me know if there's a compositor that actually has a problem with this. */
if(handle->wayland.framebuffer.surface) {
wl_surface_attach(handle->wayland.framebuffer.surface, show ? handle->wayland.framebuffer.shm_buffer : NULL, 0, 0);
@ -1382,16 +1329,16 @@ static void MwLLMakePopupImpl(MwLL handle, MwLL parent) {
}
static void MwLLSetSizeHintsImpl(MwLL handle, int minx, int miny, int maxx, int maxy) {
WIDGET_CHECK(handle);
if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) {
if(handle->wayland.has_decorations) {
xdg_toplevel_set_min_size(handle->wayland.toplevel->xdg_top_level, minx, miny);
xdg_toplevel_set_max_size(handle->wayland.toplevel->xdg_top_level, maxx, maxy);
}
}
}
static void MwLLMakeBorderlessImpl(MwLL handle, int toggle) {
(void)toggle;
WIDGET_CHECK(handle);
if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) {
if(WAYLAND_GET_INTERFACE(handle->wayland, zxdg_decoration_manager_v1) != NULL) {
zxdg_decoration_manager_v1_context_t* dec = WAYLAND_GET_INTERFACE(handle->wayland, zxdg_decoration_manager_v1)->context;
@ -1412,7 +1359,6 @@ static void MwLLFocusImpl(MwLL handle) {
static void MwLLGrabPointerImpl(MwLL handle, int toggle) {
MwLL topmost_parent = handle;
WIDGET_CHECK(handle);
while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent;
if(handle->wayland.pointer_constraints && handle->wayland.relative_pointer_manager) {
if(toggle) {
@ -1439,7 +1385,6 @@ static void MwLLGrabPointerImpl(MwLL handle, int toggle) {
static void MwLLSetClipboardImpl(MwLL handle, const char* text, int clipboard_type) {
int i;
WIDGET_CHECK(handle);
if(handle->wayland.clipboard_buffer != NULL) {
free(handle->wayland.clipboard_buffer);
@ -1466,7 +1411,6 @@ static void MwLLSetClipboardImpl(MwLL handle, const char* text, int clipboard_ty
static void MwLLGetClipboardImpl(MwLL handle, int clipboard_type) {
int i;
WIDGET_CHECK(handle);
if(clipboard_type == MwCLIPBOARD_PRIMARY) {
if(handle->wayland.supports_zwp) {
for(i = 0; i < arrlen(handle->wayland.clipboard_devices_zwp); i++) {
@ -1486,7 +1430,6 @@ static void MwLLGetClipboardImpl(MwLL handle, int clipboard_type) {
}
static void MwLLMakeToolWindowImpl(MwLL handle) {
WIDGET_CHECK(handle);
handle->wayland.type_to_be = MwLL_WAYLAND_POPUP;
}
@ -1494,14 +1437,12 @@ static void MwLLMakeToolWindowImpl(MwLL handle) {
static void MwLLGetCursorCoordImpl(MwLL handle, MwPoint* point) {
MwLL topmost_parent = handle;
WIDGET_CHECK(handle);
while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent;
*point = topmost_parent->wayland.cur_mouse_pos;
}
static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) {
WIDGET_CHECK(handle);
rect->x = 0;
rect->y = 0;
@ -1515,7 +1456,6 @@ static void MwLLBeginStateChangeImpl(MwLL handle) {
}
static void MwLLEndStateChangeImpl(MwLL handle) {
WIDGET_CHECK(handle);
if(handle->wayland.detatching) {
MwLL topmost_parent = handle->wayland.parent;
@ -1588,8 +1528,7 @@ static MwBool MwLLDoModernImpl(MwLL handle) {
static void MwLLRaiseImpl(MwLL handle) {
(void)handle;
/* WIDGET_CHECK(handle);
/*
if(handle->wayland.type == MwLL_WAYLAND_SUBLEVEL) {
MwLL topmost_parent = handle;
int children_num;

View file

@ -354,6 +354,7 @@ void MwFreeWidget(MwWidget handle) {
for(i = 0; i < arrlen(handle->children); i++) {
MwFreeWidget(handle->children[i]);
i--;
}
arrfree(handle->children);
@ -392,6 +393,15 @@ void MwFreeWidget(MwWidget handle) {
if(handle->root_monofont != NULL) MwFontFree(handle->root_monofont);
if(handle->root_boldmonofont != NULL) MwFontFree(handle->root_boldmonofont);
if(handle->parent) {
for(i = 0; i < arrlen(handle->parent->children); i++) {
if(handle->parent->children[i] == handle) {
arrdel(handle->parent->children, i);
i--;
}
}
}
free(handle);
}