summaryrefslogtreecommitdiffstats
path: root/x11vnc/xrecord.c
diff options
context:
space:
mode:
Diffstat (limited to 'x11vnc/xrecord.c')
-rw-r--r--x11vnc/xrecord.c2084
1 files changed, 0 insertions, 2084 deletions
diff --git a/x11vnc/xrecord.c b/x11vnc/xrecord.c
deleted file mode 100644
index 87e15b9..0000000
--- a/x11vnc/xrecord.c
+++ /dev/null
@@ -1,2084 +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.
-*/
-
-/* -- xrecord.c -- */
-
-#include "x11vnc.h"
-#include "xwrappers.h"
-#include "win_utils.h"
-#include "cleanup.h"
-#include "userinput.h"
-#include "winattr_t.h"
-#include "scrollevent_t.h"
-#include "unixpw.h"
-
-#define SCR_EV_MAX 128
-scroll_event_t scr_ev[SCR_EV_MAX];
-int scr_ev_cnt;
-
-int xrecording = 0;
-int xrecord_set_by_keys = 0;
-int xrecord_set_by_mouse = 0;
-Window xrecord_focus_window = None;
-Window xrecord_wm_window = None;
-Window xrecord_ptr_window = None;
-KeySym xrecord_keysym = NoSymbol;
-
-#define NAMEINFO 2048
-char xrecord_name_info[NAMEINFO];
-
-#define SCR_ATTR_CACHE 8
-winattr_t scr_attr_cache[SCR_ATTR_CACHE];
-static double attr_cache_max_age = 1.5;
-
-Display *rdpy_data = NULL; /* Data connection for RECORD */
-Display *rdpy_ctrl = NULL; /* Control connection for RECORD */
-
-Display *gdpy_ctrl = NULL;
-Display *gdpy_data = NULL;
-int xserver_grabbed = 0;
-
-int trap_record_xerror(Display *, XErrorEvent *);
-
-void initialize_xrecord(void);
-void zerodisp_xrecord(void);
-void shutdown_xrecord(void);
-int xrecord_skip_keysym(rfbKeySym keysym);
-int xrecord_skip_button(int newb, int old);
-int xrecord_scroll_keysym(rfbKeySym keysym);
-void check_xrecord_reset(int force);
-void xrecord_watch(int start, int setby);
-
-
-#if LIBVNCSERVER_HAVE_RECORD
-static XRecordRange *rr_CA = NULL;
-static XRecordRange *rr_CW = NULL;
-static XRecordRange *rr_GS = NULL;
-static XRecordRange *rr_scroll[10];
-static XRecordContext rc_scroll;
-static XRecordClientSpec rcs_scroll;
-static XRecordRange *rr_grab[10];
-static XRecordContext rc_grab;
-static XRecordClientSpec rcs_grab;
-#endif
-static XErrorEvent *trapped_record_xerror_event;
-
-static void xrecord_grabserver(int start);
-static int xrecord_vi_scroll_keysym(rfbKeySym keysym);
-static int xrecord_emacs_scroll_keysym(rfbKeySym keysym);
-static int lookup_attr_cache(Window win, int *cache_index, int *next_index);
-#if LIBVNCSERVER_HAVE_RECORD
-static void record_CA(XPointer ptr, XRecordInterceptData *rec_data);
-static void record_CW(XPointer ptr, XRecordInterceptData *rec_data);
-static void record_switch(XPointer ptr, XRecordInterceptData *rec_data);
-static void record_grab(XPointer ptr, XRecordInterceptData *rec_data);
-static void shutdown_record_context(XRecordContext rc, int bequiet, int reopen);
-#endif
-static void check_xrecord_grabserver(void);
-
-
-int trap_record_xerror(Display *d, XErrorEvent *error) {
- trapped_record_xerror = 1;
- trapped_record_xerror_event = error;
-
- if (d) {} /* unused vars warning: */
-
- return 0;
-}
-
-static void xrecord_grabserver(int start) {
- XErrorHandler old_handler = NULL;
- int rc = 0;
-
- if (debug_grabs) {
- fprintf(stderr, "xrecord_grabserver%d/%d %.5f\n",
- xserver_grabbed, start, dnowx());
- }
-
- if (! gdpy_ctrl || ! gdpy_data) {
- return;
- }
-#if LIBVNCSERVER_HAVE_RECORD
- if (!start) {
- if (! rc_grab) {
- return;
- }
- XRecordDisableContext(gdpy_ctrl, rc_grab);
- XRecordFreeContext(gdpy_ctrl, rc_grab);
- XFlush_wr(gdpy_ctrl);
- rc_grab = 0;
- return;
- }
-
- xserver_grabbed = 0;
-
- rr_grab[0] = rr_GS;
- rcs_grab = XRecordAllClients;
-
- rc_grab = XRecordCreateContext(gdpy_ctrl, 0, &rcs_grab, 1, rr_grab, 1);
- trapped_record_xerror = 0;
- old_handler = XSetErrorHandler(trap_record_xerror);
-
- XSync(gdpy_ctrl, True);
-
- if (! rc_grab || trapped_record_xerror) {
- XCloseDisplay_wr(gdpy_ctrl);
- XCloseDisplay_wr(gdpy_data);
- gdpy_ctrl = NULL;
- gdpy_data = NULL;
- XSetErrorHandler(old_handler);
- return;
- }
- rc = XRecordEnableContextAsync(gdpy_data, rc_grab, record_grab, NULL);
- if (!rc || trapped_record_xerror) {
- XCloseDisplay_wr(gdpy_ctrl);
- XCloseDisplay_wr(gdpy_data);
- gdpy_ctrl = NULL;
- gdpy_data = NULL;
- XSetErrorHandler(old_handler);
- return;
- }
- XFlush_wr(gdpy_data);
- XSetErrorHandler(old_handler);
-#else
- if (!rc || !old_handler) {}
-#endif
- if (debug_grabs) {
- fprintf(stderr, "xrecord_grabserver-done: %.5f\n", dnowx());
- }
-}
-
-void zerodisp_xrecord(void) {
- rdpy_data = NULL;
- rdpy_ctrl = NULL;
- gdpy_data = NULL;
- gdpy_ctrl = NULL;
-}
-
-void initialize_xrecord(void) {
- use_xrecord = 0;
- if (! xrecord_present) {
- return;
- }
- if (nofb) {
- return;
- }
- if (noxrecord) {
- return;
- }
- RAWFB_RET_VOID
-#if LIBVNCSERVER_HAVE_RECORD
-
- if (rr_CA) XFree_wr(rr_CA);
- if (rr_CW) XFree_wr(rr_CW);
- if (rr_GS) XFree_wr(rr_GS);
-
- rr_CA = XRecordAllocRange();
- rr_CW = XRecordAllocRange();
- rr_GS = XRecordAllocRange();
- if (!rr_CA || !rr_CW || !rr_GS) {
- return;
- }
- /* protocol request ranges: */
- rr_CA->core_requests.first = X_CopyArea;
- rr_CA->core_requests.last = X_CopyArea;
-
- rr_CW->core_requests.first = X_ConfigureWindow;
- rr_CW->core_requests.last = X_ConfigureWindow;
-
- rr_GS->core_requests.first = X_GrabServer;
- rr_GS->core_requests.last = X_UngrabServer;
-
- X_LOCK;
- /* open a 2nd control connection to DISPLAY: */
- if (rdpy_data) {
- XCloseDisplay_wr(rdpy_data);
- rdpy_data = NULL;
- }
- if (rdpy_ctrl) {
- XCloseDisplay_wr(rdpy_ctrl);
- rdpy_ctrl = NULL;
- }
- rdpy_ctrl = XOpenDisplay_wr(DisplayString(dpy));
- if (!rdpy_ctrl) {
- fprintf(stderr, "rdpy_ctrl open failed: %s / %s / %s / %s\n", getenv("DISPLAY"), DisplayString(dpy), getenv("XAUTHORITY"), getenv("XAUTHORIT_"));
- }
- XSync(dpy, True);
- XSync(rdpy_ctrl, True);
- /* open datalink connection to DISPLAY: */
- rdpy_data = XOpenDisplay_wr(DisplayString(dpy));
- if (!rdpy_data) {
- fprintf(stderr, "rdpy_data open failed\n");
- }
- if (!rdpy_ctrl || ! rdpy_data) {
- X_UNLOCK;
- return;
- }
- disable_grabserver(rdpy_ctrl, 0);
- disable_grabserver(rdpy_data, 0);
-
- use_xrecord = 1;
-
- /*
- * now set up the GrabServer watcher. We get GrabServer
- * deadlock in XRecordCreateContext() even with XTestGrabServer
- * in place, why? Not sure, so we manually watch for grabs...
- */
- if (gdpy_data) {
- XCloseDisplay_wr(gdpy_data);
- gdpy_data = NULL;
- }
- if (gdpy_ctrl) {
- XCloseDisplay_wr(gdpy_ctrl);
- gdpy_ctrl = NULL;
- }
- xserver_grabbed = 0;
-
- gdpy_ctrl = XOpenDisplay_wr(DisplayString(dpy));
- if (!gdpy_ctrl) {
- fprintf(stderr, "gdpy_ctrl open failed\n");
- }
- XSync(dpy, True);
- XSync(gdpy_ctrl, True);
- gdpy_data = XOpenDisplay_wr(DisplayString(dpy));
- if (!gdpy_data) {
- fprintf(stderr, "gdpy_data open failed\n");
- }
- if (gdpy_ctrl && gdpy_data) {
- disable_grabserver(gdpy_ctrl, 0);
- disable_grabserver(gdpy_data, 0);
- xrecord_grabserver(1);
- }
- X_UNLOCK;
-#endif
-}
-
-void shutdown_xrecord(void) {
-#if LIBVNCSERVER_HAVE_RECORD
-
- if (debug_grabs) {
- fprintf(stderr, "shutdown_xrecord%d %.5f\n",
- xserver_grabbed, dnowx());
- }
-
- if (rr_CA) XFree_wr(rr_CA);
- if (rr_CW) XFree_wr(rr_CW);
- if (rr_GS) XFree_wr(rr_GS);
-
- rr_CA = NULL;
- rr_CW = NULL;
- rr_GS = NULL;
-
- X_LOCK;
- if (rdpy_ctrl && rc_scroll) {
- XRecordDisableContext(rdpy_ctrl, rc_scroll);
- XRecordFreeContext(rdpy_ctrl, rc_scroll);
- XSync(rdpy_ctrl, False);
- rc_scroll = 0;
- }
-
- if (gdpy_ctrl && rc_grab) {
- XRecordDisableContext(gdpy_ctrl, rc_grab);
- XRecordFreeContext(gdpy_ctrl, rc_grab);
- XSync(gdpy_ctrl, False);
- rc_grab = 0;
- }
-
- if (rdpy_data) {
- XCloseDisplay_wr(rdpy_data);
- rdpy_data = NULL;
- }
- if (rdpy_ctrl) {
- XCloseDisplay_wr(rdpy_ctrl);
- rdpy_ctrl = NULL;
- }
- if (gdpy_data) {
- XCloseDisplay_wr(gdpy_data);
- gdpy_data = NULL;
- }
- if (gdpy_ctrl) {
- XCloseDisplay_wr(gdpy_ctrl);
- gdpy_ctrl = NULL;
- }
- xserver_grabbed = 0;
- X_UNLOCK;
-#endif
- use_xrecord = 0;
-
- if (debug_grabs) {
- fprintf(stderr, "shutdown_xrecord-done: %.5f\n", dnowx());
- }
-}
-
-int xrecord_skip_keysym(rfbKeySym keysym) {
- KeySym sym = (KeySym) keysym;
- int ok = -1, matched = 0;
-
- if (scroll_key_list) {
- int k, exclude = 0;
- if (scroll_key_list[0]) {
- exclude = 1;
- }
- k = 1;
- while (scroll_key_list[k] != NoSymbol) {
- if (scroll_key_list[k++] == sym) {
- matched = 1;
- break;
- }
- }
- if (exclude) {
- if (matched) {
- return 1;
- } else {
- ok = 1;
- }
- } else {
- if (matched) {
- ok = 1;
- } else {
- ok = 0;
- }
- }
- }
- if (ok == 1) {
- return 0;
- } else if (ok == 0) {
- return 1;
- }
-
- /* apply various heuristics: */
-
- if (IsModifierKey(sym)) {
- /* Shift, Control, etc, usu. generate no scrolls */
- return 1;
- }
- if (sym == XK_space && scroll_term) {
- /* space in a terminal is usu. full page... */
- Window win;
- static Window prev_top = None;
- int size = 256;
- static char name[256];
-
- X_LOCK;
- win = query_pointer(rootwin);
- X_UNLOCK;
- if (win != None && win != rootwin) {
- if (prev_top != None && win == prev_top) {
- ; /* use cached result */
- } else {
- prev_top = win;
- X_LOCK;
- win = descend_pointer(6, win, name, size);
- X_UNLOCK;
- }
- if (match_str_list(name, scroll_term)) {
- return 1;
- }
- }
- }
-
- /* TBD use typing_rate() so */
- return 0;
-}
-
-int xrecord_skip_button(int new_button, int old) {
- /* unused vars warning: */
- if (new_button || old) {}
-
- return 0;
-}
-
-static int xrecord_vi_scroll_keysym(rfbKeySym keysym) {
- KeySym sym = (KeySym) keysym;
- if (sym == XK_J || sym == XK_j || sym == XK_K || sym == XK_k) {
- return 1; /* vi */
- }
- if (sym == XK_D || sym == XK_d || sym == XK_U || sym == XK_u) {
- return 1; /* Ctrl-d/u */
- }
- if (sym == XK_Z || sym == XK_z) {
- return 1; /* zz, zt, zb .. */
- }
- return 0;
-}
-
-static int xrecord_emacs_scroll_keysym(rfbKeySym keysym) {
- KeySym sym = (KeySym) keysym;
- if (sym == XK_N || sym == XK_n || sym == XK_P || sym == XK_p) {
- return 1; /* emacs */
- }
- /* Must be some more ... */
- return 0;
-}
-
-int xrecord_scroll_keysym(rfbKeySym keysym) {
- KeySym sym = (KeySym) keysym;
- /* X11/keysymdef.h */
-
- if (sym == XK_Return || sym == XK_KP_Enter || sym == XK_Linefeed) {
- return 1; /* Enter */
- }
- if (sym==XK_Up || sym==XK_KP_Up || sym==XK_Down || sym==XK_KP_Down) {
- return 1; /* U/D arrows */
- }
- if (sym == XK_Left || sym == XK_KP_Left || sym == XK_Right ||
- sym == XK_KP_Right) {
- return 1; /* L/R arrows */
- }
- if (xrecord_vi_scroll_keysym(keysym)) {
- return 1;
- }
- if (xrecord_emacs_scroll_keysym(keysym)) {
- return 1;
- }
- return 0;
-}
-
-static int lookup_attr_cache(Window win, int *cache_index, int *next_index) {
- double now, t, oldest = 0.0;
- int i, old_index = -1, count = 0;
- Window cwin;
-
- *cache_index = -1;
- *next_index = -1;
-
- if (win == None) {
- return 0;
- }
- if (attr_cache_max_age == 0.0) {
- return 0;
- }
-
- dtime0(&now);
- for (i=0; i < SCR_ATTR_CACHE; i++) {
-
- cwin = scr_attr_cache[i].win;
- t = scr_attr_cache[i].time;
-
- if (now > t + attr_cache_max_age) {
- /* expire it even if it is the one we want */
- scr_attr_cache[i].win = cwin = None;
- scr_attr_cache[i].fetched = 0;
- scr_attr_cache[i].valid = 0;
- }
-
- if (*next_index == -1 && cwin == None) {
- *next_index = i;
- }
- if (*next_index == -1) {
- /* record oldest */
- if (old_index == -1 || t < oldest) {
- oldest = t;
- old_index = i;
- }
- }
- if (cwin != None) {
- count++;
- }
- if (cwin == win) {
- if (*cache_index == -1) {
- *cache_index = i;
- } else {
- /* remove dups */
- scr_attr_cache[i].win = None;
- scr_attr_cache[i].fetched = 0;
- scr_attr_cache[i].valid = 0;
- }
- }
- }
- if (*next_index == -1) {
- *next_index = old_index;
- }
-
-if (0) fprintf(stderr, "lookup_attr_cache count: %d\n", count);
- if (*cache_index != -1) {
- return 1;
- } else {
- return 0;
- }
-}
-
-
-static XID xrecord_seq = 0;
-static double xrecord_start = 0.0;
-
-#if LIBVNCSERVER_HAVE_RECORD
-static void record_CA(XPointer ptr, XRecordInterceptData *rec_data) {
- xCopyAreaReq *req;
- Window src = None, dst = None, c;
- XWindowAttributes attr, attr2;
- int src_x, src_y, dst_x, dst_y, rx, ry, rx2, ry2;
- int good = 1, dx = 0, dy = 0, k=0, i;
- unsigned int w, h;
- int dba = 0, db = debug_scroll;
- int cache_index, next_index, valid;
- static int must_equal = -1;
-
- if (dba || db) {
- if (rec_data->category == XRecordFromClient) {
- req = (xCopyAreaReq *) rec_data->data;
- if (req->reqType == X_CopyArea) {
- src = req->srcDrawable;
- dst = req->dstDrawable;
- }
- }
- }
-
-if (dba || db > 1) fprintf(stderr, "record_CA-%d id_base: 0x%lx ptr: 0x%lx "
- "seq: 0x%lx rc: 0x%lx cat: %d swapped: %d 0x%lx/0x%lx\n", k++,
- rec_data->id_base, (unsigned long) ptr, xrecord_seq, rc_scroll,
- rec_data->category, rec_data->client_swapped, src, dst);
-
- if (! xrecording) {
- return;
- }
-if (db > 1) fprintf(stderr, "record_CA-%d\n", k++);
-
- if (rec_data->id_base == 0) {
- return;
- }
-if (db > 1) fprintf(stderr, "record_CA-%d\n", k++);
-
- if ((XID) ptr != xrecord_seq) {
- return;
- }
-if (db > 1) fprintf(stderr, "record_CA-%d\n", k++);
-
- if (rec_data->category != XRecordFromClient) {
- return;
- }
-if (db > 1) fprintf(stderr, "record_CA-%d\n", k++);
-
- req = (xCopyAreaReq *) rec_data->data;
-
- if (req->reqType != X_CopyArea) {
- return;
- }
-if (db > 1) fprintf(stderr, "record_CA-%d\n", k++);
-
- if (must_equal < 0) {
- must_equal = 0;
- if (getenv("X11VNC_SCROLL_MUST_EQUAL")) {
- must_equal = 1;
- }
- }
-
-/*
-
-xterm, gnome-terminal, others.
-
-Note we miss the X_ImageText8 that clears the block cursor. So there is a
-short period of time with a painting error: two cursors, one above the other.
-
- X_ImageText8
- draw: 0x8c00017 nChars: 1, gc: 0x8c00013, x: 101, y: 585, chars=' '
- X_ClearArea
- window: 0x8c00018, x: 2, y: 217, w: 10, h: 5
- X_FillPoly
- draw: 0x8c00018 gc: 0x8c0000a, shape: 0, coordMode: 0,
- X_FillPoly
- draw: 0x8c00018 gc: 0x8c0000b, shape: 0, coordMode: 0,
- X_CopyArea
- src: 0x8c00017, dst: 0x8c00017, gc: 0x8c00013, srcX: 17, srcY: 15, dstX: 17, dstY: 2, w: 480, h: 572
- X_ChangeWindowAttributes
- X_ClearArea
- window: 0x8c00017, x: 17, y: 574, w: 480, h: 13
- X_ChangeWindowAttributes
-
- */
-
- src = req->srcDrawable;
- dst = req->dstDrawable;
- src_x = req->srcX;
- src_y = req->srcY;
- dst_x = req->dstX;
- dst_y = req->dstY;
- w = req->width;
- h = req->height;
-
- if (w*h < (unsigned int) scrollcopyrect_min_area) {
- if (db > 1) fprintf(stderr, "record_CA scroll area too small.\n");
- good = 0;
- } else if (!src || !dst) {
- if (db > 1) fprintf(stderr, "record_CA null src or dst.\n");
- good = 0;
- } else if (scr_ev_cnt >= SCR_EV_MAX) {
- if (db > 1) fprintf(stderr, "record_CA null too many scr events.\n");
- good = 0;
- } else if (must_equal && src != dst) {
- if (db > 1) fprintf(stderr, "record_CA src not equal dst.\n");
- good = 0;
- }
-
- if (src == dst) {
- dx = dst_x - src_x;
- dy = dst_y - src_y;
-
- if (dx != 0 && dy != 0) {
- good = 0;
- }
- }
-
-if (!good && (dba || db > 1)) fprintf(stderr, "record_CA-x src_x: %d src_y: %d "
- "dst_x: %d dst_y: %d w: %d h: %d scr_ev_cnt: %d 0x%lx/0x%lx\n",
- src_x, src_y, dst_x, dst_y, w, h, scr_ev_cnt, src, dst);
-
- if (! good) {
- return;
- }
-
-if (db > 1) fprintf(stderr, "record_CA-%d\n", k++);
-
- /*
- * after all of the above succeeds, now contact X server.
- * we try to get away with some caching here.
- */
- if (lookup_attr_cache(src, &cache_index, &next_index)) {
- i = cache_index;
- attr.x = scr_attr_cache[i].x;
- attr.y = scr_attr_cache[i].y;
- attr.width = scr_attr_cache[i].width;
- attr.height = scr_attr_cache[i].height;
- attr.map_state = scr_attr_cache[i].map_state;
- rx = scr_attr_cache[i].rx;
- ry = scr_attr_cache[i].ry;
- valid = scr_attr_cache[i].valid;
-
- } else {
- valid = valid_window(src, &attr, 1);
-
- if (valid) {
- if (!xtranslate(src, rootwin, 0, 0, &rx, &ry, &c, 1)) {
- valid = 0;
- }
- }
- if (next_index >= 0) {
- i = next_index;
- scr_attr_cache[i].win = src;
- scr_attr_cache[i].fetched = 1;
- scr_attr_cache[i].valid = valid;
- scr_attr_cache[i].time = dnow();
- if (valid) {
- scr_attr_cache[i].x = attr.x;
- scr_attr_cache[i].y = attr.y;
- scr_attr_cache[i].width = attr.width;
- scr_attr_cache[i].height = attr.height;
- scr_attr_cache[i].border_width = attr.border_width;
- scr_attr_cache[i].depth = attr.depth;
- scr_attr_cache[i].class = attr.class;
- scr_attr_cache[i].backing_store =
- attr.backing_store;
- scr_attr_cache[i].map_state = attr.map_state;
-
- scr_attr_cache[i].rx = rx;
- scr_attr_cache[i].ry = ry;
- }
- }
- }
-
- if (! valid) {
- if (db > 1) fprintf(stderr, "record_CA not valid-1.\n");
- return;
- }
-if (db > 1) fprintf(stderr, "record_CA-%d\n", k++);
-
- if (attr.map_state != IsViewable) {
- if (db > 1) fprintf(stderr, "record_CA not viewable-1.\n");
- return;
- }
-
- /* recent gdk/gtk windows use different src and dst. for compositing? */
- if (src != dst) {
- if (lookup_attr_cache(dst, &cache_index, &next_index)) {
- i = cache_index;
- attr2.x = scr_attr_cache[i].x;
- attr2.y = scr_attr_cache[i].y;
- attr2.width = scr_attr_cache[i].width;
- attr2.height = scr_attr_cache[i].height;
- attr2.map_state = scr_attr_cache[i].map_state;
- rx2 = scr_attr_cache[i].rx;
- ry2 = scr_attr_cache[i].ry;
- valid = scr_attr_cache[i].valid;
-
- } else {
- valid = valid_window(dst, &attr2, 1);
-
- if (valid) {
- if (!xtranslate(dst, rootwin, 0, 0, &rx2, &ry2, &c, 1)) {
- valid = 0;
- }
- }
- if (next_index >= 0) {
- i = next_index;
- scr_attr_cache[i].win = dst;
- scr_attr_cache[i].fetched = 1;
- scr_attr_cache[i].valid = valid;
- scr_attr_cache[i].time = dnow();
- if (valid) {
- scr_attr_cache[i].x = attr2.x;
- scr_attr_cache[i].y = attr2.y;
- scr_attr_cache[i].width = attr2.width;
- scr_attr_cache[i].height = attr2.height;
- scr_attr_cache[i].border_width = attr2.border_width;
- scr_attr_cache[i].depth = attr2.depth;
- scr_attr_cache[i].class = attr2.class;
- scr_attr_cache[i].backing_store =
- attr2.backing_store;
- scr_attr_cache[i].map_state = attr2.map_state;
-
- scr_attr_cache[i].rx = rx2;
- scr_attr_cache[i].ry = ry2;
- }
- }
- }
-
-if (dba || db > 1) fprintf(stderr, "record_CA-? src_x: %d src_y: %d "
- "dst_x: %d dst_y: %d w: %d h: %d scr_ev_cnt: %d 0x%lx/0x%lx\n",
- src_x, src_y, dst_x, dst_y, w, h, scr_ev_cnt, src, dst);
-
- if (! valid) {
- if (db > 1) fprintf(stderr, "record_CA not valid-2.\n");
- return;
- }
- if (attr2.map_state != IsViewable) {
- if (db > 1) fprintf(stderr, "record_CA not viewable-2.\n");
- return;
- }
- dst_x = dst_x - (rx - rx2);
- dst_y = dst_y - (ry - ry2);
-
- dx = dst_x - src_x;
- dy = dst_y - src_y;
-
- if (dx != 0 && dy != 0) {
- return;
- }
- }
-
-
- if (0 || dba || db) {
- double st, dt;
- st = (double) rec_data->server_time/1000.0;
- dt = (dnow() - servertime_diff) - st;
- fprintf(stderr, "record_CA-%d *FOUND_SCROLL: src: 0x%lx dx: %d dy: %d "
- "x: %d y: %d w: %d h: %d st: %.4f %.4f %.4f\n", k++, src, dx, dy,
- src_x, src_y, w, h, st, dt, dnowx());
- }
-
- i = scr_ev_cnt;
-
- scr_ev[i].win = src;
- scr_ev[i].frame = None;
- scr_ev[i].dx = dx;
- scr_ev[i].dy = dy;
- scr_ev[i].x = rx + dst_x;
- scr_ev[i].y = ry + dst_y;
- scr_ev[i].w = w;
- scr_ev[i].h = h;
- scr_ev[i].t = ((double) rec_data->server_time)/1000.0;
- scr_ev[i].win_x = rx;
- scr_ev[i].win_y = ry;
- scr_ev[i].win_w = attr.width;
- scr_ev[i].win_h = attr.height;
- scr_ev[i].new_x = 0;
- scr_ev[i].new_y = 0;
- scr_ev[i].new_w = 0;
- scr_ev[i].new_h = 0;
-
- if (dx == 0) {
- if (dy > 0) {
- scr_ev[i].new_x = rx + src_x;
- scr_ev[i].new_y = ry + src_y;
- scr_ev[i].new_w = w;
- scr_ev[i].new_h = dy;
- } else {
- scr_ev[i].new_x = rx + src_x;
- scr_ev[i].new_y = ry + dst_y + h;
- scr_ev[i].new_w = w;
- scr_ev[i].new_h = -dy;
- }
- } else if (dy == 0) {
- if (dx > 0) {
- scr_ev[i].new_x = rx + src_x;
- scr_ev[i].new_y = rx + src_y;
- scr_ev[i].new_w = dx;
- scr_ev[i].new_h = h;
- } else {
- scr_ev[i].new_x = rx + dst_x + w;
- scr_ev[i].new_y = ry + src_y;
- scr_ev[i].new_w = -dx;
- scr_ev[i].new_h = h;
- }
- }
-
- scr_ev_cnt++;
-}
-
-typedef struct cw_event {
- Window win;
- int x, y, w, h;
-} cw_event_t;
-
-#define MAX_CW 128
-static cw_event_t cw_events[MAX_CW];
-
-static void record_CW(XPointer ptr, XRecordInterceptData *rec_data) {
- xConfigureWindowReq *req;
- Window win = None, c;
- Window src = None, dst = None;
- XWindowAttributes attr;
- int absent = 0x100000;
- int src_x, src_y, dst_x, dst_y, rx, ry;
- int good = 1, dx, dy, k=0, i, j, match, list[3];
- int f_x, f_y, f_w, f_h;
- int x, y, w, h;
- int x0, y0, w0, h0, x1, y1, w1, h1, x2, y2, w2, h2;
- static int index = 0;
- unsigned int vals[4];
- unsigned tmask;
- char *data;
- int dba = 0, db = debug_scroll;
- int cache_index, next_index, valid;
-
- if (db) {
- if (rec_data->category == XRecordFromClient) {
- req = (xConfigureWindowReq *) rec_data->data;
- if (req->reqType == X_ConfigureWindow) {
- src = req->window;
- }
- }
- }
-
-if (dba || db > 1) fprintf(stderr, "record_CW-%d id_base: 0x%lx ptr: 0x%lx "
- "seq: 0x%lx rc: 0x%lx cat: %d swapped: %d 0x%lx/0x%lx\n", k++,
- rec_data->id_base, (unsigned long) ptr, xrecord_seq, rc_scroll,
- rec_data->category, rec_data->client_swapped, src, dst);
-
-
- if (! xrecording) {
- return;
- }
-if (db > 1) fprintf(stderr, "record_CW-%d\n", k++);
-
- if ((XID) ptr != xrecord_seq) {
- return;
- }
-if (db > 1) fprintf(stderr, "record_CW-%d\n", k++);
-
- if (rec_data->id_base == 0) {
- return;
- }
-if (db > 1) fprintf(stderr, "record_CW-%d\n", k++);
-
- if (rec_data->category == XRecordStartOfData) {
- index = 0;
- return;
- }
-if (db > 1) fprintf(stderr, "record_CW-%d\n", k++);
-
- if (rec_data->category != XRecordFromClient) {
- return;
- }
-if (db > 1) fprintf(stderr, "record_CW-%d\n", k++);
-
- if (rec_data->client_swapped) {
- return;
- }
-if (db > 1) fprintf(stderr, "record_CW-%d\n", k++);
-
- req = (xConfigureWindowReq *) rec_data->data;
-
- if (req->reqType != X_ConfigureWindow) {
- return;
- }
-if (db > 1) fprintf(stderr, "record_CW-%d\n", k++);
-
- tmask = req->mask;
-
- tmask &= ~CWX;
- tmask &= ~CWY;
- tmask &= ~CWWidth;
- tmask &= ~CWHeight;
-
- if (tmask) {
- /* require no more than these 4 flags */
- return;
- }
-if (db > 1) fprintf(stderr, "record_CW-%d\n", k++);
-
- f_x = req->mask & CWX;
- f_y = req->mask & CWY;
- f_w = req->mask & CWWidth;
- f_h = req->mask & CWHeight;
-
- if (! f_x || ! f_y) {
- if (f_w && f_h) {
- ; /* netscape 4.x style */
- } else {
- return;
- }
- }
-if (db > 1) fprintf(stderr, "record_CW-%d\n", k++);
-
- if ( (f_w && !f_h) || (!f_w && f_h) ) {
- return;
- }
-if (db > 1) fprintf(stderr, "record_CW-%d\n", k++);
-
- for (i=0; i<4; i++) {
- vals[i] = 0;
- }
-
- data = (char *)req;
- data += sz_xConfigureWindowReq;
-
- for (i=0; i<req->length; i++) {
- unsigned int v;
- /*
- * We use unsigned int for the values. There were
- * some crashes on 64bit machines with unsigned longs.
- * Need to check that X protocol sends 32bit values.
- */
- v = *( (unsigned int *) data);
-if (db > 1) fprintf(stderr, " vals[%d] 0x%x/%d\n", i, v, v);
- vals[i] = v;
- data += sizeof(unsigned int);
- }
-
- if (index >= MAX_CW) {
- int i, j;
-
- /* FIXME, circular, etc. */
- for (i=0; i<2; i++) {
- j = MAX_CW - 2 + i;
- cw_events[i].win = cw_events[j].win;
- cw_events[i].x = cw_events[j].x;
- cw_events[i].y = cw_events[j].y;
- cw_events[i].w = cw_events[j].w;
- cw_events[i].h = cw_events[j].h;
- }
- index = 2;
- }
-
- if (! f_x && ! f_y) {
- /* netscape 4.x style CWWidth,CWHeight */
- vals[2] = vals[0];
- vals[3] = vals[1];
- vals[0] = 0;
- vals[1] = 0;
- }
-
- cw_events[index].win = req->window;
-
- if (! f_x) {
- cw_events[index].x = absent;
- } else {
- cw_events[index].x = (int) vals[0];
- }
- if (! f_y) {
- cw_events[index].y = absent;
- } else {
- cw_events[index].y = (int) vals[1];
- }
-
- if (! f_w) {
- cw_events[index].w = absent;
- } else {
- cw_events[index].w = (int) vals[2];
- }
- if (! f_h) {
- cw_events[index].h = absent;
- } else {
- cw_events[index].h = (int) vals[3];
- }
-
- x = cw_events[index].x;
- y = cw_events[index].y;
- w = cw_events[index].w;
- h = cw_events[index].h;
- win = cw_events[index].win;
-
-if (dba || db) fprintf(stderr, " record_CW ind: %d win: 0x%lx x: %d y: %d w: %d h: %d\n",
- index, win, x, y, w, h);
-
- index++;
-
- if (index < 3) {
- good = 0;
- } else if (w != absent && h != absent &&
- w*h < scrollcopyrect_min_area) {
- good = 0;
- }
-
- if (! good) {
- return;
- }
-if (db > 1) fprintf(stderr, "record_CW-%d\n", k++);
-
- match = 0;
- for (j=index - 1; j >= 0; j--) {
- if (cw_events[j].win == win) {
- list[match++] = j;
- }
- if (match >= 3) {
- break;
- }
- }
-
- if (match != 3) {
- return;
- }
-if (db > 1) fprintf(stderr, "record_CW-%d\n", k++);
-
-/*
-
-Mozilla:
-
-Up arrow: window moves down a bit (dy > 0):
-
- X_ConfigureWindow
- length: 7, window: 0x2e000cd, mask: 0xf, v0 0, v1 -18, v2 760, v3 906, v4 327692, v5 48234701, v6 3,
- CW-mask: CWX,CWY,CWWidth,CWHeight,
- X_ConfigureWindow
- length: 5, window: 0x2e000cd, mask: 0x3, v0 0, v1 0, v2 506636, v3 48234701, v4 48234511,
- CW-mask: CWX,CWY,
- X_ConfigureWindow
- length: 7, window: 0x2e000cd, mask: 0xf, v0 0, v1 0, v2 760, v3 888, v4 65579, v5 0, v6 108009,
- CW-mask: CWX,CWY,CWWidth,CWHeight,
-
-Down arrow: window moves up a bit (dy < 0):
-
- X_ConfigureWindow
- length: 7, window: 0x2e000cd, mask: 0xf, v0 0, v1 0, v2 760, v3 906, v4 327692, v5 48234701, v6 262147,
- CW-mask: CWX,CWY,CWWidth,CWHeight,
- X_ConfigureWindow
- length: 5, window: 0x2e000cd, mask: 0x3, v0 0, v1 -18, v2 506636, v3 48234701, v4 48234511,
- CW-mask: CWX,CWY,
- X_ConfigureWindow
- length: 7, window: 0x2e000cd, mask: 0xf, v0 0, v1 0, v2 760, v3 888, v4 96555, v5 48265642, v6 48265262,
- CW-mask: CWX,CWY,CWWidth,CWHeight,
-
-
-Netscape 4.x
-
-Up arrow:
-71.76142 0.01984 X_ConfigureWindow
- length: 7, window: 0x9800488, mask: 0xf, v0 0, v1 -15, v2 785, v3 882, v4 327692, v5 159384712, v6 1769484,
- CW-mask: CWX,CWY,CWWidth,CWHeight,
-71.76153 0.00011 X_ConfigureWindow
- length: 5, window: 0x9800488, mask: 0xc, v0 785, v1 867, v2 329228, v3 159384712, v4 159383555,
- CW-mask: CWWidth,CWHeight,
- XXX,XXX
-71.76157 0.00003 X_ConfigureWindow
- length: 5, window: 0x9800488, mask: 0x3, v0 0, v1 0, v2 131132, v3 159385313, v4 328759,
- CW-mask: CWX,CWY,
- XXX,XXX
-
-Down arrow:
-72.93147 0.01990 X_ConfigureWindow
- length: 5, window: 0x9800488, mask: 0xc, v0 785, v1 882, v2 328972, v3 159384712, v4 159383555,
- CW-mask: CWWidth,CWHeight,
- XXX,XXX
-72.93156 0.00009 X_ConfigureWindow
- length: 5, window: 0x9800488, mask: 0x3, v0 0, v1 -15, v2 458764, v3 159384712, v4 159383567,
- CW-mask: CWX,CWY,
-72.93160 0.00004 X_ConfigureWindow
- length: 7, window: 0x9800488, mask: 0xf, v0 0, v1 0, v2 785, v3 867, v4 131132, v5 159385335, v6 328759,
- CW-mask: CWX,CWY,CWWidth,CWHeight,
-
-
-sadly, probably need to handle some more...
-
- */
- x0 = cw_events[list[2]].x;
- y0 = cw_events[list[2]].y;
- w0 = cw_events[list[2]].w;
- h0 = cw_events[list[2]].h;
-
- x1 = cw_events[list[1]].x;
- y1 = cw_events[list[1]].y;
- w1 = cw_events[list[1]].w;
- h1 = cw_events[list[1]].h;
-
- x2 = cw_events[list[0]].x;
- y2 = cw_events[list[0]].y;
- w2 = cw_events[list[0]].w;
- h2 = cw_events[list[0]].h;
-
- /* see NS4 XXX's above: */
- if (w2 == absent || h2 == absent) {
- /* up arrow */
- if (w2 == absent) {
- w2 = w1;
- }
- if (h2 == absent) {
- h2 = h1;
- }
- }
- if (x1 == absent || y1 == absent) {
- /* up arrow */
- if (x1 == absent) {
- x1 = x2;
- }
- if (y1 == absent) {
- y1 = y2;
- }
- }
- if (x0 == absent || y0 == absent) {
- /* down arrow */
- if (x0 == absent) {
- /* hmmm... what to do */
- x0 = x2;
- }
- if (y0 == absent) {
- y0 = y2;
- }
- }
-
-if (dba) fprintf(stderr, "%d/%d/%d/%d %d/%d/%d/%d %d/%d/%d/%d\n", x0, y0, w0, h0, x1, y1, w1, h1, x2, y2, w2, h2);
-
- dy = y1 - y0;
- dx = x1 - x0;
-
- src_x = x2;
- src_y = y2;
- w = w2;
- h = h2;
-
- /* check w and h before we modify them */
- if (w <= 0 || h <= 0) {
- good = 0;
- } else if (w == absent || h == absent) {
- good = 0;
- }
- if (! good) {
- return;
- }
-if (db > 1) fprintf(stderr, "record_CW-%d\n", k++);
-
- if (dy > 0) {
- h -= dy;
- } else {
- h += dy;
- src_y -= dy;
- }
- if (dx > 0) {
- w -= dx;
- } else {
- w += dx;
- src_x -= dx;
- }
-
- dst_x = src_x + dx;
- dst_y = src_y + dy;
-
- if (x0 == absent || x1 == absent || x2 == absent) {
- good = 0;
- } else if (y0 == absent || y1 == absent || y2 == absent) {
- good = 0;
- } else if (dx != 0 && dy != 0) {
- good = 0;
- } else if (w0 - w2 != nabs(dx)) {
- good = 0;
- } else if (h0 - h2 != nabs(dy)) {
- good = 0;
- } else if (scr_ev_cnt >= SCR_EV_MAX) {
- good = 0;
- }
-
- if (! good) {
- return;
- }
-if (db > 1) fprintf(stderr, "record_CW-%d\n", k++);
-
- /*
- * geometry OK.
- * after all of the above succeeds, now contact X server.
- */
- if (lookup_attr_cache(win, &cache_index, &next_index)) {
- i = cache_index;
- attr.x = scr_attr_cache[i].x;
- attr.y = scr_attr_cache[i].y;
- attr.width = scr_attr_cache[i].width;
- attr.height = scr_attr_cache[i].height;
- attr.map_state = scr_attr_cache[i].map_state;
- rx = scr_attr_cache[i].rx;
- ry = scr_attr_cache[i].ry;
- valid = scr_attr_cache[i].valid;
-
-if (0) fprintf(stderr, "lookup_attr_cache hit: %2d %2d 0x%lx %d\n",
- cache_index, next_index, win, valid);
-
- } else {
- valid = valid_window(win, &attr, 1);
-
-if (0) fprintf(stderr, "lookup_attr_cache MISS: %2d %2d 0x%lx %d\n",
- cache_index, next_index, win, valid);
-
- if (valid) {
- if (!xtranslate(win, rootwin, 0, 0, &rx, &ry, &c, 1)) {
- valid = 0;
- }
- }
- if (next_index >= 0) {
- i = next_index;
- scr_attr_cache[i].win = win;
- scr_attr_cache[i].fetched = 1;
- scr_attr_cache[i].valid = valid;
- scr_attr_cache[i].time = dnow();
- if (valid) {
- scr_attr_cache[i].x = attr.x;
- scr_attr_cache[i].y = attr.y;
- scr_attr_cache[i].width = attr.width;
- scr_attr_cache[i].height = attr.height;
- scr_attr_cache[i].depth = attr.depth;
- scr_attr_cache[i].class = attr.class;
- scr_attr_cache[i].backing_store =
- attr.backing_store;
- scr_attr_cache[i].map_state = attr.map_state;
-
- scr_attr_cache[i].rx = rx;
- scr_attr_cache[i].ry = ry;
- }
- }
- }
-
- if (! valid) {
- return;
- }
-if (db > 1) fprintf(stderr, "record_CW-%d\n", k++);
-
- if (attr.map_state != IsViewable) {
- return;
- }
-if (db > 1) fprintf(stderr, "record_CW-%d\n", k++);
-
- if (0 || dba || db) {
- double st, dt;
- st = (double) rec_data->server_time/1000.0;
- dt = (dnow() - servertime_diff) - st;
- fprintf(stderr, "record_CW-%d *FOUND_SCROLL: win: 0x%lx dx: %d dy: %d "
- "x: %d y: %d w: %d h: %d st: %.4f dt: %.4f %.4f\n", k++, win,
- dx, dy, src_x, src_y, w, h, st, dt, dnowx());
- }
-
- i = scr_ev_cnt;
-
- scr_ev[i].win = win;
- scr_ev[i].frame = None;
- scr_ev[i].dx = dx;
- scr_ev[i].dy = dy;
- scr_ev[i].x = rx + dst_x;
- scr_ev[i].y = ry + dst_y;
- scr_ev[i].w = w;
- scr_ev[i].h = h;
- scr_ev[i].t = ((double) rec_data->server_time)/1000.0;
- scr_ev[i].win_x = rx;
- scr_ev[i].win_y = ry;
- scr_ev[i].win_w = attr.width;
- scr_ev[i].win_h = attr.height;
- scr_ev[i].new_x = 0;
- scr_ev[i].new_y = 0;
- scr_ev[i].new_w = 0;
- scr_ev[i].new_h = 0;
-
- if (dx == 0) {
- if (dy > 0) {
- scr_ev[i].new_x = rx + src_x;
- scr_ev[i].new_y = ry + src_y;
- scr_ev[i].new_w = w;
- scr_ev[i].new_h = dy;
- } else {
- scr_ev[i].new_x = rx + src_x;
- scr_ev[i].new_y = ry + dst_y + h;
- scr_ev[i].new_w = w;
- scr_ev[i].new_h = -dy;
- }
- } else if (dy == 0) {
- if (dx > 0) {
- scr_ev[i].new_x = rx + src_x;
- scr_ev[i].new_y = rx + src_y;
- scr_ev[i].new_w = dx;
- scr_ev[i].new_h = h;
- } else {
- scr_ev[i].new_x = rx + dst_x + w;
- scr_ev[i].new_y = ry + src_y;
- scr_ev[i].new_w = -dx;
- scr_ev[i].new_h = h;
- }
- }
-
- /* indicate we have a new one */
- scr_ev_cnt++;
-
- index = 0;
-}
-
-static void record_switch(XPointer ptr, XRecordInterceptData *rec_data) {
- static int first = 1;
- xReq *req;
-
- if (first) {
- int i;
- for (i=0; i<SCR_ATTR_CACHE; i++) {
- scr_attr_cache[i].win = None;
- scr_attr_cache[i].fetched = 0;
- scr_attr_cache[i].valid = 0;
- scr_attr_cache[i].time = 0.0;
- }
- first = 0;
- }
-
- /* should handle control msgs, start/stop/etc */
- if (rec_data->category == XRecordStartOfData) {
- record_CW(ptr, rec_data);
- } else if (rec_data->category == XRecordEndOfData) {
- ;
- } else if (rec_data->category == XRecordClientStarted) {
- ;
- } else if (rec_data->category == XRecordClientDied) {
- ;
- } else if (rec_data->category == XRecordFromServer) {
- ;
- }
-
- if (rec_data->category != XRecordFromClient) {
- XRecordFreeData(rec_data);
- return;
- }
-
- req = (xReq *) rec_data->data;
-
- if (req->reqType == X_CopyArea) {
- record_CA(ptr, rec_data);
- } else if (req->reqType == X_ConfigureWindow) {
- record_CW(ptr, rec_data);
- } else {
- ;
- }
- XRecordFreeData(rec_data);
-}
-
-static void record_grab(XPointer ptr, XRecordInterceptData *rec_data) {
- xReq *req;
- int db = 0;
-
- if (debug_grabs) db = 1;
-
- /* should handle control msgs, start/stop/etc */
- if (rec_data->category == XRecordStartOfData) {
- ;
- } else if (rec_data->category == XRecordEndOfData) {
- ;
- } else if (rec_data->category == XRecordClientStarted) {
- ;
- } else if (rec_data->category == XRecordClientDied) {
- ;
- } else if (rec_data->category == XRecordFromServer) {
- ;
- }
-
- if (rec_data->category != XRecordFromClient) {
- XRecordFreeData(rec_data);
- return;
- }
-
- req = (xReq *) rec_data->data;
-
- if (req->reqType == X_GrabServer) {
- double now = dnowx();
- xserver_grabbed++;
- if (db) rfbLog("X server Grabbed: %d %.5f\n", xserver_grabbed, now);
- if (xserver_grabbed > 1) {
- /*
- * some apps do multiple grabs... very unlikely
- * two apps will be doing it at same time.
- */
- xserver_grabbed = 1;
- }
- } else if (req->reqType == X_UngrabServer) {
- double now = dnowx();
- xserver_grabbed--;
- if (xserver_grabbed < 0) {
- xserver_grabbed = 0;
- }
- if (db) rfbLog("X server Un-Grabbed: %d %.5f\n", xserver_grabbed, now);
- } else {
- ;
- }
- XRecordFreeData(rec_data);
-
- /* unused vars warning: */
- if (ptr) {}
-}
-#endif
-
-static void check_xrecord_grabserver(void) {
-#if LIBVNCSERVER_HAVE_RECORD
- int last_val, cnt = 0, i, max = 10;
- double d;
- if (!gdpy_ctrl || !gdpy_data) {
- return;
- }
- if (unixpw_in_progress) return;
-
- dtime0(&d);
- XFlush_wr(gdpy_ctrl);
- for (i=0; i<max; i++) {
- last_val = xserver_grabbed;
- XRecordProcessReplies(gdpy_data);
- if (xserver_grabbed != last_val) {
- cnt++;
- } else if (i > 2) {
- break;
- }
- }
- if (cnt) {
- XFlush_wr(gdpy_ctrl);
- }
- if (debug_grabs && cnt > 0) {
- d = dtime(&d);
-fprintf(stderr, "check_xrecord_grabserver: cnt=%d i=%d %.4f\n", cnt, i, d);
- }
-#endif
-}
-
-#if LIBVNCSERVER_HAVE_RECORD
-static void shutdown_record_context(XRecordContext rc, int bequiet, int reopen) {
- int ret1, ret2;
- int verb = (!bequiet && !quiet);
-
- RAWFB_RET_VOID
- if (0 || debug_scroll) {
- rfbLog("shutdown_record_context(0x%lx, %d, %d)\n", rc,
- bequiet, reopen);
- verb = 1;
- }
-
- ret1 = XRecordDisableContext(rdpy_ctrl, rc);
- if (!ret1 && verb) {
- rfbLog("XRecordDisableContext(0x%lx) failed.\n", rc);
- }
- ret2 = XRecordFreeContext(rdpy_ctrl, rc);
- if (!ret2 && verb) {
- rfbLog("XRecordFreeContext(0x%lx) failed.\n", rc);
- }
- XFlush_wr(rdpy_ctrl);
-
- if (reopen == 2 && ret1 && ret2) {
- reopen = 0; /* 2 means reopen only on failure */
- }
- if (reopen && gdpy_ctrl) {
- check_xrecord_grabserver();
- if (xserver_grabbed) {
- rfbLog("shutdown_record_context: skip reopen,"
- " server grabbed\n");
- reopen = 0;
- }
- }
- if (reopen) {
- char *dpystr = DisplayString(dpy);
-
- if (debug_scroll) {
- rfbLog("closing RECORD data connection.\n");
- }
- XCloseDisplay_wr(rdpy_data);
- rdpy_data = NULL;
-
- if (debug_scroll) {
- rfbLog("closing RECORD control connection.\n");
- }
- XCloseDisplay_wr(rdpy_ctrl);
- rdpy_ctrl = NULL;
-
- rdpy_ctrl = XOpenDisplay_wr(dpystr);
-
- if (! rdpy_ctrl) {
- rfbLog("Failed to reopen RECORD control connection:"
- "%s\n", dpystr);
- rfbLog(" disabling RECORD scroll detection.\n");
- use_xrecord = 0;
- return;
- }
- XSync(dpy, False);
-
- disable_grabserver(rdpy_ctrl, 0);
- XSync(rdpy_ctrl, True);
-
- rdpy_data = XOpenDisplay_wr(dpystr);
-
- if (! rdpy_data) {
- rfbLog("Failed to reopen RECORD data connection:"
- "%s\n", dpystr);
- rfbLog(" disabling RECORD scroll detection.\n");
- XCloseDisplay_wr(rdpy_ctrl);
- rdpy_ctrl = NULL;
- use_xrecord = 0;
- return;
- }
- disable_grabserver(rdpy_data, 0);
-
- if (debug_scroll || (! bequiet && reopen == 2)) {
- rfbLog("reopened RECORD data and control display"
- " connections: %s\n", dpystr);
- }
- }
-}
-#endif
-
-void check_xrecord_reset(int force) {
- static double last_reset = 0.0;
- int reset_time = 60, require_idle = 10;
- int reset_time2 = 600, require_idle2 = 40;
- double now = 0.0;
- XErrorHandler old_handler = NULL;
-
- if (gdpy_ctrl) {
- X_LOCK;
- check_xrecord_grabserver();
- X_UNLOCK;
- } else {
- /* more dicey if not watching grabserver */
- reset_time = reset_time2;
- require_idle = require_idle2;
- }
-
- if (!use_xrecord) {
- return;
- }
- if (xrecording) {
- return;
- }
- if (button_mask) {
- return;
- }
- if (xserver_grabbed) {
- return;
- }
-
- if (unixpw_in_progress) return;
-
-#if LIBVNCSERVER_HAVE_RECORD
- if (! rc_scroll) {
- return;
- }
- now = dnow();
- if (last_reset == 0.0) {
- last_reset = now;
- return;
- }
- /*
- * try to wait for a break in input to reopen the displays
- * this is only to avoid XGrabServer deadlock on the repopens.
- */
- if (force) {
- ;
- } else if (now < last_reset + reset_time) {
- return;
- } else if (now < last_pointer_click_time + require_idle) {
- return;
- } else if (now < last_keyboard_time + require_idle) {
- return;
- }
- X_LOCK;
- trapped_record_xerror = 0;
- old_handler = XSetErrorHandler(trap_record_xerror);
-
- /* unlikely, but check again since we will definitely be doing it. */
- if (gdpy_ctrl) {
- check_xrecord_grabserver();
- if (xserver_grabbed) {
- XSetErrorHandler(old_handler);
- X_UNLOCK;
- return;
- }
- }
-
- shutdown_record_context(rc_scroll, 0, 1);
- rc_scroll = 0;
-
- XSetErrorHandler(old_handler);
- X_UNLOCK;
-
- last_reset = now;
-#else
- if (!old_handler || now == 0.0 || !last_reset || !force) {}
-#endif
-}
-
-#define RECORD_ERROR_MSG(tag) \
- if (! quiet) { \
- static int cnt = 0; \
- static time_t last = 0; \
- int show = 0; \
- cnt++; \
- if (debug_scroll || cnt < 20) { \
- show = 1; \
- } else if (cnt == 20) { \
- last = time(NULL); \
- rfbLog("disabling RECORD XError messages for 600s\n"); \
- show = 1; \
- } else if (time(NULL) > last + 600) { \
- cnt = 0; \
- show = 1; \
- } \
- if (show) { \
- rfbLog("trapped RECORD XError: %s %s %d/%d/%d (0x%lx)\n", \
- tag, xerror_string(trapped_record_xerror_event), \
- (int) trapped_record_xerror_event->error_code, \
- (int) trapped_record_xerror_event->request_code, \
- (int) trapped_record_xerror_event->minor_code, \
- (int) trapped_record_xerror_event->resourceid); \
- } \
- }
-
-void xrecord_watch(int start, int setby) {
-#if LIBVNCSERVER_HAVE_RECORD
- Window focus, wm, c, clast;
- static double create_time = 0.0;
- int rc;
- int do_shutdown = 0;
- int reopen_dpys = 1;
- XErrorHandler old_handler = NULL;
- static Window last_win = None, last_result = None;
-#endif
- int db = debug_scroll;
- double now;
- static double last_error = 0.0;
-
-if (0) db = 1;
-
- if (nofb) {
- xrecording = 0;
- return;
- }
- if (use_threads) {
- /* XXX not working. Still? Painting errors. */
- static int first = 1;
- if (first) {
- if (use_xrecord && !getenv("XRECORD_THREADS")) {
- rfbLog("xrecord_watch: disabling scroll detection in -threads mode.\n");
- rfbLog("xrecord_watch: Set -env XRECORD_THREADS=1 to enable it.\n");
- use_xrecord = 0;
- xrecording = 0;
- }
- first = 0;
- }
- if (!use_xrecord && !xrecording) {
- return;
- }
- }
-
- dtime0(&now);
- if (now < last_error + 0.5) {
- return;
- }
-
- if (gdpy_ctrl) {
- X_LOCK;
- check_xrecord_grabserver();
- X_UNLOCK;
- if (xserver_grabbed) {
-if (db || debug_grabs) fprintf(stderr, "xrecord_watch: %d/%d out xserver_grabbed\n", start, setby);
- return;
- }
- }
-
-#if LIBVNCSERVER_HAVE_RECORD
- if (! start) {
- int shut_reopen = 2, shut_time = 25;
-if (db || debug_grabs) fprintf(stderr, "XRECORD OFF: %d/%d %.4f\n", xrecording, setby, now - x11vnc_start);
- xrecording = 0;
- if (! rc_scroll) {
- xrecord_focus_window = None;
- xrecord_wm_window = None;
- xrecord_ptr_window = None;
- xrecord_keysym = NoSymbol;
- rcs_scroll = 0;
- return;
- }
-
- if (! do_shutdown && now > create_time + shut_time) {
- /* XXX unstable if we keep a RECORD going forever */
- do_shutdown = 1;
- }
-
- SCR_LOCK;
-
- if (do_shutdown) {
-if (db > 1) fprintf(stderr, "=== shutdown-scroll 0x%lx\n", rc_scroll);
- X_LOCK;
- trapped_record_xerror = 0;
- old_handler = XSetErrorHandler(trap_record_xerror);
-
- shutdown_record_context(rc_scroll, 0, shut_reopen);
- rc_scroll = 0;
-
- /*
- * n.b. there is a grabserver issue wrt
- * XRecordCreateContext() even though rdpy_ctrl
- * is set imprevious to grabs. Perhaps a bug
- * in the X server or library...
- *
- * If there are further problems, a thought
- * to recreate rc_scroll right after the
- * reopen.
- */
-
- if (! use_xrecord) {
- XSetErrorHandler(old_handler);
- X_UNLOCK;
- SCR_UNLOCK;
- return;
- }
-
- XRecordProcessReplies(rdpy_data);
-
- if (trapped_record_xerror) {
- RECORD_ERROR_MSG("shutdown");
- last_error = now;
- }
-
- XSetErrorHandler(old_handler);
- X_UNLOCK;
- SCR_UNLOCK;
-
- } else {
- if (rcs_scroll) {
-if (db > 1) fprintf(stderr, "=== disab-scroll 0x%lx 0x%lx\n", rc_scroll, rcs_scroll);
- X_LOCK;
- trapped_record_xerror = 0;
- old_handler =
- XSetErrorHandler(trap_record_xerror);
-
- rcs_scroll = XRecordCurrentClients;
- XRecordUnregisterClients(rdpy_ctrl, rc_scroll,
- &rcs_scroll, 1);
- XRecordDisableContext(rdpy_ctrl, rc_scroll);
- XFlush_wr(rdpy_ctrl);
- XRecordProcessReplies(rdpy_data);
-
- if (trapped_record_xerror) {
- RECORD_ERROR_MSG("disable");
-
- shutdown_record_context(rc_scroll,
- 0, reopen_dpys);
- rc_scroll = 0;
-
- last_error = now;
-
- if (! use_xrecord) {
- XSetErrorHandler(old_handler);
- X_UNLOCK;
- SCR_UNLOCK;
- return;
- }
- }
- XSetErrorHandler(old_handler);
- X_UNLOCK;
- }
- }
-
- SCR_UNLOCK;
- /*
- * XXX if we do a XFlush_wr(rdpy_ctrl) here we get:
- *
-
- X Error of failed request: XRecordBadContext
- Major opcode of failed request: 145 (RECORD)
- Minor opcode of failed request: 5 (XRecordEnableContext)
- Context in failed request: 0x2200013
- Serial number of failed request: 29
- Current serial number in output stream: 29
-
- *
- * need to figure out what is going on... since it may lead
- * infrequent failures.
- */
- xrecord_focus_window = None;
- xrecord_wm_window = None;
- xrecord_ptr_window = None;
- xrecord_keysym = NoSymbol;
- rcs_scroll = 0;
- return;
- }
-if (db || debug_grabs) fprintf(stderr, "XRECORD ON: %d/%d %.4f\n", xrecording, setby, now - x11vnc_start);
-
- if (xrecording) {
- return;
- }
-
- if (do_shutdown && rc_scroll) {
- static int didmsg = 0;
- /* should not happen... */
- if (0 || !didmsg) {
- rfbLog("warning: do_shutdown && rc_scroll\n");
- didmsg = 1;
- }
- xrecord_watch(0, SCR_NONE);
- }
-
- xrecording = 0;
- xrecord_focus_window = None;
- xrecord_wm_window = None;
- xrecord_ptr_window = None;
- xrecord_keysym = NoSymbol;
- xrecord_set_by_keys = 0;
- xrecord_set_by_mouse = 0;
-
- /* get the window with focus and mouse pointer: */
- clast = None;
- focus = None;
- wm = None;
-
- X_LOCK;
- SCR_LOCK;
-#if 0
- /*
- * xrecord_focus_window / focus not currently used... save a
- * round trip to the X server for now.
- * N.B. our heuristic is inaccurate: if he is scrolling and
- * drifts off of the scrollbar onto another application we
- * will catch that application, not the starting ones.
- * check_xrecord_{keys,mouse} mitigates this somewhat by
- * delaying calls to xrecord_watch as much as possible.
- */
- XGetInputFocus(dpy, &focus, &i);
-#endif
-
- wm = query_pointer(rootwin);
- if (wm) {
- c = wm;
- } else {
- c = rootwin;
- }
-
- /* descend a bit to avoid wm frames: */
- if (c != rootwin && c == last_win) {
- /* use cached results to avoid roundtrips: */
- clast = last_result;
- } else if (scroll_good_all == NULL && scroll_skip_all == NULL) {
- /* more efficient if name info not needed. */
- xrecord_name_info[0] = '\0';
- clast = descend_pointer(6, c, NULL, 0);
- } else {
- char *nm;
- int matched_good = 0, matched_skip = 0;
-
- clast = descend_pointer(6, c, xrecord_name_info, NAMEINFO);
-if (db) fprintf(stderr, "name_info: %s\n", xrecord_name_info);
-
- nm = xrecord_name_info;
-
- if (scroll_good_all) {
- matched_good += match_str_list(nm, scroll_good_all);
- }
- if (setby == SCR_KEY && scroll_good_key) {
- matched_good += match_str_list(nm, scroll_good_key);
- }
- if (setby == SCR_MOUSE && scroll_good_mouse) {
- matched_good += match_str_list(nm, scroll_good_mouse);
- }
- if (scroll_skip_all) {
- matched_skip += match_str_list(nm, scroll_skip_all);
- }
- if (setby == SCR_KEY && scroll_skip_key) {
- matched_skip += match_str_list(nm, scroll_skip_key);
- }
- if (setby == SCR_MOUSE && scroll_skip_mouse) {
- matched_skip += match_str_list(nm, scroll_skip_mouse);
- }
-
- if (!matched_good && matched_skip) {
- clast = None;
- }
- }
- if (c != rootwin) {
- /* cache results for possible use next call */
- last_win = c;
- last_result = clast;
- }
-
- if (!clast || clast == rootwin) {
-if (db) fprintf(stderr, "--- xrecord_watch: SKIP.\n");
- X_UNLOCK;
- SCR_UNLOCK;
- return;
- }
-
- /* set protocol request ranges: */
- rr_scroll[0] = rr_CA;
- rr_scroll[1] = rr_CW;
-
- /*
- * start trapping... there still are some occasional failures
- * not yet understood, likely some race condition WRT the
- * context being setup.
- */
- trapped_record_xerror = 0;
- old_handler = XSetErrorHandler(trap_record_xerror);
-
- if (! rc_scroll) {
- /* do_shutdown case or first time in */
-
- if (gdpy_ctrl) {
- /*
- * Even though rdpy_ctrl is impervious to grabs
- * at this point, we still get deadlock, why?
- * It blocks in the library find_display() call.
- */
- check_xrecord_grabserver();
- if (xserver_grabbed) {
- XSetErrorHandler(old_handler);
- X_UNLOCK;
- SCR_UNLOCK;
- return;
- }
- }
- rcs_scroll = (XRecordClientSpec) clast;
- rc_scroll = XRecordCreateContext(rdpy_ctrl, 0, &rcs_scroll, 1,
- rr_scroll, 2);
-
- if (! do_shutdown) {
- XSync(rdpy_ctrl, False);
- }
-if (db) fprintf(stderr, "NEW rc: 0x%lx\n", rc_scroll);
- if (rc_scroll) {
- dtime0(&create_time);
- } else {
- rcs_scroll = 0;
- }
-
- } else if (! do_shutdown) {
- if (rcs_scroll) {
- /*
- * should have been unregistered in xrecord_watch(0)...
- */
- rcs_scroll = XRecordCurrentClients;
- XRecordUnregisterClients(rdpy_ctrl, rc_scroll,
- &rcs_scroll, 1);
-
-if (db > 1) fprintf(stderr, "=2= unreg-scroll 0x%lx 0x%lx\n", rc_scroll, rcs_scroll);
-
- }
-
- rcs_scroll = (XRecordClientSpec) clast;
-
-if (db > 1) fprintf(stderr, "=-= reg-scroll 0x%lx 0x%lx\n", rc_scroll, rcs_scroll);
-
- if (!XRecordRegisterClients(rdpy_ctrl, rc_scroll, 0,
- &rcs_scroll, 1, rr_scroll, 2)) {
- if (1 || now > last_error + 60) {
- rfbLog("failed to register client 0x%lx with"
- " X RECORD context rc_scroll.\n", clast);
- }
- last_error = now;
- rcs_scroll = 0;
- /* continue on for now... */
- }
- }
-
- XFlush_wr(rdpy_ctrl);
-
-if (db) fprintf(stderr, "rc_scroll: 0x%lx\n", rc_scroll);
- if (trapped_record_xerror) {
- RECORD_ERROR_MSG("register");
- }
-
- if (! rc_scroll) {
- XSetErrorHandler(old_handler);
- X_UNLOCK;
- SCR_UNLOCK;
- use_xrecord = 0;
- rfbLog("failed to create X RECORD context rc_scroll.\n");
- rfbLog(" switching to -noscrollcopyrect mode.\n");
- return;
- } else if (! rcs_scroll || trapped_record_xerror) {
- /* try again later */
- shutdown_record_context(rc_scroll, 0, reopen_dpys);
- rc_scroll = 0;
- last_error = now;
-
- XSetErrorHandler(old_handler);
- X_UNLOCK;
- SCR_UNLOCK;
- return;
- }
-
- xrecord_focus_window = focus;
-#if 0
- /* xrecord_focus_window currently unused. */
- if (! xrecord_focus_window) {
- xrecord_focus_window = clast;
- }
-#endif
- xrecord_wm_window = wm;
- if (! xrecord_wm_window) {
- xrecord_wm_window = clast;
- }
-
- xrecord_ptr_window = clast;
-
- xrecording = 1;
- xrecord_seq++;
- dtime0(&xrecord_start);
-
- rc = XRecordEnableContextAsync(rdpy_data, rc_scroll, record_switch,
- (XPointer) xrecord_seq);
-
- if (!rc || trapped_record_xerror) {
- if (1 || now > last_error + 60) {
- rfbLog("failed to enable RECORD context "
- "rc_scroll: 0x%lx rc: %d\n", rc_scroll, rc);
- if (trapped_record_xerror) {
- RECORD_ERROR_MSG("enable-failed");
- }
- }
- shutdown_record_context(rc_scroll, 0, reopen_dpys);
- rc_scroll = 0;
- last_error = now;
- xrecording = 0;
- /* continue on for now... */
- }
- XSetErrorHandler(old_handler);
-
- /* XXX this may cause more problems than it solves... */
- if (use_xrecord) {
- XFlush_wr(rdpy_data);
- }
-
- X_UNLOCK;
- SCR_UNLOCK;
-#endif
-}
-
-
OpenPOWER on IntegriCloud