Implement INCR transfers in the clipboard.
This commit is contained in:
		
							
								
								
									
										72
									
								
								st.c
									
									
									
									
									
								
							
							
						
						
									
										72
									
								
								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; | ||||||
|  | 	} else if(e->type == PropertyNotify) { | ||||||
|  | 		property = e->xproperty.atom; | ||||||
|  | 	} else { | ||||||
| 		return; | 		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
	
	Block a user