]> git.mdlowis.com Git - projs/tide.git/commitdiff
Persiste the clipboard selection on quit if we own it
authorMichael D. Lowis <mike@mdlowis.com>
Wed, 5 Apr 2017 00:15:31 +0000 (20:15 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Wed, 5 Apr 2017 00:15:31 +0000 (20:15 -0400)
Makefile
TODO.md
lib/x11.c
xcpd.c [new file with mode: 0644]
xedit.c

index a168ef6ef1422a949833fdc52c3658a21ae732e5..8f2272919dc93eed214f526b80f76bda2f50a8f8 100644 (file)
--- 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 8d87ad372785750b6e3a3550439ce6e1fc0ed86f..0e758fe3711ee83420b5b56c9b7665fb092a2f1e 100644 (file)
--- 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
 
index 05346ee25669371aa0083ab53a84849c85fb81fc..27104fc8d2b459f19ec2f9a74808e9f5c46a340e 100644 (file)
--- a/lib/x11.c
+++ b/lib/x11.c
@@ -4,6 +4,7 @@
 #include <stdc.h>
 #include <x11.h>
 #include <utf.h>
+#include <edit.h>
 #include <locale.h>
 
 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 (file)
index 0000000..a959454
--- /dev/null
+++ b/xcpd.c
@@ -0,0 +1,73 @@
+#include <stdc.h>
+#include <utf.h>
+#include <edit.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/Xft/Xft.h>
+#include <unistd.h>
+
+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 9677ed80f169daec3c2fc962b77c5fea3a1a0e55..c2e00eafdb4bbee377d0bc58fb9f273a09aefeb7 100644 (file)
--- 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;
 }