diff --git a/src/conio/sdl_con.c b/src/conio/sdl_con.c
index e2a4c8ecc60b453eab377bb004f4a25e3207a7a5..ae0ed62049ca24083465c5c77013aa83c132116c 100644
--- a/src/conio/sdl_con.c
+++ b/src/conio/sdl_con.c
@@ -53,6 +53,8 @@ SDL_mutex	*bitmap_init_mutex;
 static int bitmap_initialized = 0;
 
 /* *nix copy/paste stuff */
+int paste_needs_events;
+int copy_needs_events;
 SDL_sem	*sdl_pastebuf_set;
 SDL_sem	*sdl_pastebuf_copied;
 SDL_mutex	*sdl_copybuf_mutex;
@@ -400,6 +402,7 @@ void sdl_user_func(int func, ...)
 {
 	va_list argptr;
 	SDL_Event	ev;
+	int rv;
 
 	ev.type=SDL_USEREVENT;
 	ev.user.data1=NULL;
@@ -407,6 +410,8 @@ void sdl_user_func(int func, ...)
 	ev.user.code=func;
 	va_start(argptr, func);
 	sdl.mutexP(sdl_ufunc_mtx);
+	/* Drain the swamp */
+	while(sdl.SemWaitTimeout(sdl_ufunc_rec, 0)==0);
 	switch(func) {
 		case SDL_USEREVENT_SETICON:
 			ev.user.data1=va_arg(argptr, void *);
@@ -438,10 +443,12 @@ void sdl_user_func(int func, ...)
 			return;
 	}
 	while(1) {
-		while(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff)!=1)
+		while((rv = sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff))!=1)
 			YIELD();
-		if (sdl.SemWaitTimeout(sdl_ufunc_rec, 1000) != 0)
+		if (func != SDL_USEREVENT_FLUSH) {
+			if ((rv = sdl.SemWaitTimeout(sdl_ufunc_rec, 1000)) != 0)
 				continue;
+		}
 		break;
 	}
 	sdl.mutexV(sdl_ufunc_mtx);
@@ -451,6 +458,7 @@ void sdl_user_func(int func, ...)
 /* Called from main thread only */
 int sdl_user_func_ret(int func, ...)
 {
+	int rv;
 	va_list argptr;
 	SDL_Event	ev;
 
@@ -460,6 +468,8 @@ int sdl_user_func_ret(int func, ...)
 	ev.user.code=func;
 	va_start(argptr, func);
 	sdl.mutexP(sdl_ufunc_mtx);
+	/* Drain the swamp */
+	while(sdl.SemWaitTimeout(sdl_ufunc_rec, 0)==0);
 	while(1) {
 		switch(func) {
 			case SDL_USEREVENT_SETVIDMODE:
@@ -478,9 +488,10 @@ int sdl_user_func_ret(int func, ...)
 		 * we need for copy/paste on X11.
 		 * This hack can be removed for SDL2
 		 */
-		if(sdl.SemWaitTimeout(sdl_ufunc_rec, 1000)!=0)
+		if((rv = sdl.SemWaitTimeout(sdl_ufunc_rec, 1000))!=0)
 			continue;
-		if(sdl.SemWait(sdl_ufunc_ret)==0)
+		rv = sdl.SemWait(sdl_ufunc_ret);
+		if(rv==0)
 			break;
 	}
 	sdl.mutexV(sdl_ufunc_mtx);
@@ -762,8 +773,6 @@ int sdl_init(int mode)
 				sdl_x11available=FALSE;
 			}
 		}
-		if(sdl_x11available)
-			sdl.EventState(SDL_SYSWMEVENT, SDL_ENABLE);
 #endif
 		cio_api.options |= CONIO_OPT_PALETTE_SETTING | CONIO_OPT_SET_TITLE | CONIO_OPT_SET_NAME | CONIO_OPT_SET_ICON;
 		return(0);
@@ -1717,8 +1726,10 @@ int sdl_video_event_thread(void *data)
 						break;
 					case SDL_USEREVENT: {
 						struct update_rect *list;
+						struct update_rect *list_tail;
 						/* Tell SDL to do various stuff... */
-						sdl.SemPost(sdl_ufunc_rec);
+						if (ev.user.code != SDL_USEREVENT_FLUSH)
+							sdl.SemPost(sdl_ufunc_rec);
 						switch(ev.user.code) {
 							case SDL_USEREVENT_QUIT:
 								sdl_ufunc_retval=0;
@@ -1740,9 +1751,13 @@ int sdl_video_event_thread(void *data)
 									sdl.mutexP(win_mutex);
 									if(!win) {
 										sdl.mutexV(win_mutex);
-										free(list->data);
-										free(list);
-										continue;
+										/* Put it back at the start of the list... */
+										sdl.mutexP(sdl_headlock);
+										for (list_tail = list; list_tail->next; list_tail = list_tail->next);
+										list_tail->next = update_list;
+										update_list = list;
+										sdl.mutexV(sdl_headlock);
+										break;
 									}
 									sdl.mutexP(newrect_mutex);
 									scaling = cvstat.scaling;
@@ -1762,11 +1777,15 @@ int sdl_video_event_thread(void *data)
 									}
 									if(!yuv.enabled) {
 										if (!upd_rects) {
-											free(list->data);
-											free(list);
 											sdl.mutexV(newrect_mutex);
 											sdl.mutexV(win_mutex);
-											continue;
+											/* Put it back at the start of the list... */
+											sdl.mutexP(sdl_headlock);
+											for (list_tail = list; list_tail->next; list_tail = list_tail->next);
+											list_tail->next = update_list;
+											update_list = list;
+											sdl.mutexV(sdl_headlock);
+											break;
 										}
 										upd_rects[rectsused].x=list->x*scaling;
 										upd_rects[rectsused].y=list->y*scaling*vmultiplier;
@@ -1883,6 +1902,8 @@ int sdl_video_event_thread(void *data)
 
 									SDL_VERSION(&(wmi.version));
 									sdl.GetWMInfo(&wmi);
+									sdl.EventState(SDL_SYSWMEVENT, SDL_ENABLE);
+									copy_needs_events = 1;
 									sdl_x11.XSetSelectionOwner(wmi.info.x11.display, CONSOLE_CLIPBOARD, wmi.info.x11.window, CurrentTime);
 									break;
 								}
@@ -1897,6 +1918,8 @@ int sdl_video_event_thread(void *data)
 									SDL_VERSION(&(wmi.version));
 									sdl.GetWMInfo(&wmi);
 
+									paste_needs_events = 1;
+									sdl.EventState(SDL_SYSWMEVENT, SDL_ENABLE);
 									sowner=sdl_x11.XGetSelectionOwner(wmi.info.x11.display, CONSOLE_CLIPBOARD);
 									if(sowner==wmi.info.x11.window) {
 										/* Get your own primary selection */
@@ -1911,6 +1934,9 @@ int sdl_video_event_thread(void *data)
 										sdl.SemPost(sdl_pastebuf_set);
 										sdl.SemWait(sdl_pastebuf_copied);
 										FREE_AND_NULL(sdl_pastebuf);
+										paste_needs_events = 0;
+										if (!copy_needs_events)
+											sdl.EventState(SDL_SYSWMEVENT, SDL_DISABLE);
 									}
 									else if(sowner!=None) {
 										sdl_x11.XConvertSelection(wmi.info.x11.display, CONSOLE_CLIPBOARD, XA_STRING, XA_STRING, wmi.info.x11.window, CurrentTime);
@@ -1920,6 +1946,9 @@ int sdl_video_event_thread(void *data)
 										FREE_AND_NULL(sdl_pastebuf);
 										sdl.SemPost(sdl_pastebuf_set);
 										sdl.SemWait(sdl_pastebuf_copied);
+										paste_needs_events = 0;
+										if (!copy_needs_events)
+											sdl.EventState(SDL_SYSWMEVENT, SDL_DISABLE);
 									}
 									break;
 								}
@@ -2005,6 +2034,9 @@ int sdl_video_event_thread(void *data)
 											FREE_AND_NULL(sdl_copybuf);
 										}
 										sdl.mutexV(sdl_copybuf_mutex);
+										copy_needs_events = 0;
+										if (!paste_needs_events)
+											sdl.EventState(SDL_SYSWMEVENT, SDL_DISABLE);
 										break;
 								}
 								case SelectionNotify: {
@@ -2034,6 +2066,9 @@ int sdl_video_event_thread(void *data)
 										/* Set paste buffer */
 										sdl.SemPost(sdl_pastebuf_set);
 										sdl.SemWait(sdl_pastebuf_copied);
+										paste_needs_events = 0;
+										if (!copy_needs_events)
+											sdl.EventState(SDL_SYSWMEVENT, SDL_DISABLE);
 										if(sdl_pastebuf!=NULL) {
 											sdl_x11.XFree(sdl_pastebuf);
 											sdl_pastebuf=NULL;