rpe_last = to = tc = tm;
tm = 0.0;		 dtime(&tm); to = tm;
static void check_user_input4(double dt, double dtr, int tile_diffs) {	int g, g_in, i, ginput, gcnt, tmp;	int last_was_miss, consecutive_misses;	int min_frame_size = 10;	/* 10 tiles */	double spin, tm, to, tc, dtm, rpe_last;	int rfb_wait_ms = 2;	static double dt_cut = 0.050;	static int first = 1;	int Btile = tile_x * tile_y * bpp/8; 	/* Bytes per tile */	double Ttile, dt_use;	double screen_rate = 6000000.;    /* 5 MB/sec */	double vnccpu_rate = 80 * 100000.; /* 20 KB/sec @ 80X compression */	double net_rate = 50000.;	static double Tfac_r = 1.0, Tfac_v = 1.0, Tfac_n = 1.0, Tdelay = 0.001;	static double dt_min = -1.0, dt_max = -1.0;	double dt_min_fallback = 0.050;	static int ssec = 0, total_calls = 0;	static int push_frame = 0, update_count = 0;	if (first) {		char *p = getenv("SPIN");		if (p) {			sscanf(p, "%lf,%lf,%lf,%lf", &dt_cut, &Tfac_r, &Tfac_v, &Tfac_n);		}		first = 0;		ssec = time(0);	}	total_calls++;	if (dt_min < 0.0 || dt < dt_min) {		if (dt > 0.0) {			dt_min = dt;		}	}	if (dt_min < 0.0) {		/* sensible value for the very 1st call if dt = 0.0 */		dt_min = dt_min_fallback;	}	if (dt_max < 0.0 || dt > dt_max) {		dt_max = dt;	}	if (total_calls > 30 && dt_min > 0.0) {		static int first = 1;		/*		 * dt_min will soon be the quickest time to do		 * one scan_for_updates with no tiles copied.		 * use this (instead of copy_tiles) to estimate		 * screen read rate.		 */		screen_rate = (main_bytes_per_line * ntiles_y) / dt_min;		if (first) {			rfbLog("measured screen read rate: %.2f Bytes/sec\n",			    screen_rate);		}		first = 0;	}	tm = 0.0;		/* timer variable */	dtime(&tm);	if (dt < dt_cut) {		dt_use = dt_cut;	} else {		dt_use = dt;	}	if (push_frame) {		int cnt, iter = 0;		double tp = 0.0, push_spin = 0.0;		dtime(&tp);		while (push_spin < dt_use * 0.5) {			fb_update_sent(&cnt);			if (cnt != update_count) {				break;			}			/* damn, they didn't push our frame! */			iter++;			rfbPE(screen, rfb_wait_ms * 1000);						push_spin += dtime(&tp);		}		if (iter) {			X_LOCK;			XFlush(dpy);			X_UNLOCK;		}		push_frame = 0;		update_count = 0;	}	/*	 * when we first enter we require some pointer input	 */	if (!got_pointer_input) {		return;	}	vnccpu_rate = get_raw_rate();	if ((tmp = get_read_rate()) != 0) {		screen_rate = (double) tmp;	}	if ((tmp = get_net_rate()) != 0) {		net_rate = (double) tmp;	}	net_rate = (vnccpu_rate/get_cmp_rate()) * net_rate;	if ((tmp = get_net_latency()) != 0) {		Tdelay = 0.5 * ((double) tmp)/1000.;	}	Ttile = Btile * (Tfac_r/screen_rate + Tfac_v/vnccpu_rate + Tfac_n/net_rate);	spin = 0.0;		/* amount of time spinning */	last_was_miss = 0;	consecutive_misses = 1;	gcnt = 0;	ginput = 0;	rpe_last = to = tc = tm;	/* last time we did rfbPE() */	g = g_in = got_pointer_input;	tile_diffs = 0;	/* reset our knowlegde of tile_diffs to zero */	while (1) {		int got_input = 0;		gcnt++;		if (button_mask) {			/* this varible is used by our pointer handler */			drag_in_progress = 1;		}		/* turn libvncserver crank to process events: */		rfbCFD(screen, rfb_wait_ms * 1000);		dtm = dtime(&tm);		spin += dtm;		if ( (gcnt == 1 && got_pointer_input > g) || tm-tc > 2*dt_min) {			tile_diffs = scan_for_updates(1);			tc = tm;		}		if (got_pointer_input == g) {			if (last_was_miss) {				consecutive_misses++;			}			last_was_miss = 1;		} else {			ginput++;			consecutive_misses = 1;			last_was_miss = 0;		}		if (tile_diffs > min_frame_size && spin > Ttile * tile_diffs + Tdelay) {			/* we think we can push the frame */			push_frame = 1;			fb_update_sent(&update_count);			break;		} else if (got_pointer_input > g) {			/* received some input, flush it to display. */			got_input = 1;			g = got_pointer_input;			X_LOCK;			XFlush(dpy);			X_UNLOCK;		} else if (consecutive_misses >= 2) {			/* too many misses in a row */			break;		} else {			/* these are pointer input misses */			int wms;			if (gcnt == 1 && button_mask) {				/*				 * missed our first input, wait for				 * a defer time. (e.g. on slow link)				 * hopefully client will batch many				 * of them for the next read.				 */				wms = 50;			} else if (button_mask) {				wms = 10;			} else {				wms = 0;			}			if (wms) {				usleep(wms * 1000);			}		}	}	if (ginput >= 2) {		/* try for a couple more quick ones */		for (i=0; i<2; i++) {			rfbCFD(screen, rfb_wait_ms * 1000);		}	}	drag_in_progress = 0;}