rfbLog("pointer(mask: 0x%x, x:%4d, y:%4d) "
rfbLog("# pointer(mask: 0x%x, x:%4d, y:%4d) "
void pointer(int mask, int x, int y, rfbClientPtr client) {	allowed_input_t input;	int sent = 0, buffer_it = 0;	double now;	if (debug_pointer && mask >= 0) {		static int show_motion = -1;		static double last_pointer = 0.0;		double tnow, dt;		static int last_x, last_y;		if (show_motion == -1) {			if (getenv("X11VNC_DB_NOMOTION")) {				show_motion = 0;			} else {				show_motion = 1;			}		}		dtime0(&tnow);		tnow -= x11vnc_start;		dt = tnow - last_pointer;		last_pointer = tnow;		if (show_motion) {			rfbLog("pointer(mask: 0x%x, x:%4d, y:%4d) "			    "dx: %3d dy: %3d dt: %.4f t: %.4f\n", mask, x, y,			    x - last_x, y - last_y, dt, tnow);		}		last_x = x;		last_y = y;	}	if (scaling) {		/* map from rfb size to X11 size: */		x = ((double) x / scaled_x) * dpy_x;		x = nfix(x, dpy_x);		y = ((double) y / scaled_y) * dpy_y;		y = nfix(y, dpy_y);	}	if (pipeinput_fh != NULL && mask >= 0) {		pipe_pointer(mask, x, y, client);		if (! pipeinput_tee) {			if (! view_only || raw_fb) {	/* raw_fb hack */				got_user_input++;				got_keyboard_input++;				last_pointer_client = client;			}			if (view_only && raw_fb) {				/* raw_fb hack track button state */				button_mask_prev = button_mask;				button_mask = mask;			}			return;		}	}	if (view_only) {		return;	}	now = dnow();	if (mask >= 0) {		/*		 * mask = -1 is a special case call from scan_for_updates()		 * to flush the event queue; there is no real pointer event.		 */		get_allowed_input(client, &input);		if (! input.motion && ! input.button) {			return;		}		got_user_input++;		got_pointer_input++;		last_pointer_client = client;		last_pointer_time = now;	}	/*	 * The following is hopefully an improvement wrt response during	 * pointer user input (window drags) for the threaded case.	 * See check_user_input() for the more complicated things we do	 * in the non-threaded case.	 */	if ((use_threads && pointer_mode != 1) || pointer_flush_delay > 0.0) {#		define NEV 32		/* storage for the event queue */		static int mutex_init = 0;		static int nevents = 0;		static int ev[NEV][3];		int i;		/* timer things */		static double dt = 0.0, tmr = 0.0, maxwait = 0.4;		if (! mutex_init) {			INIT_MUTEX(pointerMutex);			mutex_init = 1;		}		if (pointer_flush_delay > 0.0) {			maxwait = pointer_flush_delay;		}		if (mask >= 0) {			if (fb_copy_in_progress || pointer_flush_delay > 0.0) {				buffer_it = 1;			}		}		LOCK(pointerMutex);		/* 		 * If the framebuffer is being copied in another thread		 * (scan_for_updates()), we will queue up to 32 pointer		 * events for later.  The idea is by delaying these input		 * events, the screen is less likely to change during the		 * copying period, and so will give rise to less window		 * "tearing".		 *		 * Tearing is not completely eliminated because we do		 * not suspend work in the other libvncserver threads.		 * Maybe that is a possibility with a mutex...		 */		if (buffer_it) {			/* 			 * mask = -1 is an all-clear signal from			 * scan_for_updates().			 *			 * dt is a timer in seconds; we only queue for so long.			 */			dt += dtime(&tmr);			if (nevents < NEV && dt < maxwait) {				i = nevents++;				ev[i][0] = mask;				ev[i][1] = x;				ev[i][2] = y;				if (! input.button) {					ev[i][0] = -1;				}				if (! input.motion) {					ev[i][1] = -1;					ev[i][2] = -1;				}				UNLOCK(pointerMutex);				if (debug_pointer) {					rfbLog("pointer(): deferring event %d"					    " %.4f\n", i, tmr - x11vnc_start);				}				return;			}		}		/* time to send the queue */		for (i=0; i<nevents; i++) {			int sent = 0;			if (mask < 0 && client != NULL) {				/* hack to only push the latest event */				if (i < nevents - 1) {					if (debug_pointer) {						rfbLog("- skip deferred event:"						    " %d\n", i);					}					continue;				}			}			if (debug_pointer) {				rfbLog("pointer(): sending event %d %.4f\n",				    i+1, dnow() - x11vnc_start);			}			if (ev[i][1] >= 0) {				update_x11_pointer_position(ev[i][1], ev[i][2]);				sent = 1;			}			if (ev[i][0] >= 0) {				update_x11_pointer_mask(ev[i][0]);				sent = 1;			}			if (sent) {				pointer_queued_sent++;			}		}		if (nevents && dt > maxwait) {		    if (dpy) {	/* raw_fb hack */			if (mask < 0) {				if (debug_pointer) {					rfbLog("pointer(): calling XFlush "					    "%.4f\n", dnow() - x11vnc_start);				}				X_LOCK;				XFlush(dpy);					X_UNLOCK;			}		    }		}		nevents = 0;	/* reset everything */		dt = 0.0;		dtime0(&tmr);		UNLOCK(pointerMutex);	}	if (mask < 0) {		/* -1 just means flush the event queue */		if (debug_pointer) {			rfbLog("pointer(): flush only.  %.4f\n",			    dnow() - x11vnc_start);		}		return;	}	/* update the X display with the event: */	if (input.motion) {		update_x11_pointer_position(x, y);		sent = 1;	}	if (input.button) {		if (mask != button_mask) {			button_change_x = cursor_x;			button_change_y = cursor_y;		}		update_x11_pointer_mask(mask);		sent = 1;	}	if (nofb && sent) {		/* 		 * nofb is for, e.g. Win2VNC, where fastest pointer		 * updates are desired.		 */		X_LOCK;		XFlush(dpy);		X_UNLOCK;	} else if (buffer_it) {		if (debug_pointer) {			rfbLog("pointer(): calling XFlush+"			    "%.4f\n", dnow() - x11vnc_start);		}		X_LOCK;		XFlush(dpy);			X_UNLOCK;	}}