Implement INCR transfers in the clipboard.
parent
539afe3af1
commit
f8c6e7d041
74
st.c
74
st.c
|
@ -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 *);
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -1028,21 +1034,41 @@ selcopy(Time t)
|
|||
xsetsel(getsel(), 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)) {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
|
Reference in New Issue