Home | History | Annotate | Download | only in x11vnc
      1 /*
      2    Copyright (C) 2002-2010 Karl J. Runge <runge (at) karlrunge.com>
      3    All rights reserved.
      4 
      5 This file is part of x11vnc.
      6 
      7 x11vnc is free software; you can redistribute it and/or modify
      8 it under the terms of the GNU General Public License as published by
      9 the Free Software Foundation; either version 2 of the License, or (at
     10 your option) any later version.
     11 
     12 x11vnc is distributed in the hope that it will be useful,
     13 but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with x11vnc; if not, write to the Free Software
     19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
     20 or see <http://www.gnu.org/licenses/>.
     21 
     22 In addition, as a special exception, Karl J. Runge
     23 gives permission to link the code of its release of x11vnc with the
     24 OpenSSL project's "OpenSSL" library (or with modified versions of it
     25 that use the same license as the "OpenSSL" library), and distribute
     26 the linked executables.  You must obey the GNU General Public License
     27 in all respects for all of the code used other than "OpenSSL".  If you
     28 modify this file, you may extend this exception to your version of the
     29 file, but you are not obligated to do so.  If you do not wish to do
     30 so, delete this exception statement from your version.
     31 */
     32 
     33 /* -- pointer.c -- */
     34 
     35 #include "x11vnc.h"
     36 #include "xwrappers.h"
     37 #include "keyboard.h"
     38 #include "xinerama.h"
     39 #include "xrecord.h"
     40 #include "win_utils.h"
     41 #include "cursor.h"
     42 #include "userinput.h"
     43 #include "connections.h"
     44 #include "cleanup.h"
     45 #include "unixpw.h"
     46 #include "v4l.h"
     47 #include "linuxfb.h"
     48 #include "uinput.h"
     49 #include "scan.h"
     50 #include "macosx.h"
     51 #include "screen.h"
     52 
     53 int pointer_queued_sent = 0;
     54 
     55 void initialize_pointer_map(char *pointer_remap);
     56 void do_button_mask_change(int mask, int button);
     57 void pointer_event(int mask, int x, int y, rfbClientPtr client);
     58 void initialize_pipeinput(void);
     59 int check_pipeinput(void);
     60 void update_x11_pointer_position(int x, int y);
     61 
     62 
     63 static void buttonparse(int from, char **s);
     64 static void update_x11_pointer_mask(int mask);
     65 static void pipe_pointer(int mask, int x, int y, rfbClientPtr client);
     66 
     67 /*
     68  * pointer event (motion and button click) handling routines.
     69  */
     70 typedef struct ptrremap {
     71 	KeySym keysym;
     72 	KeyCode keycode;
     73 	int end;
     74 	int button;
     75 	int down;
     76 	int up;
     77 } prtremap_t;
     78 
     79 #define MAX_BUTTON_EVENTS 50
     80 static prtremap_t pointer_map[MAX_BUTTONS+1][MAX_BUTTON_EVENTS];
     81 
     82 /*
     83  * For parsing the -buttonmap sections, e.g. "4" or ":Up+Up+Up:"
     84  */
     85 static void buttonparse(int from, char **s) {
     86 #if (0 && NO_X11)
     87 	if (!from || !s) {}
     88 	return;
     89 #else
     90 	char *q;
     91 	int to, i;
     92 	int modisdown[256];
     93 
     94 	q = *s;
     95 
     96 	for (i=0; i<256; i++) {
     97 		modisdown[i] = 0;
     98 	}
     99 
    100 	if (*q == ':') {
    101 		/* :sym1+sym2+...+symN: format */
    102 		int l = 0, n = 0;
    103 		char list[1000];
    104 		char *t, *kp = q + 1;
    105 		KeyCode kcode;
    106 
    107 		while (*(kp+l) != ':' && *(kp+l) != '\0') {
    108 			/* loop to the matching ':' */
    109 			l++;
    110 			if (l >= 1000) {
    111 				rfbLog("buttonparse: keysym list too long: "
    112 				    "%s\n", q);
    113 				break;
    114 			}
    115 		}
    116 		*(kp+l) = '\0';
    117 		strncpy(list, kp, l);
    118 		list[l] = '\0';
    119 		rfbLog("remap button %d using \"%s\"\n", from, list);
    120 
    121 		/* loop over tokens separated by '+' */
    122 		t = strtok(list, "+");
    123 		while (t) {
    124 			KeySym ksym;
    125 			unsigned int ui;
    126 			int i;
    127 			if (n >= MAX_BUTTON_EVENTS - 20) {
    128 				rfbLog("buttonparse: too many button map "
    129 					"events: %s\n", list);
    130 				break;
    131 			}
    132 			if (sscanf(t, "0x%x", &ui) == 1) {
    133 				ksym = (KeySym) ui;	/* hex value */
    134 			} else {
    135 				X_LOCK;
    136 				ksym = XStringToKeysym(t); /* string value */
    137 				X_UNLOCK;
    138 			}
    139 			if (ksym == NoSymbol) {
    140 				/* see if Button<N> "keysym" was used: */
    141 				if (sscanf(t, "Button%d", &i) == 1) {
    142 					rfbLog("   event %d: button %d\n",
    143 					    from, n+1, i);
    144 					if (i == 0) i = -1; /* bah */
    145 					pointer_map[from][n].keysym  = NoSymbol;
    146 					pointer_map[from][n].keycode = NoSymbol;
    147 					pointer_map[from][n].button = i;
    148 					pointer_map[from][n].end    = 0;
    149 					pointer_map[from][n].down   = 0;
    150 					pointer_map[from][n].up     = 0;
    151 				} else {
    152 					rfbLog("buttonparse: ignoring unknown "
    153 					    "keysym: %s\n", t);
    154 					n--;
    155 				}
    156 			} else if (dpy) {
    157 				/*
    158 				 * XXX may not work with -modtweak or -xkb
    159 				 */
    160 				char *str;
    161 				X_LOCK;
    162 #if NO_X11
    163 				kcode = NoSymbol;
    164 #else
    165 				kcode = XKeysymToKeycode(dpy, ksym);
    166 #endif
    167 
    168 				pointer_map[from][n].keysym  = ksym;
    169 				pointer_map[from][n].keycode = kcode;
    170 				pointer_map[from][n].button = 0;
    171 				pointer_map[from][n].end    = 0;
    172 				if (! ismodkey(ksym) ) {
    173 					/* do both down then up */
    174 					pointer_map[from][n].down = 1;
    175 					pointer_map[from][n].up   = 1;
    176 				} else {
    177 					if (modisdown[kcode]) {
    178 						pointer_map[from][n].down = 0;
    179 						pointer_map[from][n].up   = 1;
    180 						modisdown[kcode] = 0;
    181 					} else {
    182 						pointer_map[from][n].down = 1;
    183 						pointer_map[from][n].up   = 0;
    184 						modisdown[kcode] = 1;
    185 					}
    186 				}
    187 				str = XKeysymToString(ksym);
    188 				rfbLog("   event %d: keysym %s (0x%x) -> "
    189 				    "keycode 0x%x down=%d up=%d\n", n+1,
    190 				    str ? str : "null", ksym, kcode,
    191 				    pointer_map[from][n].down,
    192 				    pointer_map[from][n].up);
    193 				X_UNLOCK;
    194 			}
    195 			t = strtok(NULL, "+");
    196 			n++;
    197 		}
    198 
    199 		/* we must release any modifiers that are still down: */
    200 		for (i=0; i<256; i++) {
    201 			kcode = (KeyCode) i;
    202 			if (n >= MAX_BUTTON_EVENTS) {
    203 				rfbLog("buttonparse: too many button map "
    204 					"events: %s\n", list);
    205 				break;
    206 			}
    207 			if (modisdown[kcode]) {
    208 				pointer_map[from][n].keysym  = NoSymbol;
    209 				pointer_map[from][n].keycode = kcode;
    210 				pointer_map[from][n].button = 0;
    211 				pointer_map[from][n].end    = 0;
    212 				pointer_map[from][n].down = 0;
    213 				pointer_map[from][n].up   = 1;
    214 				modisdown[kcode] = 0;
    215 				n++;
    216 			}
    217 		}
    218 
    219 		/* advance the source pointer position */
    220 		(*s) += l+2;
    221 	} else {
    222 		/* single digit format */
    223 		char str[2];
    224 		str[0] = *q;
    225 		str[1] = '\0';
    226 
    227 		to = atoi(str);
    228 		if (to < 1) {
    229 			rfbLog("skipping invalid remap button \"%d\" for button"
    230 			    " %d from string \"%s\"\n",
    231 			    to, from, str);
    232 		} else {
    233 			rfbLog("remap button %d using \"%s\"\n", from, str);
    234 			rfbLog("   button: %d -> %d\n", from, to);
    235 			pointer_map[from][0].keysym  = NoSymbol;
    236 			pointer_map[from][0].keycode = NoSymbol;
    237 			pointer_map[from][0].button = to;
    238 			pointer_map[from][0].end    = 0;
    239 			pointer_map[from][0].down   = 0;
    240 			pointer_map[from][0].up     = 0;
    241 		}
    242 		/* advance the source pointer position */
    243 		(*s)++;
    244 	}
    245 #endif	/* NO_X11 */
    246 }
    247 
    248 /*
    249  * process the -buttonmap string
    250  */
    251 void initialize_pointer_map(char *pointer_remap) {
    252 	unsigned char map[MAX_BUTTONS];
    253 	int i, k;
    254 	/*
    255 	 * This routine counts the number of pointer buttons on the X
    256 	 * server (to avoid problems, even crashes, if a client has more
    257 	 * buttons).  And also initializes any pointer button remapping
    258 	 * from -buttonmap option.
    259 	 */
    260 
    261 	if (!raw_fb_str) {
    262 #if NO_X11
    263 		num_buttons = 5;
    264 #else
    265 		X_LOCK;
    266 		num_buttons = XGetPointerMapping(dpy, map, MAX_BUTTONS);
    267 		X_UNLOCK;
    268 		rfbLog("The X server says there are %d mouse buttons.\n", num_buttons);
    269 #endif
    270 	} else {
    271 		num_buttons = 5;
    272 		rfbLog("Manually set num_buttons to: %d\n", num_buttons);
    273 	}
    274 
    275 	if (num_buttons < 0) {
    276 		num_buttons = 0;
    277 	}
    278 
    279 	/* FIXME: should use info in map[] */
    280 	for (i=1; i<= MAX_BUTTONS; i++) {
    281 		for (k=0; k < MAX_BUTTON_EVENTS; k++) {
    282 			pointer_map[i][k].end = 1;
    283 		}
    284 		pointer_map[i][0].keysym  = NoSymbol;
    285 		pointer_map[i][0].keycode = NoSymbol;
    286 		pointer_map[i][0].button = i;
    287 		pointer_map[i][0].end    = 0;
    288 		pointer_map[i][0].down   = 0;
    289 		pointer_map[i][0].up     = 0;
    290 	}
    291 
    292 	if (pointer_remap && *pointer_remap != '\0') {
    293 		/* -buttonmap, format is like: 12-21=2 */
    294 		char *p, *q, *remap = strdup(pointer_remap);
    295 		int n;
    296 
    297 		if ((p = strchr(remap, '=')) != NULL) {
    298 			/* undocumented max button number */
    299 			n = atoi(p+1);
    300 			*p = '\0';
    301 			if (n < num_buttons || num_buttons == 0) {
    302 				num_buttons = n;
    303 			} else {
    304 				rfbLog("warning: increasing number of mouse "
    305 				    "buttons from %d to %d\n", num_buttons, n);
    306 				num_buttons = n;
    307 			}
    308 		}
    309 		if ((q = strchr(remap, '-')) != NULL) {
    310 			/*
    311 			 * The '-' separates the 'from' and 'to' lists,
    312 			 * then it is kind of like tr(1).
    313 			 */
    314 			char str[2];
    315 			int from;
    316 
    317 			rfbLog("remapping pointer buttons using string:\n");
    318 			rfbLog("   \"%s\"\n", remap);
    319 
    320 			p = remap;
    321 			q++;
    322 			i = 0;
    323 			str[1] = '\0';
    324 			while (*p != '-') {
    325 				str[0] = *p;
    326 				from = atoi(str);
    327 				buttonparse(from, &q);
    328 				p++;
    329 			}
    330 		}
    331 		free(remap);
    332 	}
    333 }
    334 
    335 /*
    336  * Send a pointer position event to the X server.
    337  */
    338 void update_x11_pointer_position(int x, int y) {
    339 #if NO_X11
    340 	RAWFB_RET_VOID
    341 	if (!x || !y) {}
    342 	return;
    343 #else
    344 	int rc;
    345 
    346 	RAWFB_RET_VOID
    347 
    348 	X_LOCK;
    349 	if (!always_inject && cursor_x == x && cursor_y == y) {
    350 		;
    351 	} else if (use_xwarppointer) {
    352 		/*
    353 		 * off_x and off_y not needed with XWarpPointer since
    354 		 * window is used:
    355 		 */
    356 		XWarpPointer(dpy, None, window, 0, 0, 0, 0, x + coff_x,
    357 		    y + coff_y);
    358 	} else {
    359 		XTestFakeMotionEvent_wr(dpy, scr, x + off_x + coff_x,
    360 		    y + off_y + coff_y, CurrentTime);
    361 	}
    362 	X_UNLOCK;
    363 
    364 	if (cursor_x != x || cursor_y != y) {
    365 		last_pointer_motion_time = dnow();
    366 	}
    367 
    368 	cursor_x = x;
    369 	cursor_y = y;
    370 
    371 	/* record the x, y position for the rfb screen as well. */
    372 	cursor_position(x, y);
    373 
    374 	/* change the cursor shape if necessary */
    375 	rc = set_cursor(x, y, get_which_cursor());
    376 	cursor_changes += rc;
    377 
    378 	last_event = last_input = last_pointer_input = time(NULL);
    379 #endif	/* NO_X11 */
    380 }
    381 
    382 void do_button_mask_change(int mask, int button) {
    383 #if NO_X11
    384 	if (!mask || !button) {}
    385 	return;
    386 #else
    387 	int mb, k, i = button-1;
    388 
    389 	/*
    390 	 * this expands to any pointer_map button -> keystrokes
    391 	 * remappings.  Usually just k=0 and we send one button event.
    392 	 */
    393 	for (k=0; k < MAX_BUTTON_EVENTS; k++) {
    394 		int bmask = (mask & (1<<i));
    395 
    396 		if (pointer_map[i+1][k].end) {
    397 			break;
    398 		}
    399 
    400 		if (pointer_map[i+1][k].button) {
    401 			/* send button up or down */
    402 
    403 			mb = pointer_map[i+1][k].button;
    404 			if ((num_buttons && mb > num_buttons) || mb < 1) {
    405 				rfbLog("ignoring mouse button out of "
    406 				    "bounds: %d>%d mask: 0x%x -> 0x%x\n",
    407 				    mb, num_buttons, button_mask, mask);
    408 				continue;
    409 			}
    410 			if (debug_pointer) {
    411 				rfbLog("pointer(): sending button %d"
    412 				    " %s (event %d)\n", mb, bmask
    413 				    ? "down" : "up", k+1);
    414 			}
    415 			XTestFakeButtonEvent_wr(dpy, mb, (mask & (1<<i))
    416 			    ? True : False, CurrentTime);
    417 		} else {
    418 			/* send keysym up or down */
    419 			KeyCode key = pointer_map[i+1][k].keycode;
    420 			int up   = pointer_map[i+1][k].up;
    421 			int down = pointer_map[i+1][k].down;
    422 
    423 			if (! bmask) {
    424 				/* do not send keysym on button up */
    425 				continue;
    426 			}
    427 			if (debug_pointer && dpy) {
    428 				char *str = XKeysymToString(XKeycodeToKeysym(
    429                                     dpy, key, 0));
    430 				rfbLog("pointer(): sending button %d "
    431 				    "down as keycode 0x%x (event %d)\n",
    432 				    i+1, key, k+1);
    433 				rfbLog("           down=%d up=%d keysym: "
    434 				    "%s\n", down, up, str ? str : "null");
    435 			}
    436 			if (down) {
    437 				XTestFakeKeyEvent_wr(dpy, key, True,
    438 				    CurrentTime);
    439 			}
    440 			if (up) {
    441 				XTestFakeKeyEvent_wr(dpy, key, False,
    442 				    CurrentTime);
    443 			}
    444 		}
    445 	}
    446 #endif	/* NO_X11 */
    447 }
    448 
    449 /*
    450  * Send a pointer button event to the X server.
    451  */
    452 static void update_x11_pointer_mask(int mask) {
    453 #if NO_X11
    454 	last_event = last_input = last_pointer_input = time(NULL);
    455 
    456 	RAWFB_RET_VOID
    457 	if (!mask) {}
    458 	return;
    459 #else
    460 	int snapped = 0, xr_mouse = 1, i;
    461 	last_event = last_input = last_pointer_input = time(NULL);
    462 
    463 	RAWFB_RET_VOID
    464 
    465 	if (mask != button_mask) {
    466 		last_pointer_click_time = dnow();
    467 	}
    468 
    469 	if (nofb) {
    470 		xr_mouse = 0;
    471 	} else if (!strcmp(scroll_copyrect, "never")) {
    472 		xr_mouse = 0;
    473 	} else if (!strcmp(scroll_copyrect, "keys")) {
    474 		xr_mouse = 0;
    475 	} else if (skip_cr_when_scaling("scroll")) {
    476 		xr_mouse = 0;
    477 	} else if (xrecord_skip_button(mask, button_mask)) {
    478 		xr_mouse = 0;
    479 	}
    480 
    481 	if (mask && use_xrecord && ! xrecording && xr_mouse) {
    482 		static int px, py, x, y, w, h, got_wm_frame;
    483 		static XWindowAttributes attr;
    484 		Window frame = None, mwin = None;
    485 		int skip = 0;
    486 
    487 		if (!button_mask) {
    488 			X_LOCK;
    489 			if (get_wm_frame_pos(&px, &py, &x, &y, &w, &h,
    490 			    &frame, &mwin)) {
    491 				got_wm_frame = 1;
    492 if (debug_scroll > 1) fprintf(stderr, "wm_win: 0x%lx\n", mwin);
    493 				if (mwin != None) {
    494 					if (!valid_window(mwin, &attr, 1)) {
    495 						mwin = None;
    496 					}
    497 				}
    498 			} else {
    499 				got_wm_frame = 0;
    500 			}
    501 			X_UNLOCK;
    502 		}
    503 		if (got_wm_frame) {
    504 			if (wireframe && near_wm_edge(x, y, w, h, px, py)) {
    505 				/* step out of wireframe's way */
    506 				skip = 1;
    507 			} else {
    508 				int ok = 0;
    509 				int btn4 = (1<<3);
    510 				int btn5 = (1<<4);
    511 
    512 				if (near_scrollbar_edge(x, y, w, h, px, py)) {
    513 					ok = 1;
    514 				}
    515 				if (mask & (btn4|btn5)) {
    516 					/* scroll wheel mouse */
    517 					ok = 1;
    518 				}
    519 				if (mwin != None) {
    520 					/* skinny internal window */
    521 					int w = attr.width;
    522 					int h = attr.height;
    523 					if (h > 10 * w || w > 10 * h) {
    524 if (debug_scroll > 1) fprintf(stderr, "internal scrollbar: %dx%d\n", w, h);
    525 						ok = 1;
    526 					}
    527 				}
    528 				if (! ok) {
    529 					skip = 1;
    530 				}
    531 			}
    532 		}
    533 
    534 		if (! skip) {
    535 			xrecord_watch(1, SCR_MOUSE);
    536 			snapshot_stack_list(0, 0.50);
    537 			snapped = 1;
    538 			if (button_mask) {
    539 				xrecord_set_by_mouse = 1;
    540 			} else {
    541 				update_stack_list();
    542 				xrecord_set_by_mouse = 2;
    543 			}
    544 		}
    545 	}
    546 
    547 	if (mask && !button_mask) {
    548 		/* button down, snapshot the stacking list before flushing */
    549 		if (wireframe && !wireframe_in_progress &&
    550 		    strcmp(wireframe_copyrect, "never")) {
    551 			if (! snapped) {
    552 				snapshot_stack_list(0, 0.0);
    553 			}
    554 		}
    555 	}
    556 
    557 	X_LOCK;
    558 
    559 	/* look for buttons that have be clicked or released: */
    560 	for (i=0; i < MAX_BUTTONS; i++) {
    561 	    if ( (button_mask & (1<<i)) != (mask & (1<<i)) ) {
    562 		if (debug_pointer) {
    563 			rfbLog("pointer(): mask change: mask: 0x%x -> "
    564 			    "0x%x button: %d\n", button_mask, mask,i+1);
    565 		}
    566 		do_button_mask_change(mask, i+1);	/* button # is i+1 */
    567 	    }
    568 	}
    569 
    570 	X_UNLOCK;
    571 
    572 	/*
    573 	 * Remember the button state for next time and also for the
    574 	 * -nodragging case:
    575 	 */
    576 	button_mask_prev = button_mask;
    577 	button_mask = mask;
    578 #endif	/* NO_X11 */
    579 }
    580 
    581 /* for -pipeinput */
    582 
    583 
    584 static void pipe_pointer(int mask, int x, int y, rfbClientPtr client) {
    585 	int can_input = 0, uid = 0;
    586 	allowed_input_t input;
    587 	ClientData *cd = (ClientData *) client->clientData;
    588 	char hint[MAX_BUTTONS * 20];
    589 
    590 	if (pipeinput_int == PIPEINPUT_VID) {
    591 		v4l_pointer_command(mask, x, y, client);
    592 	} else if (pipeinput_int == PIPEINPUT_CONSOLE) {
    593 		console_pointer_command(mask, x, y, client);
    594 	} else if (pipeinput_int == PIPEINPUT_UINPUT) {
    595 		uinput_pointer_command(mask, x, y, client);
    596 	} else if (pipeinput_int == PIPEINPUT_MACOSX) {
    597 		macosx_pointer_command(mask, x, y, client);
    598 	} else if (pipeinput_int == PIPEINPUT_VNC) {
    599 		vnc_reflect_send_pointer(x, y, mask);
    600 	}
    601 	if (pipeinput_fh == NULL) {
    602 		return;
    603 	}
    604 
    605 	if (! view_only) {
    606 		get_allowed_input(client, &input);
    607 		if (input.motion || input.button) {
    608 			can_input = 1;	/* XXX distinguish later */
    609 		}
    610 	}
    611 
    612 	if (cd) {
    613 		uid = cd->uid;
    614 	}
    615 	if (! can_input) {
    616 		uid = -uid;
    617 	}
    618 
    619 	hint[0] = '\0';
    620 	if (mask == button_mask) {
    621 		strcat(hint, "None");
    622 	} else {
    623 		int i, old, newb, m = 1, cnt = 0;
    624 		for (i=0; i<MAX_BUTTONS; i++) {
    625 			char s[20];
    626 
    627 			old = button_mask & m;
    628 			newb = mask & m;
    629 			m = m << 1;
    630 
    631 			if (old == newb) {
    632 				continue;
    633 			}
    634 			if (hint[0] != '\0') {
    635 				strcat(hint, ",");
    636 			}
    637 			if (newb && ! old) {
    638 				sprintf(s, "ButtonPress-%d", i+1);
    639 				cnt++;
    640 			} else if (! newb && old)  {
    641 				sprintf(s, "ButtonRelease-%d", i+1);
    642 				cnt++;
    643 			}
    644 			strcat(hint, s);
    645 		}
    646 		if (! cnt) {
    647 			strcpy(hint, "None");
    648 		}
    649 	}
    650 
    651 	fprintf(pipeinput_fh, "Pointer %d %d %d %d %s\n", uid, x, y,
    652 	    mask, hint);
    653 	fflush(pipeinput_fh);
    654 	check_pipeinput();
    655 }
    656 
    657 /*
    658  * Actual callback from libvncserver when it gets a pointer event.
    659  * This may queue pointer events rather than sending them immediately
    660  * to the X server. (see update_x11_pointer*())
    661  */
    662 void pointer_event(int mask, int x, int y, rfbClientPtr client) {
    663 	allowed_input_t input;
    664 	int sent = 0, buffer_it = 0;
    665 	double now;
    666 
    667 	if (threads_drop_input) {
    668 		return;
    669 	}
    670 
    671 	if (mask >= 0) {
    672 		got_pointer_calls++;
    673 	}
    674 
    675 	if (debug_pointer && mask >= 0) {
    676 		static int show_motion = -1;
    677 		static double last_pointer = 0.0;
    678 		double tnow, dt;
    679 		static int last_x, last_y;
    680 		if (show_motion == -1) {
    681 			if (getenv("X11VNC_DB_NOMOTION")) {
    682 				show_motion = 0;
    683 			} else {
    684 				show_motion = 1;
    685 			}
    686 		}
    687 		dtime0(&tnow);
    688 		tnow -= x11vnc_start;
    689 		dt = tnow - last_pointer;
    690 		last_pointer = tnow;
    691 		if (show_motion) {
    692 			rfbLog("# pointer(mask: 0x%x, x:%4d, y:%4d) "
    693 			    "dx: %3d dy: %3d dt: %.4f t: %.4f\n", mask, x, y,
    694 			    x - last_x, y - last_y, dt, tnow);
    695 		}
    696 		last_x = x;
    697 		last_y = y;
    698 	}
    699 
    700 	if (unixpw_in_progress) {
    701 		return;
    702 	}
    703 
    704 	get_allowed_input(client, &input);
    705 
    706 	if (rotating) {
    707 		rotate_coords_inverse(x, y, &x, &y, -1, -1);
    708 	}
    709 
    710 	if (scaling) {
    711 		/* map from rfb size to X11 size: */
    712 		x = ((double) x / scaled_x) * dpy_x;
    713 		x = nfix(x, dpy_x);
    714 		y = ((double) y / scaled_y) * dpy_y;
    715 		y = nfix(y, dpy_y);
    716 	}
    717 
    718 	INPUT_LOCK;
    719 
    720 	if ((pipeinput_fh != NULL || pipeinput_int) && mask >= 0) {
    721 		pipe_pointer(mask, x, y, client);	/* MACOSX here. */
    722 		if (! pipeinput_tee) {
    723 			if (! view_only || raw_fb) {	/* raw_fb hack */
    724 				got_user_input++;
    725 				got_pointer_input++;
    726 				last_pointer_client = client;
    727 				last_pointer_time = dnow();
    728 				last_event = last_input = last_pointer_input = time(NULL);
    729 			}
    730 			if (input.motion) {
    731 				/* raw_fb hack track button state */
    732 				button_mask_prev = button_mask;
    733 				button_mask = mask;
    734 			}
    735 			if (!view_only && (input.motion || input.button)) {
    736 				last_rfb_ptr_injected = dnow();
    737 			}
    738 			INPUT_UNLOCK;
    739 			return;
    740 		}
    741 	}
    742 
    743 	if (view_only) {
    744 		INPUT_UNLOCK;
    745 		return;
    746 	}
    747 
    748 	now = dnow();
    749 
    750 	if (mask >= 0) {
    751 		/*
    752 		 * mask = -1 is a special case call from scan_for_updates()
    753 		 * to flush the event queue; there is no real pointer event.
    754 		 */
    755 		if (! input.motion && ! input.button) {
    756 			INPUT_UNLOCK;
    757 			return;
    758 		}
    759 
    760 		got_user_input++;
    761 		got_pointer_input++;
    762 		last_pointer_client = client;
    763 
    764 		last_pointer_time = now;
    765 		last_rfb_ptr_injected = dnow();
    766 
    767 		if (blackout_ptr && blackouts) {
    768 			int b, ok = 1;
    769 			/* see if it goes into the blacked out region */
    770 			for (b=0; b < blackouts; b++) {
    771 				if (x < blackr[b].x1 || x > blackr[b].x2) {
    772 					continue;
    773 				}
    774 				if (y < blackr[b].y1 || y > blackr[b].y2) {
    775 					continue;
    776 				}
    777 				/* x1 <= x <= x2 and y1 <= y <= y2 */
    778 				ok = 0;
    779 				break;
    780 			}
    781 			if (! ok) {
    782 				if (debug_pointer) {
    783 				    rfbLog("pointer(): blackout_ptr skipping "
    784 					"x=%d y=%d in rectangle %d,%d %d,%d\n", x, y,
    785 					blackr[b].x1, blackr[b].y1,
    786 					blackr[b].x2, blackr[b].y2);
    787 				}
    788 				INPUT_UNLOCK;
    789 				return;
    790 			}
    791 		}
    792 	}
    793 
    794 	/*
    795 	 * The following is hopefully an improvement wrt response during
    796 	 * pointer user input (window drags) for the threaded case.
    797 	 * See check_user_input() for the more complicated things we do
    798 	 * in the non-threaded case.
    799 	 */
    800 	if ((use_threads && pointer_mode != 1) || pointer_flush_delay > 0.0) {
    801 #		define NEV 32
    802 		/* storage for the event queue */
    803 		static int nevents = 0;
    804 		static int ev[NEV][3];
    805 		int i;
    806 		/* timer things */
    807 		static double dt = 0.0, tmr = 0.0, maxwait = 0.4;
    808 
    809 		if (pointer_flush_delay > 0.0) {
    810 			maxwait = pointer_flush_delay;
    811 		}
    812 		if (mask >= 0) {
    813 			if (fb_copy_in_progress || pointer_flush_delay > 0.0) {
    814 				buffer_it = 1;
    815 			}
    816 		}
    817 
    818 		POINTER_LOCK;
    819 
    820 		/*
    821 		 * If the framebuffer is being copied in another thread
    822 		 * (scan_for_updates()), we will queue up to 32 pointer
    823 		 * events for later.  The idea is by delaying these input
    824 		 * events, the screen is less likely to change during the
    825 		 * copying period, and so will give rise to less window
    826 		 * "tearing".
    827 		 *
    828 		 * Tearing is not completely eliminated because we do
    829 		 * not suspend work in the other libvncserver threads.
    830 		 * Maybe that is a possibility with a mutex...
    831 		 */
    832 		if (buffer_it) {
    833 			/*
    834 			 * mask = -1 is an all-clear signal from
    835 			 * scan_for_updates().
    836 			 *
    837 			 * dt is a timer in seconds; we only queue for so long.
    838 			 */
    839 			dt += dtime(&tmr);
    840 
    841 			if (nevents < NEV && dt < maxwait) {
    842 				i = nevents++;
    843 				ev[i][0] = mask;
    844 				ev[i][1] = x;
    845 				ev[i][2] = y;
    846 				if (! input.button) {
    847 					ev[i][0] = -1;
    848 				}
    849 				if (! input.motion) {
    850 					ev[i][1] = -1;
    851 					ev[i][2] = -1;
    852 				}
    853 				if (debug_pointer) {
    854 					rfbLog("pointer(): deferring event %d"
    855 					    " %.4f\n", i, tmr - x11vnc_start);
    856 				}
    857 				POINTER_UNLOCK;
    858 				INPUT_UNLOCK;
    859 				return;
    860 			}
    861 		}
    862 
    863 		/* time to send the queue */
    864 		for (i=0; i<nevents; i++) {
    865 			int sent = 0;
    866 			if (mask < 0 && client != NULL) {
    867 				/* hack to only push the latest event */
    868 				if (i < nevents - 1) {
    869 					if (debug_pointer) {
    870 						rfbLog("- skip deferred event:"
    871 						    " %d\n", i);
    872 					}
    873 					continue;
    874 				}
    875 			}
    876 			if (debug_pointer) {
    877 				rfbLog("pointer(): sending event %d %.4f\n",
    878 				    i+1, dnowx());
    879 			}
    880 			if (ev[i][1] >= 0) {
    881 				update_x11_pointer_position(ev[i][1], ev[i][2]);
    882 				sent = 1;
    883 			}
    884 			if (ev[i][0] >= 0) {
    885 				update_x11_pointer_mask(ev[i][0]);
    886 				sent = 1;
    887 			}
    888 
    889 			if (sent) {
    890 				pointer_queued_sent++;
    891 			}
    892 		}
    893 		if (nevents && dt > maxwait) {
    894 		    if (dpy) {	/* raw_fb hack */
    895 			if (mask < 0) {
    896 				if (debug_pointer) {
    897 					rfbLog("pointer(): calling XFlush "
    898 					    "%.4f\n", dnowx());
    899 				}
    900 				X_LOCK;
    901 				XFlush_wr(dpy);
    902 				X_UNLOCK;
    903 			}
    904 		    }
    905 		}
    906 		nevents = 0;	/* reset everything */
    907 		dt = 0.0;
    908 		dtime0(&tmr);
    909 
    910 		POINTER_UNLOCK;
    911 	}
    912 	if (mask < 0) {		/* -1 just means flush the event queue */
    913 		if (debug_pointer) {
    914 			rfbLog("pointer(): flush only.  %.4f\n",
    915 			    dnowx());
    916 		}
    917 		INPUT_UNLOCK;
    918 		return;
    919 	}
    920 
    921 	/* update the X display with the event: */
    922 	if (input.motion) {
    923 		update_x11_pointer_position(x, y);
    924 		sent = 1;
    925 	}
    926 	if (input.button) {
    927 		if (mask != button_mask) {
    928 			button_change_x = cursor_x;
    929 			button_change_y = cursor_y;
    930 		}
    931 		update_x11_pointer_mask(mask);
    932 		sent = 1;
    933 	}
    934 
    935 	if (! dpy) {
    936 		;
    937 	} else if (nofb && sent) {
    938 		/*
    939 		 * nofb is for, e.g. Win2VNC, where fastest pointer
    940 		 * updates are desired.
    941 		 */
    942 		X_LOCK;
    943 		XFlush_wr(dpy);
    944 		X_UNLOCK;
    945 	} else if (buffer_it) {
    946 		if (debug_pointer) {
    947 			rfbLog("pointer(): calling XFlush+"
    948 			    "%.4f\n", dnowx());
    949 		}
    950 		X_LOCK;
    951 		XFlush_wr(dpy);
    952 		X_UNLOCK;
    953 	}
    954 	INPUT_UNLOCK;
    955 }
    956 
    957 void initialize_pipeinput(void) {
    958 	char *p = NULL;
    959 
    960 	if (pipeinput_fh != NULL) {
    961 		rfbLog("closing pipeinput stream: %p\n", pipeinput_fh);
    962 		pclose(pipeinput_fh);
    963 		pipeinput_fh = NULL;
    964 	}
    965 
    966 	pipeinput_tee = 0;
    967 	if (pipeinput_opts) {
    968 		free(pipeinput_opts);
    969 		pipeinput_opts = NULL;
    970 	}
    971 
    972 	if (! pipeinput_str) {
    973 		return;
    974 	}
    975 
    976 	/* look for options:  tee, reopen, ... */
    977 	if (strstr(pipeinput_str, "UINPUT") == pipeinput_str) {
    978 		;
    979 	} else {
    980 		p = strchr(pipeinput_str, ':');
    981 	}
    982 	if (p != NULL) {
    983 		char *str, *opt, *q;
    984 		int got = 0;
    985 		*p = '\0';
    986 		str = strdup(pipeinput_str);
    987 		opt = strdup(pipeinput_str);
    988 		*p = ':';
    989 		q = strtok(str, ",");
    990 		while (q) {
    991 			if (!strcmp(q, "key") || !strcmp(q, "keycodes")) {
    992 				got = 1;
    993 			}
    994 			if (!strcmp(q, "reopen")) {
    995 				got = 1;
    996 			}
    997 			if (!strcmp(q, "tee")) {
    998 				pipeinput_tee = 1;
    999 				got = 1;
   1000 			}
   1001 			q = strtok(NULL, ",");
   1002 		}
   1003 		if (got) {
   1004 			pipeinput_opts = opt;
   1005 		} else {
   1006 			free(opt);
   1007 		}
   1008 		free(str);
   1009 		p++;
   1010 	} else {
   1011 		p = pipeinput_str;
   1012 	}
   1013 if (0) fprintf(stderr, "initialize_pipeinput: %s -- %s\n", pipeinput_str, p);
   1014 
   1015 	if (!strcmp(p, "VID")) {
   1016 		pipeinput_int = PIPEINPUT_VID;
   1017 		return;
   1018 	} else if (strstr(p, "CONSOLE") == p) {
   1019 		int tty = 0, n;
   1020 		char dev[32];
   1021 		if (sscanf(p, "CONSOLE%d", &n) == 1) {
   1022 			tty = n;
   1023 		}
   1024 		sprintf(dev, "/dev/tty%d", tty);
   1025 		pipeinput_cons_fd = open(dev, O_WRONLY);
   1026 		if (pipeinput_cons_fd >= 0) {
   1027 			rfbLog("pipeinput: using linux console: %s\n", dev);
   1028 			if (pipeinput_cons_dev) {
   1029 				free(pipeinput_cons_dev);
   1030 			}
   1031 			pipeinput_cons_dev = strdup(dev);
   1032 			pipeinput_int = PIPEINPUT_CONSOLE;
   1033 		} else {
   1034 			rfbLog("pipeinput: could not open: %s\n", dev);
   1035 			rfbLogPerror("open");
   1036 			rfbLog("You may need to be root to open %s.\n", dev);
   1037 			rfbLog("\n");
   1038 		}
   1039 		return;
   1040 	} else if (strstr(p, "UINPUT") == p) {
   1041 		char *q = strchr(p, ':');
   1042 		if (q) {
   1043 			parse_uinput_str(q+1);
   1044 		}
   1045 		pipeinput_int = PIPEINPUT_UINPUT;
   1046 		initialize_uinput();
   1047 		return;
   1048 	} else if (strstr(p, "MACOSX") == p) {
   1049 		pipeinput_int = PIPEINPUT_MACOSX;
   1050 		return;
   1051 	} else if (strstr(p, "VNC") == p) {
   1052 		pipeinput_int = PIPEINPUT_VNC;
   1053 		return;
   1054 	}
   1055 
   1056 	set_child_info();
   1057 	/* pipeinput */
   1058 	if (no_external_cmds || !cmd_ok("pipeinput")) {
   1059 		rfbLogEnable(1);
   1060 		rfbLog("cannot run external commands in -nocmds mode:\n");
   1061 		rfbLog("   \"%s\"\n", p);
   1062 		rfbLog("   exiting.\n");
   1063 		clean_up_exit(1);
   1064 	}
   1065 	rfbLog("pipeinput: starting: \"%s\"...\n", p);
   1066 	close_exec_fds();
   1067 	pipeinput_fh = popen(p, "w");
   1068 
   1069 	if (! pipeinput_fh) {
   1070 		rfbLog("popen(\"%s\", \"w\") failed.\n", p);
   1071 		rfbLogPerror("popen");
   1072 		rfbLog("Disabling -pipeinput mode.\n");
   1073 		return;
   1074 	}
   1075 
   1076 	fprintf(pipeinput_fh, "%s",
   1077 "# \n"
   1078 "# Format of the -pipeinput stream:\n"
   1079 "# --------------------------------\n"
   1080 "#\n"
   1081 "# Lines like these beginning with '#' are to be ignored.\n"
   1082 "#\n"
   1083 "# Pointer events (mouse motion and button clicks) come in the form:\n"
   1084 "#\n"
   1085 "#\n"
   1086 "# Pointer <client#> <x> <y> <mask> <hint>\n"
   1087 "#\n"
   1088 "#\n"
   1089 "# The <client#> is a decimal integer uniquely identifying the client\n"
   1090 "# that generated the event.  If it is negative that means this event\n"
   1091 "# would have been discarded since the client was viewonly.\n"
   1092 "#\n"
   1093 "# <x> and <y> are decimal integers reflecting the position on the screen\n"
   1094 "# the event took place at.\n"
   1095 "#\n"
   1096 "# <mask> is the button mask indicating the button press state, as normal\n"
   1097 "# 0 means no buttons pressed, 1 means button 1 is down 3 (11) means buttons\n"
   1098 "# 1 and 2 are down, etc.\n"
   1099 "#\n"
   1100 "# <hint> is a string containing no spaces and may be ignored.\n"
   1101 "# It contains some interpretation about what has happened.\n"
   1102 "# It can be:\n"
   1103 "#\n"
   1104 "#	None		(nothing to report)\n"
   1105 "#	ButtonPress-N	(this event will cause button-N to be pressed) \n"
   1106 "#	ButtonRelease-N	(this event will cause button-N to be released) \n"
   1107 "#\n"
   1108 "# if two more more buttons change state in one event they are listed\n"
   1109 "# separated by commas.\n"
   1110 "#\n"
   1111 "# One might parse a Pointer line with:\n"
   1112 "#\n"
   1113 "# int client, x, y, mask; char hint[100];\n"
   1114 "# sscanf(line, \"Pointer %d %d %d %d %s\", &client, &x, &y, &mask, hint);\n"
   1115 "#\n"
   1116 "#\n"
   1117 "# Keysym events (keyboard presses and releases) come in the form:\n"
   1118 "#\n"
   1119 "#\n"
   1120 "# Keysym <client#> <down> <keysym#> <keysym-name> <hint>\n"
   1121 "#\n"
   1122 "#\n"
   1123 "# The <client#> is as with Pointer.\n"
   1124 "#\n"
   1125 "# <down> is a decimal either 1 or 0 indicating KeyPress or KeyRelease,\n"
   1126 "# respectively.\n"
   1127 "#\n"
   1128 "# <keysym#> is a decimal integer incidating the Keysym of the event.\n"
   1129 "#\n"
   1130 "# <keysym-name> is the corresponding Keysym name.\n"
   1131 "#\n"
   1132 "# See the file /usr/include/X11/keysymdef.h for the mappings.\n"
   1133 "# You basically remove the leading 'XK_' prefix from the macro name in\n"
   1134 "# that file to get the Keysym name.\n"
   1135 "#\n"
   1136 "# One might parse a Keysym line with:\n"
   1137 "#\n"
   1138 "# int client, down, keysym; char name[100], hint[100];\n"
   1139 "# sscanf(line, \"Keysym %d %d %d %s %s\", &client, &down, &keysym, name, hint);\n"
   1140 "#\n"
   1141 "# The <hint> value is currently just None, KeyPress, or KeyRelease.\n"
   1142 "#\n"
   1143 "# In the future <hint> will provide a hint for the sequence of KeyCodes\n"
   1144 "# (i.e. keyboard scancodes) that x11vnc would inject to an X display to\n"
   1145 "# simulate the Keysym.\n"
   1146 "#\n"
   1147 "# You see, some Keysyms will require more than one injected Keycode to\n"
   1148 "# generate the symbol.  E.g. the Keysym \"ampersand\" going down usually\n"
   1149 "# requires a Shift key going down, then the key with the \"&\" on it going\n"
   1150 "# down, and, perhaps, the Shift key going up (that is how x11vnc does it).\n"
   1151 "#\n"
   1152 "# The Keysym => Keycode(s) stuff gets pretty messy.  Hopefully the Keysym\n"
   1153 "# info will be enough for most purposes (having identical keyboards on\n"
   1154 "# both sides helps).\n"
   1155 "#\n"
   1156 "# Parsing example for perl:\n"
   1157 "#\n"
   1158 "# while (<>) {\n"
   1159 "#     chomp;\n"
   1160 "#     if (/^Pointer/) {\n"
   1161 "#         my ($p, $client, $x, $y, $mask, $hint) = split(' ', $_, 6);\n"
   1162 "#         do_pointer($client, $x, $y, $mask, $hint);\n"
   1163 "#     } elsif (/^Keysym/) {\n"
   1164 "#         my ($k, $client, $down, $keysym, $name, $hint) = split(' ', $_, 6);\n"
   1165 "#         do_keysym($client, $down, $keysym, $name, $hint);\n"
   1166 "#     }\n"
   1167 "# }\n"
   1168 "#\n"
   1169 "#\n"
   1170 "# Here comes your stream.  The following token will always indicate the\n"
   1171 "# end of this informational text:\n"
   1172 "# END_OF_TOP\n"
   1173 );
   1174 	fflush(pipeinput_fh);
   1175 	if (raw_fb_str) {
   1176 		/* the pipe program may actually create the fb */
   1177 		sleep(1);
   1178 	}
   1179 }
   1180 
   1181 int check_pipeinput(void) {
   1182 	if (! pipeinput_fh) {
   1183 		return 1;
   1184 	}
   1185 	if (ferror(pipeinput_fh)) {
   1186 		rfbLog("pipeinput pipe has ferror. %p\n", pipeinput_fh);
   1187 
   1188 		if (pipeinput_opts && strstr(pipeinput_opts, "reopen")) {
   1189 			rfbLog("restarting -pipeinput pipe...\n");
   1190 			initialize_pipeinput();
   1191 			if (pipeinput_fh) {
   1192 				return 1;
   1193 			} else {
   1194 				return 0;
   1195 			}
   1196 		} else {
   1197 			rfbLog("closing -pipeinput pipe...\n");
   1198 			pclose(pipeinput_fh);
   1199 			pipeinput_fh = NULL;
   1200 			return 0;
   1201 		}
   1202 	}
   1203 	return 1;
   1204 }
   1205 
   1206 
   1207