diff options
Diffstat (limited to 'x11vnc/pointer.c')
-rw-r--r-- | x11vnc/pointer.c | 1206 |
1 files changed, 0 insertions, 1206 deletions
diff --git a/x11vnc/pointer.c b/x11vnc/pointer.c deleted file mode 100644 index f2995c3..0000000 --- a/x11vnc/pointer.c +++ /dev/null @@ -1,1206 +0,0 @@ -/* - Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com> - All rights reserved. - -This file is part of x11vnc. - -x11vnc is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or (at -your option) any later version. - -x11vnc is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with x11vnc; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA -or see <http://www.gnu.org/licenses/>. - -In addition, as a special exception, Karl J. Runge -gives permission to link the code of its release of x11vnc with the -OpenSSL project's "OpenSSL" library (or with modified versions of it -that use the same license as the "OpenSSL" library), and distribute -the linked executables. You must obey the GNU General Public License -in all respects for all of the code used other than "OpenSSL". If you -modify this file, you may extend this exception to your version of the -file, but you are not obligated to do so. If you do not wish to do -so, delete this exception statement from your version. -*/ - -/* -- pointer.c -- */ - -#include "x11vnc.h" -#include "xwrappers.h" -#include "keyboard.h" -#include "xinerama.h" -#include "xrecord.h" -#include "win_utils.h" -#include "cursor.h" -#include "userinput.h" -#include "connections.h" -#include "cleanup.h" -#include "unixpw.h" -#include "v4l.h" -#include "linuxfb.h" -#include "uinput.h" -#include "scan.h" -#include "macosx.h" -#include "screen.h" - -int pointer_queued_sent = 0; - -void initialize_pointer_map(char *pointer_remap); -void do_button_mask_change(int mask, int button); -void pointer_event(int mask, int x, int y, rfbClientPtr client); -void initialize_pipeinput(void); -int check_pipeinput(void); -void update_x11_pointer_position(int x, int y); - - -static void buttonparse(int from, char **s); -static void update_x11_pointer_mask(int mask); -static void pipe_pointer(int mask, int x, int y, rfbClientPtr client); - -/* - * pointer event (motion and button click) handling routines. - */ -typedef struct ptrremap { - KeySym keysym; - KeyCode keycode; - int end; - int button; - int down; - int up; -} prtremap_t; - -#define MAX_BUTTON_EVENTS 50 -static prtremap_t pointer_map[MAX_BUTTONS+1][MAX_BUTTON_EVENTS]; - -/* - * For parsing the -buttonmap sections, e.g. "4" or ":Up+Up+Up:" - */ -static void buttonparse(int from, char **s) { -#if (0 && NO_X11) - if (!from || !s) {} - return; -#else - char *q; - int to, i; - int modisdown[256]; - - q = *s; - - for (i=0; i<256; i++) { - modisdown[i] = 0; - } - - if (*q == ':') { - /* :sym1+sym2+...+symN: format */ - int l = 0, n = 0; - char list[1000]; - char *t, *kp = q + 1; - KeyCode kcode; - - while (*(kp+l) != ':' && *(kp+l) != '\0') { - /* loop to the matching ':' */ - l++; - if (l >= 1000) { - rfbLog("buttonparse: keysym list too long: " - "%s\n", q); - break; - } - } - *(kp+l) = '\0'; - strncpy(list, kp, l); - list[l] = '\0'; - rfbLog("remap button %d using \"%s\"\n", from, list); - - /* loop over tokens separated by '+' */ - t = strtok(list, "+"); - while (t) { - KeySym ksym; - unsigned int ui; - int i; - if (n >= MAX_BUTTON_EVENTS - 20) { - rfbLog("buttonparse: too many button map " - "events: %s\n", list); - break; - } - if (sscanf(t, "0x%x", &ui) == 1) { - ksym = (KeySym) ui; /* hex value */ - } else { - X_LOCK; - ksym = XStringToKeysym(t); /* string value */ - X_UNLOCK; - } - if (ksym == NoSymbol) { - /* see if Button<N> "keysym" was used: */ - if (sscanf(t, "Button%d", &i) == 1) { - rfbLog(" event %d: button %d\n", - from, n+1, i); - if (i == 0) i = -1; /* bah */ - pointer_map[from][n].keysym = NoSymbol; - pointer_map[from][n].keycode = NoSymbol; - pointer_map[from][n].button = i; - pointer_map[from][n].end = 0; - pointer_map[from][n].down = 0; - pointer_map[from][n].up = 0; - } else { - rfbLog("buttonparse: ignoring unknown " - "keysym: %s\n", t); - n--; - } - } else if (dpy) { - /* - * XXX may not work with -modtweak or -xkb - */ - char *str; - X_LOCK; -#if NO_X11 - kcode = NoSymbol; -#else - kcode = XKeysymToKeycode(dpy, ksym); -#endif - - pointer_map[from][n].keysym = ksym; - pointer_map[from][n].keycode = kcode; - pointer_map[from][n].button = 0; - pointer_map[from][n].end = 0; - if (! ismodkey(ksym) ) { - /* do both down then up */ - pointer_map[from][n].down = 1; - pointer_map[from][n].up = 1; - } else { - if (modisdown[kcode]) { - pointer_map[from][n].down = 0; - pointer_map[from][n].up = 1; - modisdown[kcode] = 0; - } else { - pointer_map[from][n].down = 1; - pointer_map[from][n].up = 0; - modisdown[kcode] = 1; - } - } - str = XKeysymToString(ksym); - rfbLog(" event %d: keysym %s (0x%x) -> " - "keycode 0x%x down=%d up=%d\n", n+1, - str ? str : "null", ksym, kcode, - pointer_map[from][n].down, - pointer_map[from][n].up); - X_UNLOCK; - } - t = strtok(NULL, "+"); - n++; - } - - /* we must release any modifiers that are still down: */ - for (i=0; i<256; i++) { - kcode = (KeyCode) i; - if (n >= MAX_BUTTON_EVENTS) { - rfbLog("buttonparse: too many button map " - "events: %s\n", list); - break; - } - if (modisdown[kcode]) { - pointer_map[from][n].keysym = NoSymbol; - pointer_map[from][n].keycode = kcode; - pointer_map[from][n].button = 0; - pointer_map[from][n].end = 0; - pointer_map[from][n].down = 0; - pointer_map[from][n].up = 1; - modisdown[kcode] = 0; - n++; - } - } - - /* advance the source pointer position */ - (*s) += l+2; - } else { - /* single digit format */ - char str[2]; - str[0] = *q; - str[1] = '\0'; - - to = atoi(str); - if (to < 1) { - rfbLog("skipping invalid remap button \"%d\" for button" - " %d from string \"%s\"\n", - to, from, str); - } else { - rfbLog("remap button %d using \"%s\"\n", from, str); - rfbLog(" button: %d -> %d\n", from, to); - pointer_map[from][0].keysym = NoSymbol; - pointer_map[from][0].keycode = NoSymbol; - pointer_map[from][0].button = to; - pointer_map[from][0].end = 0; - pointer_map[from][0].down = 0; - pointer_map[from][0].up = 0; - } - /* advance the source pointer position */ - (*s)++; - } -#endif /* NO_X11 */ -} - -/* - * process the -buttonmap string - */ -void initialize_pointer_map(char *pointer_remap) { - unsigned char map[MAX_BUTTONS]; - int i, k; - /* - * This routine counts the number of pointer buttons on the X - * server (to avoid problems, even crashes, if a client has more - * buttons). And also initializes any pointer button remapping - * from -buttonmap option. - */ - - if (!raw_fb_str) { -#if NO_X11 - num_buttons = 5; -#else - X_LOCK; - num_buttons = XGetPointerMapping(dpy, map, MAX_BUTTONS); - X_UNLOCK; - rfbLog("The X server says there are %d mouse buttons.\n", num_buttons); -#endif - } else { - num_buttons = 5; - rfbLog("Manually set num_buttons to: %d\n", num_buttons); - } - - if (num_buttons < 0) { - num_buttons = 0; - } - - /* FIXME: should use info in map[] */ - for (i=1; i<= MAX_BUTTONS; i++) { - for (k=0; k < MAX_BUTTON_EVENTS; k++) { - pointer_map[i][k].end = 1; - } - pointer_map[i][0].keysym = NoSymbol; - pointer_map[i][0].keycode = NoSymbol; - pointer_map[i][0].button = i; - pointer_map[i][0].end = 0; - pointer_map[i][0].down = 0; - pointer_map[i][0].up = 0; - } - - if (pointer_remap && *pointer_remap != '\0') { - /* -buttonmap, format is like: 12-21=2 */ - char *p, *q, *remap = strdup(pointer_remap); - int n; - - if ((p = strchr(remap, '=')) != NULL) { - /* undocumented max button number */ - n = atoi(p+1); - *p = '\0'; - if (n < num_buttons || num_buttons == 0) { - num_buttons = n; - } else { - rfbLog("warning: increasing number of mouse " - "buttons from %d to %d\n", num_buttons, n); - num_buttons = n; - } - } - if ((q = strchr(remap, '-')) != NULL) { - /* - * The '-' separates the 'from' and 'to' lists, - * then it is kind of like tr(1). - */ - char str[2]; - int from; - - rfbLog("remapping pointer buttons using string:\n"); - rfbLog(" \"%s\"\n", remap); - - p = remap; - q++; - i = 0; - str[1] = '\0'; - while (*p != '-') { - str[0] = *p; - from = atoi(str); - buttonparse(from, &q); - p++; - } - } - free(remap); - } -} - -/* - * Send a pointer position event to the X server. - */ -void update_x11_pointer_position(int x, int y) { -#if NO_X11 - RAWFB_RET_VOID - if (!x || !y) {} - return; -#else - int rc; - - RAWFB_RET_VOID - - X_LOCK; - if (!always_inject && cursor_x == x && cursor_y == y) { - ; - } else if (use_xwarppointer) { - /* - * off_x and off_y not needed with XWarpPointer since - * window is used: - */ - XWarpPointer(dpy, None, window, 0, 0, 0, 0, x + coff_x, - y + coff_y); - } else { - XTestFakeMotionEvent_wr(dpy, scr, x + off_x + coff_x, - y + off_y + coff_y, CurrentTime); - } - X_UNLOCK; - - if (cursor_x != x || cursor_y != y) { - last_pointer_motion_time = dnow(); - } - - cursor_x = x; - cursor_y = y; - - /* record the x, y position for the rfb screen as well. */ - cursor_position(x, y); - - /* change the cursor shape if necessary */ - rc = set_cursor(x, y, get_which_cursor()); - cursor_changes += rc; - - last_event = last_input = last_pointer_input = time(NULL); -#endif /* NO_X11 */ -} - -void do_button_mask_change(int mask, int button) { -#if NO_X11 - if (!mask || !button) {} - return; -#else - int mb, k, i = button-1; - - /* - * this expands to any pointer_map button -> keystrokes - * remappings. Usually just k=0 and we send one button event. - */ - for (k=0; k < MAX_BUTTON_EVENTS; k++) { - int bmask = (mask & (1<<i)); - - if (pointer_map[i+1][k].end) { - break; - } - - if (pointer_map[i+1][k].button) { - /* send button up or down */ - - mb = pointer_map[i+1][k].button; - if ((num_buttons && mb > num_buttons) || mb < 1) { - rfbLog("ignoring mouse button out of " - "bounds: %d>%d mask: 0x%x -> 0x%x\n", - mb, num_buttons, button_mask, mask); - continue; - } - if (debug_pointer) { - rfbLog("pointer(): sending button %d" - " %s (event %d)\n", mb, bmask - ? "down" : "up", k+1); - } - XTestFakeButtonEvent_wr(dpy, mb, (mask & (1<<i)) - ? True : False, CurrentTime); - } else { - /* send keysym up or down */ - KeyCode key = pointer_map[i+1][k].keycode; - int up = pointer_map[i+1][k].up; - int down = pointer_map[i+1][k].down; - - if (! bmask) { - /* do not send keysym on button up */ - continue; - } - if (debug_pointer && dpy) { - char *str = XKeysymToString(XKeycodeToKeysym( - dpy, key, 0)); - rfbLog("pointer(): sending button %d " - "down as keycode 0x%x (event %d)\n", - i+1, key, k+1); - rfbLog(" down=%d up=%d keysym: " - "%s\n", down, up, str ? str : "null"); - } - if (down) { - XTestFakeKeyEvent_wr(dpy, key, True, - CurrentTime); - } - if (up) { - XTestFakeKeyEvent_wr(dpy, key, False, - CurrentTime); - } - } - } -#endif /* NO_X11 */ -} - -/* - * Send a pointer button event to the X server. - */ -static void update_x11_pointer_mask(int mask) { -#if NO_X11 - last_event = last_input = last_pointer_input = time(NULL); - - RAWFB_RET_VOID - if (!mask) {} - return; -#else - int snapped = 0, xr_mouse = 1, i; - last_event = last_input = last_pointer_input = time(NULL); - - RAWFB_RET_VOID - - if (mask != button_mask) { - last_pointer_click_time = dnow(); - } - - if (nofb) { - xr_mouse = 0; - } else if (!strcmp(scroll_copyrect, "never")) { - xr_mouse = 0; - } else if (!strcmp(scroll_copyrect, "keys")) { - xr_mouse = 0; - } else if (skip_cr_when_scaling("scroll")) { - xr_mouse = 0; - } else if (xrecord_skip_button(mask, button_mask)) { - xr_mouse = 0; - } - - if (mask && use_xrecord && ! xrecording && xr_mouse) { - static int px, py, x, y, w, h, got_wm_frame; - static XWindowAttributes attr; - Window frame = None, mwin = None; - int skip = 0; - - if (!button_mask) { - X_LOCK; - if (get_wm_frame_pos(&px, &py, &x, &y, &w, &h, - &frame, &mwin)) { - got_wm_frame = 1; -if (debug_scroll > 1) fprintf(stderr, "wm_win: 0x%lx\n", mwin); - if (mwin != None) { - if (!valid_window(mwin, &attr, 1)) { - mwin = None; - } - } - } else { - got_wm_frame = 0; - } - X_UNLOCK; - } - if (got_wm_frame) { - if (wireframe && near_wm_edge(x, y, w, h, px, py)) { - /* step out of wireframe's way */ - skip = 1; - } else { - int ok = 0; - int btn4 = (1<<3); - int btn5 = (1<<4); - - if (near_scrollbar_edge(x, y, w, h, px, py)) { - ok = 1; - } - if (mask & (btn4|btn5)) { - /* scroll wheel mouse */ - ok = 1; - } - if (mwin != None) { - /* skinny internal window */ - int w = attr.width; - int h = attr.height; - if (h > 10 * w || w > 10 * h) { -if (debug_scroll > 1) fprintf(stderr, "internal scrollbar: %dx%d\n", w, h); - ok = 1; - } - } - if (! ok) { - skip = 1; - } - } - } - - if (! skip) { - xrecord_watch(1, SCR_MOUSE); - snapshot_stack_list(0, 0.50); - snapped = 1; - if (button_mask) { - xrecord_set_by_mouse = 1; - } else { - update_stack_list(); - xrecord_set_by_mouse = 2; - } - } - } - - if (mask && !button_mask) { - /* button down, snapshot the stacking list before flushing */ - if (wireframe && !wireframe_in_progress && - strcmp(wireframe_copyrect, "never")) { - if (! snapped) { - snapshot_stack_list(0, 0.0); - } - } - } - - X_LOCK; - - /* look for buttons that have be clicked or released: */ - for (i=0; i < MAX_BUTTONS; i++) { - if ( (button_mask & (1<<i)) != (mask & (1<<i)) ) { - if (debug_pointer) { - rfbLog("pointer(): mask change: mask: 0x%x -> " - "0x%x button: %d\n", button_mask, mask,i+1); - } - do_button_mask_change(mask, i+1); /* button # is i+1 */ - } - } - - X_UNLOCK; - - /* - * Remember the button state for next time and also for the - * -nodragging case: - */ - button_mask_prev = button_mask; - button_mask = mask; -#endif /* NO_X11 */ -} - -/* for -pipeinput */ - - -static void pipe_pointer(int mask, int x, int y, rfbClientPtr client) { - int can_input = 0, uid = 0; - allowed_input_t input; - ClientData *cd = (ClientData *) client->clientData; - char hint[MAX_BUTTONS * 20]; - - if (pipeinput_int == PIPEINPUT_VID) { - v4l_pointer_command(mask, x, y, client); - } else if (pipeinput_int == PIPEINPUT_CONSOLE) { - console_pointer_command(mask, x, y, client); - } else if (pipeinput_int == PIPEINPUT_UINPUT) { - uinput_pointer_command(mask, x, y, client); - } else if (pipeinput_int == PIPEINPUT_MACOSX) { - macosx_pointer_command(mask, x, y, client); - } else if (pipeinput_int == PIPEINPUT_VNC) { - vnc_reflect_send_pointer(x, y, mask); - } - if (pipeinput_fh == NULL) { - return; - } - - if (! view_only) { - get_allowed_input(client, &input); - if (input.motion || input.button) { - can_input = 1; /* XXX distinguish later */ - } - } - - if (cd) { - uid = cd->uid; - } - if (! can_input) { - uid = -uid; - } - - hint[0] = '\0'; - if (mask == button_mask) { - strcat(hint, "None"); - } else { - int i, old, newb, m = 1, cnt = 0; - for (i=0; i<MAX_BUTTONS; i++) { - char s[20]; - - old = button_mask & m; - newb = mask & m; - m = m << 1; - - if (old == newb) { - continue; - } - if (hint[0] != '\0') { - strcat(hint, ","); - } - if (newb && ! old) { - sprintf(s, "ButtonPress-%d", i+1); - cnt++; - } else if (! newb && old) { - sprintf(s, "ButtonRelease-%d", i+1); - cnt++; - } - strcat(hint, s); - } - if (! cnt) { - strcpy(hint, "None"); - } - } - - fprintf(pipeinput_fh, "Pointer %d %d %d %d %s\n", uid, x, y, - mask, hint); - fflush(pipeinput_fh); - check_pipeinput(); -} - -/* - * Actual callback from libvncserver when it gets a pointer event. - * This may queue pointer events rather than sending them immediately - * to the X server. (see update_x11_pointer*()) - */ -void pointer_event(int mask, int x, int y, rfbClientPtr client) { - allowed_input_t input; - int sent = 0, buffer_it = 0; - double now; - - if (threads_drop_input) { - return; - } - - if (mask >= 0) { - got_pointer_calls++; - } - - 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 (unixpw_in_progress) { - return; - } - - get_allowed_input(client, &input); - - if (rotating) { - rotate_coords_inverse(x, y, &x, &y, -1, -1); - } - - 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); - } - - INPUT_LOCK; - - if ((pipeinput_fh != NULL || pipeinput_int) && mask >= 0) { - pipe_pointer(mask, x, y, client); /* MACOSX here. */ - if (! pipeinput_tee) { - if (! view_only || raw_fb) { /* raw_fb hack */ - got_user_input++; - got_pointer_input++; - last_pointer_client = client; - last_pointer_time = dnow(); - last_event = last_input = last_pointer_input = time(NULL); - } - if (input.motion) { - /* raw_fb hack track button state */ - button_mask_prev = button_mask; - button_mask = mask; - } - if (!view_only && (input.motion || input.button)) { - last_rfb_ptr_injected = dnow(); - } - INPUT_UNLOCK; - return; - } - } - - if (view_only) { - INPUT_UNLOCK; - 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. - */ - if (! input.motion && ! input.button) { - INPUT_UNLOCK; - return; - } - - got_user_input++; - got_pointer_input++; - last_pointer_client = client; - - last_pointer_time = now; - last_rfb_ptr_injected = dnow(); - - if (blackout_ptr && blackouts) { - int b, ok = 1; - /* see if it goes into the blacked out region */ - for (b=0; b < blackouts; b++) { - if (x < blackr[b].x1 || x > blackr[b].x2) { - continue; - } - if (y < blackr[b].y1 || y > blackr[b].y2) { - continue; - } - /* x1 <= x <= x2 and y1 <= y <= y2 */ - ok = 0; - break; - } - if (! ok) { - if (debug_pointer) { - rfbLog("pointer(): blackout_ptr skipping " - "x=%d y=%d in rectangle %d,%d %d,%d\n", x, y, - blackr[b].x1, blackr[b].y1, - blackr[b].x2, blackr[b].y2); - } - INPUT_UNLOCK; - return; - } - } - } - - /* - * 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 nevents = 0; - static int ev[NEV][3]; - int i; - /* timer things */ - static double dt = 0.0, tmr = 0.0, maxwait = 0.4; - - 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; - } - } - - POINTER_LOCK; - - /* - * 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; - } - if (debug_pointer) { - rfbLog("pointer(): deferring event %d" - " %.4f\n", i, tmr - x11vnc_start); - } - POINTER_UNLOCK; - INPUT_UNLOCK; - 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, dnowx()); - } - 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", dnowx()); - } - X_LOCK; - XFlush_wr(dpy); - X_UNLOCK; - } - } - } - nevents = 0; /* reset everything */ - dt = 0.0; - dtime0(&tmr); - - POINTER_UNLOCK; - } - if (mask < 0) { /* -1 just means flush the event queue */ - if (debug_pointer) { - rfbLog("pointer(): flush only. %.4f\n", - dnowx()); - } - INPUT_UNLOCK; - 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 (! dpy) { - ; - } else if (nofb && sent) { - /* - * nofb is for, e.g. Win2VNC, where fastest pointer - * updates are desired. - */ - X_LOCK; - XFlush_wr(dpy); - X_UNLOCK; - } else if (buffer_it) { - if (debug_pointer) { - rfbLog("pointer(): calling XFlush+" - "%.4f\n", dnowx()); - } - X_LOCK; - XFlush_wr(dpy); - X_UNLOCK; - } - INPUT_UNLOCK; -} - -void initialize_pipeinput(void) { - char *p = NULL; - - if (pipeinput_fh != NULL) { - rfbLog("closing pipeinput stream: %p\n", pipeinput_fh); - pclose(pipeinput_fh); - pipeinput_fh = NULL; - } - - pipeinput_tee = 0; - if (pipeinput_opts) { - free(pipeinput_opts); - pipeinput_opts = NULL; - } - - if (! pipeinput_str) { - return; - } - - /* look for options: tee, reopen, ... */ - if (strstr(pipeinput_str, "UINPUT") == pipeinput_str) { - ; - } else { - p = strchr(pipeinput_str, ':'); - } - if (p != NULL) { - char *str, *opt, *q; - int got = 0; - *p = '\0'; - str = strdup(pipeinput_str); - opt = strdup(pipeinput_str); - *p = ':'; - q = strtok(str, ","); - while (q) { - if (!strcmp(q, "key") || !strcmp(q, "keycodes")) { - got = 1; - } - if (!strcmp(q, "reopen")) { - got = 1; - } - if (!strcmp(q, "tee")) { - pipeinput_tee = 1; - got = 1; - } - q = strtok(NULL, ","); - } - if (got) { - pipeinput_opts = opt; - } else { - free(opt); - } - free(str); - p++; - } else { - p = pipeinput_str; - } -if (0) fprintf(stderr, "initialize_pipeinput: %s -- %s\n", pipeinput_str, p); - - if (!strcmp(p, "VID")) { - pipeinput_int = PIPEINPUT_VID; - return; - } else if (strstr(p, "CONSOLE") == p) { - int tty = 0, n; - char dev[32]; - if (sscanf(p, "CONSOLE%d", &n) == 1) { - tty = n; - } - sprintf(dev, "/dev/tty%d", tty); - pipeinput_cons_fd = open(dev, O_WRONLY); - if (pipeinput_cons_fd >= 0) { - rfbLog("pipeinput: using linux console: %s\n", dev); - if (pipeinput_cons_dev) { - free(pipeinput_cons_dev); - } - pipeinput_cons_dev = strdup(dev); - pipeinput_int = PIPEINPUT_CONSOLE; - } else { - rfbLog("pipeinput: could not open: %s\n", dev); - rfbLogPerror("open"); - rfbLog("You may need to be root to open %s.\n", dev); - rfbLog("\n"); - } - return; - } else if (strstr(p, "UINPUT") == p) { - char *q = strchr(p, ':'); - if (q) { - parse_uinput_str(q+1); - } - pipeinput_int = PIPEINPUT_UINPUT; - initialize_uinput(); - return; - } else if (strstr(p, "MACOSX") == p) { - pipeinput_int = PIPEINPUT_MACOSX; - return; - } else if (strstr(p, "VNC") == p) { - pipeinput_int = PIPEINPUT_VNC; - return; - } - - set_child_info(); - /* pipeinput */ - if (no_external_cmds || !cmd_ok("pipeinput")) { - rfbLogEnable(1); - rfbLog("cannot run external commands in -nocmds mode:\n"); - rfbLog(" \"%s\"\n", p); - rfbLog(" exiting.\n"); - clean_up_exit(1); - } - rfbLog("pipeinput: starting: \"%s\"...\n", p); - close_exec_fds(); - pipeinput_fh = popen(p, "w"); - - if (! pipeinput_fh) { - rfbLog("popen(\"%s\", \"w\") failed.\n", p); - rfbLogPerror("popen"); - rfbLog("Disabling -pipeinput mode.\n"); - return; - } - - fprintf(pipeinput_fh, "%s", -"# \n" -"# Format of the -pipeinput stream:\n" -"# --------------------------------\n" -"#\n" -"# Lines like these beginning with '#' are to be ignored.\n" -"#\n" -"# Pointer events (mouse motion and button clicks) come in the form:\n" -"#\n" -"#\n" -"# Pointer <client#> <x> <y> <mask> <hint>\n" -"#\n" -"#\n" -"# The <client#> is a decimal integer uniquely identifying the client\n" -"# that generated the event. If it is negative that means this event\n" -"# would have been discarded since the client was viewonly.\n" -"#\n" -"# <x> and <y> are decimal integers reflecting the position on the screen\n" -"# the event took place at.\n" -"#\n" -"# <mask> is the button mask indicating the button press state, as normal\n" -"# 0 means no buttons pressed, 1 means button 1 is down 3 (11) means buttons\n" -"# 1 and 2 are down, etc.\n" -"#\n" -"# <hint> is a string containing no spaces and may be ignored.\n" -"# It contains some interpretation about what has happened.\n" -"# It can be:\n" -"#\n" -"# None (nothing to report)\n" -"# ButtonPress-N (this event will cause button-N to be pressed) \n" -"# ButtonRelease-N (this event will cause button-N to be released) \n" -"#\n" -"# if two more more buttons change state in one event they are listed\n" -"# separated by commas.\n" -"#\n" -"# One might parse a Pointer line with:\n" -"#\n" -"# int client, x, y, mask; char hint[100];\n" -"# sscanf(line, \"Pointer %d %d %d %d %s\", &client, &x, &y, &mask, hint);\n" -"#\n" -"#\n" -"# Keysym events (keyboard presses and releases) come in the form:\n" -"#\n" -"#\n" -"# Keysym <client#> <down> <keysym#> <keysym-name> <hint>\n" -"#\n" -"#\n" -"# The <client#> is as with Pointer.\n" -"#\n" -"# <down> is a decimal either 1 or 0 indicating KeyPress or KeyRelease,\n" -"# respectively.\n" -"#\n" -"# <keysym#> is a decimal integer incidating the Keysym of the event.\n" -"#\n" -"# <keysym-name> is the corresponding Keysym name.\n" -"#\n" -"# See the file /usr/include/X11/keysymdef.h for the mappings.\n" -"# You basically remove the leading 'XK_' prefix from the macro name in\n" -"# that file to get the Keysym name.\n" -"#\n" -"# One might parse a Keysym line with:\n" -"#\n" -"# int client, down, keysym; char name[100], hint[100];\n" -"# sscanf(line, \"Keysym %d %d %d %s %s\", &client, &down, &keysym, name, hint);\n" -"#\n" -"# The <hint> value is currently just None, KeyPress, or KeyRelease.\n" -"#\n" -"# In the future <hint> will provide a hint for the sequence of KeyCodes\n" -"# (i.e. keyboard scancodes) that x11vnc would inject to an X display to\n" -"# simulate the Keysym.\n" -"#\n" -"# You see, some Keysyms will require more than one injected Keycode to\n" -"# generate the symbol. E.g. the Keysym \"ampersand\" going down usually\n" -"# requires a Shift key going down, then the key with the \"&\" on it going\n" -"# down, and, perhaps, the Shift key going up (that is how x11vnc does it).\n" -"#\n" -"# The Keysym => Keycode(s) stuff gets pretty messy. Hopefully the Keysym\n" -"# info will be enough for most purposes (having identical keyboards on\n" -"# both sides helps).\n" -"#\n" -"# Parsing example for perl:\n" -"#\n" -"# while (<>) {\n" -"# chomp;\n" -"# if (/^Pointer/) {\n" -"# my ($p, $client, $x, $y, $mask, $hint) = split(' ', $_, 6);\n" -"# do_pointer($client, $x, $y, $mask, $hint);\n" -"# } elsif (/^Keysym/) {\n" -"# my ($k, $client, $down, $keysym, $name, $hint) = split(' ', $_, 6);\n" -"# do_keysym($client, $down, $keysym, $name, $hint);\n" -"# }\n" -"# }\n" -"#\n" -"#\n" -"# Here comes your stream. The following token will always indicate the\n" -"# end of this informational text:\n" -"# END_OF_TOP\n" -); - fflush(pipeinput_fh); - if (raw_fb_str) { - /* the pipe program may actually create the fb */ - sleep(1); - } -} - -int check_pipeinput(void) { - if (! pipeinput_fh) { - return 1; - } - if (ferror(pipeinput_fh)) { - rfbLog("pipeinput pipe has ferror. %p\n", pipeinput_fh); - - if (pipeinput_opts && strstr(pipeinput_opts, "reopen")) { - rfbLog("restarting -pipeinput pipe...\n"); - initialize_pipeinput(); - if (pipeinput_fh) { - return 1; - } else { - return 0; - } - } else { - rfbLog("closing -pipeinput pipe...\n"); - pclose(pipeinput_fh); - pipeinput_fh = NULL; - return 0; - } - } - return 1; -} - - |