This commit is contained in:
IoI_xD 2026-03-26 22:48:14 -07:00
commit bf9474f4f4
12 changed files with 143 additions and 34 deletions

View file

@ -2,7 +2,7 @@
MwWidget window, instructions, text;
void resize(MwWidget handle, void* user_data, void* call_data) {
static void resize(MwWidget handle, void* user_data, void* call_data) {
unsigned int w, h;
(void)user_data;
@ -23,7 +23,7 @@ void resize(MwWidget handle, void* user_data, void* call_data) {
MwNheight, h - 125 - 50 * 3,
NULL);
}
void clipboard(MwWidget handle, void* user_data, void* call_data) {
static void clipboard(MwWidget handle, void* user_data, void* call_data) {
char* clipboard = call_data;
(void)handle;
@ -36,6 +36,10 @@ void clipboard(MwWidget handle, void* user_data, void* call_data) {
MwForceRender(window);
}
static void tick(MwWidget handle, void* user_data, void* call_data) {
MwGetClipboard(handle);
}
int main() {
MwLibraryInit();
@ -53,6 +57,7 @@ int main() {
MwAddUserHandler(window, MwNclipboardHandler, clipboard, NULL);
MwAddUserHandler(instructions, MwNclipboardHandler, clipboard, NULL);
MwAddUserHandler(text, MwNclipboardHandler, clipboard, NULL);
MwAddUserHandler(window, MwNtickHandler, tick, NULL);
resize(window, NULL, NULL);

View file

@ -16,8 +16,8 @@ void handler_theme(MwWidget handle, void* user_data, void* call_data) {
(void)call_data;
MwVaApply(window,
MwNdarkTheme, MwGetInteger(window, MwNdarkTheme) == 0 ? 1 : 0,
NULL);
MwNdarkTheme, MwGetInteger(window, MwNdarkTheme) == 0 ? 1 : 0,
NULL);
}
void handler_look(MwWidget handle, void* user_data, void* call_data) {
@ -26,8 +26,8 @@ void handler_look(MwWidget handle, void* user_data, void* call_data) {
(void)call_data;
MwVaApply(window,
MwNmodernLook, MwGetInteger(window, MwNmodernLook) == 0 ? 1 : 0,
NULL);
MwNmodernLook, MwGetInteger(window, MwNmodernLook) == 0 ? 1 : 0,
NULL);
}
void handler_font(MwWidget handle, void* user_data, void* call_data) {
@ -36,8 +36,8 @@ void handler_font(MwWidget handle, void* user_data, void* call_data) {
(void)call_data;
MwVaApply(window,
MwNbitmapFont, MwGetInteger(window, MwNbitmapFont) == 0 ? 1 : 0,
NULL);
MwNbitmapFont, MwGetInteger(window, MwNbitmapFont) == 0 ? 1 : 0,
NULL);
}
void resize(MwWidget handle, void* user_data, void* call_data) {

View file

@ -292,8 +292,8 @@ void vulkan_setup(MwWidget handle) {
swapchainCreateInfo.imageExtent = (VkExtent2D){.width = ow, .height = oh},
swapchainCreateInfo.imageArrayLayers = 1,
swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT;
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT;
// th is how we specify no transformation.
swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;

View file

@ -357,9 +357,16 @@ MWDECL void MwGetScreenSize(MwWidget handle, MwRect* rect);
/*!
* @brief Reports whether a widget reports global or local coordinates upon GetXY/SetXY. Anything with a parent reports local, and most backends report global coordinates being supported for top level windows, but some (Wayland) do not.
* @param handle Widget
*/
MWDECL int MwGetCoordinateType(MwWidget handle);
/*!
* @brief Queue to get clipboard content
* @param handle Widget
*/
MWDECL void MwGetClipboard(MwWidget handle);
#ifdef __cplusplus
}
#endif

View file

@ -30,9 +30,17 @@ struct _MwLLX11 {
Colormap colormap;
Atom wm_delete;
Atom wm_protocols;
Atom utf8_string;
Atom compound_text;
Atom text;
Atom clipboard;
Atom selection;
XIM xim;
XIC xic;
long clipboard_time;
int clipboard_pending; /* 1 if UTF8_STRING, 2 if COMPOUNd_TEXT, 3 if TEXT, 4 if STRING, otherwise 0 */
int top;
int toplevel;
int grabbed;

View file

@ -35,13 +35,13 @@ if (grep(/^wayland$/, @backends)) {
}
scan_wayland_protocol_core();
scan_wayland_protocol("stable", "xdg-shell", "");
scan_wayland_protocol("stable", "viewporter", "");
scan_wayland_protocol("stable", "tablet", "-v2");
scan_wayland_protocol("staging", "xdg-toplevel-icon", "-v1");
scan_wayland_protocol("staging", "cursor-shape", "-v1");
scan_wayland_protocol("unstable", "xdg-decoration", "-unstable-v1");
scan_wayland_protocol("unstable", "primary-selection", "-unstable-v1");
scan_wayland_protocol("stable", "xdg-shell", "");
scan_wayland_protocol("stable", "viewporter", "");
scan_wayland_protocol("stable", "tablet", "-v2");
scan_wayland_protocol("staging", "xdg-toplevel-icon", "-v1");
scan_wayland_protocol("staging", "cursor-shape", "-v1");
scan_wayland_protocol("unstable", "xdg-decoration", "-unstable-v1");
scan_wayland_protocol("unstable", "primary-selection", "-unstable-v1");
scan_wayland_protocol("unstable", "pointer-constraints", "-unstable-v1");
$gl_libs = "-lGL -lGLU";

View file

@ -58,7 +58,6 @@ sub use_backend {
}
}
sub scan_wayland_protocol_core {
my $proto_c = "src/backend/wayland-core-protocol.c";

View file

@ -2,6 +2,8 @@
#include "../../external/stb_ds.h"
#define ClipboardTimeout 100
typedef struct mwm_hints {
unsigned long flags;
unsigned long functions;
@ -215,6 +217,14 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) {
r->x11.wm_protocols = XInternAtom(r->x11.display, "WM_PROTOCOLS", False);
XSetWMProtocols(r->x11.display, r->x11.window, &r->x11.wm_delete, 1);
r->x11.utf8_string = XInternAtom(r->x11.display, "UTF8_STRING", False);
r->x11.compound_text = XInternAtom(r->x11.display, "COMPOUND_TEXT", False);
r->x11.text = XInternAtom(r->x11.display, "TEXT", False);
r->x11.clipboard = XInternAtom(r->x11.display, "CLIPBOARD", False);
r->x11.selection = XInternAtom(r->x11.display, "_MILSKO_SELECTION_", False);
r->x11.clipboard_pending = 0;
r->x11.gc = XCreateGC(r->x11.display, r->x11.window, 0, NULL);
create_pixmap(r);
@ -414,7 +424,11 @@ static void MwLLFreeColorImpl(MwLLColor color) {
static int MwLLPendingImpl(MwLL handle) {
XEvent ev;
if(XCheckTypedWindowEvent(handle->x11.display, handle->x11.window, ClientMessage, &ev) || XCheckWindowEvent(handle->x11.display, handle->x11.window, mask, &ev)) {
if(handle->x11.clipboard_pending && (MwTimeGetTick() - handle->x11.clipboard_time) >= ClipboardTimeout) {
return 1;
}
if(XCheckTypedWindowEvent(handle->x11.display, handle->x11.window, ClientMessage, &ev) || XCheckTypedWindowEvent(handle->x11.display, handle->x11.window, SelectionNotify, &ev) || XCheckWindowEvent(handle->x11.display, handle->x11.window, mask, &ev)) {
XPutBackEvent(handle->x11.display, &ev);
return 1;
}
@ -424,7 +438,33 @@ static int MwLLPendingImpl(MwLL handle) {
static void MwLLNextEventImpl(MwLL handle) {
XEvent ev;
while(XCheckTypedWindowEvent(handle->x11.display, handle->x11.window, ClientMessage, &ev) || XCheckWindowEvent(handle->x11.display, handle->x11.window, mask, &ev)) {
if(handle->x11.clipboard_pending && (MwTimeGetTick() - handle->x11.clipboard_time) >= ClipboardTimeout) {
Atom a = handle->x11.selection;
handle->x11.clipboard_pending++;
handle->x11.clipboard_time = MwTimeGetTick();
switch(handle->x11.clipboard_pending) {
case 2:
a = handle->x11.compound_text;
break;
case 3:
a = handle->x11.text;
break;
case 4:
a = XA_STRING;
break;
case 5:
handle->x11.clipboard_pending = 0;
break;
}
if(a != handle->x11.selection) {
XConvertSelection(handle->x11.display, handle->x11.clipboard, a, handle->x11.selection, handle->x11.window, CurrentTime);
}
}
while(XCheckTypedWindowEvent(handle->x11.display, handle->x11.window, ClientMessage, &ev) || XCheckTypedWindowEvent(handle->x11.display, handle->x11.window, SelectionNotify, &ev) || XCheckWindowEvent(handle->x11.display, handle->x11.window, mask, &ev)) {
int render = 0;
if(ev.type == Expose) {
handle->x11.force_render = 0;
@ -563,6 +603,49 @@ static void MwLLNextEventImpl(MwLL handle) {
MwLLDispatch(handle, key_released, &n);
}
}
} else if(ev.type == SelectionNotify) {
handle->x11.clipboard_pending = 0;
if(ev.xselection.property != None) {
Atom type;
int format;
unsigned long nitems, after, size;
unsigned char* pdat;
int ret = XGetWindowProperty(handle->x11.display, handle->x11.window, handle->x11.selection, 0, 0, False, AnyPropertyType, &type, &format, &nitems, &after, &pdat);
if(pdat != NULL) XFree(pdat);
size = after;
if(ret == Success && type != None && format == 8) {
char* buf = malloc(size + 1);
int offset;
for(offset = 0; after > 0; offset += nitems) {
ret = XGetWindowProperty(handle->x11.display, handle->x11.window, handle->x11.selection, offset / 4, after / 4 + 1, False, AnyPropertyType, &type, &format, &nitems, &after, &pdat);
if(ret != Success) {
free(buf);
buf = NULL;
break;
}
memcpy(buf + offset, pdat, nitems);
XFree(pdat);
}
if(buf != NULL) {
buf[size] = 0;
MwLLDispatch(handle, clipboard, buf);
free(buf);
}
}
XDeleteProperty(handle->x11.display, handle->x11.window, handle->x11.selection);
}
}
if(render) {
int x, y;
@ -961,9 +1044,12 @@ static void MwLLSetClipboardImpl(MwLL handle, const char* text) {
}
static void MwLLGetClipboardImpl(MwLL handle) {
/* TODO */
if(handle->x11.clipboard_pending) return;
(void)handle;
XConvertSelection(handle->x11.display, handle->x11.clipboard, handle->x11.utf8_string, handle->x11.selection, handle->x11.window, CurrentTime);
handle->x11.clipboard_pending = 1;
handle->x11.clipboard_time = MwTimeGetTick();
}
static void MwLLMakeToolWindowImpl(MwLL handle) {

View file

@ -134,8 +134,8 @@ static void lldarkthemehandler(MwLL handle, void* data) {
if(IsFirstVisible(h)) {
MwVaApply(h,
MwNdarkTheme, *ptr,
NULL);
MwNdarkTheme, *ptr,
NULL);
MwDispatchUserHandler(h, MwNdarkThemeHandler, data);
}
@ -449,7 +449,7 @@ void MwSetInteger(MwWidget handle, const char* key, int n) {
if(strcmp(key, MwNforceInverted) == 0) {
MwForceRender(handle);
}
if(strcmp(key, MwNmodernLook) == 0 || strcmp(key, MwNdarkTheme) == 0 || strcmp(key, MwNbitmapFont) == 0){
if(strcmp(key, MwNmodernLook) == 0 || strcmp(key, MwNdarkTheme) == 0 || strcmp(key, MwNbitmapFont) == 0) {
force_render_all(handle);
}
}
@ -762,8 +762,8 @@ void MwGrabPointer(MwWidget handle, int toggle) {
void MwSetDarkTheme(MwWidget handle, int toggle) {
MwVaApply(handle,
MwNdarkTheme, toggle,
NULL);
MwNdarkTheme, toggle,
NULL);
}
MwWidget MwGetParent(MwWidget handle) {
@ -856,4 +856,8 @@ int MwGetCoordinateType(MwWidget handle) {
} else {
return MwCoordinatesLocal;
}
};
}
void MwGetClipboard(MwWidget handle) {
MwLLGetClipboard(handle->lowlevel);
}

View file

@ -283,7 +283,6 @@ static void MwDrawFrameEx_simple(MwWidget handle, MwRect* rect, MwLLColor color,
int ColorDiff = get_color_diff(handle);
MwLLColor darker = MwLightenColor(handle, color, -ColorDiff * 3 / 2 + diff, -ColorDiff * 3 / 2 + diff, -ColorDiff * 3 / 2 + diff);
MwLLColor lighter = same ? MwLightenColor(handle, darker, 0, 0, 0) : MwLightenColor(handle, color, ColorDiff - diff, ColorDiff - diff, ColorDiff - diff);
int i;
int roundness = MwGetInteger(handle, MwNroundness);
if(roundness == MwDEFAULT) roundness = DEFAULT_ROUNDNESS;
@ -345,9 +344,11 @@ static void MwDrawFrameEx_simple(MwWidget handle, MwRect* rect, MwLLColor color,
static void frame_border_complex(MwWidget handle, MwRect* rect, MwLLColor lighter, MwLLColor darker, int invert, int border, int diff, int same, int rounded) {
MwPoint p[7];
int roundness = MwGetInteger(handle, MwNroundness);
MwRect r = *rect;
int i;
(void)diff;
(void)same;
if(roundness == MwDEFAULT) roundness = DEFAULT_ROUNDNESS;
if(roundness >= MAX_ROUNDNESS) roundness = MAX_ROUNDNESS;
if(rounded && rect->height >= (roundness * 2) && rect->width >= (roundness * 2) && roundness > 0) {
@ -493,8 +494,7 @@ static void MwDrawFrameEx_complex(MwWidget handle, MwRect* rect, MwLLColor color
int ColorDiff = get_color_diff(handle);
MwLLColor darker = MwLightenColor(handle, color, -ColorDiff * 3 / 2 + diff, -ColorDiff * 3 / 2 + diff, -ColorDiff * 3 / 2 + diff);
MwLLColor lighter = same ? MwLightenColor(handle, darker, 0, 0, 0) : MwLightenColor(handle, color, (ColorDiff / 2) - diff, (ColorDiff / 2) - diff, (ColorDiff / 2) - diff);
int i;
MwRect r = *rect;
MwRect r = *rect;
frame_border_complex(handle, rect, lighter, darker, invert, border, diff, same, rounded);

View file

@ -54,7 +54,7 @@ void (*MwLLGetScreenSize)(MwLL handle, MwRect* rect) = NULL;
void MwLLCreateCommon(MwLL handle) {
handle->common.handler = malloc(sizeof(*handle->common.handler));
memset(handle->common.handler, 0, sizeof(*handle->common.handler));
handle->common.supports_transparency = 0;
}

View file

@ -229,7 +229,7 @@ static MwErrorEnum vulkan_instance_setup(MwWidget handle, vulkan_t* o) {
if(handle->lowlevel->common.type == MwLLBackendWayland) {
arrput(enabledExtensions, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
/* take this opprutunity to set the widget to always render */
MwWaylandAlwaysRender = MwTRUE;
MwWaylandAlwaysRender = MwTRUE;
}
#endif