if (1 || dnow > last_error + 60) {
if (1 || now > last_error + 60) {
void xrecord_watch(int start, int setby) {	Window focus, wm, c, clast;	static double create_time = 0.0;	double dnow;	static double last_error = 0.0;	int rc, db = debug_scroll;	int do_shutdown = 0;	int reopen_dpys = 1;	XErrorHandler old_handler = NULL;	static Window last_win = None, last_result = None;	if (nofb) {		xrecording = 0;		return;	}	if (use_threads) {		/* XXX not working */		use_xrecord = 0;		xrecording = 0;		return;	}	dtime0(&dnow);	if (dnow < last_error + 0.5) {		return;	}#if LIBVNCSERVER_HAVE_RECORD	if (! start) {		int shut_reopen = 2, shut_time = 25;if (db) fprintf(stderr, "XRECORD OFF: %d/%d  %.4f\n", xrecording, setby, dnow - x11vnc_start);		xrecording = 0;		if (! rc_scroll) {			xrecord_focus_window = None;			xrecord_wm_window = None;			xrecord_ptr_window = None;			xrecord_keysym = NoSymbol;			rcs_scroll = 0;			return;		}		if (! do_shutdown && dnow > create_time + shut_time) {			/* XXX unstable if we keep a RECORD going forever */			do_shutdown = 1;			shut_reopen = 1;		}		SCR_LOCK;				if (do_shutdown) {if (db > 1) fprintf(stderr, "=== shutdown-scroll 0x%lx\n", rc_scroll);			X_LOCK;			trapped_record_xerror = 0;			old_handler = XSetErrorHandler(trap_record_xerror);			shutdown_record_context(rc_scroll, 0, shut_reopen);			if (! use_xrecord) return;			XRecordProcessReplies(rdpy_data);			if (trapped_record_xerror) {				RECORD_ERROR_MSG;				last_error = dnow;			}			XSetErrorHandler(old_handler);			X_UNLOCK;			rc_scroll = 0;		} else {			if (rcs_scroll) {if (db > 1) fprintf(stderr, "=== disab-scroll 0x%lx 0x%lx\n", rc_scroll, rcs_scroll);				X_LOCK;				trapped_record_xerror = 0;				old_handler =				    XSetErrorHandler(trap_record_xerror);				rcs_scroll = XRecordCurrentClients;				XRecordUnregisterClients(rdpy_ctrl, rc_scroll,				    &rcs_scroll, 1);				XRecordDisableContext(rdpy_ctrl, rc_scroll);				XFlush(rdpy_ctrl);				XRecordProcessReplies(rdpy_data);				if (trapped_record_xerror) {					RECORD_ERROR_MSG;					shutdown_record_context(rc_scroll,					    0, reopen_dpys);					last_error = dnow;					rc_scroll = 0;					if (! use_xrecord) return;				}				XSetErrorHandler(old_handler);				X_UNLOCK;			}		}		SCR_UNLOCK;		/*		 * XXX if we do a XFlush(rdpy_ctrl) here we get:		 *		X Error of failed request:  XRecordBadContext		  Major opcode of failed request:  145 (RECORD)		  Minor opcode of failed request:  5 (XRecordEnableContext)		  Context in failed request:  0x2200013		  Serial number of failed request:  29		  Current serial number in output stream:  29		 *		 * need to figure out what is going on... since it may lead		 * infrequent failures.		 */		xrecord_focus_window = None;		xrecord_wm_window = None;		xrecord_ptr_window = None;		xrecord_keysym = NoSymbol;		rcs_scroll = 0;		return;	}if (db) fprintf(stderr, "XRECORD ON:  %d/%d  %.4f\n", xrecording, setby, dnow - x11vnc_start);	if (xrecording) {		return;	}	if (do_shutdown && rc_scroll) {		static int didmsg = 0;		/* should not happen... */		if (1 || !didmsg) {			rfbLog("warning: do_shutdown && rc_scroll\n");			didmsg = 1;		}		xrecord_watch(0, SCR_NONE);	}	xrecording = 0;	xrecord_focus_window = None;	xrecord_wm_window = None;	xrecord_ptr_window = None;	xrecord_keysym = NoSymbol;	xrecord_set_by_keys  = 0;	xrecord_set_by_mouse = 0;	/* get the window with focus and mouse pointer: */	clast = None;	focus = None;	wm = None;	X_LOCK;	SCR_LOCK;#if 0	/*	 * xrecord_focus_window / focus not currently used... save a	 * round trip to the X server for now.	 * N.B. our heuristic is inaccurate: if he is scrolling and	 * drifts off of the scrollbar onto another application we	 * will catch that application, not the starting ones.	 * check_xrecord_{keys,mouse} mitigates this somewhat by	 * delaying calls to xrecord_watch as much as possible.	 */	XGetInputFocus(dpy, &focus, &i);#endif	wm = query_pointer(rootwin);	if (wm) {		c = wm;	} else {		c = rootwin;	}	/* descend a bit to avoid wm frames: */	if (c != rootwin && c == last_win) {		/* use cached results to avoid roundtrips: */		clast = last_result;	} else if (scroll_good_all == NULL && scroll_skip_all == NULL) {		/* more efficient if name info not needed. */		xrecord_name_info[0] = '\0';		clast = descend_pointer(6, c, NULL, 0);	} else {		char *nm;		int matched_good = 0, matched_skip = 0;		clast = descend_pointer(6, c, xrecord_name_info, NAMEINFO);if (db) fprintf(stderr, "name_info: %s\n", xrecord_name_info);		nm = xrecord_name_info;		if (scroll_good_all) {			matched_good += match_str_list(nm, scroll_good_all);		}		if (setby == SCR_KEY && scroll_good_key) {			matched_good += match_str_list(nm, scroll_good_key);		}		if (setby == SCR_MOUSE && scroll_good_mouse) {			matched_good += match_str_list(nm, scroll_good_mouse);		}		if (scroll_skip_all) {			matched_skip += match_str_list(nm, scroll_skip_all);		}		if (setby == SCR_KEY && scroll_skip_key) {			matched_skip += match_str_list(nm, scroll_skip_key);		}		if (setby == SCR_MOUSE && scroll_skip_mouse) {			matched_skip += match_str_list(nm, scroll_skip_mouse);		}		if (!matched_good && matched_skip) {			clast = None;		}	}	if (c != rootwin) {		/* cache results for possible use next call */		last_win = c;		last_result = clast;	}	if (!clast || clast == rootwin) {if (db) fprintf(stderr, "--- xrecord_watch: SKIP.\n");		X_UNLOCK;		SCR_UNLOCK;		return;	}	/* set protocol request ranges: */	rr_scroll[0] = rr_CA;	rr_scroll[1] = rr_CW;	/*	 * start trapping... there still are some occasional failures	 * not yet understood, likely some race condition WRT the 	 * context being setup.	 */	trapped_record_xerror = 0;	old_handler = XSetErrorHandler(trap_record_xerror);	if (! rc_scroll) {		/* do_shutdown case or first time in */		rcs_scroll = (XRecordClientSpec) clast;		rc_scroll = XRecordCreateContext(rdpy_ctrl, 0, &rcs_scroll, 1,		    rr_scroll, 2);		if (rc_scroll) {			dtime0(&create_time);		} else {			rcs_scroll = 0;		}	} else if (! do_shutdown) {		if (rcs_scroll) {			/*			 * should have been unregistered in xrecord_watch(0)...			 */			rcs_scroll = XRecordCurrentClients;			XRecordUnregisterClients(rdpy_ctrl, rc_scroll,			    &rcs_scroll, 1);if (db > 1) fprintf(stderr, "=2= unreg-scroll 0x%lx 0x%lx\n", rc_scroll, rcs_scroll);		}				rcs_scroll = (XRecordClientSpec) clast;if (db > 1) fprintf(stderr, "=-=   reg-scroll 0x%lx 0x%lx\n", rc_scroll, rcs_scroll);		if (!XRecordRegisterClients(rdpy_ctrl, rc_scroll, 0,		    &rcs_scroll, 1, rr_scroll, 2)) {			if (1 || dnow > last_error + 60) {				rfbLog("failed to register client 0x%lx with"				    " X RECORD context rc_scroll.\n", clast);			}			last_error = dnow;			rcs_scroll = 0;			/* continue on for now... */		}	}	XFlush(rdpy_ctrl);if (db) fprintf(stderr, "rc_scroll: 0x%lx\n", rc_scroll);	if (trapped_record_xerror) {		RECORD_ERROR_MSG;	}	if (! rc_scroll) {		XSetErrorHandler(old_handler);		X_UNLOCK;		SCR_UNLOCK;		use_xrecord = 0;		rfbLog("failed to create X RECORD context rc_scroll.\n");		rfbLog("  switching to -noscrollcopyrect mode.\n");		return;	} else if (! rcs_scroll || trapped_record_xerror) {		/* try again later */		shutdown_record_context(rc_scroll, 0, reopen_dpys);		if (! use_xrecord) return;		rc_scroll = 0;		last_error = dnow;		XSetErrorHandler(old_handler);		X_UNLOCK;		SCR_UNLOCK;		return;	}	xrecord_focus_window = focus;#if 0	/* xrecord_focus_window currently unused. */	if (! xrecord_focus_window) {		xrecord_focus_window = clast;	}#endif	xrecord_wm_window = wm;	if (! xrecord_wm_window) {		xrecord_wm_window = clast;	}	xrecord_ptr_window = clast;	xrecording = 1;	xrecord_seq++;	dtime0(&xrecord_start);	rc = XRecordEnableContextAsync(rdpy_data, rc_scroll, record_switch,	    (XPointer) xrecord_seq);	if (!rc || trapped_record_xerror) {		if (1 || dnow > last_error + 60) {			rfbLog("failed to enable RECORD context "			    "rc_scroll: 0x%lx\n", rc_scroll);			if (trapped_record_xerror) {				RECORD_ERROR_MSG;			}		}		shutdown_record_context(rc_scroll, 0, reopen_dpys);		if (! use_xrecord) return;		rc_scroll = 0;		last_error = dnow;		xrecording = 0;		/* continue on for now... */	}	XSetErrorHandler(old_handler);	/* XXX this may cause more problems than it solves... */	XFlush(rdpy_data);	X_UNLOCK;	SCR_UNLOCK;#endif}