Compare commits

...

3 commits

Author SHA1 Message Date
dfb56befd5 major surgery on dbus code 2026-04-17 10:04:08 +02:00
bda0c008d6 Revert "added wip fuzzer, fixed alot of memory leaks with wayland"
This reverts commit 3e49278a15.
2026-04-17 09:44:40 +02:00
30c84a915a minor adjustments for compliance 2026-04-17 09:22:30 +02:00
8 changed files with 181 additions and 219 deletions

View file

@ -223,6 +223,7 @@ if(MW_USE_WAYLAND)
Mw Mw
PRIVATE PRIVATE
USE_WAYLAND USE_WAYLAND
USE_DBUS
) )
message(STATUS "Wayland backend has been enabled") message(STATUS "Wayland backend has been enabled")
else() else()
@ -349,10 +350,14 @@ target_link_directories(
PRIVATE PRIVATE
${LIBRARY_DIRS} ${LIBRARY_DIRS}
) )
find_package(PkgConfig REQUIRED)
pkg_check_modules(DBUS REQUIRED dbus-1)
include_directories(${DBUS_INCLUDE_DIRS})
target_link_libraries( target_link_libraries(
Mw Mw
PRIVATE PRIVATE
${LIBRARIES} ${LIBRARIES}
${DBUS_LIBRARIES}
) )
if(MW_BUILD_OPENGL) if(MW_BUILD_OPENGL)

View file

@ -66,11 +66,17 @@ typedef struct _MwLLDBusFuncTable {
DBusMessage* (*dbus_message_new_method_call)(const char* bus_name, const char* path, const char* iface, const char* method); DBusMessage* (*dbus_message_new_method_call)(const char* bus_name, const char* path, const char* iface, const char* method);
void (*dbus_message_iter_init_append)(DBusMessage* message, DBusMessageIter* iter); void (*dbus_message_iter_init_append)(DBusMessage* message, DBusMessageIter* iter);
dbus_bool_t (*dbus_message_iter_append_basic)(DBusMessageIter* iter, int type, const void* value); dbus_bool_t (*dbus_message_iter_append_basic)(DBusMessageIter* iter, int type, const void* value);
void (*dbus_connection_flush)(DBusConnection* connection);
dbus_bool_t (*dbus_connection_read_write)(DBusConnection* connection, int timeout_milliseconds);
DBusMessage* (*dbus_connection_send_with_reply_and_block)(DBusConnection* connection, DBusMessage* message, int timeout_milliseconds, DBusError* error); DBusMessage* (*dbus_connection_send_with_reply_and_block)(DBusConnection* connection, DBusMessage* message, int timeout_milliseconds, DBusError* error);
DBusMessage* (*dbus_connection_pop_message)(DBusConnection* connection);
void (*dbus_bus_add_match)(DBusConnection* connection, const char* rule, DBusError* error);
void (*dbus_message_unref)(DBusMessage* message); void (*dbus_message_unref)(DBusMessage* message);
dbus_bool_t (*dbus_message_iter_init)(DBusMessage* message, DBusMessageIter* iter); dbus_bool_t (*dbus_message_iter_init)(DBusMessage* message, DBusMessageIter* iter);
dbus_bool_t (*dbus_message_is_signal)(DBusMessage* message, const char* iface, const char* signal_name);
int (*dbus_message_iter_get_arg_type)(DBusMessageIter* iter); int (*dbus_message_iter_get_arg_type)(DBusMessageIter* iter);
void (*dbus_message_iter_recurse)(DBusMessageIter* iter, DBusMessageIter* sub); void (*dbus_message_iter_recurse)(DBusMessageIter* iter, DBusMessageIter* sub);
void (*dbus_message_iter_next)(DBusMessageIter* iter);
void (*dbus_connection_unref)(DBusConnection* connection); void (*dbus_connection_unref)(DBusConnection* connection);
void (*dbus_message_iter_get_basic)(DBusMessageIter* iter, void* value); void (*dbus_message_iter_get_basic)(DBusMessageIter* iter, void* value);
} MwLLDBusFuncTable; } MwLLDBusFuncTable;
@ -80,7 +86,6 @@ typedef struct _MwLLDBusContext {
DBusError dbus_err; DBusError dbus_err;
DBusMessage* dbus_msg; DBusMessage* dbus_msg;
DBusMessage* dbus_reply; DBusMessage* dbus_reply;
DBusMessageIter dbus_args, dbus_variant, dbus_inner_variant;
} MwLLDBusContext; } MwLLDBusContext;
typedef void (*MwLLDBusPortalPollListener)(MwLL handle, MwU32 new_value); typedef void (*MwLLDBusPortalPollListener)(MwLL handle, MwU32 new_value);

View file

@ -41,7 +41,6 @@ typedef struct wayland_call_table {
MwBool has_dbus; MwBool has_dbus;
#endif #endif
int (*wl_display_dispatch)(struct wl_display* display);
int (*wl_display_dispatch_pending)(struct wl_display* display); int (*wl_display_dispatch_pending)(struct wl_display* display);
void (*wl_display_disconnect)(struct wl_display* display); void (*wl_display_disconnect)(struct wl_display* display);
void (*wl_display_cancel_read)(struct wl_display* display); void (*wl_display_cancel_read)(struct wl_display* display);
@ -59,7 +58,6 @@ typedef struct wayland_call_table {
uint32_t flags, ...); uint32_t flags, ...);
struct wl_display* (*wl_display_connect)(const char* name); struct wl_display* (*wl_display_connect)(const char* name);
uint32_t (*wl_proxy_get_version)(struct wl_proxy* proxy); uint32_t (*wl_proxy_get_version)(struct wl_proxy* proxy);
struct wl_display* (*wl_display_connect_to_fd)(int fd);
struct xkb_context* (*xkb_context_new)(enum xkb_context_flags flags); struct xkb_context* (*xkb_context_new)(enum xkb_context_flags flags);
void (*xkb_context_unref)(struct xkb_context* context); void (*xkb_context_unref)(struct xkb_context* context);
@ -158,7 +156,6 @@ MwInline int wayland_load_funcs() {
return 1; \ return 1; \
}; };
WAYLAND_FUNC(wl_display_dispatch)
WAYLAND_FUNC(wl_display_dispatch_pending) WAYLAND_FUNC(wl_display_dispatch_pending)
WAYLAND_FUNC(wl_display_disconnect) WAYLAND_FUNC(wl_display_disconnect)
WAYLAND_FUNC(wl_display_cancel_read) WAYLAND_FUNC(wl_display_cancel_read)
@ -173,7 +170,6 @@ MwInline int wayland_load_funcs() {
WAYLAND_FUNC(wl_proxy_marshal_flags) WAYLAND_FUNC(wl_proxy_marshal_flags)
WAYLAND_FUNC(wl_display_connect) WAYLAND_FUNC(wl_display_connect)
WAYLAND_FUNC(wl_proxy_get_version) WAYLAND_FUNC(wl_proxy_get_version)
WAYLAND_FUNC(wl_display_connect_to_fd)
#undef WAYLAND_FUNC #undef WAYLAND_FUNC
@ -239,7 +235,6 @@ MwInline int wayland_load_funcs() {
return 0; return 0;
} }
#define wl_display_dispatch wl_call_tbl.wl_display_dispatch
#define wl_display_dispatch_pending wl_call_tbl.wl_display_dispatch_pending #define wl_display_dispatch_pending wl_call_tbl.wl_display_dispatch_pending
#define wl_display_disconnect wl_call_tbl.wl_display_disconnect #define wl_display_disconnect wl_call_tbl.wl_display_disconnect
#define wl_display_cancel_read wl_call_tbl.wl_display_cancel_read #define wl_display_cancel_read wl_call_tbl.wl_display_cancel_read
@ -254,7 +249,6 @@ MwInline int wayland_load_funcs() {
#define wl_proxy_marshal_flags wl_call_tbl.wl_proxy_marshal_flags #define wl_proxy_marshal_flags wl_call_tbl.wl_proxy_marshal_flags
#define wl_display_connect wl_call_tbl.wl_display_connect #define wl_display_connect wl_call_tbl.wl_display_connect
#define wl_proxy_get_version wl_call_tbl.wl_proxy_get_version #define wl_proxy_get_version wl_call_tbl.wl_proxy_get_version
#define wl_display_connect_to_fd wl_call_tbl.wl_display_connect_to_fd
#define xkb_state_unref wl_call_tbl.xkb_state_unref #define xkb_state_unref wl_call_tbl.xkb_state_unref
#define xkb_context_new wl_call_tbl.xkb_context_new #define xkb_context_new wl_call_tbl.xkb_context_new
@ -379,11 +373,11 @@ enum _MwLLWaylandType {
}; };
typedef struct wl_clipboard_device_context { typedef struct wl_clipboard_device_context {
struct { union {
struct wl_data_device* wl; struct wl_data_device* wl;
struct zwp_primary_selection_device_v1* zwp; struct zwp_primary_selection_device_v1* zwp;
} device; } device;
struct { union {
struct wl_data_offer* wl; struct wl_data_offer* wl;
struct zwp_primary_selection_offer_v1* zwp; struct zwp_primary_selection_offer_v1* zwp;
} offer; } offer;
@ -415,13 +409,13 @@ struct _MwLLWayland {
/* Map of Wayland interfaces to their relevant setup functions. */ /* Map of Wayland interfaces to their relevant setup functions. */
struct { struct {
char key[255]; const char* key;
wayland_protocol_callback_table_t* value; wayland_protocol_callback_table_t* value;
}* wl_protocol_setup_map; }* wl_protocol_setup_map;
/* Map of Wayland interfaces to any information we keep about them once we've registered them. */ /* Map of Wayland interfaces to any information we keep about them once we've registered them. */
struct { struct {
char key[255]; const char* key;
wayland_protocol_t* value; wayland_protocol_t* value;
}* wl_protocol_map; }* wl_protocol_map;
@ -454,6 +448,7 @@ struct _MwLLWayland {
#endif #endif
MwBool dark_theme_detection; MwBool dark_theme_detection;
MwU32 dark_theme;
/* clipboard related stuff. /* clipboard related stuff.
* Note that unlike most interfaces, we don't keep zwp_primary_selection stuff in a wayland_protocol_t because we use wl_data_device as a fallback and want to have it share memory space.*/ * Note that unlike most interfaces, we don't keep zwp_primary_selection stuff in a wayland_protocol_t because we use wl_data_device as a fallback and want to have it share memory space.*/

View file

@ -17,8 +17,6 @@
wayland_call_table_t wl_call_tbl; wayland_call_table_t wl_call_tbl;
MwBool MwWaylandAlwaysRender = MwFALSE; MwBool MwWaylandAlwaysRender = MwFALSE;
MwU32 wl_dark_theme = -1;
/* Standard procedure before most event callbacks in Wayland ("most" because the setup ones don't need this). Wait for the Mutex to be freed, if we're deadlocking for longer then a quarter of a second then do nothing with the event. */ /* Standard procedure before most event callbacks in Wayland ("most" because the setup ones don't need this). Wait for the Mutex to be freed, if we're deadlocking for longer then a quarter of a second then do nothing with the event. */
#define WAYLAND_EVENT_OP_START(self) \ #define WAYLAND_EVENT_OP_START(self) \
do { \ do { \
@ -64,7 +62,9 @@ static void new_protocol(void* data, struct wl_registry* registry,
wayland_protocol_callback_table_t* 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)); char* inter = malloc(strlen(interface) + 1);
strcpy(inter, interface);
shput(self->wayland.wl_protocol_map, inter, cb->setup(name, data));
/* 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) { } else if(strcmp(interface, "wp_alpha_modifier_v1") == 0) {
self->common.supports_transparency = MwTRUE; self->common.supports_transparency = MwTRUE;
@ -651,24 +651,19 @@ static void keyboard_keymap(void* data,
MwLL self = data; MwLL self = data;
(void)wl_keyboard; (void)wl_keyboard;
if(!self->wayland.parent) { if(self->wayland.type == MWLL_WAYLAND_TOPLEVEL) {
char* map_shm;
struct xkb_keymap* xkb_keymap;
struct xkb_state* xkb_state;
xkb_state = NULL;
assert(format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1); assert(format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1);
map_shm = (char*)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); char* map_shm = (char*)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
assert(map_shm != MAP_FAILED); assert(map_shm != MAP_FAILED);
xkb_keymap = xkb_keymap_new_from_string( struct xkb_keymap* xkb_keymap = xkb_keymap_new_from_string(
self->wayland.xkb_context, map_shm, XKB_KEYMAP_FORMAT_TEXT_V1, self->wayland.xkb_context, map_shm, XKB_KEYMAP_FORMAT_TEXT_V1,
XKB_KEYMAP_COMPILE_NO_FLAGS); XKB_KEYMAP_COMPILE_NO_FLAGS);
munmap(map_shm, size); munmap(map_shm, size);
close(fd); close(fd);
xkb_state = xkb_state_new(xkb_keymap); struct xkb_state* xkb_state = xkb_state_new(xkb_keymap);
self->wayland.xkb_keymap = xkb_keymap; self->wayland.xkb_keymap = xkb_keymap;
self->wayland.xkb_state = xkb_state; self->wayland.xkb_state = xkb_state;
@ -981,7 +976,6 @@ static wayland_protocol_t* wl_seat_setup(MwU32 name, MwLL ll) {
static void wl_seat_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { static void wl_seat_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) {
(void)wayland; (void)wayland;
free(data->listener); free(data->listener);
free(data);
} }
/* wl_output setup function */ /* wl_output setup function */
@ -1126,8 +1120,6 @@ static int event_loop(MwLL handle) {
if(wl_display_dispatch_pending(wayland->display) < 0) { if(wl_display_dispatch_pending(wayland->display) < 0) {
wl_display_cancel_read(wayland->display); wl_display_cancel_read(wayland->display);
} }
wl_display_flush(handle->wayland.display);
return 1; return 1;
} }
@ -1238,46 +1230,66 @@ static void update_buffer(MwLL self, struct _MwLLWaylandShmBuffer* buffer) {
} }
static void buffer_setup(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height) { static void buffer_setup(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height) {
int stride = width * 4; int stride = width * 4;
char temp_name[] = "/tmp/milsko-wl-shm-XXXXXX"; char temp_name[] = "/tmp/milsko-wl-shm-XXXXXX";
char temp_name_back[] = "/tmp/milsko-wl-shm-back-XXXXXX";
buffer->buf_size = width * height * 4; buffer->buf_size = width * height * 4;
buffer->fd = mkstemp(temp_name); buffer->fd = mkstemp(temp_name);
buffer->fd_back = mkstemp(temp_name_back);
unlink(temp_name); unlink(temp_name);
unlink(temp_name_back);
if(posix_fallocate(buffer->fd, 0, buffer->buf_size) != 0) { if(posix_fallocate(buffer->fd, 0, buffer->buf_size) != 0) {
printf("failure setting up wl_shm: could not fallocate. %s.\n", strerror(errno)); printf("failure setting up wl_shm: could not fallocate. %s.\n", strerror(errno));
close(buffer->fd); close(buffer->fd);
return; return;
} }
if(posix_fallocate(buffer->fd_back, 0, buffer->buf_size) != 0) {
printf("failure setting up wl_shm: could not fallocate. %s.\n", strerror(errno));
close(buffer->fd_back);
return;
}
if(ftruncate(buffer->fd, buffer->buf_size) != 0) { if(ftruncate(buffer->fd, buffer->buf_size) != 0) {
printf("failure setting up wl_shm: could not truncate. %s.\n", strerror(errno)); printf("failure setting up wl_shm: could not truncate. %s.\n", strerror(errno));
close(buffer->fd); close(buffer->fd);
return; return;
} }
if(ftruncate(buffer->fd_back, buffer->buf_size) != 0) {
buffer->buf = mmap(NULL, buffer->buf_size, PROT_WRITE, MAP_SHARED, buffer->fd, 0); printf("failure setting up wl_shm: could not truncate. %s.\n", strerror(errno));
buffer->buf_back = malloc(buffer->buf_size); close(buffer->fd_back);
fsync(buffer->fd);
if(!(buffer->shm_pool = wl_shm_create_pool(buffer->shm, buffer->fd, buffer->buf_size))) {
close(buffer->fd);
printf("failure setting up wl_shm: could not create pool.\n");
return; return;
} }
buffer->shm_buffer = wl_shm_pool_create_buffer(buffer->shm_pool, 0, width, height, stride, WL_SHM_FORMAT_ARGB8888);
buffer->setup = MwTRUE; buffer->buf = mmap(NULL, buffer->buf_size, PROT_WRITE, MAP_SHARED, buffer->fd, 0);
buffer->buf_back = mmap(NULL, buffer->buf_size, PROT_WRITE, MAP_SHARED, buffer->fd_back, 0);
fsync(buffer->fd);
fsync(buffer->fd_back);
if(!(buffer->shm_pool = wl_shm_create_pool(buffer->shm, buffer->fd, buffer->buf_size))) {
printf("failure setting up wl_shm: could not create pool.\n");
}
if(!(buffer->shm_pool_back = wl_shm_create_pool(buffer->shm, buffer->fd_back, buffer->buf_size))) {
printf("failure setting up wl_shm: could not create pool.\n");
}
buffer->shm_buffer = wl_shm_pool_create_buffer(buffer->shm_pool, 0, width, height, stride, WL_SHM_FORMAT_ARGB8888);
buffer->shm_buffer_back = wl_shm_pool_create_buffer(buffer->shm_pool_back, 0, width, height, stride, WL_SHM_FORMAT_ARGB8888);
buffer->setup = MwTRUE;
} }
static void buffer_destroy(struct _MwLLWaylandShmBuffer* buffer) { static void buffer_destroy(struct _MwLLWaylandShmBuffer* buffer) {
close(buffer->fd); if(!buffer->setup) {
if(buffer->buf) munmap(buffer->buf, buffer->buf_size); return;
if(buffer->buf_back) free(buffer->buf_back); }
if(buffer->shm_buffer) wl_buffer_destroy(buffer->shm_buffer); if(buffer->shm_buffer) wl_buffer_destroy(buffer->shm_buffer);
if(buffer->shm_buffer_back) wl_buffer_destroy(buffer->shm_buffer_back);
if(buffer->shm_pool) wl_shm_pool_destroy(buffer->shm_pool); if(buffer->shm_pool) wl_shm_pool_destroy(buffer->shm_pool);
if(buffer->shm_pool_back) wl_shm_pool_destroy(buffer->shm_pool_back); if(buffer->shm_pool_back) wl_shm_pool_destroy(buffer->shm_pool_back);
close(buffer->fd);
close(buffer->fd_back);
buffer->setup = MwFALSE; buffer->setup = MwFALSE;
} }
@ -1516,12 +1528,12 @@ static void destroy_toplevel(MwLL r) {
xdg_toplevel_destroy(r->wayland.toplevel->xdg_top_level); xdg_toplevel_destroy(r->wayland.toplevel->xdg_top_level);
xkb_keymap_unref(r->wayland.xkb_keymap);
xkb_state_unref(r->wayland.xkb_state); xkb_state_unref(r->wayland.xkb_state);
xkb_context_unref(r->wayland.xkb_context); xkb_context_unref(r->wayland.xkb_context);
xkb_keymap_unref(r->wayland.xkb_keymap);
free(r->wayland.toplevel); free(r->wayland.toplevel);
wl_registry_destroy(r->wayland.registry); wl_registry_destroy(r->wayland.registry);
@ -1541,6 +1553,8 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) {
r->wayland.type = MWLL_WAYLAND_SUBLEVEL; r->wayland.type = MWLL_WAYLAND_SUBLEVEL;
r->wayland.display = parent->wayland.display;
setup_callbacks(&r->wayland); setup_callbacks(&r->wayland);
r->wayland.registry = wl_display_get_registry(parent->wayland.display); r->wayland.registry = wl_display_get_registry(parent->wayland.display);
@ -1578,9 +1592,10 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) {
/* Sublevel setup function */ /* Sublevel setup function */
static void destroy_sublevel(MwLL r) { static void destroy_sublevel(MwLL r) {
wl_subsurface_destroy(r->wayland.sublevel->subsurface); backbuffer_destroy(&r->wayland);
framebuffer_destroy(&r->wayland);
wl_registry_destroy(r->wayland.registry); wl_subsurface_destroy(r->wayland.sublevel->subsurface);
free(r->wayland.sublevel); free(r->wayland.sublevel);
@ -1759,9 +1774,6 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh
} }
} }
framebuffer_destroy(&r->wayland);
backbuffer_destroy(&r->wayland);
framebuffer_setup(&r->wayland); framebuffer_setup(&r->wayland);
backbuffer_setup(&r->wayland); backbuffer_setup(&r->wayland);
@ -1782,20 +1794,20 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh
#ifdef USE_DBUS #ifdef USE_DBUS
static void dark_theme_listener(MwLL handle, MwU32 new_value) { static void dark_theme_listener(MwLL handle, MwU32 new_value) {
wl_dark_theme = (new_value == 1) ? 1 : 0; handle->wayland.dark_theme = (new_value == 1) ? 1 : 0;
MwLLDispatch(handle, dark_theme, &wl_dark_theme); MwLLDispatch(handle, dark_theme, &handle->wayland.dark_theme);
} }
static void detect_dark_theme(MwLL handle) { static void detect_dark_theme(MwLL handle) {
MwU32 value = 0; MwU32 value = 0;
MwLLDBusPortalGet(&wl_call_tbl.dbus, &handle->wayland.dbus, "org.freedesktop.portal.Settings", "org.freedesktop.appearance", "color-scheme", &value); MwLLDBusPortalGet(&wl_call_tbl.dbus, &handle->wayland.dbus, "org.freedesktop.portal.Settings", "org.freedesktop.appearance", "color-scheme", &value);
wl_dark_theme = (value == 1) ? 1 : 0; handle->wayland.dark_theme = (value == 1) ? 1 : 0;
MwLLDBusPortalWatch(&wl_call_tbl.dbus, &handle->wayland.dbus, "org.freedesktop.portal.Settings"); MwLLDBusPortalWatch(&wl_call_tbl.dbus, &handle->wayland.dbus, "org.freedesktop.portal.Settings");
MwLLDispatch(handle, dark_theme, &wl_dark_theme); MwLLDispatch(handle, dark_theme, &handle->wayland.dark_theme);
} }
#endif #endif
@ -1811,6 +1823,7 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) {
if(!parent && wl_call_tbl.has_dbus) { if(!parent && wl_call_tbl.has_dbus) {
wl_call_tbl.has_dbus = MwLLDBusNewContext(&wl_call_tbl.dbus, &r->wayland.dbus); wl_call_tbl.has_dbus = MwLLDBusNewContext(&wl_call_tbl.dbus, &r->wayland.dbus);
r->wayland.dark_theme_detection = MwTRUE; r->wayland.dark_theme_detection = MwTRUE;
r->wayland.dark_theme = -1;
} }
#endif #endif
@ -1827,6 +1840,8 @@ static void MwLLDestroyImpl(MwLL handle) {
int select_ret; int select_ret;
event_loop(handle); event_loop(handle);
// wl_display_cancel_read(handle->wayland.display);
wl_flush(handle); wl_flush(handle);
if(pthread_mutex_timedlock(&handle->wayland.eventsMutex, &t) != 0) { if(pthread_mutex_timedlock(&handle->wayland.eventsMutex, &t) != 0) {
@ -1852,6 +1867,7 @@ static void MwLLDestroyImpl(MwLL handle) {
} }
#endif #endif
buffer_destroy(&handle->wayland.cursor);
wl_region_destroy(handle->wayland.region); wl_region_destroy(handle->wayland.region);
if(handle->wayland.supports_zwp) { if(handle->wayland.supports_zwp) {
@ -1859,6 +1875,10 @@ static void MwLLDestroyImpl(MwLL handle) {
} else { } else {
wl_data_source_destroy(handle->wayland.clipboard_source.wl); wl_data_source_destroy(handle->wayland.clipboard_source.wl);
} }
if(handle->wayland.icon != NULL) {
buffer_destroy(handle->wayland.icon);
wl_surface_destroy(handle->wayland.icon->surface);
}
if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) {
destroy_toplevel(handle); destroy_toplevel(handle);
@ -1868,20 +1888,6 @@ static void MwLLDestroyImpl(MwLL handle) {
destroy_popup(handle); destroy_popup(handle);
} }
if(handle->wayland.framebuffer.setup) {
framebuffer_destroy(&handle->wayland);
wl_surface_destroy(handle->wayland.framebuffer.surface);
}
if(handle->wayland.backbuffer.setup) {
backbuffer_destroy(&handle->wayland);
wl_surface_destroy(handle->wayland.backbuffer.surface);
}
buffer_destroy(&handle->wayland.cursor);
if(handle->wayland.icon != NULL) {
buffer_destroy(handle->wayland.icon);
wl_surface_destroy(handle->wayland.icon->surface);
}
for(i = 0; i < shlen(handle->wayland.wl_protocol_setup_map); i++) { for(i = 0; i < shlen(handle->wayland.wl_protocol_setup_map); i++) {
void* ctx = shget(handle->wayland.wl_protocol_map, handle->wayland.wl_protocol_setup_map[i].key); void* ctx = shget(handle->wayland.wl_protocol_map, handle->wayland.wl_protocol_setup_map[i].key);
@ -1889,30 +1895,17 @@ static void MwLLDestroyImpl(MwLL handle) {
handle->wayland.wl_protocol_setup_map[i].value->destroy(&handle->wayland, ctx); handle->wayland.wl_protocol_setup_map[i].value->destroy(&handle->wayland, ctx);
} }
shdel(handle->wayland.wl_protocol_map, handle->wayland.wl_protocol_setup_map[i].value); shdel(handle->wayland.wl_protocol_map, handle->wayland.wl_protocol_setup_map[i].value);
free(handle->wayland.wl_protocol_setup_map[i].value);
free(ctx);
} }
shfree(handle->wayland.wl_protocol_map); shfree(handle->wayland.wl_protocol_map);
shfree(handle->wayland.wl_protocol_setup_map); shfree(handle->wayland.wl_protocol_setup_map);
// wl_keyboard_destroy(handle->wayland.keyboard); wl_keyboard_destroy(handle->wayland.keyboard);
// wl_pointer_destroy(handle->wayland.pointer); wl_pointer_destroy(handle->wayland.pointer);
if(handle->wayland.supports_zwp) {
for(i = 0; i < arrlen(handle->wayland.clipboard_devices_zwp); i++) {
if(handle->wayland.clipboard_devices_zwp[i]->device.zwp) zwp_primary_selection_device_v1_destroy(handle->wayland.clipboard_devices_zwp[i]->device.zwp);
free(handle->wayland.clipboard_devices_zwp[i]);
}
} else {
printf("[WARNING] Primary clipboard requested for MwLLSetClipboard, but this Wayland compositor doesn't support it.\n");
}
for(i = 0; i < arrlen(handle->wayland.clipboard_devices_wl); i++) {
wl_data_device_destroy(handle->wayland.clipboard_devices_wl[i]->device.wl);
free(handle->wayland.clipboard_devices_wl[i]);
}
wl_flush(handle); wl_flush(handle);
// free(handle);
if(currentlyHeldWidget == handle) { if(currentlyHeldWidget == handle) {
currentlyHeldWidget = NULL; currentlyHeldWidget = NULL;
} }
@ -2177,7 +2170,6 @@ static int MwLLPendingImpl(MwLL handle) {
wl_display_cancel_read(handle->wayland.display); wl_display_cancel_read(handle->wayland.display);
} else { } else {
wl_display_read_events(handle->wayland.display); wl_display_read_events(handle->wayland.display);
wl_display_flush(handle->wayland.display);
if((pending = wl_display_dispatch_pending(handle->wayland.display)) < 0) { if((pending = wl_display_dispatch_pending(handle->wayland.display)) < 0) {
wl_display_cancel_read(handle->wayland.display); wl_display_cancel_read(handle->wayland.display);
} }
@ -2186,7 +2178,6 @@ static int MwLLPendingImpl(MwLL handle) {
if((pending = wl_display_dispatch_pending(handle->wayland.display)) < 0) { if((pending = wl_display_dispatch_pending(handle->wayland.display)) < 0) {
wl_display_cancel_read(handle->wayland.display); wl_display_cancel_read(handle->wayland.display);
} }
wl_display_flush(handle->wayland.display);
} }
if(MwWaylandAlwaysRender) { if(MwWaylandAlwaysRender) {
@ -2337,7 +2328,7 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) {
if(handle->wayland.configured) update_buffer(handle, handle->wayland.icon); if(handle->wayland.configured) update_buffer(handle, handle->wayland.icon);
xdg_toplevel_icon_v1_add_buffer(icon, handle->wayland.icon->shm_buffer, 1); xdg_toplevel_icon_v1_add_buffer(icon, handle->wayland.icon->shm_buffer_back, 1);
xdg_toplevel_icon_manager_v1_set_icon(icon_manager, handle->wayland.toplevel->xdg_top_level, icon); xdg_toplevel_icon_manager_v1_set_icon(icon_manager, handle->wayland.toplevel->xdg_top_level, icon);
} }
@ -2439,7 +2430,7 @@ static void MwLLShowImpl(MwLL handle, int show) {
static void MwLLMakePopupImpl(MwLL handle, MwLL parent) { static void MwLLMakePopupImpl(MwLL handle, MwLL parent) {
(void)handle; (void)handle;
(void)parent; (void)parent;
/* Wayland doesn't have "popups" in the Milsko sense persay. xdg_popup is closer to ToolWindow and as such is what we use there. So just like the Mac backend, this is just left alone. */ /* Wayland doesn't have "popups" in the Milsko sense per se. xdg_popup is closer to ToolWindow and as such is what we use there. So just like the Mac backend, this is just left alone. */
} }
static void MwLLSetSizeHintsImpl(MwLL handle, int minx, int miny, int maxx, int maxy) { static void MwLLSetSizeHintsImpl(MwLL handle, int minx, int miny, int maxx, int maxy) {

View file

@ -82,16 +82,22 @@ MwBool MwLLDBusFuncSetup(MwLLDBusFuncTable* tbl) {
DBUS_FUNC(dbus_error_init); DBUS_FUNC(dbus_error_init);
DBUS_FUNC(dbus_bus_get); DBUS_FUNC(dbus_bus_get);
DBUS_FUNC(dbus_bus_add_match);
DBUS_FUNC(dbus_error_is_set); DBUS_FUNC(dbus_error_is_set);
DBUS_FUNC(dbus_error_free); DBUS_FUNC(dbus_error_free);
DBUS_FUNC(dbus_message_new_method_call); DBUS_FUNC(dbus_message_new_method_call);
DBUS_FUNC(dbus_message_is_signal);
DBUS_FUNC(dbus_message_iter_init_append); DBUS_FUNC(dbus_message_iter_init_append);
DBUS_FUNC(dbus_message_iter_append_basic); DBUS_FUNC(dbus_message_iter_append_basic);
DBUS_FUNC(dbus_connection_flush);
DBUS_FUNC(dbus_connection_pop_message);
DBUS_FUNC(dbus_connection_read_write);
DBUS_FUNC(dbus_connection_send_with_reply_and_block); DBUS_FUNC(dbus_connection_send_with_reply_and_block);
DBUS_FUNC(dbus_message_unref); DBUS_FUNC(dbus_message_unref);
DBUS_FUNC(dbus_message_iter_init); DBUS_FUNC(dbus_message_iter_init);
DBUS_FUNC(dbus_message_iter_get_arg_type); DBUS_FUNC(dbus_message_iter_get_arg_type);
DBUS_FUNC(dbus_message_iter_recurse); DBUS_FUNC(dbus_message_iter_recurse);
DBUS_FUNC(dbus_message_iter_next);
DBUS_FUNC(dbus_connection_unref); DBUS_FUNC(dbus_connection_unref);
DBUS_FUNC(dbus_message_iter_get_basic); DBUS_FUNC(dbus_message_iter_get_basic);
@ -121,6 +127,8 @@ MwBool MwLLDBusNewContext(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx) {
}; };
MWDECL MwBool MwLLDBusPortalGet(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx, const char* portal, const char* namespace, const char* key, void* out) { MWDECL MwBool MwLLDBusPortalGet(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx, const char* portal, const char* namespace, const char* key, void* out) {
DBusMessageIter dbus_args, dbus_variant, dbus_inner_variant;
char arg_type;
if(!ctx->dbus_conn) { if(!ctx->dbus_conn) {
return MwFALSE; return MwFALSE;
} }
@ -135,9 +143,9 @@ MWDECL MwBool MwLLDBusPortalGet(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx, co
return MwFALSE; return MwFALSE;
} }
tbl->dbus_message_iter_init_append(ctx->dbus_msg, &ctx->dbus_args); tbl->dbus_message_iter_init_append(ctx->dbus_msg, &dbus_args);
tbl->dbus_message_iter_append_basic(&ctx->dbus_args, 's', &namespace); tbl->dbus_message_iter_append_basic(&dbus_args, 's', &namespace);
tbl->dbus_message_iter_append_basic(&ctx->dbus_args, 's', &key); tbl->dbus_message_iter_append_basic(&dbus_args, 's', &key);
ctx->dbus_reply = tbl->dbus_connection_send_with_reply_and_block(ctx->dbus_conn, ctx->dbus_msg, 100, &ctx->dbus_err); ctx->dbus_reply = tbl->dbus_connection_send_with_reply_and_block(ctx->dbus_conn, ctx->dbus_msg, 100, &ctx->dbus_err);
@ -151,25 +159,35 @@ MWDECL MwBool MwLLDBusPortalGet(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx, co
return MwFALSE; return MwFALSE;
} }
if(!tbl->dbus_message_iter_init(ctx->dbus_reply, &ctx->dbus_args)) { if(!tbl->dbus_message_iter_init(ctx->dbus_reply, &dbus_args)) {
fprintf(stderr, "[WARNING] Couldn't get %s::%s: Reply has no arguments\n", namespace, key); fprintf(stderr, "[WARNING] Couldn't get %s::%s: Reply has no arguments\n", namespace, key);
tbl->dbus_message_unref(ctx->dbus_reply); tbl->dbus_message_unref(ctx->dbus_reply);
return MwFALSE; return MwFALSE;
} }
if(tbl->dbus_message_iter_get_arg_type(&ctx->dbus_args) != 'v') { if((arg_type = tbl->dbus_message_iter_get_arg_type(&dbus_args)) != 'v') {
fprintf(stderr, "[WARNING] Couldn't get %s::%s: Expected outer variant\n", namespace, key); fprintf(stderr, "[WARNING] Couldn't get %s::%s: Expected outer variant, got: %c\n", namespace, key, arg_type);
tbl->dbus_message_unref(ctx->dbus_reply); tbl->dbus_message_unref(ctx->dbus_reply);
return MwFALSE; return MwFALSE;
} }
tbl->dbus_message_iter_recurse(&ctx->dbus_args, &ctx->dbus_variant); tbl->dbus_message_iter_recurse(&dbus_args, &dbus_variant);
/* Some portals wrap the value in a second variant */ /* Some portals wrap the value in a second variant */
if(tbl->dbus_message_iter_get_arg_type(&ctx->dbus_variant) == 'v') { arg_type = tbl->dbus_message_iter_get_arg_type(&dbus_variant);
tbl->dbus_message_iter_recurse(&ctx->dbus_variant, &ctx->dbus_inner_variant); if(arg_type == 'v') {
tbl->dbus_message_iter_get_basic(&ctx->dbus_inner_variant, out); tbl->dbus_message_iter_recurse(&dbus_variant, &dbus_inner_variant);
if((arg_type = tbl->dbus_message_iter_get_arg_type(&dbus_inner_variant)) != 'u') {
fprintf(stderr, "[WARNING] Signal reply for %s::SettingChanged: Expected 'u' (uint32) for 'value', got: %c\n", portal, arg_type);
tbl->dbus_message_unref(ctx->dbus_reply);
return MwFALSE;
}
tbl->dbus_message_iter_get_basic(&dbus_inner_variant, out);
} else if (arg_type == 'u') {
tbl->dbus_message_iter_get_basic(&dbus_variant, out);
} else { } else {
tbl->dbus_message_iter_get_basic(&ctx->dbus_variant, out); fprintf(stderr, "[WARNING] Couldn't get %s::%s: Expected variant or string, got: %c\n", namespace, key, arg_type);
tbl->dbus_message_unref(ctx->dbus_reply);
return MwFALSE;
} }
tbl->dbus_message_unref(ctx->dbus_msg); tbl->dbus_message_unref(ctx->dbus_msg);
@ -177,66 +195,104 @@ MWDECL MwBool MwLLDBusPortalGet(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx, co
} }
MWDECL MwBool MwLLDBusPortalWatch(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx, const char* portal) { MWDECL MwBool MwLLDBusPortalWatch(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx, const char* portal) {
char filter_string[2048];
if(!ctx->dbus_conn) { if(!ctx->dbus_conn) {
return MwFALSE; return MwFALSE;
} }
char filter_string[2048];
MwStringPrintIntoBuffer(filter_string, sizeof(filter_string), "type='%s',interface=%s", "signal", portal); MwStringPrintIntoBuffer(filter_string, sizeof(filter_string), "type='%s',interface=%s", "signal", portal);
dbus_bus_add_match(ctx->dbus_conn, filter_string, &ctx->dbus_err); tbl->dbus_bus_add_match(ctx->dbus_conn, filter_string, &ctx->dbus_err);
dbus_connection_flush(ctx->dbus_conn); tbl->dbus_connection_flush(ctx->dbus_conn);
return MwTRUE; return MwTRUE;
} }
// Technically this will swallow all other results, so this is not usable multiple times. /* Technically this will swallow all other results, so this is not usable multiple times.
// TODO: Use a hashmap instead TODO: Use a hashmap instead */
MWDECL MwBool MwLLDBusPortalPoll(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx, MwLL handle, const char* portal, const char* namespace, const char* key, MwLLDBusPortalPollListener listener) { MWDECL MwBool MwLLDBusPortalPoll(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx, MwLL handle, const char* portal, const char* namespace, const char* key, MwLLDBusPortalPollListener listener) {
DBusMessage* msg; DBusMessageIter args, msg_value, msg_value_inner;
DBusMessageIter args, msg_value; const char* msg_namespace;
const char* msg_namespace; const char* msg_key;
const char* msg_key; MwU32 msg_value_content;
MwU32 msg_value_content; char arg_type;
if(!ctx->dbus_conn) { if(!ctx->dbus_conn) {
return MwFALSE; return MwFALSE;
} }
dbus_connection_read_write(ctx->dbus_conn, 0); tbl->dbus_connection_read_write(ctx->dbus_conn, 0);
msg = dbus_connection_pop_message(ctx->dbus_conn); tbl->dbus_connection_read_write(ctx->dbus_conn, 0);
ctx->dbus_reply = tbl->dbus_connection_pop_message(ctx->dbus_conn);
if (NULL == msg) { if(tbl->dbus_error_is_set(&ctx->dbus_err)) {
fprintf(stderr, "[WARNING] Signal reply for %s::SettingChanged: Poll error: %s\n", portal, ctx->dbus_err.message);
tbl->dbus_error_free(&ctx->dbus_err);
return MwFALSE;
}
if(!ctx->dbus_reply) {
return MwFALSE; return MwFALSE;
} }
// check if the message is a signal from the correct interface and with the correct name /* check if the message is a signal from the correct interface and with the correct name */
if (dbus_message_is_signal(msg, portal, "SettingChanged")) { if(tbl->dbus_message_is_signal(ctx->dbus_reply, portal, "SettingChanged")) {
// read the parameters /* read the parameters */
if (!dbus_message_iter_init(msg, &args)) if(!tbl->dbus_message_iter_init(ctx->dbus_reply, &args))
fprintf(stderr, "[WARNING] Message has no arguments\n"); fprintf(stderr, "[WARNING] Signal reply for %s::SettingChanged has no arguments\n", portal);
else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args))
fprintf(stderr, "[WARNING] Argument is not string\n");
else { else {
dbus_message_iter_get_basic(&args, &msg_namespace); if((arg_type = tbl->dbus_message_iter_get_arg_type(&args)) != 's') {
fprintf(stderr, "[WARNING] Signal reply for %s::SettingChanged: Expected 's' (string) for 'namespace', got: %c\n", portal, arg_type);
tbl->dbus_message_unref(ctx->dbus_reply);
return MwFALSE;
}
tbl->dbus_message_iter_get_basic(&args, &msg_namespace);
dbus_message_iter_next(&args); tbl->dbus_message_iter_next(&args);
dbus_message_iter_get_basic(&args, &msg_key); if((arg_type = tbl->dbus_message_iter_get_arg_type(&args)) != 's') {
fprintf(stderr, "[WARNING] Signal reply for %s::SettingChanged: Expected 's' (string) for 'key', got: %c\n", portal, arg_type);
tbl->dbus_message_unref(ctx->dbus_reply);
return MwFALSE;
}
tbl->dbus_message_iter_get_basic(&args, &msg_key);
// Check that key and namespace match /* Check that key and namespace match */
if (strcmp(msg_namespace, namespace) == 0 && strcmp(msg_key, key) == 0) { if(strcmp(msg_namespace, namespace) == 0 && strcmp(msg_key, key) == 0) {
// Assuming the value is a basic type /* Assuming the value is a basic type */
dbus_message_iter_next(&args); tbl->dbus_message_iter_next(&args);
dbus_message_iter_recurse(&args, &msg_value);
dbus_message_iter_get_basic(&msg_value, &msg_value_content); if((arg_type = tbl->dbus_message_iter_get_arg_type(&args)) != 'v') {
fprintf(stderr, "[WARNING] Couldn't get %s::%s: Expected outer variant, got: %c\n", namespace, key, arg_type);
tbl->dbus_message_unref(ctx->dbus_reply);
return MwFALSE;
}
tbl->dbus_message_iter_recurse(&args, &msg_value);
/* Some portals wrap the value in a second variant */
arg_type = tbl->dbus_message_iter_get_arg_type(&msg_value);
if(arg_type == 'v') {
tbl->dbus_message_iter_recurse(&msg_value, &msg_value_inner);
if((arg_type = tbl->dbus_message_iter_get_arg_type(&msg_value_inner)) != 'u') {
fprintf(stderr, "[WARNING] Signal reply for %s::SettingChanged: Expected 'u' (uint32) for 'value', got: %c\n", portal, arg_type);
tbl->dbus_message_unref(ctx->dbus_reply);
return MwFALSE;
}
tbl->dbus_message_iter_get_basic(&msg_value_inner, &msg_value_content);
} else if (arg_type == 'u') {
tbl->dbus_message_iter_get_basic(&msg_value, &msg_value_content);
} else {
fprintf(stderr, "[WARNING] Couldn't get %s::%s: Expected variant or string, got: %c\n", namespace, key, arg_type);
tbl->dbus_message_unref(ctx->dbus_reply);
return MwFALSE;
}
listener(handle, msg_value_content); listener(handle, msg_value_content);
} }
} }
} }
// free the message /* free the message */
dbus_message_unref(msg); tbl->dbus_message_unref(ctx->dbus_reply);
return MwTRUE;
} }
void MwLLDBusFreeContext(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx) { void MwLLDBusFreeContext(MwLLDBusFuncTable* tbl, MwLLDBusContext* ctx) {

2
tools/.gitignore vendored
View file

@ -1,2 +0,0 @@
font
fuzzer

View file

@ -6,10 +6,7 @@ LIBS = `freetype-config --libs`
.PHONY: all clean .PHONY: all clean
.SUFFIXES: .c .o .SUFFIXES: .c .o
all: fuzzer font all: font
fuzzer: fuzzer.o
$(CC) -g -L../src/ -Wl,-R../src -lMw -o $@ fuzzer.o
font: font.o font: font.o
$(CC) $(LDFLAGS) -o $@ font.o $(LIBS) $(CC) $(LDFLAGS) -o $@ font.o $(LIBS)
@ -18,4 +15,4 @@ font: font.o
$(CC) $(CFLAGS) -c -o $@ $< $(CC) $(CFLAGS) -c -o $@ $<
clean: clean:
rm -f *.o font fuzzer rm -f *.o font

View file

@ -1,85 +0,0 @@
#include <Mw/Milsko.h>
#define WIDGET_AMOUNT 1
int main() {
MwWidget window, widget;
MwLibraryInit();
window = MwCreateWidget(MwWindowClass, "window", NULL, 0, 0, 400, 400);
while(true) {
int r = rand() % WIDGET_AMOUNT;
MwClass cls;
switch(r) {
case 0:
cls = MwBoxClass;
break;
case 1:
cls = MwButtonClass;
break;
case 2:
cls = MwCheckBoxClass;
break;
case 3:
cls = MwComboBoxClass;
break;
case 4:
cls = MwEntryClass;
break;
case 5:
cls = MwFrameClass;
break;
case 6:
cls = MwImageClass;
break;
case 7:
cls = MwLabelClass;
break;
case 8:
cls = MwListBoxClass;
break;
case 9:
cls = MwMenuClass;
break;
case 10:
cls = MwNumberEntryClass;
break;
case 12:
cls = MwProgressBarClass;
break;
case 13:
cls = MwRadioBoxClass;
break;
case 14:
cls = MwScrollBarClass;
break;
case 15:
cls = MwSeparatorClass;
break;
// case 16:
// cls = MwSubMenuClass;
// break;
case 17:
cls = MwTreeViewClass;
break;
case 18:
cls = MwViewportClass;
break;
default:
cls = NULL;
break;
}
if(cls) {
widget = MwCreateWidget(cls, "Cls", window, 0, 0, 100, 100);
}
if(MwPending(window)) {
MwStep(window);
}
if(cls) {
MwDestroyWidget(widget);
}
}
}