clipboard refactoring

This commit is contained in:
IoI_xD 2026-04-15 10:58:46 -07:00
commit b641a03bae
12 changed files with 116 additions and 73 deletions

View file

@ -1,6 +1,6 @@
#include <Mw/Milsko.h>
MwWidget window, instructions, text;
MwWidget window, instructions, text1, text2, cur_text;
static void resize(MwWidget handle, void* user_data, void* call_data) {
unsigned int w, h;
@ -17,9 +17,14 @@ static void resize(MwWidget handle, void* user_data, void* call_data) {
MwNheight, h - 125 - 50 * 3,
NULL);
MwVaApply(text,
MwNy, 200,
MwNwidth, w - 50 * 2,
MwVaApply(text1,
MwNy, 150,
MwNwidth, w - 25 * 2,
MwNheight, h - 125 - 50 * 3,
NULL);
MwVaApply(text2,
MwNy, 250,
MwNwidth, w - 25 * 2,
MwNheight, h - 125 - 50 * 3,
NULL);
}
@ -30,14 +35,17 @@ static void clipboard(MwWidget handle, void* user_data, void* call_data) {
(void)user_data;
if(clipboard != NULL) {
MwVaApply(text, MwNtext, clipboard, NULL);
MwForceRender(text);
MwVaApply(cur_text, MwNtext, clipboard, NULL);
MwForceRender(cur_text);
}
MwForceRender(window);
}
static void tick(MwWidget handle, void* user_data, void* call_data) {
MwGetClipboard(handle);
cur_text = text1;
MwGetClipboard(handle, MwClipboardMain);
cur_text = text2;
MwGetClipboard(handle, MwClipboardPrimary);
MwForceRender(window);
}
int main() {
@ -49,14 +57,19 @@ int main() {
instructions = MwVaCreateWidget(MwLabelClass, "button", window, 50, 50, 300, 125,
MwNtext, "clipboard contents will show up below.",
NULL);
text = MwVaCreateWidget(MwLabelClass, "label", window, 50, 200, 300, 125,
text1 = MwVaCreateWidget(MwLabelClass, "label", window, 25, 150, 300, 75,
MwNtext, "",
NULL);
text2 = MwVaCreateWidget(MwLabelClass, "label2", window, 25, 250, 300, 75,
MwNtext, "",
NULL);
cur_text = text1;
MwAddUserHandler(window, MwNresizeHandler, resize, NULL);
MwAddUserHandler(window, MwNclipboardHandler, clipboard, NULL);
MwAddUserHandler(instructions, MwNclipboardHandler, clipboard, NULL);
MwAddUserHandler(text, MwNclipboardHandler, clipboard, NULL);
MwAddUserHandler(cur_text, MwNclipboardHandler, clipboard, NULL);
MwAddUserHandler(window, MwNtickHandler, tick, NULL);
resize(window, NULL, NULL);

View file

@ -362,10 +362,11 @@ MWDECL void MwGetScreenSize(MwWidget handle, MwRect* rect);
MWDECL int MwGetCoordinateType(MwWidget handle);
/*!
* @brief Queue to get clipboard content
* @brief Queue to get clipboard content.
* @param handle Widget
* @param clipboard_type The Clipboard Type to get. See MwClipboardType. This is ignored on backends that aren't X11/Wayland, so if you're unsure, just use MwClipboardMain
*/
MWDECL void MwGetClipboard(MwWidget handle);
MWDECL void MwGetClipboard(MwWidget handle, int clipboard_type);
#ifdef __cplusplus
}

View file

@ -234,8 +234,8 @@ MWDECL void (*MwLLEndStateChange)(MwLL handle);
MWDECL void (*MwLLFocus)(MwLL handle);
MWDECL void (*MwLLGrabPointer)(MwLL handle, int toggle);
MWDECL void (*MwLLSetClipboard)(MwLL handle, const char* text);
MWDECL void (*MwLLGetClipboard)(MwLL handle);
MWDECL void (*MwLLSetClipboard)(MwLL handle, const char* text, int clipboard_type);
MWDECL void (*MwLLGetClipboard)(MwLL handle, int clipboard_type);
MWDECL void (*MwLLGetCursorCoord)(MwLL handle, MwPoint* point);
MWDECL void (*MwLLGetScreenSize)(MwLL handle, MwRect* rect);

View file

@ -439,7 +439,7 @@ struct _MwLLWayland {
/* 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.*/
union {
struct {
struct wl_data_device_manager* wl;
struct zwp_primary_selection_device_manager_v1* zwp;
} clipboard_manager;
@ -451,7 +451,8 @@ struct _MwLLWayland {
MwBool supports_zwp;
uint32_t clipboard_serial;
wl_clipboard_device_context_t** clipboard_devices;
wl_clipboard_device_context_t** clipboard_devices_wl;
wl_clipboard_device_context_t** clipboard_devices_zwp;
struct wl_pointer* pointer;
MwU32 pointer_serial;

View file

@ -239,4 +239,12 @@ enum MwCoordinateType {
MwCoordinatesLocal,
};
/* The clipboard type that MwGetClipboard should return */
enum MwClipboardType {
/* the clipboard that is present on every platform that supports it */
MwClipboardMain = 0,
/* the "primary" clipboard that Wayland stores to emulate X11's behavior. */
MwClipboardPrimary,
};
#endif

View file

@ -1042,13 +1042,15 @@ static void MwLLGrabPointerImpl(MwLL handle, int toggle) {
handle->cocoa.real->pointerLocked = toggle;
}
static void MwLLSetClipboardImpl(MwLL handle, const char* text) {
static void MwLLSetClipboardImpl(MwLL handle, const char* text, int clipboard_type) {
(void)handle;
(void)text;
(void)clipboard_type;
}
static void MwLLGetClipboardImpl(MwLL handle) {
static void MwLLGetClipboardImpl(MwLL handle, int clipboard_type) {
(void)handle;
(void)clipboard_type;
}
static void MwLLMakeToolWindowImpl(MwLL handle) {

View file

@ -735,8 +735,9 @@ static void MwLLGrabPointerImpl(MwLL handle, int toggle) {
}
}
static void MwLLSetClipboardImpl(MwLL handle, const char* text) {
static void MwLLSetClipboardImpl(MwLL handle, const char* text, int clipboard_type) {
HGLOBAL hg;
(void)clipboard_type;
if(OpenClipboard(handle->gdi.hWnd) != 0) {
char* lock;
@ -753,7 +754,8 @@ static void MwLLSetClipboardImpl(MwLL handle, const char* text) {
}
}
static void MwLLGetClipboardImpl(MwLL handle) {
static void MwLLGetClipboardImpl(MwLL handle, int clipboard_type) {
(void)clipboard_type;
handle->gdi.get_clipboard = 1; /* nishi: we do this to make clipboard api work similar to other backends */
}

View file

@ -266,7 +266,7 @@ struct zwp_primary_selection_device_v1_listener zwp_primary_selection_device_v1_
.selection = zwp_primary_selection_device_v1_selection,
};
static void wl_clipboard_read(wl_clipboard_device_context_t* ctx) {
static void wl_clipboard_read(wl_clipboard_device_context_t* ctx, int clipboard_type) {
int fds[2];
fd_set set;
char* buf = NULL;
@ -282,7 +282,7 @@ static void wl_clipboard_read(wl_clipboard_device_context_t* ctx) {
timeout.tv_sec = 0;
timeout.tv_usec = 100;
if(ctx->ll->wayland.supports_zwp) {
if(clipboard_type == MwClipboardPrimary) {
zwp_primary_selection_offer_v1_receive(ctx->offer.zwp, "text/plain", fds[1]);
} else if(ctx->offer.wl) {
wl_data_offer_receive(ctx->offer.wl, "text/plain", fds[1]);
@ -427,7 +427,7 @@ 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;
if(wayland->clipboard_manager.wl != NULL && !wayland->supports_zwp) {
if(wayland->clipboard_manager.wl != NULL) {
wl_data_device_manager_destroy(wayland->clipboard_manager.wl);
wl_data_source_destroy(wayland->clipboard_source.wl);
wayland->clipboard_manager.wl = NULL;
@ -436,10 +436,6 @@ static void wl_data_device_manager_interface_destroy(struct _MwLLWayland* waylan
/* zwp_primary_selection_device_manager_v1 setup function */
static wayland_protocol_t* zwp_primary_selection_device_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland) {
if(wayland->clipboard_manager.wl != NULL) {
wl_data_device_manager_interface_destroy(wayland, NULL);
}
wayland->clipboard_manager.zwp = wl_registry_bind(wayland->registry, name, &zwp_primary_selection_device_manager_v1_interface, 1);
wayland->clipboard_source.zwp = zwp_primary_selection_device_manager_v1_create_source(wayland->clipboard_manager.zwp);
@ -621,10 +617,6 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri
break;
case BTN_MIDDLE:
p.button = MwLLMouseMiddle;
for(i = 0; i < arrlen(self->wayland.clipboard_devices); i++) {
wl_clipboard_read(
self->wayland.clipboard_devices[i]);
}
break;
case BTN_RIGHT:
p.button = MwLLMouseRight;
@ -840,14 +832,6 @@ static void keyboard_key(void* data,
}
if((self->wayland.mod_state & 4) == 4) {
/* clipboard paste */
if(key == 'V') {
int i;
for(i = 0; i < arrlen(self->wayland.clipboard_devices); i++) {
wl_clipboard_read(
self->wayland.clipboard_devices[i]);
}
}
key |= MwLLControlMask;
}
if((self->wayland.mod_state & 8) == 8) {
@ -913,8 +897,9 @@ wl_seat_name(void* data, struct wl_seat* wl_seat, const char* name) {
/* `wl_seat.capabilities` callback */
static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat,
MwU32 capabilities) {
MwLL self = data;
wl_clipboard_device_context_t* device_ctx = malloc(sizeof(wl_clipboard_device_context_t));
MwLL self = data;
wl_clipboard_device_context_t* device_ctx_zwp = NULL;
wl_clipboard_device_context_t* device_ctx_wl = malloc(sizeof(wl_clipboard_device_context_t));
WAYLAND_EVENT_OP_START(self);
@ -930,21 +915,23 @@ static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat,
if(self->wayland.clipboard_manager.wl != NULL) {
if(self->wayland.supports_zwp) {
device_ctx->device.zwp = zwp_primary_selection_device_manager_v1_get_device(self->wayland.clipboard_manager.zwp, wl_seat);
} else {
device_ctx->device.wl = wl_data_device_manager_get_data_device(self->wayland.clipboard_manager.wl, wl_seat);
device_ctx_zwp = malloc(sizeof(wl_clipboard_device_context_t));
device_ctx_zwp->device.zwp = zwp_primary_selection_device_manager_v1_get_device(self->wayland.clipboard_manager.zwp, wl_seat);
device_ctx_zwp->ll = self;
device_ctx_zwp->seat = wl_seat;
device_ctx_zwp->capabilities = capabilities;
}
device_ctx->ll = self;
device_ctx->seat = wl_seat;
device_ctx->capabilities = capabilities;
device_ctx_wl->device.wl = wl_data_device_manager_get_data_device(self->wayland.clipboard_manager.wl, wl_seat);
device_ctx_wl->ll = self;
device_ctx_wl->seat = wl_seat;
device_ctx_wl->capabilities = capabilities;
if(self->wayland.supports_zwp) {
zwp_primary_selection_device_v1_add_listener(device_ctx->device.zwp, &zwp_primary_selection_device_v1_listener, device_ctx);
} else {
wl_data_device_add_listener(device_ctx->device.wl, &wl_data_device_listener, device_ctx);
zwp_primary_selection_device_v1_add_listener(device_ctx_zwp->device.zwp, &zwp_primary_selection_device_v1_listener, device_ctx_zwp);
arrpush(self->wayland.clipboard_devices_zwp, device_ctx_zwp);
}
arrpush(self->wayland.clipboard_devices, device_ctx);
wl_data_device_add_listener(device_ctx_wl->device.wl, &wl_data_device_listener, device_ctx_wl);
arrpush(self->wayland.clipboard_devices_wl, device_ctx_wl);
}
WAYLAND_EVENT_OP_END(self);
@ -2471,33 +2458,48 @@ static void MwLLGrabPointerImpl(MwLL handle, int toggle) {
}
}
static void MwLLSetClipboardImpl(MwLL handle, const char* text) {
static void MwLLSetClipboardImpl(MwLL handle, const char* text, int clipboard_type) {
int i;
if(handle->wayland.clipboard_buffer != NULL) {
free(handle->wayland.clipboard_buffer);
}
handle->wayland.clipboard_buffer = malloc(strlen(text));
strcpy(handle->wayland.clipboard_buffer, text);
if(handle->wayland.supports_zwp) {
int i;
for(i = 0; i < arrlen(handle->wayland.clipboard_devices); i++) {
wl_clipboard_device_context_t* device = handle->wayland.clipboard_devices[i];
zwp_primary_selection_device_v1_set_selection(device->device.zwp, handle->wayland.clipboard_source.zwp, handle->wayland.keyboard_serial);
if(clipboard_type == MwClipboardPrimary) {
if(handle->wayland.supports_zwp) {
for(i = 0; i < arrlen(handle->wayland.clipboard_devices_zwp); i++) {
wl_clipboard_device_context_t* device = handle->wayland.clipboard_devices_zwp[i];
zwp_primary_selection_device_v1_set_selection(device->device.zwp, handle->wayland.clipboard_source.zwp, handle->wayland.keyboard_serial);
}
} else {
printf("[WARNING] Primary clipboard requested for MwLLSetClipboard, but this Wayland compositor doesn't support it.\n");
}
} else {
int i;
for(i = 0; i < arrlen(handle->wayland.clipboard_devices); i++) {
wl_clipboard_device_context_t* device = handle->wayland.clipboard_devices[i];
for(i = 0; i < arrlen(handle->wayland.clipboard_devices_wl); i++) {
wl_clipboard_device_context_t* device = handle->wayland.clipboard_devices_wl[i];
wl_data_device_set_selection(device->device.wl, handle->wayland.clipboard_source.wl, handle->wayland.keyboard_serial);
}
}
}
static void MwLLGetClipboardImpl(MwLL handle) {
static void MwLLGetClipboardImpl(MwLL handle, int clipboard_type) {
int i;
for(i = 0; i < arrlen(handle->wayland.clipboard_devices); i++) {
wl_clipboard_read(
handle->wayland.clipboard_devices[i]);
if(clipboard_type == MwClipboardPrimary) {
if(handle->wayland.supports_zwp) {
for(i = 0; i < arrlen(handle->wayland.clipboard_devices_zwp); i++) {
wl_clipboard_read(
handle->wayland.clipboard_devices_zwp[i], clipboard_type);
}
} else {
printf("[WARNING] Primary clipboard requested for MwLLSetClipboard, but this Wayland compositor doesn't support it.\n");
}
} else {
for(i = 0; i < arrlen(handle->wayland.clipboard_devices_wl); i++) {
wl_clipboard_read(
handle->wayland.clipboard_devices_wl[i], clipboard_type);
}
}
return;
}

View file

@ -1220,14 +1220,14 @@ static void MwLLGrabPointerImpl(MwLL handle, int toggle) {
}
}
static void MwLLSetClipboardImpl(MwLL handle, const char* text) {
static void MwLLSetClipboardImpl(MwLL handle, const char* text, int clipboard_type) {
/* TODO */
(void)handle;
(void)text;
}
static void MwLLGetClipboardImpl(MwLL handle) {
static void MwLLGetClipboardImpl(MwLL handle, int clipboard_type) {
if(handle->x11.clipboard_pending) return;
XConvertSelection(handle->x11.display, handle->x11.clipboard, handle->x11.utf8_string, handle->x11.selection, handle->x11.window, CurrentTime);

View file

@ -958,6 +958,6 @@ int MwGetCoordinateType(MwWidget handle) {
}
}
void MwGetClipboard(MwWidget handle) {
MwLLGetClipboard(handle->lowlevel);
void MwGetClipboard(MwWidget handle, int clipboard_type) {
MwLLGetClipboard(handle->lowlevel, clipboard_type);
}

View file

@ -45,8 +45,8 @@ void (*MwLLEndStateChange)(MwLL handle) = NULL;
void (*MwLLFocus)(MwLL handle) = NULL;
void (*MwLLGrabPointer)(MwLL handle, int toggle) = NULL;
void (*MwLLSetClipboard)(MwLL handle, const char* text) = NULL;
void (*MwLLGetClipboard)(MwLL handle) = NULL;
void (*MwLLSetClipboard)(MwLL handle, const char* text, int clipboard_type) = NULL;
void (*MwLLGetClipboard)(MwLL, int clipboard_type) = NULL;
void (*MwLLGetCursorCoord)(MwLL handle, MwPoint* point) = NULL;
void (*MwLLGetScreenSize)(MwLL handle, MwRect* rect) = NULL;

View file

@ -113,7 +113,7 @@ static void key(MwWidget handle, int code) {
} else if(code == MwLLKeyEnter) {
MwDispatchUserHandler(handle, MwNactivateHandler, NULL);
} else if(code == (MwLLControlMask | 'v')) {
MwLLGetClipboard(handle->lowlevel);
MwLLGetClipboard(handle->lowlevel, MwClipboardMain);
} else if(!(code & MwLLKeyMask)) {
int incr = 0;
out = malloc(strlen(str) + 5 + 1);
@ -133,6 +133,20 @@ static void key(MwWidget handle, int code) {
MwForceRender(handle);
}
#if defined(USE_X11) || defined(USE_WAYLAND)
static void mouse_up(MwWidget handle, void* ptr) {
if(handle->lowlevel->common.type == MwLLBackendWayland || handle->lowlevel->common.type == MwLLBackendX11) {
MwLLMouse* mouse = ptr;
if(mouse->button == MwLLMouseMiddle) {
MwLLGetClipboard(handle->lowlevel, MwClipboardPrimary);
}
}
MwForceRender2(handle, NULL);
}
#else
#define mouse_up MwForceRender2
#endif
static void prop_change(MwWidget handle, const char* prop) {
if(strcmp(prop, MwNtext) == 0 || strcmp(prop, MwNhideInput) == 0) MwForceRender(handle);
@ -179,7 +193,7 @@ MwClassRec MwEntryClassRec = {
NULL, /* parent_resize */
prop_change, /* prop_change */
NULL, /* mouse_move */
MwForceRender2, /* mouse_up */
mouse_up, /* mouse_up */
MwForceRender2, /* mouse_down */
key, /* key */
NULL, /* execute */