From: Michael D. Lowis Date: Wed, 5 Apr 2017 00:15:31 +0000 (-0400) Subject: Persiste the clipboard selection on quit if we own it X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=3b01701453cfeea9cf4e9be70e439850d9e84b61;p=projs%2Ftide.git Persiste the clipboard selection on quit if we own it --- diff --git a/Makefile b/Makefile index a168ef6..8f22729 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ INCS = -Iinc/ -BINS = xedit xpick term +BINS = xedit xpick xcpd term MAN1 = docs/edit.1 docs/xedit.1 docs/xpick.1 docs/xtagpick.1 docs/xfilepick.1 LIBEDIT_OBJS = \ @@ -57,7 +57,8 @@ libedit.a: $(LIBEDIT_OBJS) $(AR) $(ARFLAGS) $@ $^ xedit: xedit.o libedit.a -xpick: xpick.o libedit.a +xpick: xpick.o libedit.a +xcpd: xcpd.o libedit.a term: term.o libedit.a tests/libedit: tests/libedit.o tests/lib/buf.o tests/lib/utf8.o libedit.a tests/xedit: tests/xedit.o libedit.a diff --git a/TODO.md b/TODO.md index 8d87ad3..0e758fe 100644 --- a/TODO.md +++ b/TODO.md @@ -3,8 +3,6 @@ Up Next: * fix crash on saving read-only file - -* clipboard does not persist after exit * Run commands in the background and don't block the main thread. * Make Fn keys execute nth command in the tags buffer diff --git a/lib/x11.c b/lib/x11.c index 05346ee..27104fc 100644 --- a/lib/x11.c +++ b/lib/x11.c @@ -4,6 +4,7 @@ #include #include #include +#include #include static struct XSel* selfetch(Atom atom); @@ -323,8 +324,7 @@ void x11_handle_events(void) { } void x11_loop(void) { - XEvent e; - while (Running) { + for (XEvent e; Running;) { XPeekEvent(X.display,&e); x11_handle_events(); if (Running) { @@ -335,6 +335,9 @@ void x11_loop(void) { } } XCloseDisplay(X.display); + /* we're exiting now. If we own the clipboard, make sure it persists */ + if (Selections[CLIPBOARD].text) + cmdwrite((char*[]){ "xcpd", NULL }, Selections[CLIPBOARD].text, NULL); } XFont x11_font_load(char* name) { diff --git a/xcpd.c b/xcpd.c new file mode 100644 index 0000000..a959454 --- /dev/null +++ b/xcpd.c @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#include +#include +#include + +char* SelText; // The text of the clipboard selection +Atom SelType; // The X11 selection name. Always CLIPBOARD +Atom SelTarget; // The conversion target for the selection (always string or utf8) +Display* XDisplay; // Handle for the X connection +Window XRoot; // The root X window +Window XWindow; // Our window used to serve the selection up + +void serve_selection(void) { + if (!(XDisplay = XOpenDisplay(0))) + die("could not open display"); + XRoot = DefaultRootWindow(XDisplay); + XWindow = XCreateSimpleWindow(XDisplay, XRoot, 0, 0, 1, 1, 0, 0, 0); + SelType = XInternAtom(XDisplay, "CLIPBOARD", 0); + SelTarget = XInternAtom(XDisplay, "UTF8_STRING", 0); + if (SelTarget == None) + SelTarget = XInternAtom(XDisplay, "STRING", 0); + XSetSelectionOwner(XDisplay, SelType, XWindow, CurrentTime); + + for (XEvent e;;) { + XNextEvent(XDisplay, &e); + if (e.type == SelectionRequest) { + XEvent s; + s.xselection.type = SelectionNotify; + s.xselection.property = e.xselectionrequest.property; + s.xselection.requestor = e.xselectionrequest.requestor; + s.xselection.selection = e.xselectionrequest.selection; + s.xselection.target = e.xselectionrequest.target; + s.xselection.time = e.xselectionrequest.time; + Atom target = e.xselectionrequest.target; + Atom xatargets = XInternAtom(XDisplay, "TARGETS", 0); + Atom xastring = XInternAtom(XDisplay, "STRING", 0); + if (target == xatargets) { + /* respond with the supported type */ + XChangeProperty( + XDisplay, s.xselection.requestor, s.xselection.property, + XA_ATOM, 32, PropModeReplace, + (unsigned char*)&SelTarget, 1); + } else if (target == SelTarget || target == xastring) { + XChangeProperty( + XDisplay, s.xselection.requestor, s.xselection.property, + SelTarget, 8, PropModeReplace, + (unsigned char*)SelText, strlen(SelText)); + } + XSendEvent(XDisplay, s.xselection.requestor, True, 0, &s); + } else if (e.type == SelectionClear) { + break; // Someone else took over. We're done here. + } + } +} + +int main(int argc, char** argv) { + SelText = fdgets(STDIN_FILENO); + if (SelText) { + int pid = fork(); + if (pid == 0) { + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + serve_selection(); + } else if (pid < 0) { + die("fork() failed"); + } + } + return 0; +} diff --git a/xedit.c b/xedit.c index 9677ed8..c2e00ea 100644 --- a/xedit.c +++ b/xedit.c @@ -552,7 +552,6 @@ int main(int argc, char** argv) { win_setruler(80); view_init(win_view(EDIT), (argc > 1 ? argv[1] : NULL)); win_setkeys(Bindings); - //win_setmouse(&MouseHandlers); win_loop(); return 0; }