summaryrefslogtreecommitdiffstats
path: root/x11vnc/xevents.c
diff options
context:
space:
mode:
Diffstat (limited to 'x11vnc/xevents.c')
-rw-r--r--x11vnc/xevents.c2175
1 files changed, 0 insertions, 2175 deletions
diff --git a/x11vnc/xevents.c b/x11vnc/xevents.c
deleted file mode 100644
index 72b6515..0000000
--- a/x11vnc/xevents.c
+++ /dev/null
@@ -1,2175 +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.
-*/
-
-/* -- xevents.c -- */
-
-#include "x11vnc.h"
-#include "xwrappers.h"
-#include "xkb_bell.h"
-#include "xrandr.h"
-#include "xdamage.h"
-#include "xrecord.h"
-#include "selection.h"
-#include "keyboard.h"
-#include "cursor.h"
-#include "gui.h"
-#include "connections.h"
-#include "unixpw.h"
-#include "cleanup.h"
-#include "macosx.h"
-#include "screen.h"
-#include "pm.h"
-#include "pointer.h"
-#include "remote.h"
-#include "inet.h"
-
-/* XXX CHECK BEFORE RELEASE */
-int grab_buster = 0;
-int grab_kbd = 0;
-int grab_ptr = 0;
-int grab_always = 0;
-int ungrab_both = 0;
-int grab_local = 0;
-int sync_tod_delay = 20;
-
-void initialize_vnc_connect_prop(void);
-void initialize_x11vnc_remote_prop(void);
-void initialize_clipboard_atom(void);
-void spawn_grab_buster(void);
-void sync_tod_with_servertime(void);
-void check_keycode_state(void);
-void check_autorepeat(void);
-void set_prop_atom(Atom atom);
-void check_xevents(int reset);
-void xcut_receive(char *text, int len, rfbClientPtr cl);
-
-void kbd_release_all_keys(rfbClientPtr cl);
-void set_single_window(rfbClientPtr cl, int x, int y);
-void set_server_input(rfbClientPtr cl, int s);
-void set_text_chat(rfbClientPtr cl, int l, char *t);
-int get_keyboard_led_state_hook(rfbScreenInfoPtr s);
-int get_file_transfer_permitted(rfbClientPtr cl);
-void get_prop(char *str, int len, Atom prop, Window w);
-int guess_dm_gone(int t1, int t2);
-
-static void initialize_xevents(int reset);
-static void print_xevent_bases(void);
-static void bust_grab(int reset);
-static int process_watch(char *str, int parent, int db);
-static void grab_buster_watch(int parent, char *dstr);
-
-
-void initialize_vnc_connect_prop(void) {
- char *prop_str;
- vnc_connect_str[0] = '\0';
- RAWFB_RET_VOID
-#if !NO_X11
- prop_str = getenv("VNC_CONNECT");
- if (prop_str == NULL) {
- prop_str = "VNC_CONNECT";
- }
- vnc_connect_prop = XInternAtom(dpy, "VNC_CONNECT", False);
-#endif
-}
-
-void initialize_x11vnc_remote_prop(void) {
- char *prop_str;
- x11vnc_remote_str[0] = '\0';
- RAWFB_RET_VOID
-#if !NO_X11
- prop_str = getenv("X11VNC_REMOTE");
- if (prop_str == NULL) {
- prop_str = "X11VNC_REMOTE";
- }
- x11vnc_remote_prop = XInternAtom(dpy, prop_str, False);
-#endif
-}
-
-void initialize_clipboard_atom(void) {
- RAWFB_RET_VOID
-#if NO_X11
- return;
-#else
- clipboard_atom = XInternAtom(dpy, "CLIPBOARD", False);
- if (clipboard_atom == None) {
- if (! quiet) rfbLog("could not find atom CLIPBOARD\n");
- if (watch_clipboard) {
- watch_clipboard = 0;
- }
- if (set_clipboard) {
- set_clipboard = 0;
- }
- }
-#endif /* NO_X11 */
-}
-
-/*
- we observed these strings:
-
- 6 gdm_string: Gnome-power-manager
- 6 gdm_string: Gnome-session
- 6 gdm_string: Gnome-settings-daemon
- 6 gdm_string: Login Window
- 6 gdm_string: Notify-osd
- 6 gdm_string: Panel
- 12 gdm_string: Metacity
- 12 gdm_string: gnome-power-manager
- 12 gdm_string: gnome-session
- 12 gdm_string: gnome-settings-daemon
- 12 gdm_string: notify-osd
- 18 gdm_string: Gdm-simple-greeter
- 24 gdm_string: metacity
- 36 gdm_string: gdm-simple-greeter
-
- kdmgreet
- Kdmgreet
- */
-
-static int dm_string(char *str) {
- char *s = getenv("DEBUG_WM_RUNNING");
- if (str == NULL) {
- return 0;
- }
- if (str[0] == '\0') {
- return 0;
- }
- if (0) fprintf(stderr, "dm_string: %s\n", str);
- if (strstr(str, "gdm-") == str || strstr(str, "Gdm-") == str) {
- if (strstr(str, "-greeter") != NULL) {
- if (s) rfbLog("dm_string: %s\n", str);
- return 1;
- }
- }
- if (!strcmp(str, "kdmgreet") || !strcmp(str, "Kdmgreet")) {
- if (s) rfbLog("dm_string: %s\n", str);
- return 1;
- }
- return 0;
-}
-
-static int dm_still_running(void) {
-#if NO_X11
- return 0;
-#else
- Window r, parent;
- Window *winlist;
- unsigned int nc;
- int rc, i;
- static XClassHint *classhint = NULL;
- XErrorHandler old_handler;
- int saw_gdm_name = 0;
-
- /* some times a window can go away before we get to it */
- trapped_xerror = 0;
- old_handler = XSetErrorHandler(trap_xerror);
-
- if (! classhint) {
- classhint = XAllocClassHint();
- }
-
- /* we are xlocked. */
- rc = XQueryTree_wr(dpy, DefaultRootWindow(dpy), &r, &parent, &winlist, &nc);
- if (!rc || winlist == NULL || nc == 0) {
- nc = 0;
- }
- for (i=0; i < (int) nc; i++) {
- char *name = NULL;
- Window w = winlist[i];
- if (XFetchName(dpy, w, &name) && name != NULL) {
- saw_gdm_name += dm_string(name);
- XFree_wr(name);
- }
- classhint->res_name = NULL;
- classhint->res_class = NULL;
- if (XGetClassHint(dpy, w, classhint)) {
- name = classhint->res_name;
- if (name != NULL) {
- saw_gdm_name += dm_string(name);
- XFree_wr(name);
- }
- name = classhint->res_class;
- if (name != NULL) {
- saw_gdm_name += dm_string(name);
- XFree_wr(name);
- }
- }
- if (saw_gdm_name > 0) {
- break;
- }
- }
- if (winlist != NULL) {
- XFree_wr(winlist);
- }
-
- XSync(dpy, False);
- XSetErrorHandler(old_handler);
- trapped_xerror = 0;
-
- return saw_gdm_name;
-#endif
-}
-
-static int wm_running(void) {
- char *s = getenv("DEBUG_WM_RUNNING");
- int ret = 0;
- RAWFB_RET(0)
-#if NO_X11
- return 0;
-#else
- /*
- * Unfortunately with recent GDM (v2.28), they run gnome-session,
- * dbus-launch, and metacity for the Login greeter! So the simple
- * XInternAtom checks below no longer work.
- * We also see a similar thing with KDE.
- */
- if (dm_still_running()) {
- return 0;
- }
-
- /* we are xlocked. */
- if (XInternAtom(dpy, "_NET_SUPPORTED", True) != None) {
- if (s) rfbLog("wm is running (_NET_SUPPORTED).\n");
- ret++;
- }
- if (XInternAtom(dpy, "_WIN_PROTOCOLS", True) != None) {
- if (s) rfbLog("wm is running (_WIN_PROTOCOLS).\n");
- ret++;
- }
- if (XInternAtom(dpy, "_XROOTPMAP_ID", True) != None) {
- if (s) rfbLog("wm is running (_XROOTPMAP_ID).\n");
- ret++;
- }
- if (XInternAtom(dpy, "_MIT_PRIORITY_COLORS", True) != None) {
- if (s) rfbLog("wm is running (_MIT_PRIORITY_COLORS).\n");
- ret++;
- }
- if (!ret) {
- if (s) rfbLog("wm is not running.\n");
- return 0;
- } else {
- if (s) rfbLog("wm is running ret=%d.\n", ret);
- return 1;
- }
-#endif /* NO_X11 */
-
-}
-
-int guess_dm_gone(int t1, int t2) {
- int wait = t2;
- char *avoid = getenv("X11VNC_AVOID_WINDOWS");
- time_t tcheck = last_client;
-
- if (last_open_xdisplay > last_client) {
- /* better time for -display WAIT:... */
- tcheck = last_open_xdisplay;
- }
-
- if (avoid && !strcmp(avoid, "never")) {
- return 1;
- }
- if (!screen || !screen->clientHead) {
- return 0;
- }
- if (avoid) {
- int n = atoi(avoid);
- if (n > 1) {
- wait = n;
- } else {
- wait = 90;
- }
- } else {
- static time_t saw_wm = 0;
-
- wait = t2;
-
- X_LOCK;
- if (wm_running()) {
- if (saw_wm == 0) {
- saw_wm = time(NULL);
- } else if (time(NULL) <= saw_wm + 2) {
- /* try to wait a few seconds after transition */
- ;
- } else {
- wait = t1;
- }
- }
- X_UNLOCK;
- }
- if (getenv("DEBUG_WM_RUNNING")) {
- rfbLog("guess_dm_gone: wait=%d\n", wait);
- }
- /* we assume they've logged in OK after wait seconds... */
- if (time(NULL) <= tcheck + wait) {
- return 0;
- }
- return 1;
-}
-
-static void initialize_xevents(int reset) {
-#if NO_X11
- RAWFB_RET_VOID
- if (!reset) {}
- return;
-#else
- static int did_xselect_input = 0;
- static int did_xcreate_simple_window = 0;
- static int did_vnc_connect_prop = 0;
- static int did_x11vnc_remote_prop = 0;
- static int did_clipboard_atom = 0;
- static int did_xfixes = 0;
- static int did_xdamage = 0;
- static int did_xrandr = 0;
-
- RAWFB_RET_VOID
-
- if (reset) {
- did_xselect_input = 0;
- did_xcreate_simple_window = 0;
- did_vnc_connect_prop = 0;
- did_x11vnc_remote_prop = 0;
- did_clipboard_atom = 0;
- did_xfixes = 0;
- did_xdamage = 0;
- did_xrandr = 0;
- }
-
- if ((watch_selection || vnc_connect) && !did_xselect_input) {
- /*
- * register desired event(s) for notification.
- * PropertyChangeMask is for CUT_BUFFER0 changes.
- * XXX: does this cause a flood of other stuff?
- */
- X_LOCK;
- xselectinput_rootwin |= PropertyChangeMask;
- XSelectInput_wr(dpy, rootwin, xselectinput_rootwin);
-
- if (subwin && freeze_when_obscured) {
- XSelectInput_wr(dpy, subwin, VisibilityChangeMask);
- }
- X_UNLOCK;
- did_xselect_input = 1;
- }
- if (watch_selection && !did_xcreate_simple_window) {
- /* create fake window for our selection ownership, etc */
-
- /*
- * We try to delay creating selwin until we are past
- * any GDM, (or other KillInitClients=true) manager.
- */
- if (guess_dm_gone(8, 45)) {
- X_LOCK;
- selwin = XCreateSimpleWindow(dpy, rootwin, 3, 2, 1, 1, 0, 0, 0);
- X_UNLOCK;
- did_xcreate_simple_window = 1;
- if (! quiet) rfbLog("created selwin: 0x%lx\n", selwin);
- }
- }
-
- if ((xrandr || xrandr_maybe) && !did_xrandr) {
- initialize_xrandr();
- did_xrandr = 1;
- }
- if (vnc_connect && !did_vnc_connect_prop) {
- initialize_vnc_connect_prop();
- did_vnc_connect_prop = 1;
- }
- if (vnc_connect && !did_x11vnc_remote_prop) {
- initialize_x11vnc_remote_prop();
- did_x11vnc_remote_prop = 1;
- }
- if (run_gui_pid > 0) {
- kill(run_gui_pid, SIGUSR1);
- run_gui_pid = 0;
- }
- if (!did_clipboard_atom) {
- initialize_clipboard_atom();
- did_clipboard_atom = 1;
- }
- if (xfixes_present && use_xfixes && !did_xfixes) {
- /*
- * We try to delay creating initializing xfixes until
- * we are past the display manager, due to Xorg bug:
- * http://bugs.freedesktop.org/show_bug.cgi?id=18451
- */
- if (guess_dm_gone(8, 45)) {
- initialize_xfixes();
- did_xfixes = 1;
- if (! quiet) rfbLog("called initialize_xfixes()\n");
- }
- }
- if (xdamage_present && !did_xdamage) {
- initialize_xdamage();
- did_xdamage = 1;
- }
-#endif /* NO_X11 */
-}
-
-static void print_xevent_bases(void) {
- fprintf(stderr, "X event bases: xkb=%d, xtest=%d, xrandr=%d, "
- "xfixes=%d, xdamage=%d, xtrap=%d\n", xkb_base_event_type,
- xtest_base_event_type, xrandr_base_event_type,
- xfixes_base_event_type, xdamage_base_event_type,
- xtrap_base_event_type);
- fprintf(stderr, " MapNotify=%d, ClientMsg=%d PropNotify=%d "
- "SelNotify=%d, SelRequest=%d\n", MappingNotify, ClientMessage,
- PropertyNotify, SelectionNotify, SelectionRequest);
- fprintf(stderr, " SelClear=%d, Expose=%d\n", SelectionClear, Expose);
-}
-
-void get_prop(char *str, int len, Atom prop, Window w) {
- int i;
-#if !NO_X11
- Atom type;
- int format, slen, dlen;
- unsigned long nitems = 0, bytes_after = 0;
- unsigned char* data = NULL;
-#endif
-
- for (i=0; i<len; i++) {
- str[i] = '\0';
- }
- if (prop == None) {
- return;
- }
-
- RAWFB_RET_VOID
-
-#if NO_X11
- return;
-#else
-
- slen = 0;
- if (w == None) {
- w = DefaultRootWindow(dpy);
- }
-
- do {
- if (XGetWindowProperty(dpy, w,
- prop, nitems/4, len/16, False,
- AnyPropertyType, &type, &format, &nitems, &bytes_after,
- &data) == Success) {
-
- dlen = nitems * (format/8);
- if (slen + dlen > len) {
- /* too big */
- XFree_wr(data);
- break;
- }
- memcpy(str+slen, data, dlen);
- slen += dlen;
- str[slen] = '\0';
- XFree_wr(data);
- }
- } while (bytes_after > 0);
-#endif /* NO_X11 */
-}
-
-static void bust_grab(int reset) {
-#if NO_X11
- if (!reset) {}
- return;
-#else
- static int bust_count = 0;
- static time_t last_bust = 0;
- time_t now = time(NULL);
- KeyCode key;
- int button, x, y, nb;
-
- if (now > last_bust + 180) {
- bust_count = 0;
- }
- if (reset) {
- bust_count = 0;
- return;
- }
-
- x = 0;
- y = 0;
- button = 0;
- key = NoSymbol;
-
- nb = 8;
- if (bust_count >= 3 * nb) {
- fprintf(stderr, "too many bust_grab's %d for me\n", bust_count);
- exit(0);
- }
- if (bust_count % nb == 0) {
- button = 1;
- } else if (bust_count % nb == 1) {
- button = 1;
- } else if (bust_count % nb == 2) {
- key = XKeysymToKeycode(dpy, XK_Escape);
- } else if (bust_count % nb == 3) {
- button = 3;
- } else if (bust_count % nb == 4) {
- key = XKeysymToKeycode(dpy, XK_space);
- } else if (bust_count % nb == 5) {
- x = bust_count * 23;
- y = bust_count * 17;
- } else if (bust_count % nb == 5) {
- button = 2;
- } else if (bust_count % nb == 6) {
- key = XKeysymToKeycode(dpy, XK_a);
- }
-
- if (key == NoSymbol) {
- key = XKeysymToKeycode(dpy, XK_a);
- if (key == NoSymbol) {
- button = 1;
- }
- }
-
- bust_count++;
-
- if (button) {
- /* try button press+release */
- fprintf(stderr, "**bust_grab: button%d %.4f\n",
- button, dnowx());
- XTestFakeButtonEvent_wr(dpy, button, True, CurrentTime);
- XFlush_wr(dpy);
- usleep(50 * 1000);
- XTestFakeButtonEvent_wr(dpy, button, False, CurrentTime);
- } else if (x > 0) {
- /* try button motion*/
- int scr = DefaultScreen(dpy);
-
- fprintf(stderr, "**bust_grab: x=%d y=%d %.4f\n", x, y,
- dnowx());
- XTestFakeMotionEvent_wr(dpy, scr, x, y, CurrentTime);
- XFlush_wr(dpy);
- usleep(50 * 1000);
-
- /* followed by button press */
- button = 1;
- fprintf(stderr, "**bust_grab: button%d\n", button);
- XTestFakeButtonEvent_wr(dpy, button, True, CurrentTime);
- XFlush_wr(dpy);
- usleep(50 * 1000);
- XTestFakeButtonEvent_wr(dpy, button, False, CurrentTime);
- } else {
- /* try Escape or Space press+release */
- fprintf(stderr, "**bust_grab: keycode: %d %.4f\n",
- (int) key, dnowx());
- XTestFakeKeyEvent_wr(dpy, key, True, CurrentTime);
- XFlush_wr(dpy);
- usleep(50 * 1000);
- XTestFakeKeyEvent_wr(dpy, key, False, CurrentTime);
- }
- XFlush_wr(dpy);
- last_bust = time(NULL);
-#endif /* NO_X11 */
-}
-
-typedef struct _grabwatch {
- int pid;
- int tick;
- unsigned long time;
- time_t change;
-} grabwatch_t;
-#define GRABWATCH 16
-
-static int grab_buster_delay = 20;
-static pid_t grab_buster_pid = 0;
-
-static int grab_npids = 1;
-
-static int process_watch(char *str, int parent, int db) {
- int i, pid, ticker, npids;
- char diff[128];
- unsigned long xtime;
- static grabwatch_t watches[GRABWATCH];
- static int first = 1;
- time_t now = time(NULL);
- static time_t last_bust = 0;
- int too_long, problems = 0;
-
- if (first) {
- for (i=0; i < GRABWATCH; i++) {
- watches[i].pid = 0;
- watches[i].tick = 0;
- watches[i].time = 0;
- watches[i].change = 0;
- }
- first = 0;
- }
-
- /* record latest value of prop */
- if (str && *str != '\0') {
- if (sscanf(str, "%d/%d/%lu/%s", &pid, &ticker, &xtime, diff)
- == 4) {
- int got = -1, free = -1;
-
- if (db) fprintf(stderr, "grab_buster %d - %d - %lu - %s"
- "\n", pid, ticker, xtime, diff);
-
- if (pid == parent && !strcmp(diff, "QUIT")) {
- /* that's it. */
- return 0;
- }
- if (pid == 0 || ticker == 0 || xtime == 0) {
- /* bad prop read. */
- goto badtickerstr;
- }
- for (i=0; i < GRABWATCH; i++) {
- if (watches[i].pid == pid) {
- got = i;
- break;
- }
- if (free == -1 && watches[i].pid == 0) {
- free = i;
- }
- }
- if (got == -1) {
- if (free == -1) {
- /* bad news */;
- free = GRABWATCH - 1;
- }
- watches[free].pid = pid;
- watches[free].tick = ticker;
- watches[free].time = xtime;
- watches[free].change = now;
- if (db) fprintf(stderr, "grab_buster free slot: %d\n", free);
- } else {
- if (db) fprintf(stderr, "grab_buster got slot: %d\n", got);
- if (watches[got].tick != ticker) {
- watches[got].change = now;
- }
- if (watches[got].time != xtime) {
- watches[got].change = now;
- }
- watches[got].tick = ticker;
- watches[got].time = xtime;
- }
- } else {
- if (db) fprintf(stderr, "grab_buster bad prop str: %s\n", str);
- }
- }
-
- badtickerstr:
-
- too_long = grab_buster_delay;
- if (too_long < 3 * sync_tod_delay) {
- too_long = 3 * sync_tod_delay;
- }
-
- npids = 0;
- for (i=0; i < GRABWATCH; i++) {
- if (watches[i].pid) {
- npids++;
- }
- }
- grab_npids = npids;
- if (npids > 4) {
- npids = 4;
- }
-
- /* now check everyone we are tracking */
- for (i=0; i < GRABWATCH; i++) {
- int fac = 1;
- if (!watches[i].pid) {
- continue;
- }
- if (watches[i].change == 0) {
- watches[i].change = now; /* just to be sure */
- continue;
- }
-
- pid = watches[i].pid;
-
- if (pid != parent) {
- fac = 2;
- }
- if (npids > 0) {
- fac *= npids;
- }
-
- if (now > watches[i].change + fac*too_long) {
- int process_alive = 1;
-
- fprintf(stderr, "grab_buster: problem with pid: "
- "%d - %d/%d/%d\n", pid, (int) now,
- (int) watches[i].change, too_long);
-
- if (kill((pid_t) pid, 0) != 0) {
- if (1 || errno == ESRCH) {
- process_alive = 0;
- }
- }
-
- if (!process_alive) {
- watches[i].pid = 0;
- watches[i].tick = 0;
- watches[i].time = 0;
- watches[i].change = 0;
- fprintf(stderr, "grab_buster: pid gone: %d\n",
- pid);
- if (pid == parent) {
- /* that's it */
- return 0;
- }
- } else {
- int sleep = sync_tod_delay * 1000 * 1000;
-
- bust_grab(0);
- problems++;
- last_bust = now;
- usleep(1 * sleep);
- break;
- }
- }
- }
-
- if (!problems) {
- bust_grab(1);
- }
- return 1;
-}
-
-static void grab_buster_watch(int parent, char *dstr) {
-#if NO_X11
- RAWFB_RET_VOID
- if (!parent || !dstr) {}
- return;
-#else
- Atom ticker_atom = None;
- int sleep = sync_tod_delay * 921 * 1000;
- char propval[200];
- int ev, er, maj, min;
- int db = 0;
- char *ticker_str = "X11VNC_TICKER";
-
- RAWFB_RET_VOID
-
- if (grab_buster > 1) {
- db = 1;
- }
-
- /* overwrite original dpy, we let orig connection sit unused. */
- dpy = XOpenDisplay_wr(dstr);
- if (!dpy) {
- fprintf(stderr, "grab_buster_watch: could not reopen: %s\n",
- dstr);
- return;
- }
- rfbLogEnable(0);
-
- /* check for XTEST, etc, and then disable grabs for us */
- if (! XTestQueryExtension_wr(dpy, &ev, &er, &maj, &min)) {
- xtest_present = 0;
- } else {
- xtest_present = 1;
- }
- if (! XETrapQueryExtension_wr(dpy, &ev, &er, &maj)) {
- xtrap_present = 0;
- } else {
- xtrap_present = 1;
- }
-
- if (! xtest_present && ! xtrap_present) {
- fprintf(stderr, "grab_buster_watch: no grabserver "
- "protection on display: %s\n", dstr);
- return;
- }
- disable_grabserver(dpy, 0);
-
- usleep(3 * sleep);
-
- if (getenv("X11VNC_TICKER")) {
- ticker_str = getenv("X11VNC_TICKER");
- }
- ticker_atom = XInternAtom(dpy, ticker_str, False);
- if (! ticker_atom) {
- fprintf(stderr, "grab_buster_watch: no ticker atom\n");
- return;
- }
-
- while(1) {
- int slp = sleep;
- if (grab_npids > 1) {
- slp = slp / 8;
- }
- usleep(slp);
- usleep((int) (0.60 * rfac() * slp));
-
- if (kill((pid_t) parent, 0) != 0) {
- break;
- }
-
- get_prop(propval, 128, ticker_atom, None);
- if (db) fprintf(stderr, "got_prop: %s\n", propval);
-
- if (!process_watch(propval, parent, db)) {
- break;
- }
- }
-#endif /* NO_X11 */
-}
-
-void spawn_grab_buster(void) {
-#if LIBVNCSERVER_HAVE_FORK
- pid_t pid;
- int parent = (int) getpid();
- char *dstr = strdup(DisplayString(dpy));
-
- RAWFB_RET_VOID
-
- XCloseDisplay_wr(dpy);
- dpy = NULL;
-
- if ((pid = fork()) > 0) {
- grab_buster_pid = pid;
- if (! quiet) {
- rfbLog("grab_buster pid is: %d\n", (int) pid);
- }
- } else if (pid == -1) {
- fprintf(stderr, "spawn_grab_buster: could not fork\n");
- rfbLogPerror("fork");
- } else {
- signal(SIGHUP, SIG_DFL);
- signal(SIGINT, SIG_DFL);
- signal(SIGQUIT, SIG_DFL);
- signal(SIGTERM, SIG_DFL);
-
- grab_buster_watch(parent, dstr);
- exit(0);
- }
-
- dpy = XOpenDisplay_wr(dstr);
- if (!dpy) {
- rfbLog("failed to reopen display %s in spawn_grab_buster\n",
- dstr);
- exit(1);
- }
-#endif
-}
-
-void sync_tod_with_servertime(void) {
-#if NO_X11
- RAWFB_RET_VOID
- return;
-#else
- static Atom ticker_atom = None;
- XEvent xev;
- char diff[128];
- static int seq = 0;
- static unsigned long xserver_ticks = 1;
- int i, db = 0;
-
- RAWFB_RET_VOID
-
- if (atom_NET_ACTIVE_WINDOW == None) {
- atom_NET_ACTIVE_WINDOW = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", True);
- }
- if (atom_NET_CURRENT_DESKTOP == None) {
- atom_NET_CURRENT_DESKTOP = XInternAtom(dpy, "_NET_CURRENT_DESKTOP", True);
- }
- if (atom_NET_CLIENT_LIST_STACKING == None) {
- atom_NET_CLIENT_LIST_STACKING = XInternAtom(dpy, "_NET_CLIENT_LIST_STACKING", True);
- }
- if (atom_XROOTPMAP_ID == None) {
- atom_XROOTPMAP_ID = XInternAtom(dpy, "_XROOTPMAP_ID", True);
- }
-
- if (! ticker_atom) {
- char *ticker_str = "X11VNC_TICKER";
- if (getenv("X11VNC_TICKER")) {
- ticker_str = getenv("X11VNC_TICKER");
- }
- ticker_atom = XInternAtom(dpy, ticker_str, False);
- }
- if (! ticker_atom) {
- return;
- }
-
- XSync(dpy, False);
- while (XCheckTypedEvent(dpy, PropertyNotify, &xev)) {
- set_prop_atom(xev.xproperty.atom);
- }
-
- snprintf(diff, 128, "%d/%08d/%lu/%.6f", (int) getpid(), seq++,
- xserver_ticks, servertime_diff);
- XChangeProperty(dpy, rootwin, ticker_atom, XA_STRING, 8,
- PropModeReplace, (unsigned char *) diff, strlen(diff));
- XSync(dpy, False);
-
- for (i=0; i < 10; i++) {
- int k, got = 0;
-
- for (k=0; k < 5; k++) {
- while (XCheckTypedEvent(dpy, PropertyNotify, &xev)) {
- if (xev.xproperty.atom == ticker_atom) {
- double stime;
-
- xserver_ticks = xev.xproperty.time;
- stime = (double) xev.xproperty.time;
- stime = stime/1000.0;
- servertime_diff = dnow() - stime;
- if (db) rfbLog("set servertime_diff: "
- "%.6f\n", servertime_diff);
- got = 1;
- }
- }
- }
- if (got) {
- break;
- }
- usleep(1000);
- }
-#endif /* NO_X11 */
-}
-
-void check_keycode_state(void) {
- static time_t last_check = 0;
- int delay = 10, noinput = 3;
- time_t now = time(NULL);
-
- if (! client_count) {
- return;
- }
- if (unixpw_in_progress) return;
-
- RAWFB_RET_VOID
-
- /*
- * periodically update our model of the keycode_state[]
- * by correlating with the Xserver. wait for a pause in
- * keyboard input to be on the safe side. the idea here
- * is to remove stale keycode state, not to be perfectly
- * in sync with the Xserver at every instant of time.
- */
- if (now > last_check + delay && now > last_keyboard_input + noinput) {
- X_LOCK;
- init_track_keycode_state();
- X_UNLOCK;
- last_check = now;
- }
-}
-
-/*
- * To use the experimental -grablocal option configure like this:
- * env CPPFLAGS=-DENABLE_GRABLOCAL LDFLAGS=-lXss ./configure
- */
-#ifdef ENABLE_GRABLOCAL
-#include <X11/extensions/scrnsaver.h>
-
-void check_local_grab(void) {
- static double last_check = 0.0;
- double now;
-
- if (grab_local <= 0) {
- return;
- }
- if (! client_count) {
- return;
- }
- if (unixpw_in_progress) return;
-
- if (last_rfb_key_injected <= 0.0 && last_rfb_ptr_injected <= 0.0) {
- return;
- }
-
- RAWFB_RET_VOID
-
- now = dnow();
-
- if (now > last_check + 0.1) {
-#if !NO_X11
- int ret;
- double idle;
- XScreenSaverInfo info;
- static int save_viewonly = -1, local_is_idle = -1, db = -1;
-
- if (debug_keyboard) db = debug_keyboard;
- if (debug_pointer ) db = debug_pointer;
-
- if (db < 0) {
- if (getenv("LOCAL_GRAB_DEBUG")) {
- db = atoi(getenv("LOCAL_GRAB_DEBUG"));
- } else {
- db = 0;
- }
- }
-
- ret = XScreenSaverQueryInfo(dpy, RootWindowOfScreen(
- ScreenOfDisplay(dpy, 0)), &info);
-
- if (ret) {
- double tlatest_rfb = 0.0;
-
- idle = ((double) info.idle)/1000.0;
- now = dnow();
-
- if (last_rfb_key_injected > 0.0) {
- tlatest_rfb = last_rfb_key_injected;
- }
- if (last_rfb_ptr_injected > tlatest_rfb) {
- tlatest_rfb = last_rfb_ptr_injected;
- }
- if (db > 1) fprintf(stderr, "idle: %.4f latest: %.4f dt: %.4f\n", idle, now - tlatest_rfb, idle - (now - tlatest_rfb));
-
- if (now - tlatest_rfb <= idle + 0.005) {
- /* 0.005 is 5ms tolerance */
- } else if (idle < grab_local) {
- if (local_is_idle < 0 || local_is_idle) {
- save_viewonly = view_only;
- view_only = 1;
- if (db) {
- rfbLog("check_local_grab: set viewonly\n");
- }
- }
-
- local_is_idle = 0;
- } else {
- if (!local_is_idle && save_viewonly >= 0) {
- view_only = save_viewonly;
- if (db) {
- rfbLog("check_local_grab: restored viewonly; %d\n", view_only);
- }
- }
- local_is_idle = 1;
- }
- }
-#endif
- last_check = dnow();
- }
-}
-#endif
-
-void check_autorepeat(void) {
- static time_t last_check = 0;
- static int idle_timeout = -300, idle_reset = 0;
- time_t now = time(NULL);
- int autorepeat_is_on, autorepeat_initially_on;
-
- if (! no_autorepeat || ! client_count) {
- return;
- }
- if (now <= last_check + 1) {
- return;
- }
-
- if (unixpw_in_progress) return;
-
- if (idle_timeout < 0) {
- if (getenv("X11VNC_IDLE_TIMEOUT")) {
- idle_timeout = atoi(getenv("X11VNC_IDLE_TIMEOUT"));
- }
- if (idle_timeout < 0) {
- idle_timeout = -idle_timeout;
- }
- }
-
- last_check = now;
-
- autorepeat_is_on = get_autorepeat_state();
- autorepeat_initially_on = get_initial_autorepeat_state();
-
- if (view_only) {
- if (! autorepeat_is_on) {
- autorepeat(1, 1);
- }
- return;
- }
-
- if (now > last_keyboard_input + idle_timeout) {
- /* autorepeat should be on when idle */
- if (! autorepeat_is_on && autorepeat_initially_on) {
- static time_t last_msg = 0;
- static int cnt = 0;
- if (now > last_msg + idle_timeout && cnt++ < 10) {
- rfbLog("idle keyboard: turning X autorepeat"
- " back on.\n");
- last_msg = now;
- }
- autorepeat(1, 1);
- idle_reset = 1;
- }
- } else {
- if (idle_reset) {
- int i, state[256], didmsg = 0, pressed = 0;
- int mwt = 600, mmax = 20;
- static int msgcnt = 0;
- static double lastmsg = 0.0;
-
- for (i=0; i<256; i++) {
- state[i] = 0;
- }
- if (use_threads) {X_LOCK;}
- get_keystate(state);
- if (use_threads) {X_UNLOCK;}
-
- for (i=0; i<256; i++) {
- if (state[i] != 0) {
- /* better wait until all keys are up */
- pressed++;
- if (msgcnt < mmax || dnow() > lastmsg + mwt) {
- char *str = "unset";
-#if !NO_X11
- if (use_threads) {X_LOCK;}
- str = XKeysymToString(XKeycodeToKeysym(dpy, i, 0));
- if (use_threads) {X_UNLOCK;}
-#endif
- str = str ? str : "nosymbol";
- didmsg++;
- rfbLog("active keyboard: waiting until "
- "all keys are up. key_down=%d %s. "
- "If the key is inaccessible via keyboard, "
- "consider 'x11vnc -R clear_all'\n", i, str);
- }
- }
- }
- if (didmsg > 0) {
- msgcnt++;
- if (msgcnt == mmax) {
- rfbLog("active keyboard: last such "
- "message for %d secs.\n", mwt);
- }
- lastmsg = dnow();
- }
- if (pressed > 0) {
- return;
- }
- }
- if (idle_reset) {
- static time_t last_msg = 0;
- static int cnt = 0;
- if (now > last_msg + idle_timeout && cnt++ < 10) {
- rfbLog("active keyboard: turning X autorepeat"
- " off.\n");
- last_msg = now;
- }
- autorepeat(0, 1);
- idle_reset = 0;
-
- } else if (no_repeat_countdown && autorepeat_is_on) {
- int n = no_repeat_countdown - 1;
- if (n >= 0) {
- rfbLog("Battling with something for "
- "-norepeat!! (%d resets left)\n", n);
- } else {
- rfbLog("Battling with something for "
- "-norepeat!!\n");
- }
- if (no_repeat_countdown > 0) {
- no_repeat_countdown--;
- }
- autorepeat(1, 0);
- autorepeat(0, 0);
- }
- }
-}
-
-void set_prop_atom(Atom atom) {
- if (atom == None) return;
- if (atom == atom_NET_ACTIVE_WINDOW) got_NET_ACTIVE_WINDOW = dnow();
- if (atom == atom_NET_CURRENT_DESKTOP) got_NET_CURRENT_DESKTOP = dnow();
- if (atom == atom_NET_CLIENT_LIST_STACKING) got_NET_CLIENT_LIST_STACKING = dnow();
- if (atom == atom_XROOTPMAP_ID) got_XROOTPMAP_ID = dnow();
-}
-
-/*
- * This routine is periodically called to check for selection related
- * and other X11 events and respond to them as needed.
- */
-void check_xevents(int reset) {
-#if NO_X11
- RAWFB_RET_VOID
- if (!reset) {}
- return;
-#else
- XEvent xev;
- int tmp, have_clients = 0;
- static int sent_some_sel = 0;
- static time_t last_call = 0;
- static time_t last_bell = 0;
- static time_t last_init_check = 0;
- static time_t last_sync = 0;
- static time_t last_time_sync = 0;
- time_t now = time(NULL);
- static double last_request = 0.0;
- static double last_xrefresh = 0.0;
- XErrorHandler old_handler;
-
- if (unixpw_in_progress) return;
-
- RAWFB_RET_VOID
-
- if (now > last_init_check+1 || reset) {
- last_init_check = now;
- initialize_xevents(reset);
- if (reset) {
- return;
- }
- }
-
- if (screen && screen->clientHead) {
- have_clients = 1;
- }
-
- X_LOCK;
- /*
- * There is a bug where we have to wait before sending text to
- * the client... so instead of sending right away we wait a
- * the few seconds.
- */
-
- if (have_clients && watch_selection && !sent_some_sel
- && now > last_client + sel_waittime) {
- if (XGetSelectionOwner(dpy, XA_PRIMARY) == None) {
- cutbuffer_send();
- }
- sent_some_sel = 1;
- }
- if (! have_clients) {
- /*
- * If we don't have clients we can miss the X server
- * going away until a client connects.
- */
- static time_t last_X_ping = 0;
- if (now > last_X_ping + 5) {
- last_X_ping = now;
- XGetSelectionOwner(dpy, XA_PRIMARY);
- }
- }
-
- if (have_clients && xrefresh > 0.0 && dnow() > last_xrefresh + xrefresh) {
- XSetWindowAttributes swa;
- Visual visual;
- Window xrf;
- unsigned long mask;
-
- swa.override_redirect = True;
- swa.backing_store = NotUseful;
- swa.save_under = False;
- swa.background_pixmap = None;
- visual.visualid = CopyFromParent;
- mask = (CWOverrideRedirect|CWBackingStore|CWSaveUnder|CWBackPixmap);
-
- xrf = XCreateWindow(dpy, window, coff_x, coff_y, dpy_x, dpy_y, 0, CopyFromParent,
- InputOutput, &visual, mask, &swa);
- if (xrf != None) {
- if (0) fprintf(stderr, "XCreateWindow(%d, %d, %d, %d) 0x%lx\n", coff_x, coff_y, dpy_x, dpy_y, xrf);
- XMapWindow(dpy, xrf);
- XFlush_wr(dpy);
- XDestroyWindow(dpy, xrf);
- XFlush_wr(dpy);
- }
- last_xrefresh = dnow();
- }
-
- if (now > last_call+1) {
- /* we only check these once a second or so. */
- int n = 0;
-
- trapped_xerror = 0;
- old_handler = XSetErrorHandler(trap_xerror);
-
- while (XCheckTypedEvent(dpy, MappingNotify, &xev)) {
- XRefreshKeyboardMapping((XMappingEvent *) &xev);
- n++;
- }
- if (n && use_modifier_tweak) {
- X_UNLOCK;
- initialize_modtweak();
- X_LOCK;
- }
- if (xtrap_base_event_type) {
- int base = xtrap_base_event_type;
- while (XCheckTypedEvent(dpy, base, &xev)) {
- ;
- }
- }
- if (xtest_base_event_type) {
- int base = xtest_base_event_type;
- while (XCheckTypedEvent(dpy, base, &xev)) {
- ;
- }
- }
- /*
- * we can get ClientMessage from our XSendEvent() call in
- * selection_request().
- */
- while (XCheckTypedEvent(dpy, ClientMessage, &xev)) {
- ;
- }
-
- XSetErrorHandler(old_handler);
- trapped_xerror = 0;
- last_call = now;
- }
-
- if (freeze_when_obscured) {
- if (XCheckTypedEvent(dpy, VisibilityNotify, &xev)) {
- if (xev.type == VisibilityNotify && xev.xany.window == subwin) {
- int prev = subwin_obscured;
- if (xev.xvisibility.state == VisibilityUnobscured) {
- subwin_obscured = 0;
- } else if (xev.xvisibility.state == VisibilityPartiallyObscured) {
- subwin_obscured = 1;
- } else {
- subwin_obscured = 2;
- }
- rfbLog("subwin_obscured: %d -> %d\n", prev, subwin_obscured);
- }
- }
- }
-
- /* check for CUT_BUFFER0, VNC_CONNECT, X11VNC_REMOTE changes: */
- if (XCheckTypedEvent(dpy, PropertyNotify, &xev)) {
- int got_cutbuffer = 0;
- int got_vnc_connect = 0;
- int got_x11vnc_remote = 0;
- static int prop_dbg = -1;
-
- /* to avoid piling up between calls, read all PropertyNotify now */
- do {
- if (xev.type == PropertyNotify) {
- if (xev.xproperty.atom == XA_CUT_BUFFER0) {
- got_cutbuffer++;
- } else if (vnc_connect && vnc_connect_prop != None
- && xev.xproperty.atom == vnc_connect_prop) {
- got_vnc_connect++;
- } else if (vnc_connect && x11vnc_remote_prop != None
- && xev.xproperty.atom == x11vnc_remote_prop) {
- got_x11vnc_remote++;
- }
- set_prop_atom(xev.xproperty.atom);
- }
- } while (XCheckTypedEvent(dpy, PropertyNotify, &xev));
-
- if (prop_dbg < 0) {
- prop_dbg = 0;
- if (getenv("PROP_DBG")) {
- prop_dbg = 1;
- }
- }
-
- if (prop_dbg && (got_cutbuffer > 1 || got_vnc_connect > 1 || got_x11vnc_remote > 1)) {
- static double lastmsg = 0.0;
- static int count = 0;
- double now = dnow();
-
- if (1 && now > lastmsg + 300.0) {
- if (got_cutbuffer > 1) {
- rfbLog("check_xevents: warning: %d cutbuffer events since last check.\n", got_cutbuffer);
- }
- if (got_vnc_connect > 1) {
- rfbLog("check_xevents: warning: %d vnc_connect events since last check.\n", got_vnc_connect);
- }
- if (got_x11vnc_remote > 1) {
- rfbLog("check_xevents: warning: %d x11vnc_remote events since last check.\n", got_x11vnc_remote);
- }
- count++;
- if (count >= 3) {
- lastmsg = now;
- count = 0;
- }
- }
- }
-
- if (got_cutbuffer) {
- /*
- * Go retrieve CUT_BUFFER0 and send it.
- *
- * set_cutbuffer is a flag to try to avoid
- * processing our own cutbuffer changes.
- */
- if (have_clients && watch_selection && !set_cutbuffer) {
- cutbuffer_send();
- sent_some_sel = 1;
- }
- set_cutbuffer = 0;
- }
- if (got_vnc_connect) {
- /*
- * Go retrieve VNC_CONNECT string.
- */
- read_vnc_connect_prop(0);
- }
- if (got_x11vnc_remote) {
- /*
- * Go retrieve X11VNC_REMOTE string.
- */
- read_x11vnc_remote_prop(0);
- }
- }
-
- /* do this now that we have just cleared PropertyNotify */
- tmp = 0;
- if (rfac() < 0.6) {
- tmp = 1;
- }
- if (now > last_time_sync + sync_tod_delay + tmp) {
- sync_tod_with_servertime();
- last_time_sync = now;
- }
-
-#if LIBVNCSERVER_HAVE_LIBXRANDR
- if (xrandr || xrandr_maybe) {
- check_xrandr_event("check_xevents");
- }
-#endif
-#if LIBVNCSERVER_HAVE_LIBXFIXES
- if (xfixes_present && use_xfixes && xfixes_first_initialized && xfixes_base_event_type) {
- if (XCheckTypedEvent(dpy, xfixes_base_event_type +
- XFixesCursorNotify, &xev)) {
- got_xfixes_cursor_notify++;
- }
- }
-#endif
-
- /* check for our PRIMARY request notification: */
- if (watch_primary || watch_clipboard) {
- int doprimary = 1, doclipboard = 2, which, own = 0;
- double delay = 1.0;
- Atom atom;
- char *req;
-
- if (XCheckTypedEvent(dpy, SelectionNotify, &xev)) {
- if (xev.type == SelectionNotify &&
- xev.xselection.requestor == selwin &&
- xev.xselection.property != None &&
- xev.xselection.target == XA_STRING) {
- Atom s = xev.xselection.selection;
- if (s == XA_PRIMARY || s == clipboard_atom) {
- /* go retrieve it and check it */
- if (now > last_client + sel_waittime
- || sent_some_sel) {
- selection_send(&xev);
- }
- }
- }
- }
- /*
- * Every second or so, request PRIMARY or CLIPBOARD,
- * unless we already own it or there is no owner or we
- * have no clients.
- * TODO: even at this low rate we should look into
- * and performance problems in odds cases (large text,
- * modem, etc.)
- */
- which = 0;
- if (watch_primary && watch_clipboard && ! own_clipboard &&
- ! own_primary) {
- delay = 0.6;
- }
- if (dnow() > last_request + delay) {
- /*
- * It is not a good idea to do both at the same
- * time so we must choose one:
- */
- if (watch_primary && watch_clipboard) {
- static int count = 0;
- if (own_clipboard) {
- which = doprimary;
- } else if (own_primary) {
- which = doclipboard;
- } else if (count++ % 3 == 0) {
- which = doclipboard;
- } else {
- which = doprimary;
- }
- } else if (watch_primary) {
- which = doprimary;
- } else if (watch_clipboard) {
- which = doclipboard;
- }
- last_request = dnow();
- }
- atom = None;
- req = "none";
- if (which == doprimary) {
- own = own_primary;
- atom = XA_PRIMARY;
- req = "PRIMARY";
- } else if (which == doclipboard) {
- own = own_clipboard;
- atom = clipboard_atom;
- req = "CLIPBOARD";
- }
- if (which != 0 && ! own && have_clients &&
- XGetSelectionOwner(dpy, atom) != None && selwin != None) {
- XConvertSelection(dpy, atom, XA_STRING, XA_STRING,
- selwin, CurrentTime);
- if (debug_sel) {
- rfbLog("request %s\n", req);
- }
- }
- }
-
- if (own_primary || own_clipboard) {
- /* we own PRIMARY or CLIPBOARD, see if someone requested it: */
- trapped_xerror = 0;
- old_handler = XSetErrorHandler(trap_xerror);
-
- if (XCheckTypedEvent(dpy, SelectionRequest, &xev)) {
- if (own_primary && xev.type == SelectionRequest &&
- xev.xselectionrequest.selection == XA_PRIMARY) {
- selection_request(&xev, "PRIMARY");
- }
- if (own_clipboard && xev.type == SelectionRequest &&
- xev.xselectionrequest.selection == clipboard_atom) {
- selection_request(&xev, "CLIPBOARD");
- }
- }
-
- /* we own PRIMARY or CLIPBOARD, see if we no longer own it: */
- if (XCheckTypedEvent(dpy, SelectionClear, &xev)) {
- if (own_primary && xev.type == SelectionClear &&
- xev.xselectionclear.selection == XA_PRIMARY) {
- own_primary = 0;
- if (xcut_str_primary) {
- free(xcut_str_primary);
- xcut_str_primary = NULL;
- }
- if (debug_sel) {
- rfbLog("Released PRIMARY.\n");
- }
- }
- if (own_clipboard && xev.type == SelectionClear &&
- xev.xselectionclear.selection == clipboard_atom) {
- own_clipboard = 0;
- if (xcut_str_clipboard) {
- free(xcut_str_clipboard);
- xcut_str_clipboard = NULL;
- }
- if (debug_sel) {
- rfbLog("Released CLIPBOARD.\n");
- }
- }
- }
-
- XSetErrorHandler(old_handler);
- trapped_xerror = 0;
- }
-
- if (watch_bell || now > last_bell+1) {
- last_bell = now;
- check_bell_event();
- }
- if (tray_request != None) {
- static time_t last_tray_request = 0;
- if (now > last_tray_request + 2) {
- last_tray_request = now;
- if (tray_embed(tray_request, tray_unembed)) {
- tray_window = tray_request;
- tray_request = None;
- }
- }
- }
-
-#ifndef DEBUG_XEVENTS
-#define DEBUG_XEVENTS 1
-#endif
-#if DEBUG_XEVENTS
- if (debug_xevents) {
- static time_t last_check = 0;
- static time_t reminder = 0;
- static int freq = 0;
-
- if (! freq) {
- if (getenv("X11VNC_REMINDER_RATE")) {
- freq = atoi(getenv("X11VNC_REMINDER_RATE"));
- } else {
- freq = 300;
- }
- }
-
- if (now > last_check + 1) {
- int ev_type_max = 300, ev_size = 400;
- XEvent xevs[400];
- int i, tot = XEventsQueued(dpy, QueuedAlready);
-
- if (reminder == 0 || (tot && now > reminder + freq)) {
- print_xevent_bases();
- reminder = now;
- }
- last_check = now;
-
- if (tot) {
- fprintf(stderr, "Total events queued: %d\n",
- tot);
- }
- for (i=1; i<ev_type_max; i++) {
- int k, n = 0;
- while (XCheckTypedEvent(dpy, i, xevs+n)) {
- if (++n >= ev_size) {
- break;
- }
- }
- if (n) {
- fprintf(stderr, " %d%s events of type"
- " %d queued\n", n,
- (n >= ev_size) ? "+" : "", i);
- }
- for (k=n-1; k >= 0; k--) {
- XPutBackEvent(dpy, xevs+k);
- }
- }
- }
- }
-#endif
-
- if (now > last_sync + 1200) {
- /* kludge for any remaining event leaks */
- int bugout = use_xdamage ? 500 : 50;
- int qlen, i;
- if (last_sync != 0) {
- qlen = XEventsQueued(dpy, QueuedAlready);
- if (qlen >= bugout) {
- rfbLog("event leak: %d queued, "
- " calling XSync(dpy, True)\n", qlen);
- rfbLog(" for diagnostics run: 'x11vnc -R"
- " debug_xevents:1'\n");
- XSync(dpy, True);
- }
- }
- last_sync = now;
-
- /* clear these, we don't want any events on them */
- if (rdpy_ctrl) {
- qlen = XEventsQueued(rdpy_ctrl, QueuedAlready);
- for (i=0; i<qlen; i++) {
- XNextEvent(rdpy_ctrl, &xev);
- }
- }
- if (gdpy_ctrl) {
- qlen = XEventsQueued(gdpy_ctrl, QueuedAlready);
- for (i=0; i<qlen; i++) {
- XNextEvent(gdpy_ctrl, &xev);
- }
- }
- }
- X_UNLOCK;
-
-#endif /* NO_X11 */
-}
-
-extern int rawfb_vnc_reflect;
-/*
- * hook called when a VNC client sends us some "XCut" text (rfbClientCutText).
- */
-void xcut_receive(char *text, int len, rfbClientPtr cl) {
- allowed_input_t input;
-
- if (threads_drop_input) {
- return;
- }
-
- if (unixpw_in_progress) {
- rfbLog("xcut_receive: unixpw_in_progress, skipping.\n");
- return;
- }
-
- if (!watch_selection) {
- return;
- }
- if (view_only) {
- return;
- }
- if (text == NULL || len == 0) {
- return;
- }
- get_allowed_input(cl, &input);
- if (!input.clipboard) {
- return;
- }
- INPUT_LOCK;
-
- if (remote_prefix != NULL && strstr(text, remote_prefix) == text) {
- char *result, *rcmd = text + strlen(remote_prefix);
- char *tmp = (char *) calloc(len + 8, 1);
-
- if (strstr(rcmd, "cmd=") != rcmd && strstr(rcmd, "qry=") != rcmd) {
- strcat(tmp, "qry=");
- }
- strncat(tmp, rcmd, len - strlen(remote_prefix));
- rfbLog("remote_prefix command: '%s'\n", tmp);
-
- if (use_threads) {
- if (client_connect_file) {
- FILE *f = fopen(client_connect_file, "w");
- if (f) {
- fprintf(f, "%s\n", tmp);
- fclose(f);
- free(tmp);
- INPUT_UNLOCK;
- return;
- }
- }
- if (vnc_connect) {
- sprintf(x11vnc_remote_str, "%s", tmp);
- free(tmp);
- INPUT_UNLOCK;
- return;
- }
- }
- INPUT_UNLOCK;
-
-
- result = process_remote_cmd(tmp, 1);
- if (result == NULL ) {
- result = strdup("null");
- } else if (!strcmp(result, "")) {
- free(result);
- result = strdup("none");
- }
- rfbLog("remote_prefix result: '%s'\n", result);
-
- free(tmp);
- tmp = (char *) calloc(strlen(remote_prefix) + strlen(result) + 1, 1);
-
- strcat(tmp, remote_prefix);
- strcat(tmp, result);
- free(result);
-
- rfbSendServerCutText(screen, tmp, strlen(tmp));
- free(tmp);
-
- return;
- }
-
- if (! check_sel_direction("recv", "xcut_receive", text, len)) {
- INPUT_UNLOCK;
- return;
- }
-
-#ifdef MACOSX
- if (macosx_console) {
- macosx_set_sel(text, len);
- INPUT_UNLOCK;
- return;
- }
-#endif
-
- if (rawfb_vnc_reflect) {
- vnc_reflect_send_cuttext(text, len);
- INPUT_UNLOCK;
- return;
- }
-
- RAWFB_RET_VOID
-
-#if NO_X11
- INPUT_UNLOCK;
- return;
-#else
-
- X_LOCK;
-
- /* associate this text with PRIMARY (and SECONDARY...) */
- if (set_primary && ! own_primary && selwin != None) {
- own_primary = 1;
- /* we need to grab the PRIMARY selection */
- XSetSelectionOwner(dpy, XA_PRIMARY, selwin, CurrentTime);
- XFlush_wr(dpy);
- if (debug_sel) {
- rfbLog("Own PRIMARY.\n");
- }
- }
-
- if (set_clipboard && ! own_clipboard && clipboard_atom != None && selwin != None) {
- own_clipboard = 1;
- /* we need to grab the CLIPBOARD selection */
- XSetSelectionOwner(dpy, clipboard_atom, selwin, CurrentTime);
- XFlush_wr(dpy);
- if (debug_sel) {
- rfbLog("Own CLIPBOARD.\n");
- }
- }
-
- /* duplicate the text string for our own use. */
- if (set_primary) {
- if (xcut_str_primary != NULL) {
- free(xcut_str_primary);
- xcut_str_primary = NULL;
- }
- xcut_str_primary = (char *) malloc((size_t) (len+1));
- strncpy(xcut_str_primary, text, len);
- xcut_str_primary[len] = '\0'; /* make sure null terminated */
- if (debug_sel) {
- rfbLog("Set PRIMARY '%s'\n", xcut_str_primary);
- }
- }
- if (set_clipboard) {
- if (xcut_str_clipboard != NULL) {
- free(xcut_str_clipboard);
- xcut_str_clipboard = NULL;
- }
- xcut_str_clipboard = (char *) malloc((size_t) (len+1));
- strncpy(xcut_str_clipboard, text, len);
- xcut_str_clipboard[len] = '\0'; /* make sure null terminated */
- if (debug_sel) {
- rfbLog("Set CLIPBOARD '%s'\n", xcut_str_clipboard);
- }
- }
-
- /* copy this text to CUT_BUFFER0 as well: */
- XChangeProperty(dpy, rootwin, XA_CUT_BUFFER0, XA_STRING, 8,
- PropModeReplace, (unsigned char *) text, len);
- XFlush_wr(dpy);
-
- X_UNLOCK;
- INPUT_UNLOCK;
-
- set_cutbuffer = 1;
-#endif /* NO_X11 */
-}
-
-void kbd_release_all_keys(rfbClientPtr cl) {
- if (unixpw_in_progress) {
- rfbLog("kbd_release_all_keys: unixpw_in_progress, skipping.\n");
- return;
- }
- if (cl->viewOnly) {
- return;
- }
-
- RAWFB_RET_VOID
-
-#if NO_X11
- return;
-#else
- if (use_threads) {
- X_LOCK;
- }
-
- clear_keys();
- clear_modifiers(0);
-
- if (use_threads) {
- X_UNLOCK;
- }
-#endif
-}
-
-void set_single_window(rfbClientPtr cl, int x, int y) {
- int ok = 0;
- if (no_ultra_ext) {
- return;
- }
- if (unixpw_in_progress) {
- rfbLog("set_single_window: unixpw_in_progress, dropping client.\n");
- rfbCloseClient(cl);
- return;
- }
- if (cl->viewOnly) {
- return;
- }
-
- RAWFB_RET_VOID
-
-#if NO_X11
- return;
-#else
- if (x==1 && y==1) {
- if (subwin) {
- subwin = 0x0;
- ok = 1;
- }
- } else {
- Window r, c;
- int rootx, rooty, wx, wy;
- unsigned int mask;
-
- update_x11_pointer_position(x, y);
- XSync(dpy, False);
-
- if (XQueryPointer_wr(dpy, rootwin, &r, &c, &rootx, &rooty,
- &wx, &wy, &mask)) {
- if (c != None) {
- subwin = c;
- ok = 1;
- }
- }
- }
-
- if (ok) {
- check_black_fb();
- do_new_fb(1);
- }
-#endif
-
-}
-void set_server_input(rfbClientPtr cl, int grab) {
- if (no_ultra_ext) {
- return;
- }
- if (unixpw_in_progress) {
- rfbLog("set_server_input: unixpw_in_progress, dropping client.\n");
- rfbCloseClient(cl);
- return;
- }
- if (cl->viewOnly) {
- return;
- }
-
- RAWFB_RET_VOID
-
-#if NO_X11
- return;
-#else
- if (grab) {
- if (!no_ultra_dpms) {
- set_dpms_mode("enable");
- set_dpms_mode("off");
- force_dpms = 1;
- }
-
- process_remote_cmd("cmd=grabkbd", 0);
- process_remote_cmd("cmd=grabptr", 0);
-
- } else {
- process_remote_cmd("cmd=nograbkbd", 0);
- process_remote_cmd("cmd=nograbptr", 0);
-
- if (!no_ultra_dpms) {
- force_dpms = 0;
- }
- }
-#endif
-}
-
-static int wsock_timeout_sock = -1;
-
-static void wsock_timeout (int sig) {
- rfbLog("sig: %d, wsock_timeout.\n", sig);
- if (wsock_timeout_sock >= 0) {
- close(wsock_timeout_sock);
- wsock_timeout_sock = -1;
- }
-}
-
-static void try_local_chat_window(void) {
- int i, port, lsock;
- char cmd[100];
- struct sockaddr_in addr;
- pid_t pid = -1;
-#ifdef __hpux
- int addrlen = sizeof(addr);
-#else
- socklen_t addrlen = sizeof(addr);
-#endif
-
- for (i = 0; i < 90; i++) {
- /* find an open port */
- port = 7300 + i;
- /* XXX ::1 fallback */
- lsock = listen_tcp(port, htonl(INADDR_LOOPBACK), 0);
- if (lsock >= 0) {
- break;
- }
- port = 0;
- }
-
- if (port == 0) {
- return;
- }
-
- /* have ssvncvncviewer connect back to us (n.b. sockpair fails) */
-
- sprintf(cmd, "ssvnc -cmd VNC://localhost:%d -chatonly", port);
-
-#if LIBVNCSERVER_HAVE_FORK
- pid = fork();
-#endif
-
- if (pid == -1) {
- perror("fork");
- return;
- } else if (pid == 0) {
- char *args[4];
- int d;
- args[0] = "/bin/sh";
- args[1] = "-c";
- /* "ssvnc -cmd VNC://fd=0 -chatonly"; not working */
- args[2] = cmd;
- args[3] = NULL;
-
- set_env("VNCVIEWER_PASSWORD", "moo");
-#if !NO_X11
- if (dpy != NULL) {
- set_env("DISPLAY", DisplayString(dpy));
- }
-#endif
- for (d = 3; d < 256; d++) {
- close(d);
- }
-
- execvp(args[0], args);
- perror("exec");
- exit(1);
- } else {
- int i, sock = -1;
- rfbNewClientHookPtr new_save;
-
- signal(SIGALRM, wsock_timeout);
- wsock_timeout_sock = lsock;
-
- alarm(10);
- sock = accept(lsock, (struct sockaddr *)&addr, &addrlen);
- alarm(0);
-
- signal(SIGALRM, SIG_DFL);
- close(lsock);
-
- if (sock < 0) {
- return;
- }
-
- /* mutex */
- new_save = screen->newClientHook;
- screen->newClientHook = new_client_chat_helper;
-
- chat_window_client = create_new_client(sock, 1);
-
- screen->newClientHook = new_save;
-
- if (chat_window_client != NULL) {
- rfbPasswordCheckProcPtr pwchk_save = screen->passwordCheck;
- rfbBool save_shared1 = screen->alwaysShared;
- rfbBool save_shared2 = screen->neverShared;
-
- screen->alwaysShared = TRUE;
- screen->neverShared = FALSE;
-
- screen->passwordCheck = password_check_chat_helper;
- for (i=0; i<30; i++) {
- rfbPE(-1);
- if (!chat_window_client) {
- break;
- }
- if (chat_window_client->state == RFB_NORMAL) {
- break;
- }
- }
-
- screen->passwordCheck = pwchk_save;
- screen->alwaysShared = save_shared1;
- screen->neverShared = save_shared2;
- }
- }
-}
-
-void set_text_chat(rfbClientPtr cl, int len, char *txt) {
- int dochat = 1;
- rfbClientIteratorPtr iter;
- rfbClientPtr cl2;
- unsigned int ulen = (unsigned int) len;
-
- if (no_ultra_ext || ! dochat) {
- return;
- }
-
- if (unixpw_in_progress) {
- rfbLog("set_text_chat: unixpw_in_progress, dropping client.\n");
- rfbCloseClient(cl);
- return;
- }
-#if LIBVNCSERVER_HAS_TEXTCHAT
-
- if (chat_window && chat_window_client == NULL && ulen == rfbTextChatOpen) {
- try_local_chat_window();
- }
-
- saw_ultra_chat = 1;
-
- iter = rfbGetClientIterator(screen);
- while( (cl2 = rfbClientIteratorNext(iter)) ) {
- unsigned int ulen = (unsigned int) len;
- if (cl2 == cl) {
- continue;
- }
- if (cl2->state != RFB_NORMAL) {
- continue;
- }
-
- SEND_LOCK(cl2);
-
- if (ulen == rfbTextChatOpen) {
- rfbSendTextChatMessage(cl2, rfbTextChatOpen, "");
- } else if (ulen == rfbTextChatClose) {
- rfbSendTextChatMessage(cl2, rfbTextChatClose, "");
- /* not clear what is going on WRT close and finished... */
- rfbSendTextChatMessage(cl2, rfbTextChatFinished, "");
- } else if (ulen == rfbTextChatFinished) {
- rfbSendTextChatMessage(cl2, rfbTextChatFinished, "");
- } else if (len <= rfbTextMaxSize) {
- rfbSendTextChatMessage(cl2, len, txt);
- }
-
- SEND_UNLOCK(cl2);
- }
- rfbReleaseClientIterator(iter);
-
- if (ulen == rfbTextChatClose && cl != NULL) {
- /* not clear what is going on WRT close and finished... */
- SEND_LOCK(cl);
- rfbSendTextChatMessage(cl, rfbTextChatFinished, "");
- SEND_UNLOCK(cl);
- }
-#endif
-}
-
-int get_keyboard_led_state_hook(rfbScreenInfoPtr s) {
- if (s) {}
- if (unixpw_in_progress) {
- rfbLog("get_keyboard_led_state_hook: unixpw_in_progress, skipping.\n");
- return 0;
- }
- return 0;
-}
-int get_file_transfer_permitted(rfbClientPtr cl) {
- allowed_input_t input;
- if (unixpw_in_progress) {
- rfbLog("get_file_transfer_permitted: unixpw_in_progress, dropping client.\n");
- rfbCloseClient(cl);
- return FALSE;
- }
-if (0) fprintf(stderr, "get_file_transfer_permitted called\n");
- if (view_only) {
- return FALSE;
- }
- if (cl->viewOnly) {
- return FALSE;
- }
- get_allowed_input(cl, &input);
- if (!input.files) {
- return FALSE;
- }
- if (screen->permitFileTransfer) {
- saw_ultra_file = 1;
- }
- return screen->permitFileTransfer;
-}
-
-
OpenPOWER on IntegriCloud