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 brelease(XEvent *);
|
||||||
static void bpress(XEvent *);
|
static void bpress(XEvent *);
|
||||||
static void bmotion(XEvent *);
|
static void bmotion(XEvent *);
|
||||||
|
static void propnotify(XEvent *);
|
||||||
static void selnotify(XEvent *);
|
static void selnotify(XEvent *);
|
||||||
static void selclear(XEvent *);
|
static void selclear(XEvent *);
|
||||||
static void selrequest(XEvent *);
|
static void selrequest(XEvent *);
|
||||||
|
@ -500,6 +501,11 @@ static void (*handler[LASTEvent])(XEvent *) = {
|
||||||
*/
|
*/
|
||||||
/* [SelectionClear] = selclear, */
|
/* [SelectionClear] = selclear, */
|
||||||
[SelectionNotify] = selnotify,
|
[SelectionNotify] = selnotify,
|
||||||
|
/*
|
||||||
|
* PropertyNotify is only turned on when there is some INCR transfer happening
|
||||||
|
* for the selection retrieval.
|
||||||
|
*/
|
||||||
|
[PropertyNotify] = propnotify,
|
||||||
[SelectionRequest] = selrequest,
|
[SelectionRequest] = selrequest,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1028,21 +1034,41 @@ selcopy(Time t)
|
||||||
xsetsel(getsel(), 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
|
void
|
||||||
selnotify(XEvent *e)
|
selnotify(XEvent *e)
|
||||||
{
|
{
|
||||||
ulong nitems, ofs, rem;
|
ulong nitems, ofs, rem;
|
||||||
int format;
|
int format;
|
||||||
uchar *data, *last, *repl;
|
uchar *data, *last, *repl;
|
||||||
Atom type;
|
Atom type, incratom, property;
|
||||||
XSelectionEvent *xsev;
|
|
||||||
|
|
||||||
ofs = 0;
|
ofs = 0;
|
||||||
xsev = &e->xselection;
|
if (e->type == SelectionNotify) {
|
||||||
if (xsev->property == None)
|
property = e->xselection.property;
|
||||||
return;
|
} else if(e->type == PropertyNotify) {
|
||||||
|
property = e->xproperty.atom;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (property == None)
|
||||||
|
return;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (XGetWindowProperty(xw.dpy, xw.win, xsev->property, ofs,
|
if (XGetWindowProperty(xw.dpy, xw.win, property, ofs,
|
||||||
BUFSIZ/4, False, AnyPropertyType,
|
BUFSIZ/4, False, AnyPropertyType,
|
||||||
&type, &format, &nitems, &rem,
|
&type, &format, &nitems, &rem,
|
||||||
&data)) {
|
&data)) {
|
||||||
|
@ -1050,6 +1076,35 @@ selnotify(XEvent *e)
|
||||||
return;
|
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:
|
* As seen in getsel:
|
||||||
* Line endings are inconsistent in the terminal and GUI world
|
* Line endings are inconsistent in the terminal and GUI world
|
||||||
|
@ -1072,6 +1127,13 @@ selnotify(XEvent *e)
|
||||||
/* number of 32-bit chunks returned */
|
/* number of 32-bit chunks returned */
|
||||||
ofs += nitems * format / 32;
|
ofs += nitems * format / 32;
|
||||||
} while (rem > 0);
|
} 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
|
void
|
||||||
|
|
Reference in New Issue