diff options
| author | Christoph Lohmann <20h@r-36.net> | 2015-07-10 14:10:17 +0200 | 
|---|---|---|
| committer | Christoph Lohmann <20h@r-36.net> | 2015-07-10 14:10:17 +0200 | 
| commit | f8c6e7d0419d10c1425cb2c7123c5798ffb3b942 (patch) | |
| tree | 659acb41481f2c8f7e7575ecbfd174312b3efbcb | |
| parent | 539afe3af1b0d8b56b9ebfaa3bb7fc4e40f68c71 (diff) | |
Implement INCR transfers in the clipboard.
| -rw-r--r-- | st.c | 74 | 
1 files changed, 68 insertions, 6 deletions
@@ -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,  }; @@ -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)) { @@ -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  | 
