Compare commits

...

16 commits

Author SHA1 Message Date
ff4d72582a change font to normal opensans
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
2026-09-29 17:56:38 +09:00
b59ddffce6 menu fix
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
2026-09-28 18:46:12 -07:00
bbbd248051 wayland fixes
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
2026-09-28 16:18:48 -07:00
0c9aaf26db layer surface fix
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
2026-09-28 14:51:36 -07:00
6541419007 wayland: only do pointer adjustments for (all subtypes)
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
2026-09-28 14:23:32 -07:00
503a259caa turns out the one change to src/core.c was already done
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
2026-09-28 12:20:25 -07:00
37b1f86fa9 remove some bad comments
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
2026-09-28 12:18:47 -07:00
f3cb2fe15a while we're at it we haven't needed the 'valid' checks for awhile
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
2026-09-28 12:12:19 -07:00
4061112460 fix memleaks
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
2026-09-28 12:08:32 -07:00
4fe57c6d96 some bug fix
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
2026-09-28 22:25:21 +09:00
11aa9e860e update bindings.md oops
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
2026-09-27 19:34:21 -07:00
a74814f27b 2.0b
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
2026-09-27 19:29:13 -07:00
a61c199d5e MwLLWaylandSetToolWindowType
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
2026-09-27 19:26:52 -07:00
a6202258b7 ok
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
2026-09-28 10:58:21 +09:00
eb8b945995 fix
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
2026-09-28 10:56:30 +09:00
56d4d0377c ok
Some checks are pending
pyrite-dev/milsko/pipeline/head Build started...
2026-09-28 01:10:59 +09:00
25 changed files with 31008 additions and 12160 deletions

View file

@ -1,3 +1,8 @@
========================= 2.0b ========================
- Fixed scrollbar bug where it can freeze entire toolkit
- Fixed scroller bug where it bar could appear "empty"
- Added function specific to Wayland backend (MwLLWaylandSetToolWindowType) that changes what type a created layer surface is when using MwLLMakeToolWindow
========================= 2.0a ========================
- Fixed a bug where key_released was not fired in GDI backend
- Fixed examples

View file

@ -1,5 +1,5 @@
Greetings - Welcome to the Milsko GUI Toolkit (Version 2.0a)
Greetings - Welcome to the Milsko GUI Toolkit (Version 2.0b)
This document contains a brief summary of the contents of this source
distributions and building instructions for Milsko GUI Toolkit.

7
configure vendored
View file

@ -36,6 +36,7 @@ our $executable_suffix = "";
our @library_targets = ();
our @examples_targets = ();
our %examples_libs = ();
our %examples_all = ();
our $cross = 0;
our $host = "";
@ -331,11 +332,13 @@ if (param_get("examples")) {
if (param_get("shared")) {
print(OUT
"${l}: ${s}${object_suffix} src/${library_prefix}Mw${library_suffix}\n"
"${l}: ${s}${object_suffix} ${add} src/${library_prefix}Mw${library_suffix}\n"
);
}
else {
print(OUT "${l}: ${s}${object_suffix} src/${library_prefix}Mw.a\n");
print(OUT
"${l}: ${s}${object_suffix} ${add} src/${library_prefix}Mw.a\n"
);
}
if (grep(/^cocoa$/, @backends)) {
print(OUT

View file

@ -7,9 +7,9 @@
| Language | Repo | Version | Notes |
| -------- | --------------------------------------------------------------------- | ------- | -------------- |
| Node.js | [milsko-node](https://forgejo.nishi.boats/pyrite-dev/milsko-node) | 1.4 | Auto-generated |
| C++ | [mwcxx](https://forgejo.nishi.boats/pyrite-dev/mwcxx) | 2.0a | Auto-generated |
| Python | [milsko-py](https://forgejo.nishi.boats/pyrite-dev/milsko-py) | 2.0a | Auto-generated |
| Pascal | [milsko-pascal](https://forgejo.nishi.boats/pyrite-dev/milsko-pascal) | 2.0a | Auto-generated |
| C++ | [mwcxx](https://forgejo.nishi.boats/pyrite-dev/mwcxx) | 2.0b | Auto-generated |
| Python | [milsko-py](https://forgejo.nishi.boats/pyrite-dev/milsko-py) | 2.0b | Auto-generated |
| Pascal | [milsko-pascal](https://forgejo.nishi.boats/pyrite-dev/milsko-pascal) | 2.0b | Auto-generated |
# Inactive Bindings

View file

@ -341,7 +341,7 @@ int main() {
f = frame("Separator", -PaddingContent, -PaddingContent, MwSeparatorClass, NULL);
f = frame("SubWindow", -PaddingContent, -PaddingContent, MwViewportClass,
MwNcolumnSpan, 2,
MwNcolumnSpan, 3,
NULL);
w = child(f);
MwViewportSetSize(w, 512, 512);
@ -352,7 +352,9 @@ int main() {
MwNtitle, "Sub window 2",
NULL);
f = frame("Tab", -PaddingContent, -PaddingContent, MwTabClass, NULL);
f = frame("Tab", -PaddingContent, -PaddingContent, MwTabClass,
MwNcolumnSpan, 2,
NULL);
w = child(f);
MwSetString(MwTabAdd(w, "ABC"), MwNbackground, "#f00");
MwSetString(MwTabAdd(w, "DEF"), MwNbackground, "#0f0");
@ -364,7 +366,14 @@ int main() {
v = MwTreeViewAdd(w, v, NULL, "def");
v = MwTreeViewAdd(w, v, NULL, "ghi");
f = frame("Viewport", -PaddingContent, -PaddingContent, MwViewportClass, NULL);
f = frame("Text", -PaddingContent, -PaddingContent, MwViewportClass,
MwNcolumnSpan, 2,
NULL);
w = child(f);
f = frame("Viewport", -PaddingContent, -PaddingContent, MwViewportClass,
MwNcolumnSpan, 2,
NULL);
w = child(f);
MwViewportSetSize(w, 256, 256);
MwVaCreateWidget(MwButtonClass, "btn", MwViewportGetViewport(w), 64, 64, 128, 128,
@ -382,6 +391,4 @@ int main() {
NULL);
MwLoop(window);
MwDestroyPixmap(px);
}

View file

@ -381,7 +381,6 @@ struct _MwLLWayland {
struct zwp_relative_pointer_v1* relative_pointer;
struct zwp_locked_pointer_v1* locked_pointer;
MwBool pointer_constrained;
MwBool valid;
#ifdef USE_DBUS
MwLLDBusContext dbus;
@ -396,7 +395,7 @@ struct _MwLLWayland {
struct wl_data_device_manager* wl;
struct zwp_primary_selection_device_manager_v1* zwp;
} clipboard_manager;
union {
struct {
struct wl_data_source* wl;
struct zwp_primary_selection_source_v1* zwp;
} clipboard_source;
@ -464,6 +463,8 @@ struct _MwLLWayland {
MwBool accepts_dnd;
MwBool shown;
enum zwlr_layer_shell_v1_layer layer_surface_type;
};
struct _MwLLWaylandColor {
@ -526,4 +527,13 @@ typedef struct zxdg_decoration_manager_v1_context {
extern struct zwp_relative_pointer_v1_listener MwLLWaylandRelativePointerListener;
/*
* function for setting the layer surface type used when creating a tool window
* (assuming layer surfaces are used).
*
* NOTE: Must be called after MwLLMakeToolWindow, as that function sets the type to
* the default of ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY.
*/
MWDECL void MWAPI MwLLWaylandSetToolWindowType(MwLL handle, enum zwlr_layer_shell_v1_layer type);
#endif

View file

@ -169,6 +169,7 @@ struct _MwMenu {
MwMenu* sub;
void* opaque;
int cleaned;
int bold;
};
struct _MwEntry {

View file

@ -18,12 +18,12 @@
/*!
* @brief Patchlevel of version, if patchlevel_alphabet is a or bigger, this value is calculated by `patchlevel_alphabet - 'a' + 1`. Otherwise 0
*/
#define MwPATCH 1
#define MwPATCH 2
/*!
* @brief Version in string
*/
#define MwVERSION "2.0a"
#define MwVERSION "2.0b"
/*!
* @brief Version in string

View file

@ -221,6 +221,8 @@ new_example("examples/basic/subwindow");
new_example("examples/basic/tab");
new_example("examples/basic/document");
#new_example("examples/doom/mwdoom", "", 1);
if (param_get("opengl")) {
new_example("examples/gldemos/boing", $gl_libs);
new_example("examples/gldemos/clock", $gl_libs);

View file

@ -41,9 +41,12 @@ sub add_libs {
}
sub new_example {
if (@_ == 2) {
if (@_ >= 2) {
$examples_libs{"$_[0]${executable_suffix}"} = $_[1];
}
if (@_ >= 3) {
$examples_all{"$_[0]${executable_suffix}"} = $_[2];
}
push(@examples_targets, "${_[0]}${executable_suffix}");
}

Binary file not shown.

Binary file not shown.

View file

@ -137,13 +137,25 @@ void MwLLCairoBackSetup(struct _MwLLCairo* cairo, MwU8* data, MwU32 width, MwU32
void MwLLCairoFrontDestroy(struct _MwLLCairo* cairo) {
cairo_destroy(cairo->front_cairo);
cairo_destroy(cairo->front_cairo_back);
cairo_surface_destroy(cairo->front_cs);
cairo_surface_destroy(cairo->frontbuffer_cs);
cairo_destroy(cairo->frontbuffer_cairo);
cairo_surface_destroy(cairo->front_cs);
cairo_surface_destroy(cairo->front_cs_back);
cairo_surface_destroy(cairo->frontbuffer_cs);
/* set all to null so that cairo ignores future destroys */
cairo->front_cairo = NULL;
cairo->front_cairo_back = NULL;
cairo->frontbuffer_cairo = NULL;
cairo->front_cs = NULL;
cairo->front_cs_back = NULL;
cairo->frontbuffer_cs = NULL;
};
void MwLLCairoBackDestroy(struct _MwLLCairo* cairo) {
cairo_destroy(cairo->back_cairo);
cairo_surface_destroy(cairo->back_cs);
cairo->back_cairo = NULL;
cairo->back_cs = NULL;
};
void MwLLCairoDestroy(struct _MwLLCairo handle) {
@ -217,8 +229,8 @@ static void MwLLFreeColorImpl(MwLLColor color) {}
static MwBool lmao = MwFALSE;
static int MwLLPendingImpl(MwLL handle) {
lmao = !lmao;
return lmao;
lmao = !lmao;
return lmao;
}
static void MwLLNextEventImpl(MwLL handle) {
MwLLDispatch(handle, draw, NULL);
@ -262,10 +274,10 @@ static void MwLLRaiseImpl(MwLL handle) {}
static void MwLLClipImpl(MwLL handle, MwRect* rect) {}
static void MwLLSetupDragAndDropImpl(MwLL handle) {}
static int MwLLCairoCallInitImpl(void) {
if(cairo_load_funcs() != 0) {
return 1;
}
return 0;
if(cairo_load_funcs() != 0) {
return 1;
}
return 0;
}
#include "call.c"
CALL(Cairo);

View file

@ -5,6 +5,7 @@
void MwLLWaylandFramebufferSetup(struct _MwLLWayland* wayland) {
MwLLWaylandBufferSetup(&wayland->framebuffer, wayland->ww, wayland->wh);
MwLLCairoFrontDestroy(&wayland->cairo);
MwLLCairoFrontSetup(&wayland->cairo, wayland->framebuffer.buf_back, wayland->ww, wayland->wh);
memset(wayland->framebuffer.buf_back, 255, wayland->framebuffer.buf_size);
@ -38,6 +39,7 @@ void MwLLWaylandBackbufferSetup(struct _MwLLWayland* wayland) {
}
MwLLWaylandBufferSetup(&wayland->backbuffer, w, h);
MwLLCairoBackDestroy(&wayland->cairo);
MwLLCairoBackSetup(&wayland->cairo, wayland->backbuffer.buf_back, w, h);
memset(wayland->backbuffer.buf_back, 0, wayland->backbuffer.buf_size);
@ -57,40 +59,44 @@ void MwLLWaylandBackbufferDestroy(struct _MwLLWayland* wayland) {
void MwLLWaylandBufferSetup(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height) {
int stride = width * 4;
int err;
char temp_name[] = "/tmp/milsko-wl-shm-XXXXXXXX";
char temp_name_back[] = "/tmp/milsko-wl-shm-back-XXXXXXXX";
MwLLWaylandBufferDestroy(buffer);
buffer->buf_size = width * height * 4;
buffer->fd = mkstemp(temp_name);
buffer->fd_back = mkstemp(temp_name_back);
if(buffer->fd >= 65536) {
MwDispatchError(-1, "Amount of allocated buffers has gone above 65536! Cannot continue.\n");
return;
goto fail;
}
if(buffer->fd == -1 || buffer->fd_back == -1) {
printf("failure setting up wl_shm: could not create file. %s.\n", strerror(errno));
goto fail;
}
unlink(temp_name);
unlink(temp_name_back);
if(posix_fallocate(buffer->fd, 0, buffer->buf_size) != 0) {
printf("failure setting up wl_shm (front buf): could not fallocate. %s.\n", strerror(errno));
close(buffer->fd);
return;
/* posix_fallocate returns the error rather than setting errno */
if((err = posix_fallocate(buffer->fd, 0, buffer->buf_size)) != 0) {
printf("failure setting up wl_shm (front buf): could not fallocate %llu bytes. %s.\n", (unsigned long long)buffer->buf_size, strerror(err));
goto fail;
}
if(posix_fallocate(buffer->fd_back, 0, buffer->buf_size) != 0) {
printf("failure setting up wl_shm (back buf): could not fallocate. %s.\n", strerror(errno));
close(buffer->fd_back);
return;
if((err = posix_fallocate(buffer->fd_back, 0, buffer->buf_size)) != 0) {
printf("failure setting up wl_shm (back buf): could not fallocate %llu bytes. %s.\n", (unsigned long long)buffer->buf_size, strerror(err));
goto fail;
}
if(ftruncate(buffer->fd, buffer->buf_size) != 0) {
printf("failure setting up wl_shm: could not truncate. %s.\n", strerror(errno));
close(buffer->fd);
return;
goto fail;
}
if(ftruncate(buffer->fd_back, buffer->buf_size) != 0) {
printf("failure setting up wl_shm: could not truncate. %s.\n", strerror(errno));
close(buffer->fd_back);
return;
goto fail;
}
buffer->buf = mmap(NULL, buffer->buf_size, PROT_WRITE, MAP_SHARED, buffer->fd, 0);
@ -110,6 +116,13 @@ void MwLLWaylandBufferSetup(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, M
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;
return;
fail:
if(buffer->fd >= 0) close(buffer->fd);
if(buffer->fd_back >= 0) close(buffer->fd_back);
buffer->fd = -1;
buffer->fd_back = -1;
}
void MwLLWaylandBufferDestroy(struct _MwLLWaylandShmBuffer* buffer) {
@ -124,7 +137,16 @@ void MwLLWaylandBufferDestroy(struct _MwLLWaylandShmBuffer* buffer) {
if(buffer->shm_pool_back) wl_shm_pool_destroy(buffer->shm_pool_back);
close(buffer->fd);
close(buffer->fd_back);
buffer->setup = MwFALSE;
buffer->buf = NULL;
buffer->buf_back = NULL;
buffer->shm_buffer = NULL;
buffer->shm_buffer_back = NULL;
buffer->shm_pool = NULL;
buffer->shm_pool_back = NULL;
buffer->fd = -1;
buffer->fd_back = -1;
buffer->setup = MwFALSE;
}
void MwLLWaylandBufferResize(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height) {

View file

@ -17,8 +17,8 @@
static void setup_clipboard(MwLL self, struct wl_seat* wl_seat);
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);
static void destroy_clipboard(MwLL self);
static void destroy_zwp_clipboard(MwLL self);
static MwBool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwPoint* _relative_mouse_pos, MwPoint* _absolute_pos);
/* Recursively dispatch a key event to a widget and its children */
@ -133,6 +133,9 @@ static void wl_data_device_data_offer(void* data,
wl_data_offer_add_listener(offer, &offer_listener, data);
if(self->offer.wl && self->offer.wl != offer) {
wl_data_offer_destroy(self->offer.wl);
}
self->offer.wl = offer;
};
@ -320,6 +323,9 @@ static void zwp_primary_selection_device_v1_data_offer(void* data,
wl_clipboard_device_context_t* self = data;
(void)zwp_primary_selection_device_v1;
if(self->offer.zwp && self->offer.zwp != offer) {
zwp_primary_selection_offer_v1_destroy(self->offer.zwp);
}
self->offer.zwp = offer;
};
@ -491,14 +497,15 @@ static wayland_protocol_t* wl_data_device_manager_setup(MwU32 name, struct _MwLL
static void wl_data_device_manager_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) {
(void)data;
destroy_clipboard((MwLL)wayland);
if(wayland->clipboard_source.wl) {
wl_data_source_destroy(wayland->clipboard_source.wl);
wayland->clipboard_source.wl = NULL;
}
if(wayland->clipboard_manager.wl != NULL) {
wl_data_device_manager_destroy(wayland->clipboard_manager.wl);
wayland->clipboard_manager.wl = NULL;
}
if(wayland->clipboard_source.wl) {
// wl_data_source_destroy(wayland->clipboard_source.wl);
wayland->clipboard_source.wl = NULL;
}
}
/* zwp_primary_selection_device_manager_v1 setup function */
@ -526,8 +533,17 @@ static wayland_protocol_t* zwp_primary_selection_device_manager_v1_setup(MwU32 n
}
static void zwp_primary_selection_device_manager_v1_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) {
(void)wayland;
(void)data;
destroy_zwp_clipboard((MwLL)wayland);
if(wayland->clipboard_source.zwp) {
zwp_primary_selection_source_v1_destroy(wayland->clipboard_source.zwp);
wayland->clipboard_source.zwp = NULL;
}
if(wayland->clipboard_manager.zwp != NULL) {
zwp_primary_selection_device_manager_v1_destroy(wayland->clipboard_manager.zwp);
wayland->clipboard_manager.zwp = NULL;
}
wayland->supports_zwp = MwFALSE;
}
/* zwp_primary_selection_device_manager_v1 setup function */
@ -538,8 +554,15 @@ static wayland_protocol_t* zwp_pointer_constraints_v1_setup(MwU32 name, struct _
}
static void zwp_pointer_constraints_v1_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) {
(void)wayland;
(void)data;
if(wayland->locked_pointer) {
zwp_locked_pointer_v1_destroy(wayland->locked_pointer);
wayland->locked_pointer = NULL;
}
if(wayland->pointer_constraints) {
zwp_pointer_constraints_v1_destroy(wayland->pointer_constraints);
wayland->pointer_constraints = NULL;
}
}
static struct wl_surface* curSurface = NULL;
@ -667,8 +690,15 @@ static wayland_protocol_t* zwp_relative_pointer_manager_v1_setup(MwU32 name, str
}
static void zwp_relative_pointer_manager_v1_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) {
(void)wayland;
(void)data;
if(wayland->relative_pointer) {
zwp_relative_pointer_v1_destroy(wayland->relative_pointer);
wayland->relative_pointer = NULL;
}
if(wayland->relative_pointer_manager) {
zwp_relative_pointer_manager_v1_destroy(wayland->relative_pointer_manager);
wayland->relative_pointer_manager = NULL;
}
}
/* `wl_pointer.motion` callback */
@ -706,8 +736,10 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time
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) {
/* the position is relative to the surface the pointer is on (ours), so only widgets below
* us are offset from it. going further would also subtract e.g. a popup's position */
p.point = self->wayland.cur_mouse_pos;
while(new_topmost != self && new_topmost->wayland.parent) {
p.point.x -= new_topmost->wayland.x;
p.point.y -= new_topmost->wayland.y;
new_topmost = new_topmost->wayland.parent;
@ -732,8 +764,9 @@ static MwBool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwP
while(topmost_parent->wayland.parent) {
topmost_parent = topmost_parent->wayland.parent;
if(topmost_parent) {
/* if the topmost parent is a popup/subwindow then its x/y is irrelevant to us. */
if(topmost_parent->wayland.type != MwLL_WAYLAND_POPUP && topmost_parent->wayland.type != MwLL_WAYLAND_TOPLEVEL) {
/* if the topmost parent is a popup/subwindow/layer surface then its x/y is irrelevant to us,
* it's the window's position on screen and pointer coordinates are relative to the window. */
if(topmost_parent->wayland.type == MwLL_WAYLAND_SUBLEVEL || topmost_parent->wayland.type == MwLL_WAYLAND_SUBSURFACE) {
absolute_pos.x += topmost_parent->wayland.x;
absolute_pos.y += topmost_parent->wayland.y;
}
@ -918,9 +951,16 @@ static void keyboard_keymap(void* data,
struct xkb_state* xkb_state = xkb_state_new(xkb_keymap);
/* the compositor sends a new keymap whenever the layout changes */
if(self->wayland.xkb_state) xkb_state_unref(self->wayland.xkb_state);
if(self->wayland.xkb_keymap) xkb_keymap_unref(self->wayland.xkb_keymap);
self->wayland.xkb_keymap = xkb_keymap;
self->wayland.xkb_state = xkb_state;
} else {
/* we don't read it, but the fd is still ours to close */
close(fd);
self->wayland.xkb_keymap = self->wayland.parent->wayland.xkb_keymap;
self->wayland.xkb_state = self->wayland.parent->wayland.xkb_state;
}
@ -1014,21 +1054,24 @@ static void keyboard_key(void* data,
MwU64 syms_num;
int i;
if(!self->wayland.xkb_keymap) {
struct xkb_keymap* xkb_keymap = topmost_parent->wayland.xkb_keymap;
struct xkb_state* xkb_state = topmost_parent->wayland.xkb_state;
if(!xkb_keymap || !xkb_state) {
return;
}
layout = xkb_state_key_get_layout(self->wayland.xkb_state, keycode);
layout = xkb_state_key_get_layout(xkb_state, keycode);
levels =
xkb_keymap_num_levels_for_key(self->wayland.xkb_keymap, keycode, layout);
xkb_keymap_num_levels_for_key(xkb_keymap, keycode, layout);
if((((self->wayland.mod_state & 1) == 1) || ((self->wayland.mod_state & 2) == 2)) && levels >= 2) {
level = 1;
} else if(levels >= 1) {
level = 0;
}
syms_num = xkb_keymap_key_get_syms_by_level(self->wayland.xkb_keymap, keycode, layout, level, &syms_out);
syms_num = xkb_keymap_key_get_syms_by_level(xkb_keymap, keycode, layout, level, &syms_out);
if(syms_out == NULL) {
return;
@ -1159,6 +1202,31 @@ static void setup_clipboard(MwLL self, struct wl_seat* wl_seat) {
device_ctx_wl->accepted_types[5] = "text/uri-list";
};
static void destroy_zwp_clipboard(MwLL self) {
int i;
for(i = 0; i < arrlen(self->wayland.clipboard_devices_zwp); i++) {
wl_clipboard_device_context_t* ctx = self->wayland.clipboard_devices_zwp[i];
if(ctx->offer.zwp) zwp_primary_selection_offer_v1_destroy(ctx->offer.zwp);
zwp_primary_selection_device_v1_destroy(ctx->device.zwp);
free(ctx);
}
arrfree(self->wayland.clipboard_devices_zwp);
}
static void destroy_clipboard(MwLL self) {
int i;
for(i = 0; i < arrlen(self->wayland.clipboard_devices_wl); i++) {
wl_clipboard_device_context_t* ctx = self->wayland.clipboard_devices_wl[i];
if(ctx->offer.wl) wl_data_offer_destroy(ctx->offer.wl);
if(wl_proxy_get_version((struct wl_proxy*)ctx->device.wl) >= WL_DATA_DEVICE_RELEASE_SINCE_VERSION) {
wl_data_device_release(ctx->device.wl);
} else {
wl_data_device_destroy(ctx->device.wl);
}
free(ctx);
}
arrfree(self->wayland.clipboard_devices_wl);
}
static void keyboard_repeat_info(void* data,
struct wl_keyboard* wl_keyboard,
int32_t rate,
@ -1307,8 +1375,10 @@ static void wl_seat_interface_destroy(struct _MwLLWayland* wayland, wayland_prot
wayland->pointer_seat = NULL;
}
free(data->listener);
free(data);
if(data) {
free(data->listener);
free(data);
}
}
/* wl_output setup function */
@ -1321,8 +1391,11 @@ static wayland_protocol_t* wl_output_setup(MwU32 name, MwLL ll, MwU32 version) {
}
static void wl_output_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) {
(void)wayland;
(void)data;
if(wayland->output) {
wl_output_destroy(wayland->output);
wayland->output = NULL;
}
}
/* wl_compositor setup function */
@ -1334,8 +1407,11 @@ static wayland_protocol_t* wl_compositor_setup(MwU32 name, struct _MwLLWayland*
}
static void wl_compositor_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) {
(void)wayland;
(void)data;
if(wayland->compositor) {
wl_compositor_destroy(wayland->compositor);
wayland->compositor = NULL;
}
}
/* wl_subcompositor setup function */
@ -1351,13 +1427,10 @@ static wayland_protocol_t* wl_subcompositor_setup(MwU32 name, struct _MwLLWaylan
}
static void wl_subcompositor_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) {
(void)wayland;
(void)data;
if(wayland->type == MwLL_WAYLAND_TOPLEVEL) {
wl_subcompositor_destroy(wayland->toplevel->scompositor);
}
if(wayland->type == MwLL_WAYLAND_SUBSURFACE) {
wl_subcompositor_destroy(wayland->subsurface->subcompositor);
}
/* The subcompositor lives in the toplevel/subsurface struct, which is already freed by the time this runs,
* so destroy_toplevel()/destroy_subsurface() release it instead. */
}
/* xdg_wm_base setup function */
@ -1376,8 +1449,11 @@ static wayland_protocol_t* xdg_wm_base_setup(MwU32 name, struct _MwLLWayland* wa
static void xdg_wm_base_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) {
(void)wayland;
free(data->listener);
free(data);
if(data) {
xdg_wm_base_destroy(data->context);
free(data->listener);
free(data);
}
}
/* zxdg_decoration_manager_v1 setup function */
@ -1387,8 +1463,8 @@ static wayland_protocol_t* zxdg_decoration_manager_v1_setup(MwU32 name, struct _
(void)version;
proto->listener = NULL;
ctx->manager = wl_registry_bind(wayland->registry, name, &zxdg_decoration_manager_v1_interface, 1);
;
ctx->manager = wl_registry_bind(wayland->registry, name, &zxdg_decoration_manager_v1_interface, 1);
ctx->decoration = NULL;
proto->context = ctx;
@ -1396,8 +1472,15 @@ static wayland_protocol_t* zxdg_decoration_manager_v1_setup(MwU32 name, struct _
}
static void zxdg_decoration_manager_v1_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) {
zxdg_decoration_manager_v1_context_t* ctx;
(void)wayland;
(void)data;
if(!data) return;
/* the toplevel decoration itself has to go before the xdg_toplevel, so destroy_toplevel() handles that */
ctx = data->context;
zxdg_decoration_manager_v1_destroy(ctx->manager);
free(ctx);
free(data);
}
/* wl_shm setup function */
@ -1411,8 +1494,13 @@ static wayland_protocol_t* wl_shm_setup(MwU32 name, struct _MwLLWayland* wayland
}
static void wl_shm_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) {
(void)wayland;
(void)data;
if(wayland->framebuffer.shm) wl_shm_destroy(wayland->framebuffer.shm);
if(wayland->backbuffer.shm) wl_shm_destroy(wayland->backbuffer.shm);
if(wayland->cursor.shm) wl_shm_destroy(wayland->cursor.shm);
wayland->framebuffer.shm = NULL;
wayland->backbuffer.shm = NULL;
wayland->cursor.shm = NULL;
}
static wayland_protocol_t* xdg_toplevel_icon_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) {
@ -1428,8 +1516,11 @@ static wayland_protocol_t* xdg_toplevel_icon_manager_v1_setup(MwU32 name, struct
static void xdg_toplevel_icon_manager_v1_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) {
(void)wayland;
free(data->listener);
free(data);
if(data) {
xdg_toplevel_icon_manager_v1_destroy(data->context);
free(data->listener);
free(data);
}
}
static wayland_protocol_t* zwlr_layer_shell_v1_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) {
@ -1443,7 +1534,14 @@ static wayland_protocol_t* zwlr_layer_shell_v1_setup(MwU32 name, struct _MwLLWay
static void zwlr_layer_shell_v1_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) {
(void)wayland;
if(!data) return;
/* the destroy request only exists from version 3, before that the proxy is all there is to free */
if(wl_proxy_get_version(data->context) >= ZWLR_LAYER_SHELL_V1_DESTROY_SINCE_VERSION) {
zwlr_layer_shell_v1_destroy(data->context);
} else {
wl_proxy_destroy(data->context);
}
free(data);
}
@ -1458,7 +1556,9 @@ static wayland_protocol_t* wp_fifo_manager_v1_setup(MwU32 name, struct _MwLLWayl
static void wp_fifo_manager_v1_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) {
(void)wayland;
if(!data) return;
wp_fifo_manager_v1_destroy(data->context);
free(data);
}

View file

@ -342,10 +342,14 @@ static void setup_toplevel(MwLL r, int x, int y) {
/* Toplevel destroy function */
static void destroy_toplevel(MwLL r) {
if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL) {
/* The toplevel decoration must go before the xdg_toplevel. The manager itself is released in
* zxdg_decoration_manager_v1_interface_destroy along with every other global. */
if(WAYLAND_GET_INTERFACE(r->wayland, zxdg_decoration_manager_v1) != NULL) {
zxdg_decoration_manager_v1_context_t* dec = WAYLAND_GET_INTERFACE(r->wayland, zxdg_decoration_manager_v1)->context;
zxdg_toplevel_decoration_v1_destroy(dec->decoration);
zxdg_decoration_manager_v1_destroy(dec->manager);
if(dec->decoration) {
zxdg_toplevel_decoration_v1_destroy(dec->decoration);
dec->decoration = NULL;
}
}
MwLLWaylandFramebufferDestroy(&r->wayland);
@ -355,19 +359,34 @@ static void destroy_toplevel(MwLL r) {
xdg_surface_destroy(r->wayland.toplevel->xdg_surface);
wl_compositor_destroy(r->wayland.compositor);
xkb_state_unref(r->wayland.xkb_state);
xkb_keymap_unref(r->wayland.xkb_keymap);
xkb_state_unref(r->wayland.xkb_state);
xkb_context_unref(r->wayland.xkb_context);
r->wayland.xkb_state = NULL;
r->wayland.xkb_keymap = NULL;
r->wayland.xkb_context = NULL;
/* wl_pointer/wl_keyboard/wl_seat are torn down centrally in wl_seat_interface_destroy,
* after this function returns, so every widget type that binds a seat (toplevel, popup,
* layer surface) releases them the same way instead of leaking or double-freeing them. */
/* framebuffer.surface has the wl_subsurface role, so that has to go first or the compositor raises defunct_role_object. */
wl_subsurface_destroy(r->wayland.toplevel->ssurface);
wl_subcompositor_destroy(r->wayland.toplevel->scompositor);
if(r->wayland.framebuffer.fifo) {
wp_fifo_v1_destroy(r->wayland.framebuffer.fifo);
r->wayland.framebuffer.fifo = NULL;
}
wl_surface_destroy(r->wayland.framebuffer.surface);
r->wayland.framebuffer.surface = NULL;
wl_surface_destroy(r->wayland.backbuffer.surface);
r->wayland.backbuffer.surface = NULL;
free(r->wayland.toplevel);
@ -422,6 +441,10 @@ static void destroy_sublevel(MwLL r) {
MwLLWaylandBackbufferDestroy(&r->wayland);
MwLLWaylandFramebufferDestroy(&r->wayland);
/* xkb state is borrowed from the parent, so it is not ours to unref */
wl_surface_destroy(r->wayland.framebuffer.surface);
r->wayland.framebuffer.surface = NULL;
free(r->wayland.sublevel);
r->wayland.configured = MwFALSE;
@ -482,7 +505,14 @@ static void destroy_subsurface(MwLL r) {
MwLLWaylandBackbufferDestroy(&r->wayland);
MwLLWaylandFramebufferDestroy(&r->wayland);
free(r->wayland.sublevel);
/* role object before the surface */
wl_subsurface_destroy(r->wayland.subsurface->subsurface);
wl_subcompositor_destroy(r->wayland.subsurface->subcompositor);
wl_surface_destroy(r->wayland.framebuffer.surface);
r->wayland.framebuffer.surface = NULL;
free(r->wayland.subsurface);
r->wayland.configured = MwFALSE;
}
@ -586,15 +616,20 @@ static void setup_popup(MwLL r, int x, int y, MwLL parent) {
r->wayland.popup->xdg_positioner = xdg_wm_base_create_positioner(r->wayland.popup->xdg_wm_base);
xdg_positioner_set_size(r->wayland.popup->xdg_positioner, r->wayland.ww, r->wayland.wh);
/* the anchor rect is relative to the parent surface, so a layer surface's position on screen doesn't apply */
xdg_positioner_set_anchor_rect(
r->wayland.popup->xdg_positioner,
topmost_parent->wayland.x, topmost_parent->wayland.y, r->wayland.ww, r->wayland.wh);
topmost_parent->wayland.type == MwLL_WAYLAND_LAYER_SURFACE ? 0 : topmost_parent->wayland.x,
topmost_parent->wayland.type == MwLL_WAYLAND_LAYER_SURFACE ? 0 : topmost_parent->wayland.y,
r->wayland.ww, r->wayland.wh);
xdg_positioner_set_offset(
r->wayland.popup->xdg_positioner,
r->wayland.x, r->wayland.y);
xdg_positioner_set_anchor(r->wayland.popup->xdg_positioner, XDG_POSITIONER_ANCHOR_NONE);
xdg_positioner_set_gravity(r->wayland.popup->xdg_positioner, XDG_POSITIONER_GRAVITY_NONE);
/* we can't see where we are on screen, so let the compositor keep the popup on it */
xdg_positioner_set_constraint_adjustment(r->wayland.popup->xdg_positioner, XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X | XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y);
r->wayland.xkb_keymap = topmost_parent->wayland.xkb_keymap;
r->wayland.xkb_state = topmost_parent->wayland.xkb_state;
@ -642,8 +677,7 @@ static void destroy_popup(MwLL r) {
xdg_positioner_destroy(r->wayland.popup->xdg_positioner);
wl_surface_destroy(r->wayland.framebuffer.surface);
wl_registry_destroy(r->wayland.registry);
r->wayland.framebuffer.surface = NULL;
free(r->wayland.popup);
@ -725,7 +759,7 @@ static void setup_layer_surface(MwLL r, int x, int y, int width, int height) {
r->wayland.framebuffer.surface = wl_compositor_create_surface(r->wayland.compositor);
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, r->wayland.layer_surface_type, "milsko-surfaces");
zwlr_layer_surface_v1_set_size(r->wayland.layer_surface->surface, width, height);
zwlr_layer_surface_v1_set_margin(r->wayland.layer_surface->surface,
@ -747,24 +781,27 @@ static void setup_layer_surface(MwLL r, int x, int y, int width, int height) {
}
}
/* Toplevel destroy function */
/* Layer surface destroy function */
static void destroy_layer_surface(MwLL r) {
if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL) {
zxdg_decoration_manager_v1_context_t* dec = WAYLAND_GET_INTERFACE(r->wayland, zxdg_decoration_manager_v1)->context;
zxdg_decoration_manager_v1_destroy(dec->manager);
}
MwLLWaylandFramebufferDestroy(&r->wayland);
/* The role object has to go before the wl_surface, otherwise the compositor raises defunct_role_object. */
zwlr_layer_surface_v1_destroy(r->wayland.layer_surface->surface);
free(r->wayland.layer_surface);
wl_surface_destroy(r->wayland.framebuffer.surface);
wl_compositor_destroy(r->wayland.compositor);
xkb_keymap_unref(r->wayland.xkb_keymap);
r->wayland.framebuffer.surface = NULL;
xkb_state_unref(r->wayland.xkb_state);
xkb_keymap_unref(r->wayland.xkb_keymap);
xkb_context_unref(r->wayland.xkb_context);
wl_registry_destroy(r->wayland.registry);
r->wayland.xkb_state = NULL;
r->wayland.xkb_keymap = NULL;
r->wayland.xkb_context = NULL;
r->wayland.configured = MwFALSE;
}
@ -793,6 +830,9 @@ static void destroy_widget(MwLL handle) {
case MwLL_WAYLAND_LAYER_SURFACE:
destroy_layer_surface(handle);
break;
case MwLL_WAYLAND_SUBSURFACE:
destroy_subsurface(handle);
break;
default:
printf("Handle with unknown type(%d) tried to be destroyed (%p)\n", handle->wayland.type, handle);
break;
@ -805,18 +845,22 @@ static void destroy_widget(MwLL handle) {
}
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);
const char* key = handle->wayland.wl_protocol_setup_map[i].key;
if(ctx != NULL) {
handle->wayland.wl_protocol_setup_map[i].value->destroy(&handle->wayland, ctx);
/* Many setup functions keep what they bind in the MwLL and store a NULL context, so check
* whether the global was bound at all rather than whether the context is NULL. */
if(shgeti(handle->wayland.wl_protocol_map, key) != -1) {
handle->wayland.wl_protocol_setup_map[i].value->destroy(&handle->wayland, shget(handle->wayland.wl_protocol_map, key));
}
shdel(handle->wayland.wl_protocol_map, handle->wayland.wl_protocol_setup_map[i].value);
free(handle->wayland.wl_protocol_setup_map[i].value);
}
shfree(handle->wayland.wl_protocol_map);
shfree(handle->wayland.wl_protocol_setup_map);
wl_registry_destroy(handle->wayland.registry);
handle->wayland.registry = NULL;
MwLLWaylandFlush(handle);
}
@ -880,6 +924,9 @@ static void clip(MwLL handle) {
cairo_clip(handle->wayland.cairo.front_cairo_back);
}
}
/* parentless handles skip the branch above (arrfree sets ws to NULL, so this is a no-op otherwise) */
arrfree(ws);
}
static void wl_logger(const char* fmt, va_list args) {
@ -909,7 +956,6 @@ 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;
r->wayland.valid = MwTRUE;
if(ty == MwLL_WAYLAND_UNKNOWN) {
if(parent == NULL) {
@ -949,6 +995,9 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh
}
}
if(r->wayland.region) wl_region_destroy(r->wayland.region);
if(r->wayland.o_region) wl_region_destroy(r->wayland.o_region);
r->wayland.region = wl_compositor_create_region(r->wayland.compositor);
r->wayland.o_region = wl_compositor_create_region(r->wayland.compositor);
MwLLWaylandRegionSetup(r);
@ -1090,6 +1139,9 @@ static void MwLLDestroyImpl(MwLL handle) {
MwLLWaylandFlush(handle);
MwLLDestroyCommon(handle);
/* destroy_widget() roundtrips, which can still deliver events (keyboard leave etc.) to this handle;
* MwLLDispatch skips a NULL handler table instead of reading the freed one */
handle->common.handler = NULL;
tv.tv_sec = 0;
tv.tv_usec = 1000;
@ -1103,25 +1155,36 @@ static void MwLLDestroyImpl(MwLL handle) {
}
#endif
if(handle->wayland.valid) {
if(handle->wayland.cursor.setup) {
MwLLWaylandBufferDestroy(&handle->wayland.cursor);
wl_region_destroy(handle->wayland.region);
wl_surface_destroy(handle->wayland.cursor.surface);
}
wl_region_destroy(handle->wayland.region);
wl_region_destroy(handle->wayland.o_region);
if(handle->wayland.supports_zwp) {
zwp_primary_selection_source_v1_destroy(handle->wayland.clipboard_source.zwp);
} else {
wl_data_source_destroy(handle->wayland.clipboard_source.wl);
}
if(handle->wayland.icon != NULL) {
/* clipboard sources are released with their managers in destroy_widget */
if(handle->wayland.icon != NULL) {
if(handle->wayland.icon->setup) {
MwLLWaylandBufferDestroy(handle->wayland.icon);
wl_surface_destroy(handle->wayland.icon->surface);
}
destroy_widget(handle);
} else {
printf("widget invalid\n");
free(handle->wayland.icon);
}
destroy_widget(handle);
/* Only parentless handles connect (children borrow the parent's display), and children are
* always freed before their parent, so nothing else is using it by now. */
if(!handle->wayland.parent && handle->wayland.display) {
wl_display_disconnect(handle->wayland.display);
handle->wayland.display = NULL;
}
if(handle->wayland.icon_pixmap) MwLLDestroyPixmap(handle->wayland.icon_pixmap);
if(handle->wayland.snapshot) cairo_surface_destroy(handle->wayland.snapshot);
free(handle->wayland.clipboard_buffer);
arrfree(handle->wayland.currentlyHeldWidgets);
for(i = 0; i < arrlen(topmost_parent->wayland.currentlyHeldWidgets); i++) {
if(topmost_parent->wayland.currentlyHeldWidgets[i] == handle) {
arrdel(topmost_parent->wayland.currentlyHeldWidgets, i);
@ -1134,13 +1197,6 @@ static void MwLLDestroyImpl(MwLL handle) {
}
static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h) {
if(!handle->wayland.valid) {
*x = 0;
*y = 0;
*w = 1;
*h = 1;
return;
}
*x = handle->wayland.x;
*y = handle->wayland.y;
*w = handle->wayland.ww;
@ -1605,8 +1661,9 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) {
if(handle->wayland.icon == NULL) {
handle->wayland.icon = malloc(sizeof(struct _MwLLWaylandShmBuffer));
memset(handle->wayland.icon, 0, sizeof(struct _MwLLWaylandShmBuffer));
handle->wayland.icon->shm = handle->wayland.framebuffer.shm;
}
/* wl_shm is rebound whenever the widget changes state, so don't hold on to an old one */
handle->wayland.icon->shm = handle->wayland.framebuffer.shm;
if(handle->wayland.icon->setup) {
MwLLWaylandBufferDestroy(handle->wayland.icon);
@ -1619,11 +1676,17 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) {
wl_surface_attach(handle->wayland.icon->surface, handle->wayland.icon->shm_buffer, 0, 0);
wl_surface_commit(handle->wayland.icon->surface);
for(; i < size; i += 2) {
handle->wayland.icon->buf_back[i] = pixmap->common.raw[i + 2];
handle->wayland.icon->buf_back[i + 1] = pixmap->common.raw[i + 1];
handle->wayland.icon->buf_back[i + 2] = pixmap->common.raw[i + 0];
handle->wayland.icon->buf_back[i + 3] = 255;
/* RGBA -> BGRA, one pixel (4 bytes) at a time. The icon buffer is line x line, so rows
* have to be placed with its stride rather than the pixmap's. */
for(; i < size; i += 4) {
int x = (i / 4) % pixmap->common.width;
int y = (i / 4) / pixmap->common.width;
unsigned char* dst = &handle->wayland.icon->buf_back[(y * line + x) * 4];
dst[0] = pixmap->common.raw[i + 2];
dst[1] = pixmap->common.raw[i + 1];
dst[2] = pixmap->common.raw[i + 0];
dst[3] = 255;
}
if(handle->wayland.configured) MwLLWaylandBufferUpdate(handle, handle->wayland.icon);
@ -1631,6 +1694,9 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) {
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);
/* the icon is immutable once set, destroying it doesn't unset it */
xdg_toplevel_icon_v1_destroy(icon);
}
}
if(!handle->wayland.has_decorations && handle->wayland.do_csd) {
@ -1711,7 +1777,13 @@ static void MwLLDetachImpl(MwLL handle, MwPoint* point) {
int x = 0, y = 0;
while(p != NULL) {
if(p->wayland.type != MwLL_WAYLAND_TOPLEVEL) {
/* a layer surface's x/y is its position on screen, which like a toplevel's isn't part of the offset */
if(p->wayland.type == MwLL_WAYLAND_POPUP) {
/* a popup's x/y is already relative to the topmost surface, so anything above it is counted already */
x += p->wayland.x;
y += p->wayland.y;
break;
} else if(p->wayland.type != MwLL_WAYLAND_TOPLEVEL && p->wayland.type != MwLL_WAYLAND_LAYER_SURFACE) {
x += p->wayland.x;
y += p->wayland.y;
} else {
@ -1794,11 +1866,15 @@ static void MwLLGrabPointerImpl(MwLL handle, int toggle) {
while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent;
if(handle->wayland.pointer_constraints && handle->wayland.relative_pointer_manager) {
if(toggle) {
topmost_parent->wayland.locked_pointer = zwp_pointer_constraints_v1_lock_pointer(topmost_parent->wayland.pointer_constraints, topmost_parent->wayland.backbuffer.surface, topmost_parent->wayland.pointer, topmost_parent->wayland.region, ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
wl_surface_commit(topmost_parent->wayland.backbuffer.surface);
if(!topmost_parent->wayland.locked_pointer) {
topmost_parent->wayland.locked_pointer = zwp_pointer_constraints_v1_lock_pointer(topmost_parent->wayland.pointer_constraints, topmost_parent->wayland.backbuffer.surface, topmost_parent->wayland.pointer, topmost_parent->wayland.region, ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
wl_surface_commit(topmost_parent->wayland.backbuffer.surface);
}
zwp_locked_pointer_v1_set_cursor_position_hint(topmost_parent->wayland.locked_pointer, 0, CSD_BORDER_FRAME_TOP);
handle->wayland.relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(handle->wayland.relative_pointer_manager, topmost_parent->wayland.pointer);
zwp_relative_pointer_v1_add_listener(handle->wayland.relative_pointer, &MwLLWaylandRelativePointerListener, topmost_parent);
if(!topmost_parent->wayland.relative_pointer) {
topmost_parent->wayland.relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(handle->wayland.relative_pointer_manager, topmost_parent->wayland.pointer);
zwp_relative_pointer_v1_add_listener(topmost_parent->wayland.relative_pointer, &MwLLWaylandRelativePointerListener, topmost_parent);
}
} else {
if(topmost_parent->wayland.locked_pointer) {
zwp_locked_pointer_v1_destroy(topmost_parent->wayland.locked_pointer);
@ -1821,7 +1897,7 @@ static void MwLLSetClipboardImpl(MwLL handle, const char* text, int clipboard_ty
if(handle->wayland.clipboard_buffer != NULL) {
free(handle->wayland.clipboard_buffer);
}
handle->wayland.clipboard_buffer = malloc(strlen(text));
handle->wayland.clipboard_buffer = malloc(strlen(text) + 1);
strcpy(handle->wayland.clipboard_buffer, text);
if(clipboard_type == MwCLIPBOARD_PRIMARY) {
@ -1873,9 +1949,15 @@ static void MwLLMakeToolWindowImpl(MwLL handle) {
handle->wayland.type_to_be = MwLL_WAYLAND_POPUP;
}
handle->wayland.layer_surface_type = ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY;
handle->wayland.changing = MwTRUE;
}
MWDECL void MWAPI MwLLWaylandSetToolWindowType(MwLL handle, enum zwlr_layer_shell_v1_layer type) {
handle->wayland.layer_surface_type = type;
}
static void MwLLGetCursorCoordImpl(MwLL handle, MwPoint* point) {
MwLL topmost_parent = handle;

View file

@ -267,6 +267,8 @@ static MwWidget MwCreateWidget_Internal(MwClass widget_class, const char* name,
h->lowlevel = NULL;
}
h->widget_class = widget_class;
h->mouse_point.x = 0;
h->mouse_point.y = 0;
h->pressed = 0;
h->close = 0;
h->destroy_queue = NULL;
@ -751,7 +753,7 @@ void MwSetString(MwWidget handle, const char* key, const char* value) {
void MwSetPointer(MwWidget handle, const char* key, void* value) {
if(IsFirstVisible(handle) && strcmp(key, MwNiconPixmap) == 0) {
MwLLSetIcon(handle->lowlevel, value);
MwLLSetIcon(handle->lowlevel, ((MwPixmap)value)->lowlevel);
} else if(strcmp(key, MwNsizeHints) == 0) {
MwSizeHints* sz = value;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -248,6 +248,7 @@ static MwMenu mwMenuAddImpl(MwWidget handle, MwMenu menu, const char* name) {
new->wsub = NULL;
new->keep = 0;
new->cleaned = 0;
new->bold = 0;
arrput(m->sub, new);

View file

@ -27,6 +27,7 @@ static int calc_length(MwWidget handle) {
int len = MwGetInteger(handle, MwNmaxValue) - MwGetInteger(handle, MwNminValue);
int area = MwGetInteger(handle, MwNareaShown);
if(area > len) area = len;
if(len == 0) return max;
return (int)(max * (double)area / len);
}
@ -35,6 +36,7 @@ static int calc_position(MwWidget handle) {
int max = MwScrollBarGetVisibleLength(handle);
int len = MwGetInteger(handle, MwNmaxValue) - MwGetInteger(handle, MwNminValue);
int val = MwGetInteger(handle, MwNvalue);
if(len == 0) return 0;
return (int)((max - calc_length(handle)) * (double)val / len);
}
@ -49,8 +51,10 @@ static void add_value(MwWidget handle, int mul) {
if(val < min) val = min;
if(val > max) val = max;
MwSetInteger(handle, MwNvalue, val);
MwDispatchUserHandler(handle, MwNchangedHandler, NULL);
if(MwGetInteger(handle, MwNvalue) != val) {
MwSetInteger(handle, MwNvalue, val);
MwDispatchUserHandler(handle, MwNchangedHandler, NULL);
}
}
static void draw(MwWidget handle) {
@ -85,7 +89,7 @@ static void draw(MwWidget handle) {
rt.y = r.y;
if(MwGetInteger(handle, MwNshowArrows)) {
MwDrawTriangle(handle, &rt, base, (handle->pressed && scr->point.y <= uy) ? 1 : 0, MwNORTH);
if(handle->pressed && scr->point.y <= uy) {
if(handle->pressed && scr->point.y < uy) {
add_value(handle, -1);
}
} else {
@ -110,7 +114,7 @@ static void draw(MwWidget handle) {
rt.x = r.x;
if(MwGetInteger(handle, MwNshowArrows)) {
MwDrawTriangle(handle, &rt, base, (handle->pressed && scr->point.x <= ux) ? 1 : 0, MwWEST);
if(handle->pressed && scr->point.x <= ux) {
if(handle->pressed && scr->point.x < ux) {
add_value(handle, -1);
}
} else {
@ -223,6 +227,7 @@ static void mouse_down(MwWidget handle, void* ptr) {
static void prop_change(MwWidget handle, const char* key) {
if(strcmp(key, MwNminValue) == 0 || strcmp(key, MwNvalue) == 0 || strcmp(key, MwNmaxValue) == 0) {
if(MwGetInteger(handle, MwNvalue) > MwGetInteger(handle, MwNmaxValue)) MwSetInteger(handle, MwNvalue, MwGetInteger(handle, MwNmaxValue));
if(MwGetInteger(handle, MwNvalue) < MwGetInteger(handle, MwNminValue)) MwSetInteger(handle, MwNvalue, MwGetInteger(handle, MwNminValue));
MwForceRender(handle);
}
if(strcmp(key, MwNshowArrows) == 0 || strcmp(key, MwNareaShown) == 0) {

View file

@ -57,8 +57,9 @@ static void draw(MwWidget handle) {
p.y += 2 + 1;
} else {
int tw = MwTextWidth(handle, NULL, menu->sub[i]->name);
int th = MwTextHeight(handle, NULL, menu->sub[i]->name);
MwFLFont font = MwFLBuildFont(menu->sub[i]->wsub != NULL ? MwFLFlagBold : 0);
int tw = MwTextWidth(handle, font, menu->sub[i]->name);
int th = MwTextHeight(handle, NULL, menu->sub[i]->name);
if(menu->sub[i]->wsub != NULL) {
r.x = MwGetInteger(handle, MwNleftPadding);
@ -71,7 +72,7 @@ static void draw(MwWidget handle) {
p.x = 5 + tw / 2 + MwGetInteger(handle, MwNleftPadding);
p.y += th / 2;
MwDrawText(handle, MwFLBuildFont(menu->sub[i]->wsub != NULL ? MwFLFlagBold : 0), &p, menu->sub[i]->name, MwALIGNMENT_CENTER, text);
MwDrawText(handle, font, &p, menu->sub[i]->name, MwALIGNMENT_CENTER, text);
if(arrlen(menu->sub[i]->sub) > 0) {
MwRect tr;
@ -182,6 +183,11 @@ static void mwSubMenuAppearImpl(MwWidget handle, MwMenu menu, MwPoint* point, in
MwLLMakeToolWindow(handle->lowlevel);
MwLLDetach(handle->lowlevel, &p);
MwVaApply(handle,
MwNwidth, sz.width,
MwNheight, sz.height,
NULL);
if(handle->lowlevel->common.coordinate_type == MwCOORDINATE_GLOBAL) {
if(MwGetInteger(handle, MwNy) + sz.height > rc.height) {
MwVaApply(handle,
@ -208,7 +214,7 @@ static void mwSubMenuGetSizeImpl(MwWidget handle, MwMenu menu, MwRect* rect) {
if(strcmp(menu->sub[i]->name, "----") == 0) {
rect->height += 2 + 2;
} else {
int tw = MwTextWidth(handle, NULL, menu->sub[i]->name);
int tw = MwTextWidth(handle, MwFLBuildFont(arrlen(menu->sub[i]->sub) > 0 ? MwFLFlagBold : 0), menu->sub[i]->name);
rect->height += MwTextHeight(handle, NULL, menu->sub[i]->name) + 3;
if(tw > rect->width) {
rect->width = tw;

View file

@ -1,11 +1,13 @@
#!/bin/sh
for out in src/font/ttf.c src/font/boldttf.c; do
for out in src/text/font/ttf.c src/text/font/boldttf.c src/text/font/monottf.c src/text/font/boldmonottf.c; do
echo '#include <Mw/Milsko.h>' > $out
echo '' >> $out
echo '#if defined(USE_STB_TRUETYPE) || defined(USE_FREETYPE2)' >> $out
echo '#if defined(USE_STB_TRUETYPE) || defined(USE_FREETYPE2) || defined(USE_GDI_TEXT)' >> $out
done
xxd -n MwTTFData -i resource/font/IBMPlexMono.ttf | sed s/_len/Size/ >> src/font/ttf.c
xxd -n MwBoldTTFData -i resource/font/IBMPlexMono-Bold.ttf | sed s/_len/Size/ >> src/font/boldttf.c
for out in src/font/ttf.c src/font/boldttf.c; do
xxd -n MwMonospaceTTFData -i resource/font/IBMPlexMono-Regular.ttf | sed s/_len/Size/ >> src/text/font/monottf.c
xxd -n MwBoldMonospaceTTFData -i resource/font/IBMPlexMono-Bold.ttf | sed s/_len/Size/ >> src/text/font/boldmonottf.c
xxd -n MwTTFData -i resource/font/OpenSans-Regular.ttf | sed s/_len/Size/ >> src/text/font/ttf.c
xxd -n MwBoldTTFData -i resource/font/OpenSans-Bold.ttf | sed s/_len/Size/ >> src/text/font/boldttf.c
for out in src/text/font/ttf.c src/text/font/boldttf.c src/text/font/monottf.c src/text/font/boldmonottf.c; do
echo '#endif' >> $out
done