From 83dd2f6039d6f0758e82f7b12242a9fc4a3d9ed7 Mon Sep 17 00:00:00 2001 From: Matthew Date: Sun, 5 Oct 2025 15:03:17 +1100 Subject: [PATCH] clipboard fixes --- platform.d | 146 +++++++++++++++++++++++++++-------------------------- 1 file changed, 74 insertions(+), 72 deletions(-) diff --git a/platform.d b/platform.d index db7e249..34ef094 100644 --- a/platform.d +++ b/platform.d @@ -528,7 +528,7 @@ struct PlatformWindow Inputs[2] inputs; TicketMut input_mutex; - Mut cb_mut; + TicketMut cb_mut; Selection[CBM.max] selections; version(linux) u32 cb_transfer_size; }; @@ -566,7 +566,7 @@ CreateWindow(string name, u16 width, u16 height) h: height, input_mutex: CreateTicketMut(), msg_queue: CreateMessageQueue(), - cb_mut: CreateMut(), + cb_mut: CreateTicketMut(), inputs: [ { arena: CreateArena(MB(1)) }, { arena: CreateArena(MB(1)) }, @@ -819,35 +819,34 @@ TransmitSelection(PlatformWindow* w, xcb_selection_request_event_t* ev) else if(ev.target == w.atoms[Atoms.Utf8String]) { Selection* sel = null; - if(TryLock(&w.cb_mut)) + Lock(&w.cb_mut); + + foreach(i; CBM.min .. CBM.max) { - foreach(i; CBM.min .. CBM.max) + if(w.selections[i].xmode == ev.selection) { - if(w.selections[i].xmode == ev.selection) - { - sel = &w.selections[i]; - break; - } + sel = &w.selections[i]; + break; } - - if(sel != null && sel.owned && sel.data.length > 0 && sel.target == ev.target) - { - xcb_change_property( - w.conn, - XCB_PROP_MODE_REPLACE, - ev.requestor, - ev.property, - ev.target, - 8, - cast(u32)sel.data.length, - sel.data.ptr - ); - - result = true; - } - - Unlock(&w.cb_mut); } + + if(sel != null && sel.owned && sel.data.length > 0 && sel.target == ev.target) + { + xcb_change_property( + w.conn, + XCB_PROP_MODE_REPLACE, + ev.requestor, + ev.property, + ev.target, + 8, + cast(u32)sel.data.length, + sel.data.ptr + ); + + result = true; + } + + Unlock(&w.cb_mut); } return result; @@ -858,11 +857,10 @@ ClipboardOwns(PlatformWindow* w, ClipboardMode mode) { bool result; - if(TryLock(&w.cb_mut)) - { - result = w.selections[mode].owned; - Unlock(&w.cb_mut); - } + Lock(&w.cb_mut); + + result = w.selections[mode].owned; + Unlock(&w.cb_mut); return result; } @@ -872,51 +870,48 @@ ClipboardText(PlatformWindow* w, ClipboardMode mode) { u8[] buf; - if(TryLock(&w.cb_mut)) + Lock(&w.cb_mut); + + scope(exit) Unlock(&w.cb_mut); + + Selection* sel = &w.selections[mode]; + + if(sel.owned) { - scope(exit) Unlock(&w.cb_mut); + buf = GetClipboardSelection(w, sel); + } + else + { + timeval now; + timespec timeout; + int pret = 0; - Selection* sel = &w.selections[mode]; + auto owner = xcb_get_selection_owner_reply(w.conn, xcb_get_selection_owner(w.conn, sel.xmode), null); + scope(exit) pureFree(owner); - if(sel.owned) + if(owner != null && owner.owner != 0) { - buf = GetClipboardSelection(w, sel); - } - else - { - timeval now; - timespec timeout; - int pret = 0; + FreeArray(sel.data); + sel.data = []; - auto owner = xcb_get_selection_owner_reply(w.conn, xcb_get_selection_owner(w.conn, sel.xmode), null); - scope(exit) pureFree(owner); + sel.target = w.atoms[Atoms.Utf8String]; + xcb_convert_selection(w.conn, w.window, sel.xmode, sel.target, sel.xmode, XCB_CURRENT_TIME); + xcb_flush(w.conn); - if(owner != null && owner.owner != 0) + gettimeofday(&now, null); + + timeout.tv_sec = now.tv_sec + (X11_TIMEOUT_DEFAULT / 1000); + timeout.tv_nsec = (now.tv_usec * 1000UL) * ((X11_TIMEOUT_DEFAULT % 1000) * 1000000UL); + if(timeout.tv_nsec >= 1000000000UL) { - FreeArray(sel.data); - sel.data = []; - - sel.target = w.atoms[Atoms.Utf8String]; - xcb_convert_selection(w.conn, w.window, sel.xmode, sel.target, sel.xmode, XCB_CURRENT_TIME); - xcb_flush(w.conn); - - gettimeofday(&now, null); - - timeout.tv_sec = now.tv_sec + (X11_TIMEOUT_DEFAULT / 1000); - timeout.tv_nsec = (now.tv_usec * 1000UL) * ((X11_TIMEOUT_DEFAULT % 1000) * 1000000UL); - if(timeout.tv_nsec >= 1000000000UL) - { - timeout.tv_sec += timeout.tv_nsec / 1000000000UL; - timeout.tv_nsec = timeout.tv_nsec % 1000000000UL; - } - - while(pret == 0 && sel.data.length == 0) - { - pret = PThreadCondTimedWait(&w.thread.cond, &w.thread.mut, &timeout); - } - - GetClipboardSelection(w, sel); + timeout.tv_sec += timeout.tv_nsec / 1000000000UL; + timeout.tv_nsec = timeout.tv_nsec % 1000000000UL; } + + Lock(&w.cb_mut); + Unlock(&w.cb_mut); + + GetClipboardSelection(w, sel); } } @@ -934,8 +929,11 @@ SetClipboard(PlatformWindow* w, u8[] data, ClipboardMode mode) { bool result = true; - if(data.length > 0 && TryLock(&w.cb_mut)) + if(data.length > 0) { + Lock(&w.cb_mut); + scope(exit) Unlock(&w.cb_mut); + Selection* sel = &w.selections[mode]; if(sel.data.length > 0) { @@ -1043,8 +1041,10 @@ RetrieveSelection(PlatformWindow* w, xcb_selection_notify_event_t* ev) } } - if(buf != null && TryLock(&w.cb_mut)) + if(buf != null) { + Lock(&w.cb_mut); + Selection* sel; foreach(i; CBM.min .. CBM.max) { @@ -1082,8 +1082,10 @@ ClearSelection(PlatformWindow* w, xcb_selection_clear_event_t* ev) foreach(i; CBM.min .. CBM.max) { Selection* sel = &w.selections[i]; - if(sel.xmode == ev.selection && TryLock(&w.cb_mut)) + if(sel.xmode == ev.selection) { + Lock(&w.cb_mut); + FreeArray(sel.data); sel.data = []; sel.owned = false;