tImplement INCR transfers in the clipboard. - st - [fork] customized build of s… | |
git clone git://src.adamsgaard.dk/st | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit f8c6e7d0419d10c1425cb2c7123c5798ffb3b942 | |
parent 539afe3af1b0d8b56b9ebfaa3bb7fc4e40f68c71 | |
Author: Christoph Lohmann <[email protected]> | |
Date: Fri, 10 Jul 2015 14:10:17 +0200 | |
Implement INCR transfers in the clipboard. | |
Diffstat: | |
M st.c | 74 ++++++++++++++++++++++++++++-… | |
1 file changed, 68 insertions(+), 6 deletions(-) | |
--- | |
diff --git a/st.c b/st.c | |
t@@ -452,6 +452,7 @@ static void focus(XEvent *); | |
static void brelease(XEvent *); | |
static void bpress(XEvent *); | |
static void bmotion(XEvent *); | |
+static void propnotify(XEvent *); | |
static void selnotify(XEvent *); | |
static void selclear(XEvent *); | |
static void selrequest(XEvent *); | |
t@@ -500,6 +501,11 @@ static void (*handler[LASTEvent])(XEvent *) = { | |
*/ | |
/* [SelectionClear] = selclear, */ | |
[SelectionNotify] = selnotify, | |
+/* | |
+ * PropertyNotify is only turned on when there is some INCR transfer happening | |
+ * for the selection retrieval. | |
+ */ | |
+ [PropertyNotify] = propnotify, | |
[SelectionRequest] = selrequest, | |
}; | |
t@@ -1029,20 +1035,40 @@ selcopy(Time t) | |
} | |
void | |
+propnotify(XEvent *e) | |
+{ | |
+ XPropertyEvent *xpev; | |
+ Atom clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); | |
+ | |
+ xpev = &e->xproperty; | |
+ if (xpev->state == PropertyNewValue && | |
+ (xpev->atom == XA_PRIMARY || | |
+ xpev->atom == clipboard)) { | |
+ slenotify(e); | |
+ } | |
+} | |
+ | |
+void | |
selnotify(XEvent *e) | |
{ | |
ulong nitems, ofs, rem; | |
int format; | |
uchar *data, *last, *repl; | |
- Atom type; | |
- XSelectionEvent *xsev; | |
+ Atom type, incratom, property; | |
ofs = 0; | |
- xsev = &e->xselection; | |
- if (xsev->property == None) | |
- return; | |
+ if (e->type == SelectionNotify) { | |
+ property = e->xselection.property; | |
+ } else if(e->type == PropertyNotify) { | |
+ property = e->xproperty.atom; | |
+ } else { | |
+ return; | |
+ } | |
+ if (property == None) | |
+ return; | |
+ | |
do { | |
- if (XGetWindowProperty(xw.dpy, xw.win, xsev->property, ofs, | |
+ if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, | |
BUFSIZ/4, False, AnyPropertyType, | |
&type, &format, &nitems, &rem, | |
&data)) { | |
t@@ -1050,6 +1076,35 @@ selnotify(XEvent *e) | |
return; | |
} | |
+ if (e->type == PropertyNotify && nitems == 0 && rem == 0) { | |
+ /* | |
+ * If there is some PropertyNotify with no data, then | |
+ * this is the signal of the selection owner that all | |
+ * data has been transferred. We won't need to receive | |
+ * PropertyNotify events anymore. | |
+ */ | |
+ MODBIT(xw.attrs.event_mask, 0, PropertyChangeMask); | |
+ XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, | |
+ &xw.attrs); | |
+ } | |
+ | |
+ if (type == incratom) { | |
+ /* | |
+ * Activate the PropertyNotify events so we receive | |
+ * when the selection owner does send us the next | |
+ * chunk of data. | |
+ */ | |
+ MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask); | |
+ XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, | |
+ &xw.attrs); | |
+ | |
+ /* | |
+ * Deleting the property is the transfer start signal. | |
+ */ | |
+ XDeleteProperty(xw.dpy, xw.win, (int)property); | |
+ continue; | |
+ } | |
+ | |
/* | |
* As seen in getsel: | |
* Line endings are inconsistent in the terminal and GUI world | |
t@@ -1072,6 +1127,13 @@ selnotify(XEvent *e) | |
/* number of 32-bit chunks returned */ | |
ofs += nitems * format / 32; | |
} while (rem > 0); | |
+ | |
+ /* | |
+ * Deleting the property again tells the selection owner to send the | |
+ * next data chunk in the property. | |
+ */ | |
+ if (e->type == PropertyNotify) | |
+ XDeleteProperty(xw.dpy, xw.win, (int)property); | |
} | |
void |