diff options
Diffstat (limited to 'x11vnc/userinput.c')
-rw-r--r-- | x11vnc/userinput.c | 10199 |
1 files changed, 0 insertions, 10199 deletions
diff --git a/x11vnc/userinput.c b/x11vnc/userinput.c deleted file mode 100644 index 84bcb7b..0000000 --- a/x11vnc/userinput.c +++ /dev/null @@ -1,10199 +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. -*/ - -/* -- userinput.c -- */ - -#include "x11vnc.h" -#include "xwrappers.h" -#include "xdamage.h" -#include "xrecord.h" -#include "xinerama.h" -#include "win_utils.h" -#include "xevents.h" -#include "user.h" -#include "scan.h" -#include "cleanup.h" -#include "pointer.h" -#include "rates.h" -#include "keyboard.h" -#include "solid.h" -#include "xrandr.h" -#include "8to24.h" -#include "unixpw.h" -#include "macosx.h" -#include "macosxCGS.h" -#include "cursor.h" -#include "screen.h" -#include "connections.h" - -/* - * user input handling heuristics - */ -int defer_update_nofb = 4; /* defer a shorter time under -nofb */ -int last_scroll_type = SCR_NONE; - - -int get_wm_frame_pos(int *px, int *py, int *x, int *y, int *w, int *h, - Window *frame, Window *win); -void parse_scroll_copyrect(void); -void parse_fixscreen(void); -void parse_wireframe(void); - -void set_wirecopyrect_mode(char *str); -void set_scrollcopyrect_mode(char *str); -void initialize_scroll_keys(void); -void initialize_scroll_matches(void); -void initialize_scroll_term(void); -void initialize_max_keyrepeat(void); - -int direct_fb_copy(int x1, int y1, int x2, int y2, int mark); -void fb_push(void); -int fb_push_wait(double max_wait, int flags); -void eat_viewonly_input(int max_eat, int keep); - -void mark_for_xdamage(int x, int y, int w, int h); -void mark_region_for_xdamage(sraRegionPtr region); -void set_xdamage_mark(int x, int y, int w, int h); -int near_wm_edge(int x, int y, int w, int h, int px, int py); -int near_scrollbar_edge(int x, int y, int w, int h, int px, int py); - -void check_fixscreen(void); -int check_xrecord(void); -int check_wireframe(void); -int fb_update_sent(int *count); -int check_user_input(double dt, double dtr, int tile_diffs, int *cnt); -void do_copyregion(sraRegionPtr region, int dx, int dy, int mode); - -int check_ncache(int reset, int mode); -int find_rect(int idx, int x, int y, int w, int h); -int bs_restore(int idx, int *nbatch, sraRegionPtr rmask, XWindowAttributes *attr, int clip, int nopad, int *valid, int verb); -int try_to_fix_su(Window win, int idx, Window above, int *nbatch, char *mode); -int try_to_fix_resize_su(Window orig_frame, int orig_x, int orig_y, int orig_w, int orig_h, - int x, int y, int w, int h, int try_batch); -int lookup_win_index(Window); -void set_ncache_xrootpmap(void); - -static void get_client_regions(int *req, int *mod, int *cpy, int *num) ; -static void parse_scroll_copyrect_str(char *scr); -static void parse_wireframe_str(char *wf); -static void destroy_str_list(char **list); -static void draw_box(int x, int y, int w, int h, int restore); -static int do_bdpush(Window wm_win, int x0, int y0, int w0, int h0, int bdx, - int bdy, int bdskinny); -static int set_ypad(void); -static void scale_mark(int x1, int y1, int x2, int y2, int mark); -static int push_scr_ev(double *age, int type, int bdpush, int bdx, int bdy, - int bdskinny, int first_push); -static int crfix(int x, int dx, int Lx); -static int scrollability(Window win, int set); -static int eat_pointer(int max_ptr_eat, int keep); -static void set_bdpush(int type, double *last_bdpush, int *pushit); -static int repeat_check(double last_key_scroll); -static int check_xrecord_keys(void); -static int check_xrecord_mouse(void); -static int try_copyrect(Window orig_frame, Window frame, int x, int y, int w, int h, - int dx, int dy, int *obscured, sraRegionPtr extra_clip, double max_wait, int *nbatch); -static int wireframe_mod_state(); -static void check_user_input2(double dt); -static void check_user_input3(double dt, double dtr, int tile_diffs); -static void check_user_input4(double dt, double dtr, int tile_diffs); - -winattr_t *cache_list; - -/* - * For -wireframe: find the direct child of rootwin that has the - * pointer, assume that is the WM frame that contains the application - * (i.e. wm reparents the app toplevel) return frame position and size - * if successful. - */ -int get_wm_frame_pos(int *px, int *py, int *x, int *y, int *w, int *h, - Window *frame, Window *win) { -#if !NO_X11 - Window r, c; - XWindowAttributes attr; - Bool ret; - int rootx, rooty, wx, wy; - unsigned int mask; -#endif - -#ifdef MACOSX - if (macosx_console) { - return macosx_get_wm_frame_pos(px, py, x, y, w, h, frame, win); - } -#endif - - RAWFB_RET(0) - -#if NO_X11 - if (!px || !py || !x || !y || !w || !h || !frame || !win) {} - return 0; -#else - - - ret = XQueryPointer_wr(dpy, rootwin, &r, &c, &rootx, &rooty, &wx, &wy, - &mask); - - *frame = c; - - /* current pointer position is returned too */ - *px = rootx; - *py = rooty; - - if (!ret || ! c || c == rootwin) { - /* no immediate child */ - return 0; - } - - /* child window position and size */ - if (! valid_window(c, &attr, 1)) { - return 0; - } - - *x = attr.x; - *y = attr.y; - *w = attr.width; - *h = attr.height; - -#if 0 - /* more accurate, but the animation is bogus anyway */ - if (attr.border_width > 0) { - *w += 2 * attr.border_width; - *h += 2 * attr.border_width; - } -#endif - - if (win != NULL) { - *win = descend_pointer(5, c, NULL, 0); - } - - return 1; -#endif /* NO_X11 */ -} - -static int scrollcopyrect_top, scrollcopyrect_bot; -static int scrollcopyrect_left, scrollcopyrect_right; -static double scr_key_time, scr_key_persist; -static double scr_mouse_time, scr_mouse_persist, scr_mouse_maxtime; -static double scr_mouse_pointer_delay; -static double scr_key_bdpush_time, scr_mouse_bdpush_time; - -static void parse_scroll_copyrect_str(char *scr) { - char *p, *str; - int i; - char *part[16]; - - for (i=0; i<16; i++) { - part[i] = NULL; - } - - if (scr == NULL || *scr == '\0') { - return; - } - - str = strdup(scr); - - p = strtok(str, ","); - i = 0; - while (p) { - part[i++] = strdup(p); - p = strtok(NULL, ","); - if (i >= 16) break; - } - free(str); - - - /* - * Top, Bottom, Left, Right tolerances for scrollbar locations. - */ - if ((str = part[0]) != NULL) { - int t, b, l, r; - if (sscanf(str, "%d+%d+%d+%d", &t, &b, &l, &r) == 4) { - scrollcopyrect_top = t; - scrollcopyrect_bot = b; - scrollcopyrect_left = l; - scrollcopyrect_right = r; - } - free(str); - } - - /* key scrolling timing heuristics. */ - if ((str = part[1]) != NULL) { - double t1, t2, t3; - if (sscanf(str, "%lf+%lf+%lf", &t1, &t2, &t3) == 3) { - scr_key_time = t1; - scr_key_persist = t2; - scr_key_bdpush_time = t3; - } - free(str); - } - - /* mouse scrolling timing heuristics. */ - if ((str = part[2]) != NULL) { - double t1, t2, t3, t4, t5; - if (sscanf(str, "%lf+%lf+%lf+%lf+%lf", &t1, &t2, &t3, &t4, - &t5) == 5) { - scr_mouse_time = t1; - scr_mouse_persist = t2; - scr_mouse_bdpush_time = t3; - scr_mouse_pointer_delay = t4; - scr_mouse_maxtime = t5; - } - free(str); - } -} - -void parse_scroll_copyrect(void) { - parse_scroll_copyrect_str(SCROLL_COPYRECT_PARMS); - if (! scroll_copyrect_str) { - scroll_copyrect_str = strdup(SCROLL_COPYRECT_PARMS); - } - parse_scroll_copyrect_str(scroll_copyrect_str); -} - -void parse_fixscreen(void) { - char *str, *p; - - screen_fixup_V = 0.0; - screen_fixup_C = 0.0; - screen_fixup_X = 0.0; - screen_fixup_8 = 0.0; - - if (! screen_fixup_str) { - return; - } - - str = strdup(screen_fixup_str); - - p = strtok(str, ","); - while (p) { - double t; - if (*p == 'V' && sscanf(p, "V=%lf", &t) == 1) { - screen_fixup_V = t; - } else if (*p == 'C' && sscanf(p, "C=%lf", &t) == 1) { - screen_fixup_C = t; - } else if (*p == 'X' && sscanf(p, "X=%lf", &t) == 1) { - screen_fixup_X = t; - } else if (*p == 'X' && sscanf(p, "8=%lf", &t) == 1) { - screen_fixup_8 = t; - } - p = strtok(NULL, ","); - } - free(str); - - if (screen_fixup_V < 0.0) screen_fixup_V = 0.0; - if (screen_fixup_C < 0.0) screen_fixup_C = 0.0; - if (screen_fixup_X < 0.0) screen_fixup_X = 0.0; - if (screen_fixup_8 < 0.0) screen_fixup_8 = 0.0; -} - -/* -WIREFRAME_PARMS "0xff,2,0,30+6+6+6,Alt,0.05+0.3+2.0,8" - 0xff,2,0,32+8+8+8,all,0.15+0.30+5.0+0.125 -shade,linewidth,percent,T+B+L+R,mods,t1+t2+t3+t4 - */ -#define LW_MAX 8 -static unsigned long wireframe_shade = 0xff; -static int wireframe_lw; -static double wireframe_frac; -static int wireframe_top, wireframe_bot, wireframe_left, wireframe_right; -static double wireframe_t1, wireframe_t2, wireframe_t3, wireframe_t4; -static char *wireframe_mods = NULL; - -/* - * Parse the gory -wireframe string for parameters. - */ -static void parse_wireframe_str(char *wf) { - char *p, *str; - int i; - char *part[16]; - - for (i=0; i<16; i++) { - part[i] = NULL; - } - - if (wf == NULL || *wf == '\0') { - return; - } - - str = strdup(wf); - - /* leading ",", make it start with ignorable string "z" */ - if (*str == ',') { - char *tmp = (char *) malloc(strlen(str)+2); - strcpy(tmp, "z"); - strcat(tmp, str); - free(str); - str = tmp; - } - - p = strtok(str, ","); - i = 0; - while (p) { - part[i++] = strdup(p); - p = strtok(NULL, ","); - if (i >= 16) break; - } - free(str); - - - /* Wireframe shade, color, RGB: */ - if ((str = part[0]) != NULL) { - unsigned long n; - int r, g, b, ok = 0; - XColor cdef; - Colormap cmap; - if (dpy && (bpp == 32 || bpp == 16)) { -#if !NO_X11 - X_LOCK; - cmap = DefaultColormap (dpy, scr); - if (XParseColor(dpy, cmap, str, &cdef) && - XAllocColor(dpy, cmap, &cdef)) { - r = cdef.red >> 8; - g = cdef.green >> 8; - b = cdef.blue >> 8; - if (r == 0 && g == 0) { - g = 1; /* need to be > 255 */ - } - n = 0; - n |= (r << main_red_shift); - n |= (g << main_green_shift); - n |= (b << main_blue_shift); - wireframe_shade = n; - ok = 1; - } - X_UNLOCK; -#else - r = g = b = 0; - cmap = 0; - cdef.pixel = 0; -#endif - } - if (ok) { - ; - } else if (sscanf(str, "0x%lx", &n) == 1) { - wireframe_shade = n; - } else if (sscanf(str, "%lu", &n) == 1) { - wireframe_shade = n; - } else if (sscanf(str, "%lx", &n) == 1) { - wireframe_shade = n; - } - free(str); - } - - /* linewidth: # of pixels wide for the wireframe lines */ - if ((str = part[1]) != NULL) { - int n; - if (sscanf(str, "%d", &n) == 1) { - wireframe_lw = n; - if (wireframe_lw < 1) { - wireframe_lw = 1; - } - if (wireframe_lw > LW_MAX) { - wireframe_lw = LW_MAX; - } - } - free(str); - } - - /* percentage cutoff for opaque move/resize (like WM's) */ - if ((str = part[2]) != NULL) { - if (*str == '\0') { - ; - } else if (strchr(str, '.')) { - wireframe_frac = atof(str); - } else { - wireframe_frac = ((double) atoi(str))/100.0; - } - free(str); - } - - /* - * Top, Bottom, Left, Right tolerances to guess the wm frame is - * being grabbed (Top is traditionally bigger, i.e. titlebar): - */ - if ((str = part[3]) != NULL) { - int t, b, l, r; - if (sscanf(str, "%d+%d+%d+%d", &t, &b, &l, &r) == 4) { - wireframe_top = t; - wireframe_bot = b; - wireframe_left = l; - wireframe_right = r; - } - free(str); - } - - /* - * wireframe in interior with Modifier down. - * 0 => no mods - * 1 => all mods - * Shift,Alt,Control,Meta,Super,Hyper - */ - if (wireframe_mods) { - free(wireframe_mods); - } - wireframe_mods = NULL; - if ((str = part[4]) != NULL) { - if (*str == '0' || !strcmp(str, "none")) { - ; - } else if (*str == '1' || !strcmp(str, "all")) { - wireframe_mods = strdup("all"); - } else if (!strcmp(str, "Alt") || !strcmp(str, "Shift") - || !strcmp(str, "Control") || !strcmp(str, "Meta") - || !strcmp(str, "Super") || !strcmp(str, "Hyper")) { - wireframe_mods = strdup(str); - } - } - - /* check_wireframe() timing heuristics. */ - if ((str = part[5]) != NULL) { - double t1, t2, t3, t4; - if (sscanf(str, "%lf+%lf+%lf+%lf", &t1, &t2, &t3, &t4) == 4) { - wireframe_t1 = t1; - wireframe_t2 = t2; - wireframe_t3 = t3; - wireframe_t4 = t4; - } - free(str); - } -} - -/* - * First parse the defaults and apply any user supplied ones (may be a subset) - */ -void parse_wireframe(void) { - parse_wireframe_str(WIREFRAME_PARMS); - if (! wireframe_str) { - wireframe_str = strdup(WIREFRAME_PARMS); - } - parse_wireframe_str(wireframe_str); -} - -/* - * Set wireframe_copyrect based on desired mode. - */ -void set_wirecopyrect_mode(char *str) { - char *orig = wireframe_copyrect; - if (str == NULL || *str == '\0') { - wireframe_copyrect = strdup(wireframe_copyrect_default); - } else if (!strcmp(str, "always") || !strcmp(str, "all")) { - wireframe_copyrect = strdup("always"); - } else if (!strcmp(str, "top")) { - wireframe_copyrect = strdup("top"); - } else if (!strcmp(str, "never") || !strcmp(str, "none")) { - wireframe_copyrect = strdup("never"); - } else { - if (! wireframe_copyrect) { - wireframe_copyrect = strdup(wireframe_copyrect_default); - } else { - orig = NULL; - } - rfbLog("unknown -wirecopyrect mode: %s, using: %s\n", str, - wireframe_copyrect); - } - if (orig) { - free(orig); - } -} - -/* - * Set scroll_copyrect based on desired mode. - */ -void set_scrollcopyrect_mode(char *str) { - char *orig = scroll_copyrect; - if (str == NULL || *str == '\0') { - scroll_copyrect = strdup(scroll_copyrect_default); - } else if (!strcmp(str, "always") || !strcmp(str, "all") || - !strcmp(str, "both")) { - scroll_copyrect = strdup("always"); - } else if (!strcmp(str, "keys") || !strcmp(str, "keyboard")) { - scroll_copyrect = strdup("keys"); - } else if (!strcmp(str, "mouse") || !strcmp(str, "pointer")) { - scroll_copyrect = strdup("mouse"); - } else if (!strcmp(str, "never") || !strcmp(str, "none")) { - scroll_copyrect = strdup("never"); - } else { - if (! scroll_copyrect) { - scroll_copyrect = strdup(scroll_copyrect_default); - } else { - orig = NULL; - } - rfbLog("unknown -scrollcopyrect mode: %s, using: %s\n", str, - scroll_copyrect); - } - if (orig) { - free(orig); - } -} - -void initialize_scroll_keys(void) { - char *str, *p; - int i, nkeys = 0, saw_builtin = 0; - int ks_max = 2 * 0xFFFF; - - if (scroll_key_list) { - free(scroll_key_list); - scroll_key_list = NULL; - } - if (! scroll_key_list_str || *scroll_key_list_str == '\0') { - return; - } - - if (strstr(scroll_key_list_str, "builtin")) { - int k; - /* add in number of keysyms builtin gives */ - for (k=1; k<ks_max; k++) { - if (xrecord_scroll_keysym((rfbKeySym) k)) { - nkeys++; - } - } - } - - nkeys++; /* first key, i.e. no commas. */ - p = str = strdup(scroll_key_list_str); - while(*p) { - if (*p == ',') { - nkeys++; /* additional key. */ - } - p++; - } - - nkeys++; /* exclude/include 0 element */ - nkeys++; /* trailing NoSymbol */ - - scroll_key_list = (KeySym *) malloc(nkeys*sizeof(KeySym)); - for (i=0; i<nkeys; i++) { - scroll_key_list[i] = NoSymbol; - } - if (*str == '-') { - scroll_key_list[0] = 1; - p = strtok(str+1, ","); - } else { - p = strtok(str, ","); - } - i = 1; - while (p) { - if (!strcmp(p, "builtin")) { - int k; - if (saw_builtin) { - p = strtok(NULL, ","); - continue; - } - saw_builtin = 1; - for (k=1; k<ks_max; k++) { - if (xrecord_scroll_keysym((rfbKeySym) k)) { - scroll_key_list[i++] = (rfbKeySym) k; - } - } - } else { - unsigned int in; - if (sscanf(p, "%u", &in) == 1) { - scroll_key_list[i++] = (rfbKeySym) in; - } else if (sscanf(p, "0x%x", &in) == 1) { - scroll_key_list[i++] = (rfbKeySym) in; - } else if (XStringToKeysym(p) != NoSymbol) { - scroll_key_list[i++] = XStringToKeysym(p); - } else { - rfbLog("initialize_scroll_keys: skip unknown " - "keysym: %s\n", p); - } - } - p = strtok(NULL, ","); - } - free(str); -} - -static void destroy_str_list(char **list) { - int i = 0; - if (! list) { - return; - } - while (list[i] != NULL) { - free(list[i++]); - } - free(list); -} - -void initialize_scroll_matches(void) { - char *str, *imp = "__IMPOSSIBLE_STR__"; - int i, n, nkey, nmouse; - - destroy_str_list(scroll_good_all); - scroll_good_all = NULL; - destroy_str_list(scroll_good_key); - scroll_good_key = NULL; - destroy_str_list(scroll_good_mouse); - scroll_good_mouse = NULL; - - destroy_str_list(scroll_skip_all); - scroll_skip_all = NULL; - destroy_str_list(scroll_skip_key); - scroll_skip_key = NULL; - destroy_str_list(scroll_skip_mouse); - scroll_skip_mouse = NULL; - - /* scroll_good: */ - if (scroll_good_str != NULL && *scroll_good_str != '\0') { - str = scroll_good_str; - } else { - str = scroll_good_str0; - } - scroll_good_all = create_str_list(str); - - nkey = 0; - nmouse = 0; - n = 0; - while (scroll_good_all[n] != NULL) { - char *s = scroll_good_all[n++]; - if (strstr(s, "KEY:") == s) nkey++; - if (strstr(s, "MOUSE:") == s) nmouse++; - } - if (nkey++) { - scroll_good_key = (char **) malloc(nkey*sizeof(char *)); - for (i=0; i<nkey; i++) scroll_good_key[i] = NULL; - } - if (nmouse++) { - scroll_good_mouse = (char **) malloc(nmouse*sizeof(char *)); - for (i=0; i<nmouse; i++) scroll_good_mouse[i] = NULL; - } - nkey = 0; - nmouse = 0; - for (i=0; i<n; i++) { - char *s = scroll_good_all[i]; - if (strstr(s, "KEY:") == s) { - scroll_good_key[nkey++] = strdup(s+strlen("KEY:")); - free(s); - scroll_good_all[i] = strdup(imp); - } else if (strstr(s, "MOUSE:") == s) { - scroll_good_mouse[nmouse++]=strdup(s+strlen("MOUSE:")); - free(s); - scroll_good_all[i] = strdup(imp); - } - } - - /* scroll_skip: */ - if (scroll_skip_str != NULL && *scroll_skip_str != '\0') { - str = scroll_skip_str; - } else { - str = scroll_skip_str0; - } - scroll_skip_all = create_str_list(str); - - nkey = 0; - nmouse = 0; - n = 0; - while (scroll_skip_all[n] != NULL) { - char *s = scroll_skip_all[n++]; - if (strstr(s, "KEY:") == s) nkey++; - if (strstr(s, "MOUSE:") == s) nmouse++; - } - if (nkey++) { - scroll_skip_key = (char **) malloc(nkey*sizeof(char *)); - for (i=0; i<nkey; i++) scroll_skip_key[i] = NULL; - } - if (nmouse++) { - scroll_skip_mouse = (char **) malloc(nmouse*sizeof(char *)); - for (i=0; i<nmouse; i++) scroll_skip_mouse[i] = NULL; - } - nkey = 0; - nmouse = 0; - for (i=0; i<n; i++) { - char *s = scroll_skip_all[i]; - if (strstr(s, "KEY:") == s) { - scroll_skip_key[nkey++] = strdup(s+strlen("KEY:")); - free(s); - scroll_skip_all[i] = strdup(imp); - } else if (strstr(s, "MOUSE:") == s) { - scroll_skip_mouse[nmouse++]=strdup(s+strlen("MOUSE:")); - free(s); - scroll_skip_all[i] = strdup(imp); - } - } -} - -void initialize_scroll_term(void) { - char *str; - int n; - - destroy_str_list(scroll_term); - scroll_term = NULL; - - if (scroll_term_str != NULL && *scroll_term_str != '\0') { - str = scroll_term_str; - } else { - str = scroll_term_str0; - } - if (!strcmp(str, "none")) { - return; - } - scroll_term = create_str_list(str); - - n = 0; - while (scroll_term[n] != NULL) { - char *s = scroll_good_all[n++]; - /* pull parameters out at some point */ - s = NULL; - } -} - -void initialize_max_keyrepeat(void) { - char *str; - int lo, hi; - - if (max_keyrepeat_str != NULL && *max_keyrepeat_str != '\0') { - str = max_keyrepeat_str; - } else { - str = max_keyrepeat_str0; - } - - if (sscanf(str, "%d-%d", &lo, &hi) != 2) { - rfbLog("skipping invalid -scr_keyrepeat string: %s\n", str); - sscanf(max_keyrepeat_str0, "%d-%d", &lo, &hi); - } - max_keyrepeat_lo = lo; - max_keyrepeat_hi = hi; - if (max_keyrepeat_lo < 1) { - max_keyrepeat_lo = 1; - } - if (max_keyrepeat_hi > 40) { - max_keyrepeat_hi = 40; - } -} - -typedef struct saveline { - int x0, y0, x1, y1; - int shift; - int vert; - int saved; - char *data; -} saveline_t; - -/* - * Draw the wireframe box onto the framebuffer. Saves the real - * framebuffer data to some storage lines. Restores previous lines. - * use restore = 1 to clean up (done with animation). - * This works with -scale. - */ -static void draw_box(int x, int y, int w, int h, int restore) { - int x0, y0, x1, y1, i, pixelsize = bpp/8; - char *dst, *src, *use_fb; - static saveline_t *save[4]; - static int first = 1, len = 0; - int max = dpy_x > dpy_y ? dpy_x : dpy_y; - int use_Bpl, lw = wireframe_lw; - unsigned long shade = wireframe_shade; - int color = 0; - unsigned short us = 0; - unsigned long ul = 0; - - if (clipshift) { - x -= coff_x; - y -= coff_y; - } - - /* handle -8to24 mode: use 2nd fb only */ - use_fb = main_fb; - use_Bpl = main_bytes_per_line; - - if (cmap8to24 && cmap8to24_fb) { - use_fb = cmap8to24_fb; - pixelsize = 4; - if (depth <= 8) { - use_Bpl *= 4; - } else if (depth <= 16) { - use_Bpl *= 2; - } - } - - if (max > len) { - /* create/resize storage lines: */ - for (i=0; i<4; i++) { - len = max; - if (! first && save[i]) { - if (save[i]->data) { - free(save[i]->data); - save[i]->data = NULL; - } - free(save[i]); - } - save[i] = (saveline_t *) malloc(sizeof(saveline_t)); - save[i]->saved = 0; - save[i]->data = (char *) malloc( (LW_MAX+1)*len*4 ); - - /* - * Four types of lines: - * 0) top horizontal - * 1) bottom horizontal - * 2) left vertical - * 3) right vertical - * - * shift means shifted by width or height. - */ - if (i == 0) { - save[i]->vert = 0; - save[i]->shift = 0; - } else if (i == 1) { - save[i]->vert = 0; - save[i]->shift = 1; - } else if (i == 2) { - save[i]->vert = 1; - save[i]->shift = 0; - } else if (i == 3) { - save[i]->vert = 1; - save[i]->shift = 1; - } - } - } - first = 0; - - /* - * restore any saved lines. see below for algorithm and - * how x0, etc. are used. we just reverse those steps. - */ - for (i=0; i<4; i++) { - int s = save[i]->shift; - int yu, y_min = -1, y_max = -1; - int y_start, y_stop, y_step; - - if (! save[i]->saved) { - continue; - } - x0 = save[i]->x0; - y0 = save[i]->y0; - x1 = save[i]->x1; - y1 = save[i]->y1; - if (save[i]->vert) { - y_start = y0+lw; - y_stop = y1-lw; - y_step = lw*pixelsize; - } else { - y_start = y0 - s*lw; - y_stop = y_start + lw; - y_step = max*pixelsize; - } - for (yu = y_start; yu < y_stop; yu++) { - if (x0 == x1) { - continue; - } - if (yu < 0 || yu >= dpy_y) { - continue; - } - if (y_min < 0 || yu < y_min) { - y_min = yu; - } - if (y_max < 0 || yu > y_max) { - y_max = yu; - } - src = save[i]->data + (yu-y_start)*y_step; - dst = use_fb + yu*use_Bpl + x0*pixelsize; - memcpy(dst, src, (x1-x0)*pixelsize); - } - if (y_min >= 0) { -if (0) fprintf(stderr, "Mark-1 %d %d %d %d\n", x0, y_min, x1, y_max+1); - mark_rect_as_modified(x0, y_min, x1, y_max+1, 0); - } - save[i]->saved = 0; - } - -if (0) fprintf(stderr, " DrawBox: %04dx%04d+%04d+%04d B=%d rest=%d lw=%d %.4f\n", w, h, x, y, 2*(w+h)*(2-restore)*pixelsize*lw, restore, lw, dnowx()); - - if (restore) { - return; - } - - - /* - * work out shade/color for the wireframe line, could be a color - * for 16bpp or 24bpp. - */ - if (shade > 255) { - if (pixelsize == 2) { - us = (unsigned short) (shade & 0xffff); - color = 1; - } else if (pixelsize == 4) { - ul = (unsigned long) shade; - color = 1; - } else { - shade = shade % 256; - } - } - - for (i=0; i<4; i++) { - int s = save[i]->shift; - int yu, y_min = -1, y_max = -1; - int yblack = -1, xblack1 = -1, xblack2 = -1; - int y_start, y_stop, y_step; - - if (save[i]->vert) { - /* - * make the narrow x's be on the screen, let - * the y's hang off (not drawn). - */ - save[i]->x0 = x0 = nfix(x + s*w - s*lw, dpy_x); - save[i]->y0 = y0 = y; - save[i]->x1 = x1 = nfix(x + s*w - s*lw + lw, dpy_x); - save[i]->y1 = y1 = y + h; - - /* - * start and stop a linewidth away from true edge, - * to avoid interfering with horizontal lines. - */ - y_start = y0+lw; - y_stop = y1-lw; - y_step = lw*pixelsize; - - /* draw a black pixel for the border if lw > 1 */ - if (s) { - xblack1 = x1-1; - } else { - xblack1 = x0; - } - } else { - /* - * make the wide x's be on the screen, let the y's - * hang off (not drawn). - */ - save[i]->x0 = x0 = nfix(x, dpy_x); - save[i]->y0 = y0 = y + s*h; - save[i]->x1 = x1 = nfix(x + w, dpy_x); - save[i]->y1 = y1 = y0 + lw; - y_start = y0 - s*lw; - y_stop = y_start + lw; - y_step = max*pixelsize; - - /* draw a black pixels for the border if lw > 1 */ - if (s) { - yblack = y_stop - 1; - } else { - yblack = y_start; - } - xblack1 = x0; - xblack2 = x1-1; - } - - /* now loop over the allowed y's for either case */ - for (yu = y_start; yu < y_stop; yu++) { - if (x0 == x1) { - continue; - } - if (yu < 0 || yu >= dpy_y) { - continue; - } - - /* record min and max y's for marking rectangle: */ - if (y_min < 0 || yu < y_min) { - y_min = yu; - } - if (y_max < 0 || yu > y_max) { - y_max = yu; - } - - /* save fb data for this line: */ - save[i]->saved = 1; - src = use_fb + yu*use_Bpl + x0*pixelsize; - dst = save[i]->data + (yu-y_start)*y_step; - memcpy(dst, src, (x1-x0)*pixelsize); - - /* apply the shade/color to make the wireframe line: */ - if (! color) { - memset(src, shade, (x1-x0)*pixelsize); - } else { - char *csrc = src; - unsigned short *usp; - unsigned long *ulp; - int k; - for (k=0; k < x1 - x0; k++) { - if (pixelsize == 4) { - ulp = (unsigned long *)csrc; - *ulp = ul; - } else if (pixelsize == 2) { - usp = (unsigned short *)csrc; - *usp = us; - } - csrc += pixelsize; - } - } - - /* apply black border for lw >= 2 */ - if (lw > 1) { - if (yu == yblack) { - memset(src, 0, (x1-x0)*pixelsize); - } - if (xblack1 >= 0) { - src = src + (xblack1 - x0)*pixelsize; - memset(src, 0, pixelsize); - } - if (xblack2 >= 0) { - src = src + (xblack2 - x0)*pixelsize; - memset(src, 0, pixelsize); - } - } - } - /* mark it for sending: */ - if (save[i]->saved) { -if (0) fprintf(stderr, "Mark-2 %d %d %d %d\n", x0, y_min, x1, y_max+1); - mark_rect_as_modified(x0, y_min, x1, y_max+1, 0); - } - } -} - -int direct_fb_copy(int x1, int y1, int x2, int y2, int mark) { - char *src, *dst; - int y, pixelsize = bpp/8; - int xmin = -1, xmax = -1, ymin = -1, ymax = -1; - int do_cmp = 2; - double tm; - int db = 0; - -if (db) dtime0(&tm); - - x1 = nfix(x1, dpy_x); - y1 = nfix(y1, dpy_y); - x2 = nfix(x2, dpy_x+1); - y2 = nfix(y2, dpy_y+1); - - if (x1 == x2) { - return 1; - } - if (y1 == y2) { - return 1; - } - - X_LOCK; - for (y = y1; y < y2; y++) { - XRANDR_SET_TRAP_RET(0, "direct_fb_copy-set"); - copy_image(scanline, x1, y, x2 - x1, 1); - XRANDR_CHK_TRAP_RET(0, "direct_fb_copy-chk"); - - src = scanline->data; - dst = main_fb + y * main_bytes_per_line + x1 * pixelsize; - - if (do_cmp == 0 || !mark) { - memcpy(dst, src, (x2 - x1)*pixelsize); - - } else if (do_cmp == 1) { - if (memcmp(dst, src, (x2 - x1)*pixelsize)) { - if (ymin == -1 || y < ymin) { - ymin = y; - } - if (ymax == -1 || y > ymax) { - ymax = y; - } - memcpy(dst, src, (x2 - x1)*pixelsize); - } - - } else if (do_cmp == 2) { - int n, shift, xlo, xhi, k, block = 32; - char *dst2, *src2; - - for (k=0; k*block < (x2 - x1); k++) { - shift = k*block; - xlo = x1 + shift; - xhi = xlo + block; - if (xhi > x2) { - xhi = x2; - } - n = xhi - xlo; - if (n < 1) { - continue; - } - src2 = src + shift*pixelsize; - dst2 = dst + shift*pixelsize; - if (memcmp(dst2, src2, n*pixelsize)) { - if (ymin == -1 || y < ymin) { - ymin = y; - } - if (ymax == -1 || y > ymax) { - ymax = y; - } - if (xmin == -1 || xlo < xmin) { - xmin = xlo; - } - if (xmax == -1 || xhi > xmax) { - xmax = xhi; - } - memcpy(dst2, src2, n*pixelsize); - } - } - } - } - X_UNLOCK; - - if (do_cmp == 0) { - xmin = x1; - ymin = y1; - xmax = x2; - ymax = y2; - } else if (do_cmp == 1) { - xmin = x1; - xmax = x2; - } - - if (xmin < 0 || ymin < 0 || xmax < 0 || xmin < 0) { - /* no diffs */ - return 1; - } - - if (xmax < x2) { - xmax++; - } - if (ymax < y2) { - ymax++; - } - - if (mark) { - mark_rect_as_modified(xmin, ymin, xmax, ymax, 0); - } - - if (db) { - fprintf(stderr, "direct_fb_copy: %dx%d+%d+%d - %d %.4f\n", - x2 - x1, y2 - y1, x1, y1, mark, dtime(&tm)); - } - - return 1; -} - -static int do_bdpush(Window wm_win, int x0, int y0, int w0, int h0, int bdx, - int bdy, int bdskinny) { - - XWindowAttributes attr; - sraRectangleIterator *iter; - sraRect rect; - sraRegionPtr frame, whole, tmpregion; - int tx1, ty1, tx2, ty2; - static Window last_wm_win = None; - static int last_x, last_y, last_w, last_h; - int do_fb_push = 0; - int db = debug_scroll; - - if (wm_win == last_wm_win) { - attr.x = last_x; - attr.y = last_y; - attr.width = last_w; - attr.height = last_h; - } else { - if (!valid_window(wm_win, &attr, 1)) { - return do_fb_push; - } - last_wm_win = wm_win; - last_x = attr.x; - last_y = attr.y; - last_w = attr.width; - last_h = attr.height; - } -if (db > 1) fprintf(stderr, "BDP %d %d %d %d %d %d %d %d %d %d %d\n", - x0, y0, w0, h0, bdx, bdy, bdskinny, last_x, last_y, last_w, last_h); - - /* wm frame: */ - tx1 = attr.x; - ty1 = attr.y; - tx2 = attr.x + attr.width; - ty2 = attr.y + attr.height; - - whole = sraRgnCreateRect(0, 0, dpy_x, dpy_y); - if (clipshift) { - sraRgnOffset(whole, coff_x, coff_y); - } - if (subwin) { - sraRgnOffset(whole, off_x, off_y); - } - frame = sraRgnCreateRect(tx1, ty1, tx2, ty2); - sraRgnAnd(frame, whole); - - /* scrolling window: */ - tmpregion = sraRgnCreateRect(x0, y0, x0 + w0, y0 + h0); - sraRgnAnd(tmpregion, whole); - - sraRgnSubtract(frame, tmpregion); - sraRgnDestroy(tmpregion); - - if (!sraRgnEmpty(frame)) { - double dt = 0.0, dm; - dtime0(&dm); - iter = sraRgnGetIterator(frame); - while (sraRgnIteratorNext(iter, &rect)) { - tx1 = rect.x1; - ty1 = rect.y1; - tx2 = rect.x2; - ty2 = rect.y2; - - if (bdskinny > 0) { - int ok = 0; - if (nabs(ty2-ty1) <= bdskinny) { - ok = 1; - } - if (nabs(tx2-tx1) <= bdskinny) { - ok = 1; - } - if (! ok) { - continue; - } - } - - if (bdx >= 0) { - if (bdx < tx1 || tx2 <= bdx) { - continue; - } - } - if (bdy >= 0) { - if (bdy < ty1 || ty2 <= bdy) { - continue; - } - } - if (clipshift) { - tx1 -= coff_x; - ty1 -= coff_y; - tx2 -= coff_x; - ty2 -= coff_y; - } - if (subwin) { - tx1 -= off_x; - ty1 -= off_y; - tx2 -= off_x; - ty2 -= off_y; - } - - direct_fb_copy(tx1, ty1, tx2, ty2, 1); - - do_fb_push++; - dt += dtime(&dm); -if (db > 1) fprintf(stderr, " BDP(%d,%d-%d,%d) dt: %.4f\n", tx1, ty1, tx2, ty2, dt); - } - sraRgnReleaseIterator(iter); - } - sraRgnDestroy(whole); - sraRgnDestroy(frame); - - return do_fb_push; -} - -static int set_ypad(void) { - int ev, ev_tot = scr_ev_cnt; - static Window last_win = None; - static double last_time = 0.0; - static int y_accum = 0, last_sign = 0; - double now, cut = 0.1; - int dy_sum = 0, ys = 0, sign; - int font_size = 15; - int win_y, scr_y, loc_cut = 4*font_size, y_cut = 10*font_size; - - if (!xrecord_set_by_keys || !xrecord_name_info) { - return 0; - } - if (xrecord_name_info[0] == '\0') { - return 0; - } - if (! ev_tot) { - return 0; - } - if (xrecord_keysym == NoSymbol) { - return 0; - } - if (!xrecord_scroll_keysym(xrecord_keysym)) { - return 0; - } - if (!scroll_term) { - return 0; - } - if (!match_str_list(xrecord_name_info, scroll_term)) { - return 0; - } - - for (ev=0; ev < ev_tot; ev++) { - dy_sum += nabs(scr_ev[ev].dy); - if (scr_ev[ev].dy < 0) { - ys--; - } else if (scr_ev[ev].dy > 0) { - ys++; - } else { - ys = 0; - break; - } - if (scr_ev[ev].win != scr_ev[0].win) { - ys = 0; - break; - } - if (scr_ev[ev].dx != 0) { - ys = 0; - break; - } - } - if (ys != ev_tot && ys != -ev_tot) { - return 0; - } - if (ys < 0) { - sign = -1; - } else { - sign = 1; - } - - if (sign > 0) { - /* - * this case is not as useful as scrolling near the - * bottom of a terminal. But there are problems for it too. - */ - return 0; - } - - win_y = scr_ev[0].win_y + scr_ev[0].win_h; - scr_y = scr_ev[0].y + scr_ev[0].h; - if (nabs(scr_y - win_y) > loc_cut) { - /* require it to be near the bottom. */ - return 0; - } - - now = dnow(); - - if (now < last_time + cut) { - int ok = 1; - if (last_win && scr_ev[0].win != last_win) { - ok = 0; - } - if (last_sign && sign != last_sign) { - ok = 0; - } - if (! ok) { - last_win = None; - last_sign = 0; - y_accum = 0; - last_time = 0.0; - return 0; - } - } else { - last_win = None; - last_sign = 0; - last_time = 0.0; - y_accum = 0; - } - - y_accum += sign * dy_sum; - - if (4 * nabs(y_accum) > scr_ev[0].h && y_cut) { - ; /* TBD */ - } - - last_sign = sign; - last_win = scr_ev[0].win; - last_time = now; - - return y_accum; -} - -static void scale_mark(int x1, int y1, int x2, int y2, int mark) { - int s = 2; - x1 = nfix(x1 - s, dpy_x); - y1 = nfix(y1 - s, dpy_y); - x2 = nfix(x2 + s, dpy_x+1); - y2 = nfix(y2 + s, dpy_y+1); - scale_and_mark_rect(x1, y1, x2, y2, mark); -} - -#define PUSH_TEST(n) \ -if (n) { \ - double dt = 0.0, tm; dtime0(&tm); \ - fprintf(stderr, "PUSH---\n"); \ - while (dt < 2.0) { rfbPE(50000); dt += dtime(&tm); } \ - fprintf(stderr, "---PUSH\n"); \ -} - -int batch_dxs[], batch_dys[]; -sraRegionPtr batch_reg[]; -void batch_push(int ncr, double delay); - -static int push_scr_ev(double *age, int type, int bdpush, int bdx, int bdy, - int bdskinny, int first_push) { - Window frame, win, win0; - int x, y, w, h, wx, wy, ww, wh, dx, dy; - int x0, y0, w0, h0; - int nx, ny, nw, nh; - int dret = 1, do_fb_push = 0, obscured; - int ev, ev_tot = scr_ev_cnt; - double tm, dt, st, waittime = 0.125; - double max_age = *age; - int db = debug_scroll, rrate = get_read_rate(); - sraRegionPtr backfill, whole, tmpregion, tmpregion2; - int link, latency, netrate; - int ypad = 0; - double last_scroll_event_save = last_scroll_event; - int fast_push = 0, rc; - - /* we return the oldest one. */ - *age = 0.0; - - if (ev_tot == 0) { - return dret; - } - - link = link_rate(&latency, &netrate); - - if (link == LR_DIALUP) { - waittime *= 5; - } else if (link == LR_BROADBAND) { - waittime *= 3; - } else if (latency > 80 || netrate < 40) { - waittime *= 3; - } - - backfill = sraRgnCreate(); - whole = sraRgnCreateRect(0, 0, dpy_x, dpy_y); - if (clipshift) { - sraRgnOffset(whole, coff_x, coff_y); - } - if (subwin) { - sraRgnOffset(whole, off_x, off_y); - } - - win0 = scr_ev[0].win; - x0 = scr_ev[0].win_x; - y0 = scr_ev[0].win_y; - w0 = scr_ev[0].win_w; - h0 = scr_ev[0].win_h; - - ypad = set_ypad(); - -if (db) fprintf(stderr, "ypad: %d dy[0]: %d ev_tot: %d\n", ypad, scr_ev[0].dy, ev_tot); - - for (ev=0; ev < ev_tot; ev++) { - double ag; - - x = scr_ev[ev].x; - y = scr_ev[ev].y; - w = scr_ev[ev].w; - h = scr_ev[ev].h; - dx = scr_ev[ev].dx; - dy = scr_ev[ev].dy; - win = scr_ev[ev].win; - wx = scr_ev[ev].win_x; - wy = scr_ev[ev].win_y; - ww = scr_ev[ev].win_w; - wh = scr_ev[ev].win_h; - nx = scr_ev[ev].new_x; - ny = scr_ev[ev].new_y; - nw = scr_ev[ev].new_w; - nh = scr_ev[ev].new_h; - st = scr_ev[ev].t; - - ag = (dnow() - servertime_diff) - st; - if (ag > *age) { - *age = ag; - } - - if (dabs(ag) > max_age) { -if (db) fprintf(stderr, "push_scr_ev: TOO OLD: %.4f :: (%.4f - %.4f) " - "- %.4f \n", ag, dnow(), servertime_diff, st); - dret = 0; - break; - } else { -if (db) fprintf(stderr, "push_scr_ev: AGE: %.4f\n", ag); - } - if (win != win0) { -if (db) fprintf(stderr, "push_scr_ev: DIFF WIN: 0x%lx != 0x%lx\n", win, win0); - dret = 0; - break; - } - if (wx != x0 || wy != y0) { -if (db) fprintf(stderr, "push_scr_ev: WIN SHIFT: %d %d, %d %d", wx, x0, wy, y0); - dret = 0; - break; - } - if (ww != w0 || wh != h0) { -if (db) fprintf(stderr, "push_scr_ev: WIN RESIZE: %d %d, %d %d", ww, w0, wh, h0); - dret = 0; - break; - } - if (w < 1 || h < 1 || ww < 1 || wh < 1) { -if (db) fprintf(stderr, "push_scr_ev: NEGATIVE h/w: %d %d %d %d\n", w, h, ww, wh); - dret = 0; - break; - } - -if (db > 1) fprintf(stderr, "push_scr_ev: got: %d x: %4d y: %3d" - " w: %4d h: %3d dx: %d dy: %d %dx%d+%d+%d win: 0x%lx\n", - ev, x, y, w, h, dx, dy, w, h, x, y, win); - -if (db > 1) fprintf(stderr, "------------ got: %d x: %4d y: %3d" - " w: %4d h: %3d %dx%d+%d+%d\n", - ev, wx, wy, ww, wh, ww, wh, wx, wy); - -if (db > 1) fprintf(stderr, "------------ got: %d x: %4d y: %3d" - " w: %4d h: %3d %dx%d+%d+%d\n", - ev, nx, ny, nw, nh, nw, nh, nx, ny); - - frame = None; - if (xrecord_wm_window) { - frame = xrecord_wm_window; - } - if (! frame) { - X_LOCK; - frame = query_pointer(rootwin); - X_UNLOCK; - } - if (! frame) { - frame = win; - } - - dtime0(&tm); - - tmpregion = sraRgnCreateRect(0, 0, dpy_x, dpy_y); - if (clipshift) { - sraRgnOffset(tmpregion, coff_x, coff_y); - } - if (subwin) { - sraRgnOffset(tmpregion, off_x, off_y); - } - tmpregion2 = sraRgnCreateRect(wx, wy, wx+ww, wy+wh); - sraRgnAnd(tmpregion2, whole); - sraRgnSubtract(tmpregion, tmpregion2); - sraRgnDestroy(tmpregion2); - - /* do the wm frame just incase the above is bogus too. */ - if (frame && frame != win) { - int k, gotk = -1; - for (k = stack_list_num - 1; k >= 0; k--) { - if (stack_list[k].win == frame && - stack_list[k].fetched && - stack_list[k].valid && - stack_list[k].map_state == IsViewable) { - gotk = k; - break; - } - } - if (gotk != -1) { - int tx1, ty1, tx2, ty2; - tx1 = stack_list[gotk].x; - ty1 = stack_list[gotk].y; - tx2 = tx1 + stack_list[gotk].width; - ty2 = ty1 + stack_list[gotk].height; - tmpregion2 = sraRgnCreateRect(tx1,ty1,tx2,ty2); - sraRgnAnd(tmpregion2, whole); - sraRgnSubtract(tmpregion, tmpregion2); - sraRgnDestroy(tmpregion2); - } - } - - /* - * XXX Need to also clip: - * children of win - * siblings of win higher in stacking order. - * ignore for now... probably will make some apps - * act very strangely. - */ - if (ypad) { - if (ypad < 0) { - if (h > -ypad) { - h += ypad; - } else { - ypad = 0; - } - } else { - if (h > ypad) { - y += ypad; - } else { - ypad = 0; - } - } - } - - if (fast_push) { - int nbatch = 0; - double delay, d1 = 0.1, d2 = 0.02; - rc = try_copyrect(frame, frame, x, y, w, h, dx, dy, &obscured, - tmpregion, waittime, &nbatch); - - if (first_push) { - delay = d1; - } else { - delay = d2; - } - - batch_push(nbatch, delay); - fb_push(); - } else { - rc = try_copyrect(frame, frame, x, y, w, h, dx, dy, &obscured, - tmpregion, waittime, NULL); - if (rc) { - last_scroll_type = type; - dtime0(&last_scroll_event); - - do_fb_push++; - urgent_update = 1; - sraRgnDestroy(tmpregion); -PUSH_TEST(0); - } - } - - if (! rc) { - dret = 0; - sraRgnDestroy(tmpregion); - break; - } - dt = dtime(&tm); -if (0) fprintf(stderr, " try_copyrect dt: %.4f\n", dt); - - if (ev > 0) { - sraRgnOffset(backfill, dx, dy); - sraRgnAnd(backfill, whole); - } - - if (ypad) { - if (ypad < 0) { - ny += ypad; - nh -= ypad; - } else { - ; - } - } - - tmpregion = sraRgnCreateRect(nx, ny, nx + nw, ny + nh); - sraRgnAnd(tmpregion, whole); - sraRgnOr(backfill, tmpregion); - sraRgnDestroy(tmpregion); - } - - /* try to update the backfill region (new window contents) */ - if (dret != 0) { - double est, win_area = 0.0, area = 0.0; - sraRectangleIterator *iter; - sraRect rect; - int tx1, ty1, tx2, ty2; - - tmpregion = sraRgnCreateRect(x0, y0, x0 + w0, y0 + h0); - sraRgnAnd(tmpregion, whole); - - sraRgnAnd(backfill, tmpregion); - - iter = sraRgnGetIterator(tmpregion); - while (sraRgnIteratorNext(iter, &rect)) { - tx1 = rect.x1; - ty1 = rect.y1; - tx2 = rect.x2; - ty2 = rect.y2; - - win_area += (tx2 - tx1)*(ty2 - ty1); - } - sraRgnReleaseIterator(iter); - - sraRgnDestroy(tmpregion); - - - iter = sraRgnGetIterator(backfill); - while (sraRgnIteratorNext(iter, &rect)) { - tx1 = rect.x1; - ty1 = rect.y1; - tx2 = rect.x2; - ty2 = rect.y2; - - area += (tx2 - tx1)*(ty2 - ty1); - } - sraRgnReleaseIterator(iter); - - est = (area * (bpp/8)) / (1000000.0 * rrate); -if (db) fprintf(stderr, " area %.1f win_area %.1f est: %.4f", area, win_area, est); - if (area > 0.90 * win_area) { -if (db) fprintf(stderr, " AREA_TOO_MUCH"); - dret = 0; - } else if (est > 0.6) { -if (db) fprintf(stderr, " EST_TOO_LARGE"); - dret = 0; - } else if (area <= 0.0) { - ; - } else { - dtime0(&tm); - iter = sraRgnGetIterator(backfill); - while (sraRgnIteratorNext(iter, &rect)) { - tx1 = rect.x1; - ty1 = rect.y1; - tx2 = rect.x2; - ty2 = rect.y2; - - if (clipshift) { - tx1 -= coff_x; - ty1 -= coff_y; - tx2 -= coff_x; - ty2 -= coff_y; - } - if (subwin) { - tx1 -= off_x; - ty1 -= off_y; - tx2 -= off_x; - ty2 -= off_y; - } - tx1 = nfix(tx1, dpy_x); - ty1 = nfix(ty1, dpy_y); - tx2 = nfix(tx2, dpy_x+1); - ty2 = nfix(ty2, dpy_y+1); - - dtime(&tm); -if (db) fprintf(stderr, " DFC(%d,%d-%d,%d)", tx1, ty1, tx2, ty2); - direct_fb_copy(tx1, ty1, tx2, ty2, 1); - if (fast_push) { - fb_push(); - } - do_fb_push++; -PUSH_TEST(0); - } - sraRgnReleaseIterator(iter); - - dt = dtime(&tm); -if (db) fprintf(stderr, " dfc---- dt: %.4f", dt); - - } -if (db && dret) fprintf(stderr, " **** dret=%d", dret); -if (db && !dret) fprintf(stderr, " ---- dret=%d", dret); -if (db) fprintf(stderr, "\n"); - } - -if (db && bdpush) fprintf(stderr, "BDPUSH-TIME: 0x%lx\n", xrecord_wm_window); - - if (bdpush && xrecord_wm_window != None) { - int x, y, w, h; - x = scr_ev[0].x; - y = scr_ev[0].y; - w = scr_ev[0].w; - h = scr_ev[0].h; - do_fb_push += do_bdpush(xrecord_wm_window, x, y, w, h, - bdx, bdy, bdskinny); - if (fast_push) { - fb_push(); - } - } - - if (do_fb_push) { - dtime0(&tm); - fb_push(); - dt = dtime(&tm); -if (0) fprintf(stderr, " fb_push dt: %.4f", dt); - if (scaling) { - static double last_time = 0.0; - double now = dnow(), delay = 0.4, first_wait = 3.0; - double trate; - int repeating, lat, rate; - int link = link_rate(&lat, &rate); - int skip_first = 0; - - if (link == LR_DIALUP || rate < 35) { - delay *= 4; - } else if (link != LR_LAN || rate < 100) { - delay *= 2; - } - - trate = typing_rate(0.0, &repeating); - - if (xrecord_set_by_mouse || repeating >= 3) { - if (now > last_scroll_event_save + first_wait) { - skip_first = 1; - } - } - - if (skip_first) { - /* - * try not to send the first one, but a - * single keystroke scroll would be OK. - */ - } else if (now > last_time + delay) { - - scale_mark(x0, y0, x0 + w0, y0 + h0, 1); - last_copyrect_fix = now; - } - last_time = now; - } - } - - sraRgnDestroy(backfill); - sraRgnDestroy(whole); - return dret; -} - -static void get_client_regions(int *req, int *mod, int *cpy, int *num) { - - rfbClientIteratorPtr i; - rfbClientPtr cl; - - *req = 0; - *mod = 0; - *cpy = 0; - *num = 0; - - i = rfbGetClientIterator(screen); - while( (cl = rfbClientIteratorNext(i)) ) { - if (use_threads) LOCK(cl->updateMutex); - *req += sraRgnCountRects(cl->requestedRegion); - *mod += sraRgnCountRects(cl->modifiedRegion); - *cpy += sraRgnCountRects(cl->copyRegion); - *num += 1; - if (use_threads) UNLOCK(cl->updateMutex); - } - rfbReleaseClientIterator(i); -} - -/* - * Wrapper to apply the rfbDoCopyRegion taking into account if scaling - * is being done. Note that copyrect under the scaling case is often - * only approximate. - */ -int DCR_Normal = 0; -int DCR_FBOnly = 1; -int DCR_Direct = 2; - -void do_copyregion(sraRegionPtr region, int dx, int dy, int mode) { - sraRectangleIterator *iter; - sraRect rect; - int Bpp0 = bpp/8, Bpp; - int x1, y1, x2, y2, w, stride, stride0; - int sx1, sy1, sx2, sy2, sdx, sdy; - int req, mod, cpy, ncli; - char *dst = NULL, *src = NULL; - - last_copyrect = dnow(); - - if (rfb_fb == main_fb && ! rotating && mode == DCR_Normal) { - /* normal case, no -scale or -8to24 */ - get_client_regions(&req, &mod, &cpy, &ncli); -if (0 || debug_scroll > 1) fprintf(stderr, ">>>-rfbDoCopyRect req: %d mod: %d cpy: %d\n", req, mod, cpy); - - rfbDoCopyRegion(screen, region, dx, dy); - - get_client_regions(&req, &mod, &cpy, &ncli); -if (0 || debug_scroll > 1) fprintf(stderr, "<<<-rfbDoCopyRect req: %d mod: %d cpy: %d\n", req, mod, cpy); - - return; - } - - /* rarer case, we need to call rfbDoCopyRect with scaled xy */ - stride0 = dpy_x * Bpp0; - - iter = sraRgnGetReverseIterator(region, dx < 0, dy < 0); - while(sraRgnIteratorNext(iter, &rect)) { - int j, c, t; - - x1 = rect.x1; - y1 = rect.y1; - x2 = rect.x2; - y2 = rect.y2; - - for (c= 0; c < 2; c++) { - - Bpp = Bpp0; - stride = stride0; - - if (c == 0) { - dst = main_fb + y1*stride + x1*Bpp; - src = main_fb + (y1-dy)*stride + (x1-dx)*Bpp; - - } else if (c == 1) { - if (!cmap8to24 || !cmap8to24_fb) { - continue; - } - if (cmap8to24_fb == rfb_fb) { - if (mode == DCR_FBOnly) { - ; - } else if (mode == DCR_Direct) { - ; - } else if (mode == DCR_Normal) { - continue; - } - } -if (0) fprintf(stderr, "copyrect: cmap8to24_fb: mode=%d\n", mode); - if (cmap8to24) { - if (depth <= 8) { - Bpp = 4 * Bpp0; - stride = 4 * stride0; - } else if (depth <= 16) { - Bpp = 2 * Bpp0; - stride = 2 * stride0; - } - } - dst = cmap8to24_fb + y1*stride + x1*Bpp; - src = cmap8to24_fb + (y1-dy)*stride + (x1-dx)*Bpp; - } - - w = (x2 - x1)*Bpp; - - if (dy < 0) { - for (j=y1; j<y2; j++) { - memmove(dst, src, w); - dst += stride; - src += stride; - } - } else { - dst += (y2 - y1 - 1)*stride; - src += (y2 - y1 - 1)*stride; - for (j=y2-1; j>=y1; j--) { - memmove(dst, src, w); - dst -= stride; - src -= stride; - } - } - } - - if (mode == DCR_FBOnly) { - continue; - } - - - if (scaling) { - sx1 = ((double) x1 / dpy_x) * scaled_x; - sy1 = ((double) y1 / dpy_y) * scaled_y; - sx2 = ((double) x2 / dpy_x) * scaled_x; - sy2 = ((double) y2 / dpy_y) * scaled_y; - sdx = ((double) dx / dpy_x) * scaled_x; - sdy = ((double) dy / dpy_y) * scaled_y; - } else { - sx1 = x1; - sy1 = y1; - sx2 = x2; - sy2 = y2; - sdx = dx; - sdy = dy; - } -if (0) fprintf(stderr, "sa.. %d %d %d %d %d %d\n", sx1, sy1, sx2, sy2, sdx, sdy); - - if (rotating) { - rotate_coords(sx1, sy1, &sx1, &sy1, -1, -1); - rotate_coords(sx2, sy2, &sx2, &sy2, -1, -1); - if (rotating == ROTATE_X) { - sdx = -sdx; - } else if (rotating == ROTATE_Y) { - sdy = -sdy; - } else if (rotating == ROTATE_XY) { - sdx = -sdx; - sdy = -sdy; - } else if (rotating == ROTATE_90) { - t = sdx; - sdx = -sdy; - sdy = t; - } else if (rotating == ROTATE_90X) { - t = sdx; - sdx = sdy; - sdy = t; - } else if (rotating == ROTATE_90Y) { - t = sdx; - sdx = -sdy; - sdy = -t; - } else if (rotating == ROTATE_270) { - t = sdx; - sdx = sdy; - sdy = -t; - } - } - - /* XXX -1? */ - if (sx2 < 0) sx2 = 0; - if (sy2 < 0) sy2 = 0; - - if (sx2 < sx1) { - t = sx1; - sx1 = sx2; - sx2 = t; - } - if (sy2 < sy1) { - t = sy1; - sy1 = sy2; - sy2 = t; - } -if (0) fprintf(stderr, "sb.. %d %d %d %d %d %d\n", sx1, sy1, sx2, sy2, sdx, sdy); - - if (mode == DCR_Direct) { - rfbClientIteratorPtr i; - rfbClientPtr cl; - sraRegionPtr r = sraRgnCreateRect(sx1, sy1, sx2, sy2); - - i = rfbGetClientIterator(screen); - while( (cl = rfbClientIteratorNext(i)) ) { - if (use_threads) LOCK(cl->updateMutex); - rfbSendCopyRegion(cl, r, sdx, sdy); - if (use_threads) UNLOCK(cl->updateMutex); - } - rfbReleaseClientIterator(i); - sraRgnDestroy(r); - - } else { - rfbDoCopyRect(screen, sx1, sy1, sx2, sy2, sdx, sdy); - } - } - sraRgnReleaseIterator(iter); -} - -void batch_copyregion(sraRegionPtr* region, int *dx, int *dy, int ncr, double delay) { - rfbClientIteratorPtr i; - rfbClientPtr cl; - int k, direct, mode, nrects = 0, bad = 0; - double t1, t2, start = dnow(); - - for (k=0; k < ncr; k++) { - sraRectangleIterator *iter; - sraRect rect; - - iter = sraRgnGetIterator(region[k]); - while (sraRgnIteratorNext(iter, &rect)) { - int x1 = rect.x1; - int y1 = rect.y1; - int x2 = rect.x2; - int y2 = rect.y2; - int ym = dpy_y * (ncache+1); - int xm = dpy_x; - if (x1 > xm || y1 > ym || x2 > xm || y2 > ym) { - if (ncdb) fprintf(stderr, "batch_copyregion: BAD RECTANGLE: %d,%d %d,%d\n", x1, y1, x2, y2); - bad = 1; - } - if (x1 < 0 || y1 < 0 || x2 < 0 || y2 < 0) { - if (ncdb) fprintf(stderr, "batch_copyregion: BAD RECTANGLE: %d,%d %d,%d\n", x1, y1, x2, y2); - bad = 1; - } - } - sraRgnReleaseIterator(iter); - nrects += sraRgnCountRects(region[k]); - } - if (bad || nrects == 0) { - return; - } - - if (delay < 0.0) { - delay = 0.1; - } - if (!fb_push_wait(delay, FB_COPY|FB_MOD)) { - if (use_threads) usleep(100 * 1000); - fb_push_wait(0.75, FB_COPY|FB_MOD); - } - - t1 = dnow(); - - bad = 0; - i = rfbGetClientIterator(screen); - while( (cl = rfbClientIteratorNext(i)) ) { - - if (use_threads) LOCK(cl->updateMutex); - - if (cl->ublen != 0) { - fprintf(stderr, "batch_copyregion: *** BAD ublen != 0: %d\n", cl->ublen); - bad++; - } - - if (use_threads) UNLOCK(cl->updateMutex); - } - rfbReleaseClientIterator(i); - - if (bad) { - return; - } - - i = rfbGetClientIterator(screen); - while( (cl = rfbClientIteratorNext(i)) ) { - rfbFramebufferUpdateMsg *fu; - - if (use_threads) LOCK(cl->updateMutex); - - fu = (rfbFramebufferUpdateMsg *)cl->updateBuf; - fu->nRects = Swap16IfLE((uint16_t)(nrects)); - fu->type = rfbFramebufferUpdate; - - if (cl->ublen != 0) fprintf(stderr, "batch_copyregion: *** BAD-2 ublen != 0: %d\n", cl->ublen); - - cl->ublen = sz_rfbFramebufferUpdateMsg; - - if (use_threads) UNLOCK(cl->updateMutex); - } - rfbReleaseClientIterator(i); - - if (rfb_fb == main_fb && !rotating) { - direct = 0; - mode = DCR_FBOnly; - } else { - direct = 1; - mode = DCR_Direct; - } - for (k=0; k < ncr; k++) { - do_copyregion(region[k], dx[k], dy[k], mode); - } - - t2 = dnow(); - - i = rfbGetClientIterator(screen); - while( (cl = rfbClientIteratorNext(i)) ) { - - if (use_threads) LOCK(cl->updateMutex); - - if (!direct) { - for (k=0; k < ncr; k++) { - rfbSendCopyRegion(cl, region[k], dx[k], dy[k]); - } - } - rfbSendUpdateBuf(cl); - - if (use_threads) UNLOCK(cl->updateMutex); - } - rfbReleaseClientIterator(i); - - last_copyrect = dnow(); - -if (0) fprintf(stderr, "batch_copyregion: nrects: %d nregions: %d tot=%.4f t10=%.4f t21=%.4f t32=%.4f %.4f\n", - nrects, ncr, last_copyrect - start, t1 - start, t2 - t1, last_copyrect - t2, dnowx()); - -} - -void batch_push(int nreg, double delay) { - int k; - batch_copyregion(batch_reg, batch_dxs, batch_dys, nreg, delay); - /* XXX Y */ - fb_push(); - for (k=0; k < nreg; k++) { - sraRgnDestroy(batch_reg[k]); - } -} - -void fb_push(void) { - int req0, mod0, cpy0, req1, mod1, cpy1, ncli; - int db = (debug_scroll || debug_wireframe); - rfbClientIteratorPtr i; - rfbClientPtr cl; - - if (use_threads) { - return; - } - -if (db) get_client_regions(&req0, &mod0, &cpy0, &ncli); - - i = rfbGetClientIterator(screen); - while( (cl = rfbClientIteratorNext(i)) ) { - if (use_threads) LOCK(cl->updateMutex); - if (cl->sock >= 0 && !cl->onHold && FB_UPDATE_PENDING(cl) && - !sraRgnEmpty(cl->requestedRegion)) { - if (!rfbSendFramebufferUpdate(cl, cl->modifiedRegion)) { - fprintf(stderr, "*** rfbSendFramebufferUpdate *FAILED* #1\n"); - if (cl->ublen) fprintf(stderr, "*** fb_push ublen not zero: %d\n", cl->ublen); - if (use_threads) UNLOCK(cl->updateMutex); - break; - } - if (cl->ublen) fprintf(stderr, "*** fb_push ublen NOT ZERO: %d\n", cl->ublen); - } - if (use_threads) UNLOCK(cl->updateMutex); - } - rfbReleaseClientIterator(i); - -if (db) { - get_client_regions(&req1, &mod1, &cpy1, &ncli); - fprintf(stderr, "\nFB_push: req: %d/%d mod: %d/%d cpy: %d/%d %.4f\n", - req0, req1, mod0, mod1, cpy0, cpy1, dnowx()); -} - -} - -int fb_push_wait(double max_wait, int flags) { - double tm, dt = 0.0; - int req, mod, cpy, ncli; - int ok = 0, first = 1; - - dtime0(&tm); - while (dt < max_wait) { - int done = 1; - fb_push(); - get_client_regions(&req, &mod, &cpy, &ncli); - if (flags & FB_COPY && cpy) { - done = 0; - } - if (flags & FB_MOD && mod) { - done = 0; - } - if (flags & FB_REQ && req) { - done = 0; - } - if (done) { - ok = 1; - break; - } - if (first) { - first = 0; - continue; - } - - rfbCFD(0); - usleep(1000); - dt += dtime(&tm); - } - return ok; -} - -/* - * utility routine for CopyRect of the window (but not CopyRegion) - */ -static int crfix(int x, int dx, int Lx) { - /* adjust x so that copy source is on screen */ - if (dx > 0) { - if (x-dx < 0) { - /* off on the left */ - x = dx; - } - } else { - if (x-dx >= Lx) { - /* off on the right */ - x = Lx + dx - 1; - } - } - return x; -} - -typedef struct scroll_result { - Window win; - double time; - int result; -} scroll_result_t; - -#define SCR_RESULTS_MAX 256 -static scroll_result_t scroll_results[SCR_RESULTS_MAX]; - -static int scrollability(Window win, int set) { - double oldest = -1.0; - int i, index = -1, next_index = -1; - static int first = 1; - - if (first) { - for (i=0; i<SCR_RESULTS_MAX; i++) { - scroll_results[i].win = None; - scroll_results[i].time = 0.0; - scroll_results[i].result = 0; - } - first = 0; - } - - if (win == None) { - return 0; - } - if (set == SCR_NONE) { - /* lookup case */ - for (i=0; i<SCR_RESULTS_MAX; i++) { - if (win == scroll_results[i].win) { - return scroll_results[i].result; - } - if (scroll_results[i].win == None) { - break; - } - } - return 0; - } - - for (i=0; i<SCR_RESULTS_MAX; i++) { - if (oldest == -1.0 || scroll_results[i].time < oldest) { - next_index = i; - oldest = scroll_results[i].time; - } - if (win == scroll_results[i].win) { - index = i; - break; - } - if (next_index >= 0 && scroll_results[i].win == None) { - break; - } - } - - if (set == SCR_SUCCESS) { - set = 1; - } else if (set == SCR_FAIL) { - set = -1; - } else { - set = 0; - } - if (index == -1) { - scroll_results[next_index].win = win; - scroll_results[next_index].time = dnow(); - scroll_results[next_index].result = set; - } else { - if (scroll_results[index].result == 1) { - /* - * once a success, always a success, until they - * forget about us... - */ - set = 1; - } else { - scroll_results[index].result = set; - } - scroll_results[index].time = dnow(); - } - - return set; -} - -void eat_viewonly_input(int max_eat, int keep) { - int i, gp, gk; - - for (i=0; i<max_eat; i++) { - int cont = 0; - gp = got_pointer_calls; - gk = got_keyboard_calls; - rfbCFD(0); - if (got_pointer_calls > gp) { - if (debug_pointer) { - rfbLog("eat_viewonly_input: pointer: %d\n", i); - } - cont++; - } - if (got_keyboard_calls > gk) { - if (debug_keyboard) { - rfbLog("eat_viewonly_input: keyboard: %d\n", i); - } - cont++; - } - if (i >= keep - 1 && ! cont) { - break; - } - } -} - -static int eat_pointer(int max_ptr_eat, int keep) { - int i, count = 0, gp = got_pointer_input; - - for (i=0; i<max_ptr_eat; i++) { - rfbCFD(0); - if (got_pointer_input > gp) { - count++; -if (0) fprintf(stderr, "GP*-%d\n", i); - gp = got_pointer_input; - } else if (i > keep) { - break; - } - } - return count; -} - -static void set_bdpush(int type, double *last_bdpush, int *pushit) { - double now, delay = 0.0; - int link, latency, netrate; - - *pushit = 0; - - if (type == SCR_MOUSE) { - delay = scr_mouse_bdpush_time; - } else if (type == SCR_KEY) { - delay = scr_key_bdpush_time; - } - - link = link_rate(&latency, &netrate); - if (link == LR_DIALUP) { - delay *= 1.5; - } else if (link == LR_BROADBAND) { - delay *= 1.25; - } - - dtime0(&now); - if (delay > 0.0 && now > *last_bdpush + delay) { - *pushit = 1; - *last_bdpush = now; - } -} - -void mark_for_xdamage(int x, int y, int w, int h) { - int tx1, ty1, tx2, ty2; - sraRegionPtr tmpregion; - - if (! use_xdamage) { - return; - } - - tx1 = nfix(x, dpy_x); - ty1 = nfix(y, dpy_y); - tx2 = nfix(x + w, dpy_x+1); - ty2 = nfix(y + h, dpy_y+1); - - tmpregion = sraRgnCreateRect(tx1, ty1, tx2, ty2); - add_region_xdamage(tmpregion); - sraRgnDestroy(tmpregion); -} - -void mark_region_for_xdamage(sraRegionPtr region) { - sraRectangleIterator *iter; - sraRect rect; - iter = sraRgnGetIterator(region); - while (sraRgnIteratorNext(iter, &rect)) { - int x1 = rect.x1; - int y1 = rect.y1; - int x2 = rect.x2; - int y2 = rect.y2; - mark_for_xdamage(x1, y1, x2 - x1, y2 - y1); - } - sraRgnReleaseIterator(iter); -} - -void set_xdamage_mark(int x, int y, int w, int h) { - sraRegionPtr region; - - if (! use_xdamage) { - return; - } - mark_for_xdamage(x, y, w, h); - - if (xdamage_scheduled_mark == 0.0) { - xdamage_scheduled_mark = dnow() + 2.0; - } - - if (xdamage_scheduled_mark_region == NULL) { - xdamage_scheduled_mark_region = sraRgnCreate(); - } - region = sraRgnCreateRect(x, y, x + w, y + w); - sraRgnOr(xdamage_scheduled_mark_region, region); - sraRgnDestroy(region); -} - -static int repeat_check(double last_key_scroll) { - int repeating; - double rate = typing_rate(0.0, &repeating); - double now = dnow(), delay = 0.5; - if (rate > 2.0 && repeating && now > last_key_scroll + delay) { - return 0; - } else { - return 1; - } -} - -static int check_xrecord_keys(void) { - static int last_wx, last_wy, last_ww, last_wh; - double spin = 0.0, tm, tnow; - int scr_cnt = 0, input = 0, scroll_rep; - int get_out, got_one = 0, flush1 = 0, flush2 = 0; - int gk, gk0, ret = 0, db = debug_scroll; - int fail = 0; - int link, latency, netrate; - - static double last_key_scroll = 0.0; - static double persist_start = 0.0; - static double last_bdpush = 0.0; - static int persist_count = 0; - int scroll_keysym = 0; - double last_scroll, scroll_persist = scr_key_persist; - double spin_fac = 1.0, scroll_fac = 2.0, noscroll_fac = 0.75; - double max_spin, max_long_spin = 0.3; - double set_repeat_in; - static double set_repeat = 0.0; - - - RAWFB_RET(0) - - if (unixpw_in_progress) return 0; - - set_repeat_in = set_repeat; - set_repeat = 0.0; - - get_out = 1; - if (got_keyboard_input) { - get_out = 0; - } - - dtime0(&tnow); - if (tnow < last_key_scroll + scroll_persist) { - get_out = 0; - } - - if (set_repeat_in > 0.0 && tnow < last_key_scroll + set_repeat_in) { - get_out = 0; - } - - if (get_out) { - persist_start = 0.0; - persist_count = 0; - last_bdpush = 0.0; - if (xrecording) { - xrecord_watch(0, SCR_KEY); - } - return 0; - } - -#if 0 - /* not used for keyboard yet */ - scroll_rep = scrollability(xrecord_ptr_window, SCR_NONE) + 1; - if (scroll_rep == 1) { - scroll_rep = 2; /* if no info, assume the best. */ - } -#endif - - scroll_keysym = xrecord_scroll_keysym(last_rfb_keysym); - - max_spin = scr_key_time; - - if (set_repeat_in > 0.0 && tnow < last_key_scroll + 2*set_repeat_in) { - max_spin = 2 * set_repeat_in; - } else if (tnow < last_key_scroll + scroll_persist) { - max_spin = 1.25*(tnow - last_key_scroll); - } else if (tnow < last_key_to_button_remap_time + 1.5*scroll_persist) { - /* mostly a hack I use for testing -remap key -> btn4/btn5 */ - max_spin = scroll_persist; - } else if (scroll_keysym) { - if (repeat_check(last_key_scroll)) { - spin_fac = scroll_fac; - } else { - spin_fac = noscroll_fac; - } - } - if (max_spin > max_long_spin) { - max_spin = max_long_spin; - } - - /* XXX use this somehow */ -if (0) link = link_rate(&latency, &netrate); - - gk = gk0 = got_keyboard_input; - dtime0(&tm); - -if (db) fprintf(stderr, "check_xrecord_keys: BEGIN LOOP: scr_ev_cnt: " - "%d max: %.3f %.4f\n", scr_ev_cnt, max_spin, tm - x11vnc_start); - - while (1) { - - if (scr_ev_cnt) { - got_one = 1; - - scrollability(xrecord_ptr_window, SCR_SUCCESS); - scroll_rep = 2; - - dtime0(&last_scroll); - last_key_scroll = last_scroll; - scr_cnt++; - break; - } - - X_LOCK; - flush1 = 1; - XFlush_wr(dpy); - X_UNLOCK; - - if (set_repeat_in > 0.0) { - max_keyrepeat_time = set_repeat_in; - } - - if (use_threads) { - usleep(1000); - } else { - rfbCFD(1000); - } - spin += dtime(&tm); - - X_LOCK; - if (got_keyboard_input > gk) { - gk = got_keyboard_input; - input++; - if (set_repeat_in) { - ; - } else if (xrecord_scroll_keysym(last_rfb_keysym)) { - if (repeat_check(last_key_scroll)) { - spin_fac = scroll_fac; - } else { - spin_fac = noscroll_fac; - } - } -if (0 || db) fprintf(stderr, "check_xrecord: more keys: %.3f 0x%x " - " %.4f %s %s\n", spin, last_rfb_keysym, last_rfb_keytime - x11vnc_start, - last_rfb_down ? "down":"up ", last_rfb_key_accepted ? "accept":"skip"); - flush2 = 1; - XFlush_wr(dpy); - } -#if LIBVNCSERVER_HAVE_RECORD - SCR_LOCK; - XRecordProcessReplies(rdpy_data); - SCR_UNLOCK; -#endif - X_UNLOCK; - - if (spin >= max_spin * spin_fac) { -if (0 || db) fprintf(stderr, "check_xrecord: SPIN-OUT: %.3f/%.3f\n", spin, - max_spin * spin_fac); - fail = 1; - break; - } - } - - max_keyrepeat_time = 0.0; - - if (scr_ev_cnt) { - int dret, ev = scr_ev_cnt - 1; - int bdx, bdy, bdskinny, bdpush = 0; - double max_age = 0.25, age, tm, dt; - static double last_scr_ev = 0.0; - - last_wx = scr_ev[ev].win_x; - last_wy = scr_ev[ev].win_y; - last_ww = scr_ev[ev].win_w; - last_wh = scr_ev[ev].win_h; - - /* assume scrollbar on rhs: */ - bdx = last_wx + last_ww + 3; - bdy = last_wy + last_wh/2; - bdskinny = 32; - - if (persist_start == 0.0) { - bdpush = 0; - } else { - set_bdpush(SCR_KEY, &last_bdpush, &bdpush); - } - - dtime0(&tm); - age = max_age; - dret = push_scr_ev(&age, SCR_KEY, bdpush, bdx, bdy, bdskinny, 1); - dt = dtime(&tm); - - ret = 1 + dret; - scr_ev_cnt = 0; - - if (ret == 2 && xrecord_scroll_keysym(last_rfb_keysym)) { - int repeating; - double time_lo = 1.0/max_keyrepeat_lo; - double time_hi = 1.0/max_keyrepeat_hi; - double rate = typing_rate(0.0, &repeating); -if (0 || db) fprintf(stderr, "Typing: dt: %.4f rate: %.1f\n", dt, rate); - if (repeating) { - /* n.b. the "quantum" is about 1/30 sec. */ - max_keyrepeat_time = 1.0*dt; - if (max_keyrepeat_time > time_lo || - max_keyrepeat_time < time_hi) { - max_keyrepeat_time = 0.0; - } else { - set_repeat = max_keyrepeat_time; -if (0 || db) fprintf(stderr, "set max_keyrepeat_time: %.2f\n", max_keyrepeat_time); - } - } - } - - last_scr_ev = dnow(); - } - - if ((got_one && ret < 2) || persist_count) { - set_xdamage_mark(last_wx, last_wy, last_ww, last_wh); - } - - if (fail) { - scrollability(xrecord_ptr_window, SCR_FAIL); - } - - if (xrecording) { - if (ret < 2) { - xrecord_watch(0, SCR_KEY); - } - } - - if (ret == 2) { - if (persist_start == 0.0) { - dtime(&persist_start); - last_bdpush = persist_start; - } - } else { - persist_start = 0.0; - last_bdpush = 0.0; - } - - /* since we've flushed it, we might as well avoid -input_skip */ - if (flush1 || flush2) { - got_keyboard_input = 0; - got_pointer_input = 0; - } - - return ret; -} - -static int check_xrecord_mouse(void) { - static int last_wx, last_wy, last_ww, last_wh; - double spin = 0.0, tm, tnow; - int i, scr_cnt = 0, input = 0, scroll_rep; - int get_out, got_one = 0, flush1 = 0, flush2 = 0; - int gp, gp0, ret = 0, db = debug_scroll; - int gk, gk0; - int fail = 0; - int link, latency, netrate; - - int start_x, start_y, last_x, last_y; - static double last_mouse_scroll = 0.0; - double last_scroll; - double max_spin[3], max_long[3], persist[3]; - double flush1_time = 0.01; - static double last_flush = 0.0; - double last_bdpush = 0.0, button_up_time = 0.0; - int button_mask_save; - int already_down = 0, max_ptr_eat = 20; - static int want_back_in = 0; - int came_back_in; - int first_push = 1; - - int scroll_wheel = 0; - int btn4 = (1<<3); - int btn5 = (1<<4); - - RAWFB_RET(0) - - get_out = 1; - if (button_mask) { - get_out = 0; - } - if (want_back_in) { - get_out = 0; - } - dtime0(&tnow); -if (0) fprintf(stderr, "check_xrecord_mouse: IN xrecording: %d\n", xrecording); - - if (get_out) { - if (xrecording) { - xrecord_watch(0, SCR_MOUSE); - } - return 0; - } - - scroll_rep = scrollability(xrecord_ptr_window, SCR_NONE) + 1; - if (scroll_rep == 1) { - scroll_rep = 2; /* if no info, assume the best. */ - } - - if (button_mask_prev) { - already_down = 1; - } - if (want_back_in) { - came_back_in = 1; - first_push = 0; - } else { - came_back_in = 0; - } - want_back_in = 0; - - if (button_mask & (btn4|btn5)) { - scroll_wheel = 1; - } - - /* - * set up times for the various "reputations" - * - * 0 => -1, has been tried but never found a scroll. - * 1 => 0, has not been tried. - * 2 => +1, has been tried and found a scroll. - */ - - /* first spin-out time (no events) */ - max_spin[0] = 1*scr_mouse_time; - max_spin[1] = 2*scr_mouse_time; - max_spin[2] = 4*scr_mouse_time; - if (!already_down) { - for (i=0; i<3; i++) { - max_spin[i] *= 1.5; - } - } - - /* max time between events */ - persist[0] = 1*scr_mouse_persist; - persist[1] = 2*scr_mouse_persist; - persist[2] = 4*scr_mouse_persist; - - /* absolute max time in the loop */ - max_long[0] = scr_mouse_maxtime; - max_long[1] = scr_mouse_maxtime; - max_long[2] = scr_mouse_maxtime; - - pointer_flush_delay = scr_mouse_pointer_delay; - - /* slow links: */ - link = link_rate(&latency, &netrate); - if (link == LR_DIALUP) { - for (i=0; i<3; i++) { - max_spin[i] *= 2.0; - } - pointer_flush_delay *= 2; - } else if (link == LR_BROADBAND) { - pointer_flush_delay *= 2; - } - - gp = gp0 = got_pointer_input; - gk = gk0 = got_keyboard_input; - dtime0(&tm); - - /* - * this is used for border pushes (bdpush) to guess location - * of scrollbar (region rects containing this point are pushed). - */ - last_x = start_x = cursor_x; - last_y = start_y = cursor_y; - -if (db) fprintf(stderr, "check_xrecord_mouse: BEGIN LOOP: scr_ev_cnt: " - "%d max: %.3f %.4f\n", scr_ev_cnt, max_spin[scroll_rep], tm - x11vnc_start); - - while (1) { - double spin_check; - if (scr_ev_cnt) { - int dret, ev = scr_ev_cnt - 1; - int bdpush = 0, bdx, bdy, bdskinny; - double tm, dt, age = 0.35; - - got_one = 1; - scrollability(xrecord_ptr_window, SCR_SUCCESS); - scroll_rep = 2; - - scr_cnt++; - - dtime0(&last_scroll); - last_mouse_scroll = last_scroll; - - if (last_bdpush == 0.0) { - last_bdpush = last_scroll; - } - - bdx = start_x; - bdy = start_y; - if (clipshift) { - bdx += coff_x; - bdy += coff_y; - } - if (subwin) { - bdx += off_x; - bdy += off_y; - } - bdskinny = 32; - - set_bdpush(SCR_MOUSE, &last_bdpush, &bdpush); - - dtime0(&tm); - - dret = push_scr_ev(&age, SCR_MOUSE, bdpush, bdx, - bdy, bdskinny, first_push); - if (first_push) first_push = 0; - ret = 1 + dret; - - dt = dtime(&tm); - -if (db) fprintf(stderr, " dret: %d scr_ev_cnt: %d dt: %.4f\n", - dret, scr_ev_cnt, dt); - - last_wx = scr_ev[ev].win_x; - last_wy = scr_ev[ev].win_y; - last_ww = scr_ev[ev].win_w; - last_wh = scr_ev[ev].win_h; - scr_ev_cnt = 0; - - if (! dret) { - break; - } - if (0 && button_up_time > 0.0) { - /* we only take 1 more event with button up */ -if (db) fprintf(stderr, "check_xrecord: BUTTON_UP_SCROLL: %.3f\n", spin); - break; - } - } - - - if (! flush1) { - if (! already_down || (!scr_cnt && spin>flush1_time)) { - flush1 = 1; - X_LOCK; - XFlush_wr(dpy); - X_UNLOCK; - dtime0(&last_flush); - } - } - - if (use_threads) { - usleep(1000); - } else { - rfbCFD(1000); - rfbCFD(0); - } - spin += dtime(&tm); - - if (got_pointer_input > gp) { - flush2 = 1; - input += eat_pointer(max_ptr_eat, 1); - gp = got_pointer_input; - } - if (got_keyboard_input > gk) { - gk = got_keyboard_input; - input++; - } - X_LOCK; -#if LIBVNCSERVER_HAVE_RECORD - SCR_LOCK; - XRecordProcessReplies(rdpy_data); - SCR_UNLOCK; -#endif - X_UNLOCK; - - if (! input) { - spin_check = 1.5 * max_spin[scroll_rep]; - } else { - spin_check = max_spin[scroll_rep]; - } - - if (button_up_time > 0.0) { - if (tm > button_up_time + max_spin[scroll_rep]) { -if (db) fprintf(stderr, "check_xrecord: SPIN-OUT-BUTTON_UP: %.3f/%.3f\n", spin, tm - button_up_time); - break; - } - } else if (!scr_cnt) { - if (spin >= spin_check) { - -if (db) fprintf(stderr, "check_xrecord: SPIN-OUT-1: %.3f/%.3f\n", spin, spin_check); - fail = 1; - break; - } - } else { - if (tm >= last_scroll + persist[scroll_rep]) { - -if (db) fprintf(stderr, "check_xrecord: SPIN-OUT-2: %.3f/%.3f\n", spin, tm - last_scroll); - break; - } - } - if (spin >= max_long[scroll_rep]) { - -if (db) fprintf(stderr, "check_xrecord: SPIN-OUT-3: %.3f/%.3f\n", spin, max_long[scroll_rep]); - break; - } - - if (! button_mask) { - int doflush = 0; - if (button_up_time > 0.0) { - ; - } else if (came_back_in) { - dtime0(&button_up_time); - doflush = 1; - } else if (scroll_wheel) { -if (db) fprintf(stderr, "check_xrecord: SCROLL-WHEEL-BUTTON-UP-KEEP-GOING: %.3f/%.3f %d/%d %d/%d\n", spin, max_long[scroll_rep], last_x, last_y, cursor_x, cursor_y); - doflush = 1; - dtime0(&button_up_time); - } else if (last_x == cursor_x && last_y == cursor_y) { -if (db) fprintf(stderr, "check_xrecord: BUTTON-UP: %.3f/%.3f %d/%d %d/%d\n", spin, max_long[scroll_rep], last_x, last_y, cursor_x, cursor_y); - break; - } else { -if (db) fprintf(stderr, "check_xrecord: BUTTON-UP-KEEP-GOING: %.3f/%.3f %d/%d %d/%d\n", spin, max_long[scroll_rep], last_x, last_y, cursor_x, cursor_y); - doflush = 1; - dtime0(&button_up_time); - } - if (doflush) { - flush1 = 1; - X_LOCK; - XFlush_wr(dpy); - X_UNLOCK; - dtime0(&last_flush); - } - } - - last_x = cursor_x; - last_y = cursor_y; - } - - if (got_one) { - set_xdamage_mark(last_wx, last_wy, last_ww, last_wh); - } - - if (fail) { - scrollability(xrecord_ptr_window, SCR_FAIL); - } - - /* flush any remaining pointer events. */ - button_mask_save = button_mask; - pointer_queued_sent = 0; - last_x = cursor_x; - last_y = cursor_y; - pointer_event(-1, 0, 0, NULL); - pointer_flush_delay = 0.0; - - if (xrecording && pointer_queued_sent && button_mask_save && - (last_x != cursor_x || last_y != cursor_y) ) { -if (db) fprintf(stderr, " pointer() push yields events on: ret=%d\n", ret); - if (ret == 2) { -if (db) fprintf(stderr, " we decide to send ret=3\n"); - want_back_in = 1; - ret = 3; - flush2 = 1; - } else { - if (ret) { - ret = 1; - } else { - ret = 0; - } - xrecord_watch(0, SCR_MOUSE); - } - } else { - if (ret) { - ret = 1; - } else { - ret = 0; - } - if (xrecording) { - xrecord_watch(0, SCR_MOUSE); - } - } - - if (flush2) { - X_LOCK; - XFlush_wr(dpy); - XFlush_wr(rdpy_ctrl); - X_UNLOCK; - - flush2 = 1; - dtime0(&last_flush); - -if (db) fprintf(stderr, "FLUSH-2\n"); - } - - /* since we've flushed it, we might as well avoid -input_skip */ - if (flush1 || flush2) { - got_keyboard_input = 0; - got_pointer_input = 0; - } - - if (ret) { - return ret; - } else if (scr_cnt) { - return 1; - } else { - return 0; - } -} - -int check_xrecord(void) { - int watch_keys = 0, watch_mouse = 0, consider_mouse; - static int mouse_wants_back_in = 0; - - RAWFB_RET(0) - - if (! use_xrecord) { - return 0; - } - if (unixpw_in_progress) return 0; - - if (skip_cr_when_scaling("scroll")) { - return 0; - } - -if (0) fprintf(stderr, "check_xrecord: IN xrecording: %d\n", xrecording); - - if (! xrecording) { - return 0; - } - - if (!strcmp(scroll_copyrect, "always")) { - watch_keys = 1; - watch_mouse = 1; - } else if (!strcmp(scroll_copyrect, "keys")) { - watch_keys = 1; - } else if (!strcmp(scroll_copyrect, "mouse")) { - watch_mouse = 1; - } - - if (button_mask || mouse_wants_back_in) { - consider_mouse = 1; - } else { - consider_mouse = 0; - } -if (0) fprintf(stderr, "check_xrecord: button_mask: %d mouse_wants_back_in: %d\n", button_mask, mouse_wants_back_in); - - if (watch_mouse && consider_mouse && xrecord_set_by_mouse) { - int ret = check_xrecord_mouse(); - if (ret == 3) { - mouse_wants_back_in = 1; - } else { - mouse_wants_back_in = 0; - } - return ret; - } else if (watch_keys && xrecord_set_by_keys) { - mouse_wants_back_in = 0; - return check_xrecord_keys(); - } else { - mouse_wants_back_in = 0; - return 0; - } -} - -#define DB_SET \ - int db = 0; \ - int db2 = 0; \ - if (debug_wireframe == 1) { \ - db = 1; \ - } \ - if (debug_wireframe == 2) { \ - db2 = 1; \ - } \ - if (debug_wireframe == 3) { \ - db = 1; \ - db2 = 1; \ - } - -#define NBATCHMAX 1024 -int batch_dxs[NBATCHMAX], batch_dys[NBATCHMAX]; -sraRegionPtr batch_reg[NBATCHMAX]; - -static int try_copyrect(Window orig_frame, Window frame, int x, int y, int w, int h, - int dx, int dy, int *obscured, sraRegionPtr extra_clip, double max_wait, int *nbatch) { - - static int dt_bad = 0; - static time_t dt_bad_check = 0; - int x1, y1, x2, y2, sent_copyrect = 0; - int req, mod, cpy, ncli; - double tm, dt; - DB_SET - - if (nbatch == NULL) { - get_client_regions(&req, &mod, &cpy, &ncli); - if (cpy) { - /* one is still pending... try to force it out: */ - if (!fb_push_wait(max_wait, FB_COPY)) { - fb_push_wait(max_wait/2, FB_COPY); - } - - get_client_regions(&req, &mod, &cpy, &ncli); - } - if (cpy) { - return 0; - } - } - - *obscured = 0; - /* - * XXX KDE and xfce do some weird things with the - * stacking, it does not match XQueryTree. Work around - * it for now by CopyRect-ing the *whole* on-screen - * rectangle (whether obscured or not!) - */ - if (time(NULL) > dt_bad_check + 5) { - char *dt = guess_desktop(); - if (!strcmp(dt, "kde_maybe_is_ok_now...")) { - dt_bad = 1; - } else if (!strcmp(dt, "xfce")) { - dt_bad = 1; - } else { - dt_bad = 0; - } - dt_bad_check = time(NULL); - } - - if (clipshift) { - x -= coff_x; - y -= coff_y; - } - if (subwin) { - x -= off_x; - y -= off_y; - } -if (db2) fprintf(stderr, "try_copyrect: 0x%lx/0x%lx bad: %d stack_list_num: %d\n", orig_frame, frame, dt_bad, stack_list_num); - -/* XXX Y dt_bad = 0 */ - if (dt_bad && wireframe_in_progress) { - sraRegionPtr rect; - /* send the whole thing... */ - x1 = crfix(nfix(x, dpy_x), dx, dpy_x); - y1 = crfix(nfix(y, dpy_y), dy, dpy_y); - x2 = crfix(nfix(x+w, dpy_x+1), dx, dpy_x+1); - y2 = crfix(nfix(y+h, dpy_y+1), dy, dpy_y+1); - - rect = sraRgnCreateRect(x1, y1, x2, y2); - - if (blackouts) { - int i; - sraRegionPtr bo_rect; - for (i=0; i<blackouts; i++) { - bo_rect = sraRgnCreateRect(blackr[i].x1, - blackr[i].y1, blackr[i].x2, blackr[i].y2); - sraRgnSubtract(rect, bo_rect); - sraRgnDestroy(bo_rect); - } - } - if (!nbatch) { - do_copyregion(rect, dx, dy, 0); - } else { - batch_dxs[*nbatch] = dx; - batch_dys[*nbatch] = dy; - batch_reg[*nbatch] = sraRgnCreateRgn(rect); - (*nbatch)++; - } - sraRgnDestroy(rect); - - sent_copyrect = 1; - *obscured = 1; /* set to avoid an aggressive push */ - - } else if (stack_list_num || dt_bad) { - int k, tx1, tx2, ty1, ty2; - sraRegionPtr moved_win, tmp_win, whole; - sraRectangleIterator *iter; - sraRect rect; - int saw_me = 0; - int orig_x, orig_y; - int boff, bwin; - XWindowAttributes attr; - - orig_x = x - dx; - orig_y = y - dy; - - tx1 = nfix(orig_x, dpy_x); - ty1 = nfix(orig_y, dpy_y); - tx2 = nfix(orig_x+w, dpy_x+1); - ty2 = nfix(orig_y+h, dpy_y+1); - -if (db2) fprintf(stderr, "moved_win: %4d %3d, %4d %3d 0x%lx ---\n", - tx1, ty1, tx2, ty2, frame); - - moved_win = sraRgnCreateRect(tx1, ty1, tx2, ty2); - - dtime0(&tm); - - boff = get_boff(); - bwin = get_bwin(); - - X_LOCK; - - /* - * loop over the stack, top to bottom until we - * find our wm frame: - */ - for (k = stack_list_num - 1; k >= 0; k--) { - Window swin; - - if (0 && dt_bad) { - break; - } - - swin = stack_list[k].win; -if (db2) fprintf(stderr, "sw: %d/%lx\n", k, swin); - if (swin == frame || swin == orig_frame) { - if (db2) { - saw_me = 1; fprintf(stderr, " ----------\n"); - } else { - break; - } - } - - /* skip some unwanted cases: */ -#ifndef MACOSX - if (swin == None) { - continue; - } -#endif - if (boff <= (int) swin && (int) swin < boff + bwin) { - ; /* blackouts */ - } else if (! stack_list[k].fetched || - stack_list[k].time > tm + 2.0) { - if (!valid_window(swin, &attr, 1)) { - stack_list[k].valid = 0; - } else { - stack_list[k].valid = 1; - stack_list[k].x = attr.x; - stack_list[k].y = attr.y; - stack_list[k].width = attr.width; - stack_list[k].height = attr.height; - stack_list[k].border_width = attr.border_width; - stack_list[k].depth = attr.depth; - stack_list[k].class = attr.class; - stack_list[k].backing_store = - attr.backing_store; - stack_list[k].map_state = - attr.map_state; - } - stack_list[k].fetched = 1; - stack_list[k].time = tm; - } - if (!stack_list[k].valid) { - continue; - } - - attr.x = stack_list[k].x; - attr.y = stack_list[k].y; - attr.depth = stack_list[k].depth; - attr.width = stack_list[k].width; - attr.height = stack_list[k].height; - attr.border_width = stack_list[k].border_width; - attr.map_state = stack_list[k].map_state; - - if (attr.map_state != IsViewable) { - continue; - } -if (db2) fprintf(stderr, "sw: %d/%lx %dx%d+%d+%d\n", k, swin, stack_list[k].width, stack_list[k].height, stack_list[k].x, stack_list[k].y); - - if (clipshift) { - attr.x -= coff_x; - attr.y -= coff_y; - } - if (subwin) { - attr.x -= off_x; - attr.y -= off_y; - } - - /* - * first subtract any overlap from the initial - * window rectangle - */ - - /* clip the window to the visible screen: */ - tx1 = nfix(attr.x, dpy_x); - ty1 = nfix(attr.y, dpy_y); - tx2 = nfix(attr.x + attr.width, dpy_x+1); - ty2 = nfix(attr.y + attr.height, dpy_y+1); - -if (db2) fprintf(stderr, " tmp_win-1: %4d %3d, %4d %3d 0x%lx\n", - tx1, ty1, tx2, ty2, swin); -if (db2 && saw_me) continue; - - /* see if window clips us: */ - tmp_win = sraRgnCreateRect(tx1, ty1, tx2, ty2); - if (sraRgnAnd(tmp_win, moved_win)) { - *obscured = 1; -if (db2) fprintf(stderr, " : clips it.\n"); - } - sraRgnDestroy(tmp_win); - - /* subtract it from our region: */ - tmp_win = sraRgnCreateRect(tx1, ty1, tx2, ty2); - sraRgnSubtract(moved_win, tmp_win); - sraRgnDestroy(tmp_win); - - /* - * next, subtract from the initial window rectangle - * anything that would clip it. - */ - - /* clip the window to the visible screen: */ - tx1 = nfix(attr.x - dx, dpy_x); - ty1 = nfix(attr.y - dy, dpy_y); - tx2 = nfix(attr.x - dx + attr.width, dpy_x+1); - ty2 = nfix(attr.y - dy + attr.height, dpy_y+1); - -if (db2) fprintf(stderr, " tmp_win-2: %4d %3d, %4d %3d 0x%lx\n", - tx1, ty1, tx2, ty2, swin); -if (db2 && saw_me) continue; - - /* subtract it from our region: */ - tmp_win = sraRgnCreateRect(tx1, ty1, tx2, ty2); - sraRgnSubtract(moved_win, tmp_win); - sraRgnDestroy(tmp_win); - } - - X_UNLOCK; - - if (extra_clip && ! sraRgnEmpty(extra_clip)) { - whole = sraRgnCreateRect(0, 0, dpy_x, dpy_y); - - if (clipshift) { - sraRgnOffset(extra_clip, -coff_x, -coff_y); - } - if (subwin) { - sraRgnOffset(extra_clip, -off_x, -off_y); - } - - iter = sraRgnGetIterator(extra_clip); - while (sraRgnIteratorNext(iter, &rect)) { - /* clip the window to the visible screen: */ - tx1 = rect.x1; - ty1 = rect.y1; - tx2 = rect.x2; - ty2 = rect.y2; - tmp_win = sraRgnCreateRect(tx1, ty1, tx2, ty2); - sraRgnAnd(tmp_win, whole); - - /* see if window clips us: */ - if (sraRgnAnd(tmp_win, moved_win)) { - *obscured = 1; - } - sraRgnDestroy(tmp_win); - - /* subtract it from our region: */ - tmp_win = sraRgnCreateRect(tx1, ty1, tx2, ty2); - sraRgnSubtract(moved_win, tmp_win); - sraRgnDestroy(tmp_win); - - /* - * next, subtract from the initial window rectangle - * anything that would clip it. - */ - tmp_win = sraRgnCreateRect(tx1, ty1, tx2, ty2); - sraRgnOffset(tmp_win, -dx, -dy); - - /* clip the window to the visible screen: */ - sraRgnAnd(tmp_win, whole); - - /* subtract it from our region: */ - sraRgnSubtract(moved_win, tmp_win); - sraRgnDestroy(tmp_win); - } - sraRgnReleaseIterator(iter); - sraRgnDestroy(whole); - } - - dt = dtime(&tm); -if (db2) fprintf(stderr, " stack_work dt: %.4f\n", dt); - - if (*obscured && !strcmp(wireframe_copyrect, "top")) { - ; /* cannot send CopyRegion */ - } else if (! sraRgnEmpty(moved_win)) { - sraRegionPtr whole, shifted_region; - - whole = sraRgnCreateRect(0, 0, dpy_x, dpy_y); - shifted_region = sraRgnCreateRgn(moved_win); - sraRgnOffset(shifted_region, dx, dy); - sraRgnAnd(shifted_region, whole); - - sraRgnDestroy(whole); - - /* now send the CopyRegion: */ - if (! sraRgnEmpty(shifted_region)) { - dtime0(&tm); - if (!nbatch) { - do_copyregion(shifted_region, dx, dy, 0); - } else { - batch_dxs[*nbatch] = dx; - batch_dys[*nbatch] = dy; - batch_reg[*nbatch] = sraRgnCreateRgn(shifted_region); - (*nbatch)++; - - } - dt = dtime(&tm); -if (0 || db2) fprintf(stderr, "do_copyregion: %d %d %d %d dx: %d dy: %d dt: %.4f\n", - tx1, ty1, tx2, ty2, dx, dy, dt); - sent_copyrect = 1; - } - sraRgnDestroy(shifted_region); - } - sraRgnDestroy(moved_win); - } - return sent_copyrect; -} - -int near_wm_edge(int x, int y, int w, int h, int px, int py) { - /* heuristics: */ - int wf_t = wireframe_top; - int wf_b = wireframe_bot; - int wf_l = wireframe_left; - int wf_r = wireframe_right; - - int near_edge = 0; - - if (wf_t || wf_b || wf_l || wf_r) { - if (nabs(y - py) < wf_t) { - near_edge = 1; - } - if (nabs(y + h - py) < wf_b) { - near_edge = 1; - } - if (nabs(x - px) < wf_l) { - near_edge = 1; - } - if (nabs(x + w - px) < wf_r) { - near_edge = 1; - } - } else { - /* all zero; always "near" edge: */ - near_edge = 1; - } - return near_edge; -} - -int near_scrollbar_edge(int x, int y, int w, int h, int px, int py) { - /* heuristics: */ - int sb_t = scrollcopyrect_top; - int sb_b = scrollcopyrect_bot; - int sb_l = scrollcopyrect_left; - int sb_r = scrollcopyrect_right; - - int near_edge = 0; - - if (sb_t || sb_b || sb_l || sb_r) { - if (nabs(y - py) < sb_t) { - near_edge = 1; - } - if (nabs(y + h - py) < sb_b) { - near_edge = 1; - } - if (nabs(x - px) < sb_l) { - near_edge = 1; - } - if (nabs(x + w - px) < sb_r) { - near_edge = 1; - } - } else { - /* all zero; always "near" edge: */ - near_edge = 1; - } - return near_edge; -} - -void check_fixscreen(void) { - double now = dnow(); - int didfull = 0, db = 0; - - if (!client_count) { - return; - } - if (unixpw_in_progress) return; - - if (screen_fixup_X > 0.0) { - static double last = 0.0; - if (now > last + screen_fixup_X) { - if (db) rfbLog("doing screen_fixup_X\n"); - do_copy_screen = 1; - last = now; - didfull = 1; - } - - } - if (screen_fixup_V > 0.0) { - static double last = 0.0; - if (now > last + screen_fixup_V) { - if (! didfull) { - refresh_screen(0); - if (db) rfbLog("doing screen_fixup_V\n"); - } - last = now; - didfull = 1; - } - } - if (screen_fixup_C > 0.0) { - static double last = 0.0; - if (last_copyrect_fix < last_copyrect && - now > last_copyrect + screen_fixup_C) { - if (! didfull) { - refresh_screen(0); - if (db) rfbLog("doing screen_fixup_C\n"); - } - last_copyrect_fix = now; - last = now; - didfull = 1; - } - } - if (scaling && last_copyrect_fix < last_copyrect) { - static double last = 0.0; - double delay = 3.0; - if (now > last + delay) { - if (! didfull) { - scale_and_mark_rect(0, 0, dpy_x, dpy_y, 1); - if (db) rfbLog("doing scale screen_fixup\n"); - } - last_copyrect_fix = now; - last = now; - didfull = 1; - } - } - if (advertise_truecolor && advertise_truecolor_reset && indexed_color) { - /* this will reset framebuffer to correct colors, if needed */ - static double dlast = 0.0; - now = dnow(); - if (now > last_client + 1.0 && now < last_client + 3.0 && now > dlast + 5.0) { - rfbLog("advertise truecolor reset framebuffer\n"); - do_new_fb(1); - dlast = dnow(); - return; - } - } -} - -static int wireframe_mod_state() { - if (! wireframe_mods) { - return 0; - } - if (!strcmp(wireframe_mods, "all")) { - if (track_mod_state(NoSymbol, FALSE, FALSE)) { - return 1; - } else { - return 0; - } - - } else if (!strcmp(wireframe_mods, "Alt")) { - if (track_mod_state(XK_Alt_L, FALSE, FALSE) == 1) { - return 1; - } else if (track_mod_state(XK_Alt_R, FALSE, FALSE) == 1) { - return 1; - } - } else if (!strcmp(wireframe_mods, "Shift")) { - if (track_mod_state(XK_Shift_L, FALSE, FALSE) == 1) { - return 1; - } else if (track_mod_state(XK_Shift_R, FALSE, FALSE) == 1) { - return 1; - } - } else if (!strcmp(wireframe_mods, "Control")) { - if (track_mod_state(XK_Control_L, FALSE, FALSE) == 1) { - return 1; - } else if (track_mod_state(XK_Control_R, FALSE, FALSE) == 1) { - return 1; - } - } else if (!strcmp(wireframe_mods, "Meta")) { - if (track_mod_state(XK_Meta_L, FALSE, FALSE) == 1) { - return 1; - } else if (track_mod_state(XK_Meta_R, FALSE, FALSE) == 1) { - return 1; - } - } else if (!strcmp(wireframe_mods, "Super")) { - if (track_mod_state(XK_Super_L, FALSE, FALSE) == 1) { - return 1; - } else if (track_mod_state(XK_Super_R, FALSE, FALSE) == 1) { - return 1; - } - } else if (!strcmp(wireframe_mods, "Hyper")) { - if (track_mod_state(XK_Hyper_L, FALSE, FALSE) == 1) { - return 1; - } else if (track_mod_state(XK_Hyper_R, FALSE, FALSE) == 1) { - return 1; - } - } - return 0; -} - -static int NPP_nreg = 0; -static sraRegionPtr NPP_roffscreen = NULL; -static sraRegionPtr NPP_r_bs_tmp = NULL; -static Window NPP_nwin = None; - -void clear_win_events(Window win, int vis) { -#if !NO_X11 - if (dpy && win != None && ncache) { - XEvent ev; - XErrorHandler old_handler; - old_handler = XSetErrorHandler(trap_xerror); - trapped_xerror = 0; - while (XCheckTypedWindowEvent(dpy, win, ConfigureNotify, &ev)) { - if (ncdb) fprintf(stderr, "."); - if (trapped_xerror) { - break; - } - trapped_xerror = 0; - } -/* XXX Y */ - if (vis) { - while (XCheckTypedWindowEvent(dpy, win, VisibilityNotify, &ev)) { - if (ncdb) fprintf(stderr, "+"); - if (trapped_xerror) { - break; - } - trapped_xerror = 0; - } - } - XSetErrorHandler(old_handler); - if (ncdb) fprintf(stderr, " 0x%lx\n", win); - } -#endif -} - -void push_borders(sraRect *rects, int nrect) { - int i, s = 2; - sraRegionPtr r0, r1, r2; - - r0 = sraRgnCreate(); - r1 = sraRgnCreateRect(0, 0, dpy_x, dpy_y); - - for (i=0; i<nrect; i++) { - int x = rects[i].x1; - int y = rects[i].y1; - int w = rects[i].x2; - int h = rects[i].y2; - - if (w > 0 && h > 0 && w * h > 64 * 64) { - r2 = sraRgnCreateRect(x - s, y , x , y + h); - sraRgnOr(r0, r2); - sraRgnDestroy(r2); - - r2 = sraRgnCreateRect(x + w, y , x + w + s, y + h); - sraRgnOr(r0, r2); - sraRgnDestroy(r2); - - r2 = sraRgnCreateRect(x - s, y - s, x + w + s, y + s); - sraRgnOr(r0, r2); - sraRgnDestroy(r2); - - r2 = sraRgnCreateRect(x - s, y , x + w + s, y + h + s); - sraRgnOr(r0, r2); - sraRgnDestroy(r2); - } - } - - sraRgnAnd(r0, r1); - - if (!sraRgnEmpty(r0)) { - double d = dnow(); - sraRectangleIterator *iter; - sraRect rect; - int db = 0; - - if (db) fprintf(stderr, "SCALE_BORDER\n"); - fb_push_wait(0.05, FB_MOD|FB_COPY); - - iter = sraRgnGetIterator(r0); - while (sraRgnIteratorNext(iter, &rect)) { - /* clip the window to the visible screen: */ - int tx1 = rect.x1; - int ty1 = rect.y1; - int tx2 = rect.x2; - int ty2 = rect.y2; - scale_and_mark_rect(tx1, ty1, tx2, ty2, 1); - } - sraRgnReleaseIterator(iter); - - if (db) fprintf(stderr, "SCALE_BORDER %.4f\n", dnow() - d); - fb_push_wait(0.1, FB_MOD|FB_COPY); - if (db) fprintf(stderr, "SCALE_BORDER %.4f\n", dnow() - d); - } - sraRgnDestroy(r0); - sraRgnDestroy(r1); -} - -void ncache_pre_portions(Window orig_frame, Window frame, int *nidx_in, int try_batch, int *use_batch, - int orig_x, int orig_y, int orig_w, int orig_h, int x, int y, int w, int h, double ntim) { - int nidx, np = ncache_pad; - - if (!ntim) {} - *use_batch = 0; - *nidx_in = -1; - NPP_nreg = 0; - NPP_roffscreen = NULL; - NPP_r_bs_tmp = NULL; - NPP_nwin = None; - - if (ncache <= 0) { - return; - } - - if (rotating) { - try_batch = 0; - } - - if (*nidx_in == -1) { - nidx = lookup_win_index(orig_frame); - NPP_nwin = orig_frame; - if (nidx < 0) { - nidx = lookup_win_index(frame); - NPP_nwin = frame; - } - } else { - nidx = *nidx_in; - } - if (nidx > 0) { - sraRegionPtr r0, r1, r2; - int dx, dy; - int bs_x = cache_list[nidx].bs_x; - int bs_y = cache_list[nidx].bs_y; - int bs_w = cache_list[nidx].bs_w; - int bs_h = cache_list[nidx].bs_h; - - *nidx_in = nidx; - - if (bs_x < 0) { - if (!find_rect(nidx, x, y, w, h)) { - nidx = -1; - return; - } - bs_x = cache_list[nidx].bs_x; - bs_y = cache_list[nidx].bs_y; - bs_w = cache_list[nidx].bs_w; - bs_h = cache_list[nidx].bs_h; - } - if (bs_x < 0) { - nidx = -1; - return; - } - - if (try_batch) { - *use_batch = 1; - } - - if (ncache_pad) { - orig_x -= np; - orig_y -= np; - orig_w += 2 * np; - orig_h += 2 * np; - x -= np; - y -= np; - w += 2 * np; - h += 2 * np; - } - - if (clipshift) { - orig_x -= coff_x; - orig_y -= coff_y; - x -= coff_x; - y -= coff_y; - } - - r0 = sraRgnCreateRect(0, 0, dpy_x, dpy_y); - - r2 = sraRgnCreateRect(orig_x, orig_y, orig_x + orig_w, orig_y + orig_h); - sraRgnSubtract(r2, r0); - if (! sraRgnEmpty(r2) && cache_list[nidx].bs_time > 0.0) { - /* some is initially offscreen */ - dx = bs_x - orig_x; - dy = bs_y - orig_y; - sraRgnOffset(r2, dx, dy); - dx = 0; - dy = dpy_y; - sraRgnOffset(r2, dx, dy); -if (ncdb) fprintf(stderr, "FB_COPY: %.4f 1) offscreen: dx, dy: %d, %d -> %d, %d orig %dx%d+%d+%d bs_xy: %d %d\n", - dnow() - ntim, bs_x - orig_x, bs_y - orig_y, dx, dy, orig_w, orig_h, orig_x, orig_y, bs_x, bs_y); - - /* 0) save it in the invalid (offscreen) SU portion */ - if (! *use_batch) { - do_copyregion(r2, dx, dy, 0); - if (! fb_push_wait(0.2, FB_COPY)) { - fb_push_wait(0.1, FB_COPY); - } - } else { - batch_dxs[NPP_nreg] = dx; - batch_dys[NPP_nreg] = dy; - batch_reg[NPP_nreg++] = sraRgnCreateRgn(r2); - } - NPP_roffscreen = sraRgnCreateRgn(r2); - } - sraRgnDestroy(r2); - - /* 1) use bs for temp storage of the new save under. */ - r1 = sraRgnCreateRect(x, y, x + w, y + h); - sraRgnAnd(r1, r0); - - dx = bs_x - x; - dy = bs_y - y; - sraRgnOffset(r1, dx, dy); - -if (ncdb) fprintf(stderr, "FB_COPY: %.4f 1) use tmp bs:\n", dnow() - ntim); - if (! *use_batch) { - do_copyregion(r1, dx, dy, 0); - if (! fb_push_wait(0.2, FB_COPY)) { -if (ncdb) fprintf(stderr, "FB_COPY: %.4f 1) FAILED.\n", dnow() - ntim); - fb_push_wait(0.1, FB_COPY); - } - } else { - batch_dxs[NPP_nreg] = dx; - batch_dys[NPP_nreg] = dy; - batch_reg[NPP_nreg++] = sraRgnCreateRgn(r1); - } - NPP_r_bs_tmp = sraRgnCreateRgn(r1); - sraRgnDestroy(r0); - sraRgnDestroy(r1); - } -} - -void ncache_post_portions(int nidx, int use_batch, int orig_x, int orig_y, int orig_w, int orig_h, - int x, int y, int w, int h, double batch_delay, double ntim) { - int np = ncache_pad; - int db = 0; - - if (ncache > 0 && nidx >= 0) { - sraRegionPtr r0, r1, r2, r3; - int dx, dy; - int su_x = cache_list[nidx].su_x; - int su_y = cache_list[nidx].su_y; - int su_w = cache_list[nidx].su_w; - int su_h = cache_list[nidx].su_h; - int bs_x = cache_list[nidx].bs_x; - int bs_y = cache_list[nidx].bs_y; - int bs_w = cache_list[nidx].bs_w; - int bs_h = cache_list[nidx].bs_h; - int some_su = 0; - -if (db) fprintf(stderr, "su: %dx%d+%d+%d bs: %dx%d+%d+%d\n", su_w, su_h, su_x, su_y, bs_w, bs_h, bs_x, bs_y); - - if (bs_x < 0) { - if (!find_rect(nidx, x, y, w, h)) { - return; - } - su_x = cache_list[nidx].su_x; - su_y = cache_list[nidx].su_y; - su_w = cache_list[nidx].su_w; - su_h = cache_list[nidx].su_h; - bs_x = cache_list[nidx].bs_x; - bs_y = cache_list[nidx].bs_y; - bs_w = cache_list[nidx].bs_w; - bs_h = cache_list[nidx].bs_h; - } - if (bs_x < 0) { - return; - } - - if (ncache_pad) { - orig_x -= np; - orig_y -= np; - orig_w += 2 * np; - orig_h += 2 * np; - x -= np; - y -= np; - w += 2 * np; - h += 2 * np; - } - - if (clipshift) { - orig_x -= coff_x; - orig_y -= coff_y; - x -= coff_x; - y -= coff_y; - } - - r0 = sraRgnCreateRect(0, 0, dpy_x, dpy_y); - - /* 0b) copy this bs part stored in saveunder */ - if (NPP_roffscreen != NULL) { - dx = x - su_x; - dy = y - su_y; - sraRgnOffset(NPP_roffscreen, dx, dy); - sraRgnAnd(NPP_roffscreen, r0); - - if (! use_batch) { - do_copyregion(NPP_roffscreen, dx, dy, 0); - if (!fb_push_wait(0.2, FB_COPY)) { - fb_push_wait(0.1, FB_COPY); - } - } else { - batch_dxs[NPP_nreg] = dx; - batch_dys[NPP_nreg] = dy; - batch_reg[NPP_nreg++] = sraRgnCreateRgn(NPP_roffscreen); - } - sraRgnDestroy(NPP_roffscreen); - } - - /* 3) copy from the saveunder to where orig win was */ - r1 = sraRgnCreateRect(orig_x, orig_y, orig_x + orig_w, orig_y + orig_h); - sraRgnAnd(r1, r0); - r2 = sraRgnCreateRect(x+np, y+np, x + w-np, y + h-np); - sraRgnAnd(r2, r0); - sraRgnSubtract(r1, r2); - - dx = orig_x - su_x; - dy = orig_y - su_y; -if (db && ncdb) fprintf(stderr, "FB_COPY: %.4f 3) sent_copyrect: su_restore: %d %d\n", dnow() - ntim, dx, dy); - if (cache_list[nidx].su_time == 0.0) { - ; - } else if (! use_batch) { - do_copyregion(r1, dx, dy, 0); - if (!fb_push_wait(0.2, FB_COPY)) { -if (db && ncdb) fprintf(stderr, "FB_COPY: %.4f 3) FAILED.\n", dnow() - ntim); - fb_push_wait(0.1, FB_COPY); - } - } else { - batch_dxs[NPP_nreg] = dx; - batch_dys[NPP_nreg] = dy; - batch_reg[NPP_nreg++] = sraRgnCreateRgn(r1); - } -if (db && ncdb) fprintf(stderr, "sent_copyrect: %.4f su_restore: done.\n", dnow() - ntim); - sraRgnDestroy(r0); - sraRgnDestroy(r1); - sraRgnDestroy(r2); - - /* 4) if overlap between orig and displaced, move the corner that will still be su: */ - r0 = sraRgnCreateRect(0, 0, dpy_x, dpy_y); - - r1 = sraRgnCreateRect(orig_x, orig_y, orig_x + orig_w, orig_y + orig_h); - sraRgnAnd(r1, r0); - r2 = sraRgnCreateRect(x, y, x + w, y + h); - sraRgnAnd(r2, r0); - r3 = NULL; - if (sraRgnAnd(r2, r1) && cache_list[nidx].su_time > 0.0) { - int dx2 = su_x - orig_x; - int dy2 = su_y - orig_y; - - r3 = sraRgnCreateRgn(r2); - sraRgnOffset(r2, dx2, dy2); - - dx = su_x - x; - dy = su_y - y; - sraRgnOffset(r3, dx, dy); - - dx = dx - dx2; - dy = dy - dy2; - -if (db && ncdb) fprintf(stderr, "FB_COPY: %.4f 4) move overlap inside su:\n", dnow() - ntim); - if (! use_batch) { - do_copyregion(r3, dx, dy, 0); - if (!fb_push_wait(0.2, FB_COPY)) { -if (db) fprintf(stderr, "FB_COPY: %.4f 4) FAILED.\n", dnow() - ntim); - fb_push_wait(0.1, FB_COPY); - } - } else { - batch_dxs[NPP_nreg] = dx; - batch_dys[NPP_nreg] = dy; - batch_reg[NPP_nreg++] = sraRgnCreateRgn(r3); - } - } - sraRgnDestroy(r0); - sraRgnDestroy(r1); - sraRgnDestroy(r2); - - /* 5) copy our temporary stuff from bs to su: */ - dx = su_x - bs_x; - dy = su_y - bs_y; - if (NPP_r_bs_tmp == NULL) { - r1 = sraRgnCreateRect(su_x, su_y, su_x + su_w, su_y + su_h); - } else { - r1 = sraRgnCreateRgn(NPP_r_bs_tmp); - sraRgnOffset(r1, dx, dy); - sraRgnDestroy(NPP_r_bs_tmp); - } - if (r3 != NULL) { - sraRgnSubtract(r1, r3); - sraRgnDestroy(r3); - } -if (db) fprintf(stderr, "FB_COPY: %.4f 5) move tmp bs to su:\n", dnow() - ntim); - if (! use_batch) { - do_copyregion(r1, dx, dy, 0); - if (!fb_push_wait(0.2, FB_COPY)) { -if (db) fprintf(stderr, "FB_COPY: %.4f 5) FAILED.\n", dnow() - ntim); - fb_push_wait(0.1, FB_COPY); - } - } else { - batch_dxs[NPP_nreg] = dx; - batch_dys[NPP_nreg] = dy; - batch_reg[NPP_nreg++] = sraRgnCreateRgn(r1); - } - if (! sraRgnEmpty(r1)) { - some_su = 1; - } - sraRgnDestroy(r1); - - /* 6) not really necessary, update bs with current view: */ - r0 = sraRgnCreateRect(0, 0, dpy_x, dpy_y); - r1 = sraRgnCreateRect(x, y, x + w, y + h); - sraRgnAnd(r1, r0); - dx = bs_x - x; - dy = bs_y - y; - sraRgnOffset(r1, dx, dy); -if (db) fprintf(stderr, "FB_COPY: %.4f 6) snapshot bs:\n", dnow() - ntim); - if (! use_batch) { - do_copyregion(r1, dx, dy, 0); - if (!fb_push_wait(0.2, FB_COPY)) { -if (db) fprintf(stderr, "FB_COPY: %.4f 6) FAILED.\n", dnow() - ntim); - fb_push_wait(0.1, FB_COPY); - } - } else { - batch_dxs[NPP_nreg] = dx; - batch_dys[NPP_nreg] = dy; - batch_reg[NPP_nreg++] = sraRgnCreateRgn(r1); - } - sraRgnDestroy(r0); - sraRgnDestroy(r1); - - if (use_batch) { - batch_push(NPP_nreg, batch_delay); -if (ncdb) fprintf(stderr, "FB_COPY: %.4f XX did batch 0x%x %3d su: %dx%d+%d+%d bs: %dx%d+%d+%d\n", dnow() - ntim, - (unsigned int) cache_list[nidx].win, nidx, su_w, su_h, su_x, su_y, bs_w, bs_h, bs_x, bs_y); - } - cache_list[nidx].x = x + np; - cache_list[nidx].y = y + np; - - /* XXX Y */ - cache_list[nidx].bs_time = dnow(); - if (some_su) { - cache_list[nidx].su_time = dnow(); - } - } else { - if (use_batch) { - batch_push(NPP_nreg, batch_delay); - } - } - - if (scaling) { - sraRect rects[2]; - - rects[0].x1 = orig_x; - rects[0].y1 = orig_y; - rects[0].x2 = orig_w; - rects[0].y2 = orig_h; - - rects[1].x1 = x; - rects[1].y1 = y; - rects[1].x2 = w; - rects[1].y2 = h; - push_borders(rects, 2); - } -} - -void do_copyrect_drag_move(Window orig_frame, Window frame, int *nidx, int try_batch, - int now_x, int now_y, int orig_w, int orig_h, int x, int y, int w, int h, double batch_delay) { - - int sent_copyrect = 1, obscured = 0; - int dx, dy; - int use_batch = 0; - double ntim = dnow(); - static int nob = -1; - sraRegionPtr r0, r1; - - if (nob < 0) { - if (getenv("NOCRBATCH")) { - nob = 1; - } else { - nob = 0; - } - } - if (nob) { - try_batch = 0; - } - - dx = x - now_x; - dy = y - now_y; - if (dx == 0 && dy == 0) { - return; - } -if (ncdb) fprintf(stderr, "do_COPY: now_xy: %d %d, orig_wh: %d %d, xy: %d %d, wh: %d %d\n",now_x, now_y, orig_w, orig_h, x, y, w, h); - - ncache_pre_portions(orig_frame, frame, nidx, try_batch, &use_batch, - now_x, now_y, orig_w, orig_h, x, y, w, h, ntim); - - r0 = sraRgnCreateRect(0, 0, dpy_x, dpy_y); - r1 = sraRgnCreateRect(x, y, x + w, y + h); - sraRgnAnd(r1, r0); - - dx = x - now_x; - dy = y - now_y; - - /* make sure the source is on-screen too */ - sraRgnOffset(r1, -dx, -dy); - sraRgnAnd(r1, r0); - sraRgnOffset(r1, +dx, +dy); - sraRgnAnd(r1, r0); /* just to be sure, problably not needed */ - - if (! use_batch) { - do_copyregion(r1, dx, dy, 0); - if (!fb_push_wait(0.2, FB_COPY)) { -if (ncdb) fprintf(stderr, "FB_COPY: %.4f 3) *FAILED*\n", dnow() - ntim); - fb_push_wait(0.1, FB_COPY); - } - } else { - batch_dxs[NPP_nreg] = dx; - batch_dys[NPP_nreg] = dy; - batch_reg[NPP_nreg++] = sraRgnCreateRgn(r1); - } - sraRgnDestroy(r0); - sraRgnDestroy(r1); - - if (sent_copyrect) { - if (use_batch) { - ; - } else if (! obscured) { - fb_push_wait(0.1, FB_COPY); - } else { - /* no diff for now... */ - fb_push_wait(0.1, FB_COPY); - } - ncache_post_portions(*nidx, use_batch, - now_x, now_y, orig_w, orig_h, x, y, w, h, batch_delay, ntim); - } -if (ncdb) fprintf(stderr, "do_COPY: %.4f -- post_portion done.\n", dnow() - ntim); -} - -void check_macosx_iconify(Window orig_frame, Window frame, int flush) { -#ifdef MACOSX - static double last = 0.0; - double now; - int j, m = 5, idx = -1, ok = 0, unmapped = 0; - - if (! macosx_console) { - return; - } - - now = dnow(); - if (now < last + 0.3) { - return; - } - last = now; - - if (ncache > 0 && orig_frame != None) { - idx = lookup_win_index(orig_frame); - if (idx >= 0) { - if (cache_list[idx].map_state == IsUnmapped) { -if (0) fprintf(stderr, "FAW orig_frame unmapped.\n"); - unmapped = 1; - m = 3; - } - } - } - - if (unmapped) { - ; - } else if (orig_frame && macosxCGS_follow_animation_win(orig_frame, -1, 0)) { - if (0) fprintf(stderr, "FAW orig_frame %d\n", (int) orig_frame); - } else if (0 && frame && macosxCGS_follow_animation_win(frame, -1, 0)) { - if (0) fprintf(stderr, "FAW frame %d\n", (int) frame); - } - for (j=0; j<m; j++) { - macosxCGS_get_all_windows(); - if (macosx_checkevent(NULL)) { - ok = 1; - if (0) fprintf(stderr, "Check Event 1\n"); - } else { - if (0) fprintf(stderr, "Check Event 0\n"); - } - if (ok) { - break; - } - usleep(10 * 1000); - } - if (ok) { - if (flush) { - fb_push_wait(0.1, FB_COPY|FB_MOD); - } - check_ncache(0, 2); - } -#else - if (!orig_frame || !frame || !flush) {} -#endif -} - -void check_macosx_click_frame(void) { -#ifdef MACOSX - if (macosx_console) { -if (0) fprintf(stderr, "macosx_click_frame: 0x%x\n", macosx_click_frame); - check_macosx_iconify(macosx_click_frame, None, 0); - macosx_click_frame = None; - if (button_mask && !macosx_checkevent(NULL)) { - check_macosx_iconify(None, None, 0); - } - } -#endif -} - -int clipped(int idx); -void snap_old(void); - -int check_copyrect_raise(int idx, Window orig_frame, int try_batch) { - char *no = "none"; - int doraise = 1; - int valid; - XWindowAttributes attr; - - if (! ncache_wf_raises) { - doraise = 0; - no = "ncache_wf_raises"; - } else if (cache_list[idx].bs_time == 0.0) { - doraise = 0; - no = "bs_time"; - } else if (0 && cache_list[idx].vis_state == VisibilityUnobscured) { - doraise = 0; - no = "VisibilityUnobscured"; - } else if (!clipped(idx)) { - doraise = 0; - no = "!clipped()"; - } - if (doraise) { - int nr = 0, *nb = NULL; -if (ncdb) fprintf(stderr, "--YES, wf_raise\n"); - if (try_batch) { - nb = &nr; - } - valid = 1; - bs_restore(idx, nb, NULL, &attr, 0, 1, &valid, 1); - try_to_fix_su(orig_frame, idx, 0x1, nb, NULL); - if (nb && nr) { - batch_push(nr, -1.0); - } - fb_push(); /* XXX Y */ - } else { -if (ncdb && no) fprintf(stderr, "--NO, wf_raise: %s\n", no); - } - if (ncache_wf_raises) { - snapshot_stack_list(0, 0.0); - snap_old(); - } - return 1; -} - -int set_copyrect_drag(int idx, Window orig_frame, int try_batch) { - if (idx < 0) { - return 0; - } - if (cache_list[idx].su_time > 0.0) { - check_copyrect_raise(idx, orig_frame, try_batch); - return 1; - } - return 0; -} - -/* - * Applied just before any check_user_input() modes. Look for a - * ButtonPress; find window it happened in; find the wm frame window - * for it; watch for that window moving or resizing. If it does, do the - * wireframe animation. Do this until ButtonRelease or timeouts occur. - * Remove wireframe. - * - * Under -nowirecopyrect, return control to base scheme - * (check_user_input() ...) that will repaint the screen with the window - * in the new postion or size. Under -wirecopyrect, apply rfbDoCopyRect - * or rfbDoCopyRegion: this "pollutes" our framebuffer, but the normal - * polling will quickly repair it. Under happy circumstances, this - * reduces actual XShmGetImage work (i.e. if we correctly predicted how - * the X fb has changed. - * - * -scale doesn't always work under -wirecopyrect, but the wireframe does. - * - * testing of this mode under -threads is incomplete. - * - * returns 1 if it did an animation, 0 if no move/resize triggers - * went off. - * - * TBD: see if we can select StructureNotify ConfigureNotify events for - * the toplevel windows to get better info on moves and resizes. - */ -int check_wireframe(void) { - Window frame = None, orig_frame = None; - XWindowAttributes attr; - int dx, dy; - - int orig_px, orig_py, orig_x, orig_y, orig_w, orig_h; - int px, py, x, y, w, h; - int box_x, box_y, box_w, box_h; - int orig_cursor_x, orig_cursor_y, g, gd; - int already_down = 0, win_gone = 0, win_unmapped = 0; - double spin = 0.0, tm, last_ptr = 0.0, last_draw; - - int frame_changed = 0, drew_box = 0, got_2nd_pointer = 0; - int try_copyrect_drag = 1, do_copyrect_drag = -1; - int now_x = 0, now_y = 0, nidx = -1; - double copyrect_drag_delay = -1.0; - int try_batch = 1; /* XXX Y */ - int mac_skip = 0; - - int special_t1 = 0, break_reason = 0, last_draw_cnt = 0, gpi = 0; - static double first_dt_ave = 0.0; - static int first_dt_cnt = 0; - static time_t last_save_stacklist = 0; - int bdown0, bdown, gotui, cnt = 0; - - /* heuristics: */ - double first_event_spin = wireframe_t1; - double frame_changed_spin = wireframe_t2; - double max_spin = wireframe_t3; - double min_draw = wireframe_t4; - int try_it = 0; - DB_SET - - if (unixpw_in_progress) return 0; - if (copyrect_drag_delay) {} - -#ifdef MACOSX - if (macosx_console) { - ; - } else { - RAWFB_RET(0) - } -#else - RAWFB_RET(0) -#endif - - if (nofb) { - return 0; - } - if (subwin) { - return 0; /* don't even bother for -id case */ - } - -if (db > 1 && button_mask) fprintf(stderr, "check_wireframe: bm: %d gpi: %d\n", button_mask, got_pointer_input); - - bdown0 = 0; - if (button_mask) { - bdown0 = 1; - } else if (wireframe_local && display_button_mask) { - bdown0 = 2; - } - if (! bdown0) { - return 0; /* no button pressed down */ - } - - gotui = 0; - if (got_pointer_input) { - gotui = 1; - } else if (wireframe_local && display_button_mask) { - gotui = 2; - } - if (!use_threads && !gotui) { - return 0; /* need ptr input, e.g. button down, motion */ - } - -if (db > 1) fprintf(stderr, "check_wireframe: %d\n", db); - -if (db) fprintf(stderr, "\n*** button down!! x: %d y: %d\n", cursor_x, cursor_y); - - /* - * Query where the pointer is and which child of the root - * window. We will assume this is the frame the window manager - * makes when it reparents the toplevel window. - */ - X_LOCK; - if (! get_wm_frame_pos(&px, &py, &x, &y, &w, &h, &frame, NULL)) { -if (db) fprintf(stderr, "NO get_wm_frame_pos-1: 0x%lx\n", frame); - X_UNLOCK; -#ifdef MACOSX - check_macosx_click_frame(); -#endif - return 0; - } - X_UNLOCK; - - last_get_wm_frame_time = dnow(); - last_get_wm_frame = frame; - -if (db) fprintf(stderr, "a: %d wf: %.3f A: %d origfrm: 0x%lx\n", w*h, wireframe_frac, (dpy_x*dpy_y), frame); - - /* - * apply the percentage size criterion (allow opaque moves for - * small windows) - */ - if ((double) w*h < wireframe_frac * (dpy_x * dpy_y)) { -if (db) fprintf(stderr, "small window %.3f\n", ((double) w*h)/(dpy_x * dpy_y)); - return 0; - } -if (db) fprintf(stderr, " frame: x: %d y: %d w: %d h: %d px: %d py: %d fr: 0x%lx\n", x, y, w, h, px, py, frame); - - /* - * see if the pointer is within range of the assumed wm frame - * decorations on the edge of the window. - */ - - try_it = near_wm_edge(x, y, w, h, px, py); - - /* Often Alt+ButtonDown starts a window move: */ - if (! try_it && wireframe_mod_state()) { - try_it = 1; - } - if (try_it && clipshift) { - sraRegionPtr r1, r2; - int xc = off_x + coff_x; - int yc = off_y + coff_y; - r1 = sraRgnCreateRect(x, y, x+w, y+h); - r2 = sraRgnCreateRect(xc, yc, xc+dpy_x, yc+dpy_y); - if (!sraRgnAnd(r1, r2)) { -if (db) fprintf(stderr, "OUTSIDE CLIPSHIFT\n"); - try_it = 0; - } - sraRgnDestroy(r1); - sraRgnDestroy(r2); - } - if (! try_it) { -if (db) fprintf(stderr, "INTERIOR\n"); -#ifdef MACOSX - check_macosx_click_frame(); -#endif - return 0; - } - - wireframe_in_progress = 1; - - if (button_mask_prev) { - already_down = 1; - } - - if (! wireframe_str || !strcmp(wireframe_str, WIREFRAME_PARMS)) { - int link, latency, netrate; - static int didmsg = 0; - - link = link_rate(&latency, &netrate); - if (link == LR_DIALUP || link == LR_BROADBAND) { - /* slow link, e.g. dialup, increase timeouts: */ - first_event_spin *= 2.0; - frame_changed_spin *= 2.0; - max_spin *= 2.0; - min_draw *= 1.5; - if (link == LR_DIALUP) { - max_spin *= 1.2; - min_draw *= 1.7; - } - if (! didmsg) { - rfbLog("increased wireframe timeouts for " - "slow network connection.\n"); - rfbLog("netrate: %d KB/sec, latency: %d ms\n", - netrate, latency); - didmsg = 1; - } - } - } - - /* - * pointer() should have snapped the stacking list for us, if - * not, do it now (if the XFakeButtonEvent has been flushed by - * now the stacking order may be incorrect). - */ - if (strcmp(wireframe_copyrect, "never")) { - if (already_down) { - double age = 0.0; - /* - * see if we can reuse the stack list (pause - * with button down) - */ - if (stack_list_num) { - int k, got_me = 0; - for (k = stack_list_num -1; k >=0; k--) { - if (frame == stack_list[k].win) { - got_me = 1; - break; - } - } - if (got_me) { - age = 1.0; - } - snapshot_stack_list(0, age); - } - } - if (! stack_list_num) { - snapshot_stack_list(0, 0.0); - } - } - - - /* store initial parameters, we look for changes in them */ - orig_frame = frame; - orig_px = px; /* pointer position */ - orig_py = py; - orig_x = x; /* frame position */ - orig_y = y; - orig_w = w; /* frame size */ - orig_h = h; - - orig_cursor_x = cursor_x; - orig_cursor_y = cursor_y; - - /* this is the box frame we would draw */ - box_x = x; - box_y = y; - box_w = w; - box_h = h; - - dtime0(&tm); - - last_draw = spin; - - /* -threads support for check_wireframe() is rough... crash? */ - if (use_threads) { - /* purge any stored up pointer events: */ - pointer_event(-1, 0, 0, NULL); - } - - if (cursor_noshape_updates_clients(screen)) { - try_batch = 0; - } - if (rotating) { - try_batch = 0; - } - if (use_threads && ncache > 0 && ncache_copyrect) { - try_batch = 0; - } - - g = got_pointer_input; - gd = got_local_pointer_input; - - while (1) { - - X_LOCK; - XFlush_wr(dpy); - X_UNLOCK; - - /* try to induce/waitfor some more user input */ - if (use_threads) { - usleep(1000); - } else if (drew_box && do_copyrect_drag != 1) { - rfbPE(1000); - } else { - rfbCFD(1000); - } - if (bdown0 == 2) { - /* - * This is to just update display_button_mask - * which will also update got_local_pointer_input. - */ - check_x11_pointer(); -#if 0 - /* what was this for? */ - Window frame; - int px, py, x, y, w, h; -#ifdef MACOSX - if (macosx_console) { - macosx_get_cursor_pos(&x, &y); - } - else -#endif - get_wm_frame_pos(&px, &py, &x, &y, &w, &h, &frame, NULL); -#endif - } - - cnt++; - spin += dtime(&tm); - -if (0) fprintf(stderr, "wf-spin: %.3f\n", spin); - - /* check for any timeouts: */ - if (frame_changed) { - double delay; - /* max time we play this game: */ - if (spin > max_spin) { -if (db || db2) fprintf(stderr, " SPIN-OUT-MAX: %.3f\n", spin); - break_reason = 1; - break; - } - /* watch for pointer events slowing down: */ - if (special_t1) { - delay = max_spin; - } else { - delay = 2.0* frame_changed_spin; - if (spin > 3.0 * frame_changed_spin) { - delay = 1.5 * delay; - } - } - if (spin > last_ptr + delay) { -if (db || db2) fprintf(stderr, " SPIN-OUT-NOT-FAST: %.3f\n", spin); - break_reason = 2; - break; - } - } else if (got_2nd_pointer) { - /* - * pointer is moving, max time we wait for wm - * move or resize to be detected - */ - if (spin > frame_changed_spin) { -if (db || db2) fprintf(stderr, " SPIN-OUT-NOFRAME-SPIN: %.3f\n", spin); - break_reason = 3; - break; - } - } else { - /* max time we wait for any pointer input */ - if (spin > first_event_spin) { -if (db || db2) fprintf(stderr, " SPIN-OUT-NO2ND_PTR: %.3f\n", spin); - break_reason = 4; - break; - } - } - - gpi = 0; - /* see if some pointer input occurred: */ - if (got_pointer_input > g || - (wireframe_local && (got_local_pointer_input > gd))) { - -if (db) fprintf(stderr, " ++pointer event!! [%02d] dt: %.3f x: %d y: %d mask: %d\n", - got_2nd_pointer+1, spin, cursor_x, cursor_y, button_mask); - - g = got_pointer_input; - gd = got_local_pointer_input; - gpi = 1; - - X_LOCK; - XFlush_wr(dpy); - X_UNLOCK; - - /* periodically try to let the wm get moving: */ - if (!frame_changed && got_2nd_pointer % 4 == 0) { - if (got_2nd_pointer == 0) { - usleep(50 * 1000); - } else { - usleep(25 * 1000); - } - } - got_2nd_pointer++; - last_ptr = spin; - - /* - * see where the pointer currently is. It may - * not be our starting frame (i.e. mouse now - * outside of the moving window). - */ - frame = 0x0; - X_LOCK; - - if (! get_wm_frame_pos(&px, &py, &x, &y, &w, &h, - &frame, NULL)) { - frame = 0x0; -if (db) fprintf(stderr, "NO get_wm_frame_pos-2: 0x%lx\n", frame); - } - - if (frame != orig_frame) { - /* see if our original frame is still there */ - if (!valid_window(orig_frame, &attr, 1)) { - X_UNLOCK; - /* our window frame went away! */ - win_gone = 1; -if (db) fprintf(stderr, "FRAME-GONE: 0x%lx\n", orig_frame); - break_reason = 5; - break; - } - if (attr.map_state == IsUnmapped) { - X_UNLOCK; - /* our window frame is now unmapped! */ - win_unmapped = 1; -if (db) fprintf(stderr, "FRAME-UNMAPPED: 0x%lx\n", orig_frame); - break_reason = 5; - break; - } - -if (db) fprintf(stderr, "OUT-OF-FRAME: old: x: %d y: %d px: %d py: %d 0x%lx\n", x, y, px, py, frame); - - /* new parameters for our frame */ - x = attr.x; /* n.b. rootwin is parent */ - y = attr.y; - w = attr.width; - h = attr.height; - } - X_UNLOCK; - -if (db) fprintf(stderr, " frame: x: %d y: %d w: %d h: %d px: %d py: %d fr: 0x%lx\n", x, y, w, h, px, py, frame); -if (db) fprintf(stderr, " MO,PT,FR: %d/%d %d/%d %d/%d\n", cursor_x - orig_cursor_x, cursor_y - orig_cursor_y, px - orig_px, py - orig_py, x - orig_x, y - orig_y); - - if (frame_changed && frame != orig_frame) { -if (db) fprintf(stderr, "CHANGED and window switch: 0x%lx\n", frame); - } - if (frame_changed && px - orig_px != x - orig_x) { -if (db) fprintf(stderr, "MOVED and diff DX\n"); - } - if (frame_changed && py - orig_py != y - orig_y) { -if (db) fprintf(stderr, "MOVED and diff DY\n"); - } - - /* check and see if our frame has been resized: */ - if (!frame_changed && (w != orig_w || h != orig_h)) { - int n; - if (!already_down) { - first_dt_ave += spin; - first_dt_cnt++; - } - n = first_dt_cnt ? first_dt_cnt : 1; - frame_changed = 2; - -if (db) fprintf(stderr, "WIN RESIZE 1st-dt: %.3f\n", first_dt_ave/n); - } - - /* check and see if our frame has been moved: */ - if (!frame_changed && (x != orig_x || y != orig_y)) { - int n; - if (!already_down) { - first_dt_ave += spin; - first_dt_cnt++; - } - n = first_dt_cnt ? first_dt_cnt : 1; - frame_changed = 1; -if (db) fprintf(stderr, "FRAME MOVE 1st-dt: %.3f\n", first_dt_ave/n); - } - } - - /* - * see if it is time to draw any or a new wireframe box - */ - - if (frame_changed) { - int drawit = 0; - if (x != box_x || y != box_y) { - /* moved since last */ -if (0) fprintf(stderr, "DRAW1 %d %d\n", x - box_x, y - box_y); - drawit = 1; - } else if (w != box_w || h != box_h) { - /* resize since last */ - drawit = 1; - } - if (drawit) { - int doit = 0; - /* - * check time (to avoid too much - * animations on slow machines - * or links). - */ - if (gpi) { - if (spin > last_draw + min_draw || ! drew_box) { - doit = 1; - } - if (macosx_console && doit && !mac_skip) { - if (x != box_x && y != box_y && w != box_w && h != box_h) { - doit = 0; - } else if (!button_mask) { - doit = 0; - } - mac_skip++; - } - } else { - if (drew_box && cnt > last_draw_cnt) { - doit = 1; -if (0) fprintf(stderr, "*** NO GPI DRAW_BOX\n"); - } - } - - if (doit) { - if (try_copyrect_drag && ncache > 0) { - if (!ncache_copyrect) { - do_copyrect_drag = 0; - } else if (w != box_w || h != box_h) { - do_copyrect_drag = 0; - } else if (do_copyrect_drag < 0) { - Window fr = orig_frame; - int idx = lookup_win_index(fr); - if (idx < 0) { - fr = frame; - idx = lookup_win_index(fr); - } - if (idx >= 0) { - do_copyrect_drag = set_copyrect_drag(idx, fr, try_batch); - if (do_copyrect_drag) { - min_draw *= 0.66; - } - nidx = idx; - } else { - do_copyrect_drag = 0; - } - now_x = orig_x; - now_y = orig_y; - } - if (do_copyrect_drag) { - if (orig_w != w || orig_h != h) { - do_copyrect_drag = 0; - } - } - } - - if (do_copyrect_drag <= 0) { - if (ncache <= 0) { - ; - } else if (!drew_box && ncache_wf_raises) { - Window fr = orig_frame; - int idx = lookup_win_index(fr); - if (idx < 0) { - fr = frame; - idx = lookup_win_index(fr); - } - if (idx >= 0) { - check_copyrect_raise(idx, fr, try_batch); - } - } - draw_box(x, y, w, h, 0); - fb_push(); /* XXX Y */ - rfbPE(1000); - } else { -#ifndef NO_NCACHE - int tb = use_threads ? 0 : try_batch; - do_copyrect_drag_move(orig_frame, frame, &nidx, - tb, now_x, now_y, orig_w, orig_h, x, y, w, h, - copyrect_drag_delay); - now_x = x; - now_y = y; - if (copyrect_drag_delay == -1.0) { - copyrect_drag_delay = 0.04; - } -#endif - } - drew_box = 1; - last_wireframe = dnow(); - - last_draw = spin; - last_draw_cnt = cnt; - } - } - box_x = x; - box_y = y; - box_w = w; - box_h = h; - } - - /* - * Now (not earlier) check if the button has come back up. - * we check here to get a better location and size of - * the final window. - */ - bdown = 0; - if (button_mask) { - bdown = 1; - } else if (wireframe_local && display_button_mask) { - bdown = 2; - } - if (! bdown) { -if (db || db2) fprintf(stderr, "NO button_mask\n"); - break_reason = 6; - break; - } - } - - if (! drew_box) { - /* nice try, but no move or resize detected. cleanup. */ - if (stack_list_num) { - stack_list_num = 0; - } - wireframe_in_progress = 0; - if (macosx_console && (break_reason == 6 || break_reason == 5)) { - check_macosx_iconify(orig_frame, frame, drew_box); - } - return 0; - } - - /* remove the wireframe */ - if (do_copyrect_drag <= 0) { - draw_box(0, 0, 0, 0, 1); - fb_push(); /* XXX Y */ - } else { - int tb = use_threads ? 0 : try_batch; - do_copyrect_drag_move(orig_frame, frame, &nidx, - tb, now_x, now_y, orig_w, orig_h, x, y, w, h, -1.0); - fb_push_wait(0.15, FB_COPY|FB_MOD); - } - - dx = x - orig_x; - dy = y - orig_y; - - /* - * see if we can apply CopyRect or CopyRegion to the change: - */ - if (!strcmp(wireframe_copyrect, "never")) { - ; - } else if (win_gone || win_unmapped) { - ; - } else if (skip_cr_when_scaling("wireframe")) { - ; - } else if (w != orig_w || h != orig_h) { - if (ncache > 0) { - try_to_fix_resize_su(orig_frame, orig_x, orig_y, orig_w, orig_h, x, y, w, h, try_batch); - X_LOCK; - clear_win_events(orig_frame, 1); - if (frame != orig_frame) { - clear_win_events(frame, 1); - } - X_UNLOCK; - } - } else if (dx == 0 && dy == 0) { - ; - } else if (do_copyrect_drag > 0) { - X_LOCK; - clear_win_events(NPP_nwin, 0); - X_UNLOCK; - } else { - int spin_ms = (int) (spin * 1000 * 1000); - int obscured, sent_copyrect = 0; - - int nidx = -1; - int use_batch = 0; - double ntim; - - /* - * set a timescale comparable to the spin time, - * but not too short or too long. - */ - if (spin_ms < 30) { - spin_ms = 30; - } else if (spin_ms > 400) { - spin_ms = 400; - } - ntim = dnow(); - - /* try to flush the wireframe removal: */ -if (ncdb && ncache) fprintf(stderr, "\nSEND_COPYRECT %.4f %.4f\n", dnowx(), dnow() - ntim); - - if (! fb_push_wait(0.15, FB_COPY|FB_MOD)) { - -if (ncdb && ncache) fprintf(stderr, "FB_COPY *FAILED*, try one more... %.4f", dnow() - ntim); - - if (! fb_push_wait(0.15, FB_COPY|FB_MOD)) { - -if (ncdb && ncache) fprintf(stderr, "FB_COPY *FAILED* again! %.4f", dnow() - ntim); - - } - } - - ncache_pre_portions(orig_frame, frame, &nidx, try_batch, &use_batch, - orig_x, orig_y, orig_w, orig_h, x, y, w, h, ntim); - - /* 2) try to send a clipped copyrect of translation: */ - - if (! try_batch) { - sent_copyrect = try_copyrect(orig_frame, frame, x, y, w, h, dx, dy, - &obscured, NULL, 0.15, NULL); - } else { - try_copyrect(orig_frame, frame, x, y, w, h, dx, dy, - &obscured, NULL, 0.15, &NPP_nreg); /* XXX */ - sent_copyrect = 1; - use_batch = 1; - } - -if ((ncache || db) && ncdb) fprintf(stderr, "sent_copyrect: %d - obs: %d frame: 0x%lx\n", sent_copyrect, obscured, frame); - if (sent_copyrect) { - /* try to push the changes to viewers: */ - if (use_batch) { - ; - } else if (! obscured) { - fb_push_wait(0.1, FB_COPY); - } else { - /* no diff for now... */ - fb_push_wait(0.1, FB_COPY); - } - ncache_post_portions(nidx, use_batch, - orig_x, orig_y, orig_w, orig_h, x, y, w, h, -1.0, ntim); - X_LOCK; - clear_win_events(NPP_nwin, 0); - X_UNLOCK; - - if (scaling && !use_batch) { - static double last_time = 0.0; - double now = dnow(), delay = 0.35; - - fb_push_wait(0.1, FB_COPY); - - if (now > last_time + delay) { - int xt = x, yt = y; - - if (clipshift) { - xt -= coff_x; - yt -= coff_y; - } - if (subwin) { - xt -= off_x; - yt -= off_y; - } - - scale_mark(xt, yt, xt+w, yt+h, 1); - last_time = now; - last_copyrect_fix = now; - } - } - } - } - - if (stack_list_num) { - /* clean up stack_list for next time: */ - if (break_reason == 1 || break_reason == 2) { - /* - * save the stack list, perhaps the user has - * paused with button down. - */ - last_save_stacklist = time(NULL); - } else { - stack_list_num = 0; - } - } - - /* final push (for -nowirecopyrect) */ - rfbPE(1000); - wireframe_in_progress = 0; - - if (1) { - /* In principle no longer needed... see draw_box() */ - if (frame_changed && cmap8to24 /* && multivis_count */) { - /* handle -8to24 kludge, mark area and check 8bpp... */ - int x1, x2, y1, y2, f = 16; - x1 = nmin(box_x, orig_x) - f; - y1 = nmin(box_y, orig_y) - f; - x2 = nmax(box_x + box_w, orig_x + orig_w) + f; - y2 = nmax(box_y + box_h, orig_y + orig_h) + f; - x1 = nfix(x1, dpy_x); - x2 = nfix(x2, dpy_x+1); - y1 = nfix(y1, dpy_y); - y2 = nfix(y2, dpy_y+1); - if (0) { - check_for_multivis(); - mark_rect_as_modified(x1, y1, x2, y2, 0); - } else { - if (1) { - bpp8to24(x1, y1, x2, y2); - } else { - bpp8to24(0, 0, dpy_x, dpy_y); - } - } - } - } - - urgent_update = 1; - if (use_xdamage) { - /* DAMAGE can queue ~1000 rectangles for a move */ - clear_xdamage_mark_region(NULL, 1); - xdamage_scheduled_mark = dnow() + 2.0; - } - - if (macosx_console && (break_reason == 6 || break_reason == 5)) { - check_macosx_iconify(orig_frame, frame, drew_box); - } - - return 1; -} - -/* - * We need to handle user input, particularly pointer input, carefully. - * This function is only called when non-threaded. Note that - * rfbProcessEvents() only processes *one* pointer event per call, - * so if we interlace it with scan_for_updates(), we can get swamped - * with queued up pointer inputs. And if the pointer inputs are inducing - * large changes on the screen (e.g. window drags), the whole thing - * bogs down miserably and only comes back to life at some time after - * one stops moving the mouse. So, to first approximation, we are trying - * to eat as much user input here as we can using some hints from the - * duration of the previous scan_for_updates() call (in dt). - * - * note: we do this even under -nofb - * - * return of 1 means watch_loop should short-circuit and reloop, - * return of 0 means watch_loop should proceed to scan_for_updates(). - * (this is for pointer_mode == 1 mode, the others do it all internally, - * cnt is also only for that mode). - */ - -static void check_user_input2(double dt) { - - int eaten = 0, miss = 0, max_eat = 50, do_flush = 1; - int g, g_in; - double spin = 0.0, tm; - double quick_spin_fac = 0.40; - double grind_spin_time = 0.175; - - dtime0(&tm); - g = g_in = got_pointer_input; - if (!got_pointer_input) { - return; - } - /* - * Try for some "quick" pointer input processing. - * - * About as fast as we can, we try to process user input calling - * rfbProcessEvents or rfbCheckFds. We do this for a time on - * order of the last scan_for_updates() time, dt, but if we stop - * getting user input we break out. We will also break out if - * we have processed max_eat inputs. - * - * Note that rfbCheckFds() does not send any framebuffer updates, - * so is more what we want here, although it is likely they have - * all be sent already. - */ - while (1) { - if (show_multiple_cursors) { - rfbPE(1000); - } else { - rfbCFD(1000); - } - rfbCFD(0); - - spin += dtime(&tm); - - if (spin > quick_spin_fac * dt) { - /* get out if spin time comparable to last scan time */ - break; - } - if (got_pointer_input > g) { - int i, max_extra = max_eat / 2; - g = got_pointer_input; - eaten++; - for (i=0; i<max_extra; i++) { - rfbCFD(0); - if (got_pointer_input > g) { - g = got_pointer_input; - eaten++; - } else if (i > 1) { - break; - } - } - X_LOCK; - do_flush = 0; -if (0) fprintf(stderr, "check_user_input2-A: XFlush %.4f\n", tm); - XFlush_wr(dpy); - X_UNLOCK; - if (eaten < max_eat) { - continue; - } - } else { - miss++; - } - if (miss > 1) { /* 1 means out on 2nd miss */ - break; - } - } - if (do_flush) { - X_LOCK; -if (0) fprintf(stderr, "check_user_input2-B: XFlush %.4f\n", tm); - XFlush_wr(dpy); - X_UNLOCK; - } - - - /* - * Probably grinding with a lot of fb I/O if dt is this large. - * (need to do this more elegantly) - * - * Current idea is to spin our wheels here *not* processing any - * fb I/O, but still processing the user input. This user input - * goes to the X display and changes it, but we don't poll it - * while we "rest" here for a time on order of dt, the previous - * scan_for_updates() time. We also break out if we miss enough - * user input. - */ - if (dt > grind_spin_time) { - int i, ms, split = 30; - double shim; - - /* - * Break up our pause into 'split' steps. We get at - * most one input per step. - */ - shim = 0.75 * dt / split; - - ms = (int) (1000 * shim); - - /* cutoff how long the pause can be */ - if (split * ms > 300) { - ms = 300 / split; - } - - spin = 0.0; - dtime0(&tm); - - g = got_pointer_input; - miss = 0; - for (i=0; i<split; i++) { - usleep(ms * 1000); - if (show_multiple_cursors) { - rfbPE(1000); - } else { - rfbCFD(1000); - } - spin += dtime(&tm); - if (got_pointer_input > g) { - int i, max_extra = max_eat / 2; - for (i=0; i<max_extra; i++) { - rfbCFD(0); - if (got_pointer_input > g) { - g = got_pointer_input; - } else if (i > 1) { - break; - } - } - X_LOCK; -if (0) fprintf(stderr, "check_user_input2-C: XFlush %.4f\n", tm); - XFlush_wr(dpy); - X_UNLOCK; - miss = 0; - } else { - miss++; - } - g = got_pointer_input; - if (miss > 2) { - break; - } - if (1000 * spin > ms * split) { - break; - } - } - } -} - -static void check_user_input3(double dt, double dtr, int tile_diffs) { - - int allowed_misses, miss_tweak, i, g, g_in; - int last_was_miss, consecutive_misses; - double spin, spin_max, tm, to, dtm; - int rfb_wait_ms = 2; - static double dt_cut = 0.075; - int gcnt, ginput; - static int first = 1; - - if (dtr || tile_diffs) {} /* unused vars warning: */ - - if (first) { - char *p = getenv("SPIN"); - if (p) { - double junk; - sscanf(p, "%lf,%lf", &dt_cut, &junk); - } - first = 0; - } - - if (!got_pointer_input) { - return; - } - - - if (dt < dt_cut) { - dt = dt_cut; /* this is to try to avoid early exit */ - } - spin_max = 0.5; - - spin = 0.0; /* amount of time spinning */ - allowed_misses = 10; /* number of ptr inputs we can miss */ - miss_tweak = 8; - last_was_miss = 0; - consecutive_misses = 1; - gcnt = 0; - ginput = 0; - - dtime0(&tm); - to = tm; /* last time we did rfbPE() */ - - g = g_in = got_pointer_input; - - while (1) { - int got_input = 0; - - gcnt++; - - if (button_mask) { - drag_in_progress = 1; - } - - rfbCFD(rfb_wait_ms * 1000); - - dtm = dtime(&tm); - spin += dtm; - - if (got_pointer_input == g) { - if (last_was_miss) { - consecutive_misses++; - } - last_was_miss = 1; - } else { - ginput++; - if (ginput % miss_tweak == 0) { - allowed_misses++; - } - consecutive_misses = 1; - last_was_miss = 0; - } - - if (spin > spin_max) { - /* get out if spin time over limit */ - break; - - } else if (got_pointer_input > g) { - /* received some input, flush to display. */ - got_input = 1; - g = got_pointer_input; - X_LOCK; - XFlush_wr(dpy); - X_UNLOCK; - } else if (--allowed_misses <= 0) { - /* too many misses */ - break; - } else if (consecutive_misses >=3) { - /* too many misses */ - break; - } else { - /* these are misses */ - int wms = 0; - if (gcnt == 1 && button_mask) { - /* - * missed our first input, wait - * for a defer time. (e.g. on - * slow link) hopefully client - * will batch them. - */ - wms = 50; - } else if (button_mask) { - wms = 10; - } else { - } - if (wms) { - usleep(wms * 1000); - } - } - } - - if (ginput >= 2) { - /* try for a couple more quick ones */ - for (i=0; i<2; i++) { - rfbCFD(rfb_wait_ms * 1000); - } - } - - drag_in_progress = 0; -} - -int fb_update_sent(int *count) { - static int last_count = 0; - int sent = 0, rc = 0; - rfbClientIteratorPtr i; - rfbClientPtr cl; - - if (nofb) { - return 0; - } - - i = rfbGetClientIterator(screen); - while( (cl = rfbClientIteratorNext(i)) ) { -#if 0 - sent += cl->framebufferUpdateMessagesSent; -#else -#if LIBVNCSERVER_HAS_STATS - sent += rfbStatGetMessageCountSent(cl, rfbFramebufferUpdate); -#endif -#endif - } - rfbReleaseClientIterator(i); - if (sent != last_count) { - rc = 1; - } - if (count != NULL) { - *count = sent; - } - last_count = sent; - return rc; -} - -static void check_user_input4(double dt, double dtr, int tile_diffs) { - - int g, g_in, i, ginput, gcnt, tmp; - int last_was_miss, consecutive_misses; - int min_frame_size = 10; /* 10 tiles */ - double spin, tm, to, tc, dtm, rpe_last; - int rfb_wait_ms = 2; - static double dt_cut = 0.050; - static int first = 1; - - int Btile = tile_x * tile_y * bpp/8; /* Bytes per tile */ - double Ttile, dt_use; - double screen_rate = 6000000.; /* 5 MB/sec */ - double vnccpu_rate = 80 * 100000.; /* 20 KB/sec @ 80X compression */ - double net_rate = 50000.; - static double Tfac_r = 1.0, Tfac_v = 1.0, Tfac_n = 1.0, Tdelay = 0.001; - static double dt_min = -1.0, dt_max = -1.0; - double dt_min_fallback = 0.050; - static int ssec = 0, total_calls = 0; - static int push_frame = 0, update_count = 0; - - if (first) { - char *p = getenv("SPIN"); - if (p) { - sscanf(p, "%lf,%lf,%lf,%lf", &dt_cut, &Tfac_r, &Tfac_v, &Tfac_n); - } - first = 0; - ssec = time(NULL); - - if (dtr) {} /* unused vars warning: */ - } - - total_calls++; - - if (dt_min < 0.0 || dt < dt_min) { - if (dt > 0.0) { - dt_min = dt; - } - } - if (dt_min < 0.0) { - /* sensible value for the very 1st call if dt = 0.0 */ - dt_min = dt_min_fallback; - } - if (dt_max < 0.0 || dt > dt_max) { - dt_max = dt; - } - - if (total_calls > 30 && dt_min > 0.0) { - static int first = 1; - /* - * dt_min will soon be the quickest time to do - * one scan_for_updates with no tiles copied. - * use this (instead of copy_tiles) to estimate - * screen read rate. - */ - screen_rate = (main_bytes_per_line * ntiles_y) / dt_min; - if (first) { - rfbLog("measured screen read rate: %.2f Bytes/sec\n", - screen_rate); - } - first = 0; - } - - dtime0(&tm); - - if (dt < dt_cut) { - dt_use = dt_cut; - } else { - dt_use = dt; - } - - if (push_frame) { - int cnt, iter = 0; - double tp, push_spin = 0.0; - dtime0(&tp); - while (push_spin < dt_use * 0.5) { - fb_update_sent(&cnt); - if (cnt != update_count) { - break; - } - /* damn, they didn't push our frame! */ - iter++; - rfbPE(rfb_wait_ms * 1000); - - push_spin += dtime(&tp); - } - if (iter) { - X_LOCK; - XFlush_wr(dpy); - X_UNLOCK; - } - push_frame = 0; - update_count = 0; - } - - /* - * when we first enter we require some pointer input - */ - if (!got_pointer_input) { - return; - } - - vnccpu_rate = get_raw_rate(); - - if ((tmp = get_read_rate()) != 0) { - screen_rate = (double) tmp; - } - if ((tmp = get_net_rate()) != 0) { - net_rate = (double) tmp; - } - net_rate = (vnccpu_rate/get_cmp_rate()) * net_rate; - - if ((tmp = get_net_latency()) != 0) { - Tdelay = 0.5 * ((double) tmp)/1000.; - } - - Ttile = Btile * (Tfac_r/screen_rate + Tfac_v/vnccpu_rate + Tfac_n/net_rate); - - spin = 0.0; /* amount of time spinning */ - last_was_miss = 0; - consecutive_misses = 1; - gcnt = 0; - ginput = 0; - - rpe_last = to = tc = tm; /* last time we did rfbPE() */ - g = g_in = got_pointer_input; - - tile_diffs = 0; /* reset our knowlegde of tile_diffs to zero */ - - while (1) { - int got_input = 0; - - gcnt++; - - if (button_mask) { - /* this varible is used by our pointer handler */ - drag_in_progress = 1; - } - - /* turn libvncserver crank to process events: */ - rfbCFD(rfb_wait_ms * 1000); - - dtm = dtime(&tm); - spin += dtm; - - if ( (gcnt == 1 && got_pointer_input > g) || tm-tc > 2*dt_min) { - tile_diffs = scan_for_updates(1); - tc = tm; - } - - if (got_pointer_input == g) { - if (last_was_miss) { - consecutive_misses++; - } - last_was_miss = 1; - } else { - ginput++; - consecutive_misses = 1; - last_was_miss = 0; - } - - if (tile_diffs > min_frame_size && spin > Ttile * tile_diffs + Tdelay) { - /* we think we can push the frame */ - push_frame = 1; - fb_update_sent(&update_count); - break; - - } else if (got_pointer_input > g) { - /* received some input, flush it to display. */ - got_input = 1; - g = got_pointer_input; - X_LOCK; - XFlush_wr(dpy); - X_UNLOCK; - - } else if (consecutive_misses >= 2) { - /* too many misses in a row */ - break; - - } else { - /* these are pointer input misses */ - int wms; - if (gcnt == 1 && button_mask) { - /* - * missed our first input, wait for - * a defer time. (e.g. on slow link) - * hopefully client will batch many - * of them for the next read. - */ - wms = 50; - - } else if (button_mask) { - wms = 10; - } else { - wms = 0; - } - if (wms) { - usleep(wms * 1000); - } - } - } - if (ginput >= 2) { - /* try for a couple more quick ones */ - for (i=0; i<2; i++) { - rfbCFD(rfb_wait_ms * 1000); - } - } - drag_in_progress = 0; -} - -int check_user_input(double dt, double dtr, int tile_diffs, int *cnt) { - - if (rawfb_vnc_reflect) { - if (got_user_input) { - if (0) vnc_reflect_process_client(); - } - if (got_user_input && *cnt % ui_skip != 0) { - /* every n-th drops thru to scan */ - *cnt = *cnt + 1; - return 1; /* short circuit watch_loop */ - } - } -#ifdef MACOSX - if (! macosx_console) { - RAWFB_RET(0) - } -#else - RAWFB_RET(0) -#endif - - if (use_xrecord) { - int rc = check_xrecord(); - /* - * 0: nothing found, proceed to other user input schemes. - * 1: events found, want to do a screen update now. - * 2: events found, want to loop back for some more. - * 3: events found, want to loop back for some more, - * and not have rfbPE() called. - * - * For 0, we precede below, otherwise return rc-1. - */ -if (debug_scroll && rc > 1) fprintf(stderr, " CXR: check_user_input ret %d\n", rc - 1); - if (rc == 0) { - ; /* proceed below. */ - } else { - return rc - 1; - } - } - - if (wireframe) { - if (check_wireframe()) { - return 0; - } - } - - if (pointer_mode == 1) { - if ((got_user_input || ui_skip < 0) && *cnt % ui_skip != 0) { - /* every ui_skip-th drops thru to scan */ - *cnt = *cnt + 1; - X_LOCK; - XFlush_wr(dpy); - X_UNLOCK; - return 1; /* short circuit watch_loop */ - } else { - return 0; - } - } - if (pointer_mode >= 2 && pointer_mode <= 4) { - if (got_keyboard_input) { - /* - * for these modes, short circuit watch_loop on - * *keyboard* input. - */ - if (*cnt % ui_skip != 0) { - *cnt = *cnt + 1; - return 1; - } - } - /* otherwise continue below with pointer input method */ - } - - if (pointer_mode == 2) { - check_user_input2(dt); - } else if (pointer_mode == 3) { - check_user_input3(dt, dtr, tile_diffs); - } else if (pointer_mode == 4) { - check_user_input4(dt, dtr, tile_diffs); - } - return 0; -} - -#if defined(NO_NCACHE) || (NO_X11 && !defined(MACOSX)) -int check_ncache(int a, int b) { - if (!a || !b) {} - ncache = 0; - return 0; -} -int lookup_win_index(Window win) { - if (!win) {} - return -1; -} -int find_rect(int idx, int x, int y, int w, int h) { - if (!idx || !x || !y || !w || !h) {} - return 0; -} -void snap_old(void) { - return; -} -int clipped(int idx) { - if (!idx) {} - return 0; -} -int bs_restore(int idx, int *nbatch, sraRegionPtr rmask, XWindowAttributes *attr, int clip, int nopad, int *valid, int verb) { - if (!idx || !nbatch || !rmask || !attr || !clip || !nopad || !valid || !verb) {} - return 0; -} -int try_to_fix_su(Window win, int idx, Window above, int *nbatch, char *mode) { - if (!win || !idx || !above || !nbatch || !mode) {} - return 0; -} -int try_to_fix_resize_su(Window orig_frame, int orig_x, int orig_y, int orig_w, int orig_h, - int x, int y, int w, int h, int try_batch) { - if (!orig_frame || !orig_x || !orig_y || !orig_w || !orig_h || !x || !y || !w || !h || !try_batch) {} - return 0; -} -void set_ncache_xrootpmap(void) { - return; -} -#else -/* maybe ncache.c it if works */ - -winattr_t* cache_list = NULL; -int cache_list_num = 0; -int cache_list_len = 0; - -void snapshot_cache_list(int free_only, double allowed_age) { - static double last_snap = 0.0, last_free = 0.0; - double now; - int num, rc, i; - unsigned int ui; - Window r, w; - Window *list; - int start = 512; - - if (! cache_list) { - cache_list = (winattr_t *) calloc(start*sizeof(winattr_t), 1); - cache_list_num = 0; - cache_list_len = start; - } - - dtime0(&now); - if (free_only) { - /* we really don't free it, just reset to zero windows */ - cache_list_num = 0; - last_free = now; - return; - } - - if (cache_list_num && now < last_snap + allowed_age) { - return; - } - - cache_list_num = 0; - last_free = now; - -#ifdef MACOSX - if (! macosx_console) { - RAWFB_RET_VOID - } -#else - RAWFB_RET_VOID -#endif - - -#if NO_X11 && !defined(MACOSX) - num = rc = i = 0; /* compiler warnings */ - ui = 0; - r = w = None; - list = NULL; - return; -#else - - X_LOCK; - /* no need to trap error since rootwin */ - rc = XQueryTree_wr(dpy, rootwin, &r, &w, &list, &ui); - X_UNLOCK; - num = (int) ui; - - if (! rc) { - cache_list_num = 0; - last_free = now; - last_snap = 0.0; - return; - } - - last_snap = now; - if (num > cache_list_len) { - int n = 2*num; - n = num + 3; - free(cache_list); - cache_list = (winattr_t *) calloc(n*sizeof(winattr_t), 1); - cache_list_len = n; - } - for (i=0; i<num; i++) { - cache_list[i].win = list[i]; - cache_list[i].fetched = 0; - cache_list[i].valid = 0; - cache_list[i].time = now; - cache_list[i].selectinput = 0; - cache_list[i].vis_cnt = 0; - cache_list[i].map_cnt = 0; - cache_list[i].unmap_cnt = 0; - cache_list[i].create_cnt = 0; - cache_list[i].vis_state = -1; - cache_list[i].above = None; - } - if (num == 0) { - cache_list[0].win = None; - cache_list[0].fetched = 0; - cache_list[0].valid = 0; - cache_list[0].time = now; - cache_list[0].selectinput = 0; - cache_list[0].vis_cnt = 0; - cache_list[0].map_cnt = 0; - cache_list[0].unmap_cnt = 0; - cache_list[0].create_cnt = 0; - cache_list[0].vis_state = -1; - cache_list[0].above = None; - num++; - } - - cache_list_num = num; - - if (num) { - X_LOCK; - XFree_wr(list); - X_UNLOCK; - } -#endif /* NO_X11 */ -} - -void quick_snap(Window *wins, int *size) { - int num, rc, i; - unsigned int ui; - Window r, w; - Window *list; - -#ifdef MACOSX - if (1 || ! macosx_console) { - RAWFB_RET_VOID - } -#else - RAWFB_RET_VOID -#endif - - -#if NO_X11 && !defined(MACOSX) - num = rc = i = 0; /* compiler warnings */ - ui = 0; - r = w = None; - list = NULL; - return; -#else - - X_LOCK; - /* no need to trap error since rootwin */ - rc = XQueryTree_wr(dpy, rootwin, &r, &w, &list, &ui); - X_UNLOCK; - num = (int) ui; - - if (! rc || num == 0) { - *size = 0; - return; - } else { - int m = *size; - if (num < m) { - m = num; - } - for (i=0; i < m; i++) { - wins[i] = list[i]; - } - if (num) { - X_LOCK; - XFree_wr(list); - X_UNLOCK; - } - *size = m; - } -#endif /* NO_X11 */ -} - -int get_bs_n(int y) { - int n; - for (n = 1; n < ncache; n += 2) { - if (n*dpy_y <= y && y < (n+1)*dpy_y) { - return n; - } - } - return -1; -} - -#define NRECENT 32 -Window recent[NRECENT]; -int recidx[NRECENT]; -int rlast, rfree; - -int lookup_win_index(Window win) { - int k, idx = -1; - int foundfree = 0; - static int s1 = 0, s2 = 0, s3 = 0; - - if (win == rootwin || win == None) { - return -1; - } - for (k = 0; k < NRECENT; k++) { - if (recent[k] == win) { - int k2 = recidx[k]; - if (cache_list[k2].win == win) { - idx = k2; -if (0) fprintf(stderr, "recentA(shortcut): %d 0x%lx\n", idx, win); - s1++; - break; - } - } - } - if (idx < 0) { - for(k=0; k<cache_list_num; k++) { - if (!foundfree && cache_list[k].win == None) { - rfree = k; - foundfree = 1; - } - if (cache_list[k].win == win) { - idx = k; -if (0) fprintf(stderr, "recentB(normal): %d 0x%lx\n", idx, win); - s2++; - break; - } - } - if (idx >= 0) { - recent[rlast] = win; - recidx[rlast++] = idx; - rlast = rlast % NRECENT; - } - } - if (idx < 0) { -if (ncdb) fprintf(stderr, "recentC(fail): %d 0x%lx\n", idx, win); - s3++; - } - if (s1 + s2 + s3 >= 1000) { -if (ncdb) fprintf(stderr, "lookup_win_index recent hit stats: %d/%d/%d\n", s1, s2, s3); - s1 = s2 = s3 = 0; - } - return idx; -} - -int lookup_free_index(void) { - int k; - - if (rfree >= 0) { - if (cache_list[rfree].win == None) { -if (ncdb) fprintf(stderr, "lookup_freeA: %d\n", rfree); - return rfree; - } - } - rfree = -1; - for(k=0; k<cache_list_num; k++) { - if (cache_list[k].win == None) { - rfree = k; - break; - } - } - if (rfree < 0) { - if (ncdb) fprintf(stderr, "*** LOOKUP_FREE_INDEX: incrementing cache_list_num %d/%d\n", cache_list_num, cache_list_len); - - rfree = cache_list_num++; - if (rfree >= cache_list_len) { - int i, n = 2*cache_list_len; - winattr_t *cache_new; - - if (ncdb) fprintf(stderr, "lookup_free_index: growing cache_list_len: %d -> %d\n", cache_list_len, n); - - cache_new = (winattr_t *) calloc(n*sizeof(winattr_t), 1); - for (i=0; i<cache_list_num-1; i++) { - cache_new[i] = cache_list[i]; - } - cache_list_len = n; - free(cache_list); - cache_list = cache_new; - } - cache_list[rfree].win = None; - cache_list[rfree].fetched = 0; - cache_list[rfree].valid = 0; - cache_list[rfree].time = 0.0; - cache_list[rfree].selectinput = 0; - cache_list[rfree].vis_cnt = 0; - cache_list[rfree].map_cnt = 0; - cache_list[rfree].unmap_cnt = 0; - cache_list[rfree].create_cnt = 0; - cache_list[rfree].vis_state = -1; - cache_list[rfree].above = None; - } - -if (ncdb) fprintf(stderr, "lookup_freeB: %d\n", rfree); - return rfree; -} - -#define STACKMAX 4096 -Window old_stack[STACKMAX]; -Window new_stack[STACKMAX]; -Window old_stack_map[STACKMAX]; -Window new_stack_map[STACKMAX]; -int old_stack_index[STACKMAX]; -int old_stack_mapped[STACKMAX]; -int old_stack_n = 0; -int new_stack_n = 0; -int old_stack_map_n = 0; -int new_stack_map_n = 0; - -void snap_old(void) { - int i; - old_stack_n = STACKMAX; - quick_snap(old_stack, &old_stack_n); -if (0) fprintf(stderr, "snap_old: %d %.4f\n", old_stack_n, dnowx()); -#if 0 - for (i= old_stack_n - 1; i >= 0; i--) { - int idx = lookup_win_index(old_stack[i]); - if (idx >= 0) { - if (cache_list[idx].map_state == IsViewable) { - if (ncdb) fprintf(stderr, " %03d 0x%x\n", i, old_stack[i]); - } - } - } -#endif - for (i=0; i < old_stack_n; i++) { - old_stack_mapped[i] = -1; - } -} - -void snap_old_index(void) { - int i, idx; - for (i=0; i < old_stack_n; i++) { - idx = lookup_win_index(old_stack[i]); - old_stack_index[i] = idx; - if (idx >= 0) { - if (cache_list[idx].map_state == IsViewable) { - old_stack_mapped[i] = 1; - } else { - old_stack_mapped[i] = 0; - } - } - } -} - -int lookup_old_stack_index(int ic) { - int idx = old_stack_index[ic]; - - if (idx < 0) { - return -1; - } - if (cache_list[idx].win != old_stack[ic]) { - snap_old_index(); - } - idx = old_stack_index[ic]; - if (idx < 0 || cache_list[idx].win != old_stack[ic]) { - return -1; - } - if (cache_list[idx].map_state == IsViewable) { - old_stack_mapped[ic] = 1; - } else { - old_stack_mapped[ic] = 0; - } - return idx; -} - -#define STORE(k, w, attr) \ - if (0) fprintf(stderr, "STORE(%d) = 0x%lx\n", k, w); \ - cache_list[k].win = w; \ - cache_list[k].fetched = 1; \ - cache_list[k].valid = 1; \ - cache_list[k].x = attr.x; \ - cache_list[k].y = attr.y; \ - cache_list[k].width = attr.width; \ - cache_list[k].height = attr.height; \ - cache_list[k].border_width = attr.border_width; \ - cache_list[k].map_state = attr.map_state; \ - cache_list[k].time = dnow(); - -#if 0 - cache_list[k].width = attr.width + 2*attr.border_width; \ - cache_list[k].height = attr.height + 2*attr.border_width; \ - -#endif - -#define CLEAR(k) \ - if (0) fprintf(stderr, "CLEAR(%d)\n", k); \ - cache_list[k].bs_x = -1; \ - cache_list[k].bs_y = -1; \ - cache_list[k].bs_w = -1; \ - cache_list[k].bs_h = -1; \ - cache_list[k].su_x = -1; \ - cache_list[k].su_y = -1; \ - cache_list[k].su_w = -1; \ - cache_list[k].su_h = -1; \ - cache_list[k].time = 0.0; \ - cache_list[k].bs_time = 0.0; \ - cache_list[k].su_time = 0.0; \ - cache_list[k].vis_obs_time = 0.0; \ - cache_list[k].vis_unobs_time = 0.0; - -#define DELETE(k) \ - if (0) fprintf(stderr, "DELETE(%d) = 0x%lx\n", k, cache_list[k].win); \ - cache_list[k].win = None; \ - cache_list[k].fetched = 0; \ - cache_list[k].valid = 0; \ - cache_list[k].selectinput = 0; \ - cache_list[k].vis_cnt = 0; \ - cache_list[k].map_cnt = 0; \ - cache_list[k].unmap_cnt = 0; \ - cache_list[k].create_cnt = 0; \ - cache_list[k].vis_state = -1; \ - cache_list[k].above = None; \ - free_rect(k); /* does CLEAR(k) */ - -static char unk[32]; - -char *Etype(int type) { - if (type == KeyPress) return "KeyPress"; - if (type == KeyRelease) return "KeyRelease"; - if (type == ButtonPress) return "ButtonPress"; - if (type == ButtonRelease) return "ButtonRelease"; - if (type == MotionNotify) return "MotionNotify"; - if (type == EnterNotify) return "EnterNotify"; - if (type == LeaveNotify) return "LeaveNotify"; - if (type == FocusIn) return "FocusIn"; - if (type == FocusOut) return "FocusOut"; - if (type == KeymapNotify) return "KeymapNotify"; - if (type == Expose) return "Expose"; - if (type == GraphicsExpose) return "GraphicsExpose"; - if (type == NoExpose) return "NoExpose"; - if (type == VisibilityNotify) return "VisibilityNotify"; - if (type == CreateNotify) return "CreateNotify"; - if (type == DestroyNotify) return "DestroyNotify"; - if (type == UnmapNotify) return "UnmapNotify"; - if (type == MapNotify) return "MapNotify"; - if (type == MapRequest) return "MapRequest"; - if (type == ReparentNotify) return "ReparentNotify"; - if (type == ConfigureNotify) return "ConfigureNotify"; - if (type == ConfigureRequest) return "ConfigureRequest"; - if (type == GravityNotify) return "GravityNotify"; - if (type == ResizeRequest) return "ResizeRequest"; - if (type == CirculateNotify) return "CirculateNotify"; - if (type == CirculateRequest) return "CirculateRequest"; - if (type == PropertyNotify) return "PropertyNotify"; - if (type == SelectionClear) return "SelectionClear"; - if (type == SelectionRequest) return "SelectionRequest"; - if (type == SelectionNotify) return "SelectionNotify"; - if (type == ColormapNotify) return "ColormapNotify"; - if (type == ClientMessage) return "ClientMessage"; - if (type == MappingNotify) return "MappingNotify"; - if (type == LASTEvent) return "LASTEvent"; - sprintf(unk, "Unknown %d", type); - return unk; -} -char *VState(int state) { - if (state == VisibilityFullyObscured) return "VisibilityFullyObscured"; - if (state == VisibilityPartiallyObscured) return "VisibilityPartiallyObscured"; - if (state == VisibilityUnobscured) return "VisibilityUnobscured"; - sprintf(unk, "Unknown %d", state); - return unk; -} -char *MState(int state) { - if (state == IsViewable) return "IsViewable"; - if (state == IsUnmapped) return "IsUnmapped"; - sprintf(unk, "Unknown %d", state); - return unk; -} -sraRegionPtr rect_reg[64]; -sraRegionPtr zero_rects = NULL; - -int free_rect(int idx) { - int n, ok = 0; - sraRegionPtr r1, r2; - int x, y, w, h; - - if (idx < 0 || idx >= cache_list_num) { -if (0) fprintf(stderr, "free_rect: bad index: %d\n", idx); - clean_up_exit(1); - } - - x = cache_list[idx].bs_x; - y = cache_list[idx].bs_y; - w = cache_list[idx].bs_w; - h = cache_list[idx].bs_h; - - if (x < 0) { - CLEAR(idx); -if (dnow() > last_client + 5 && ncdb) fprintf(stderr, "free_rect: already bs_x invalidated: %d bs_x: %d\n", idx, x); - return 1; - } - - r2 = sraRgnCreateRect(x, y, x+w, y+h); - - n = get_bs_n(y); - if (n >= 0) { - r1 = rect_reg[n]; - sraRgnOr(r1, r2); - ok = 1; - } - - if (zero_rects) { - sraRgnOr(zero_rects, r2); - x = cache_list[idx].su_x; - y = cache_list[idx].su_y; - w = cache_list[idx].su_w; - h = cache_list[idx].su_h; - if (x >= 0) { - sraRgnDestroy(r2); - r2 = sraRgnCreateRect(x, y, x+w, y+h); - sraRgnOr(zero_rects, r2); - } - } - sraRgnDestroy(r2); - - CLEAR(idx); -if (! ok && ncdb) fprintf(stderr, "**** free_rect: not-found %d\n", idx); - return ok; -} - -int fr_BIG1 = 0; -int fr_BIG2 = 0; -int fr_REGION = 0; -int fr_GRID = 0; -int fr_EXPIRE = 0; -int fr_FORCE = 0; -int fr_FAIL = 0; -int fr_BIG1t = 0; -int fr_BIG2t = 0; -int fr_REGIONt = 0; -int fr_GRIDt = 0; -int fr_EXPIREt = 0; -int fr_FORCEt = 0; -int fr_FAILt = 0; - -void expire_rects1(int idx, int w, int h, int *x_hit, int *y_hit, int big1, int big2, int cram) { - sraRegionPtr r1, r2, r3; - int x = -1, y = -1, n; - - if (*x_hit < 0) { - int i, k, old[10], N = 4; - double dold[10], fa, d, d1, d2, d3; - int a0 = w * h, a1; - - for (k=1; k<=N; k++) { - old[k] = -1; - dold[k] = -1.0; - } - for (i=0; i<cache_list_num; i++) { - int wb = cache_list[i].bs_w; - int hb = cache_list[i].bs_h; - if (cache_list[i].bs_x < 0) { - continue; - } - if (w > wb || h > hb) { - continue; - } - if (wb == 0 || hb == 0) { - continue; - } - if (a0 == 0) { - continue; - } - if (i == idx) { - continue; - } - a1 = wb * hb; - fa = ((double) a1) / a0; - k = (int) fa; - - if (k < 1) k = 1; - if (k > N) continue; - - d1 = cache_list[i].time; - d2 = cache_list[i].bs_time; - d3 = cache_list[i].su_time; - - d = d1; - if (d2 > d) d = d2; - if (d3 > d) d = d3; - - if (dold[k] == -1.0 || d < dold[k]) { - old[k] = i; - dold[k] = d; - } - } - - for (k=1; k<=N; k++) { - if (old[k] >= 0) { - int ik = old[k]; - int k_x = cache_list[ik].bs_x; - int k_y = cache_list[ik].bs_y; - int k_w = cache_list[ik].bs_w; - int k_h = cache_list[ik].bs_h; - -if (ncdb) fprintf(stderr, ">>**--**>> found rect via EXPIRE: %d 0x%lx -- %dx%d+%d+%d %d %d -- %dx%d+%d+%d A: %d/%d\n", - ik, cache_list[ik].win, w, h, x, y, *x_hit, *y_hit, k_w, k_h, k_x, k_y, k_w * k_h, w * h); - - free_rect(ik); - fr_EXPIRE++; - fr_EXPIREt++; - *x_hit = k_x; - *y_hit = k_y; - n = get_bs_n(*y_hit); - if (n >= 0) { - r1 = rect_reg[n]; - r2 = sraRgnCreateRect(*x_hit, *y_hit, *x_hit + w, *y_hit + h); - sraRgnSubtract(r1, r2); - sraRgnDestroy(r2); - } else { - fprintf(stderr, "failure to find y n in find_rect\n"); - clean_up_exit(1); - } - break; - } - } - } - - /* next, force ourselves into some corner, expiring many */ - if (*x_hit < 0) { - int corner_x = (int) (2 * rfac()); - int corner_y = (int) (2 * rfac()); - int x0 = 0, y0 = 0, i, nrand, nr = ncache/2; - if (nr == 1) { - nrand = 1; - } else { - if (! big1) { - nrand = 1; - } else { - if (big2 && nr > 2) { - nrand = 1 + (int) ((nr - 2) * rfac()); - nrand += 2; - } else { - nrand = 1 + (int) ((nr - 1) * rfac()); - nrand += 1; - } - } - } - if (nrand < 0 || nrand > nr) { - nrand = nr; - } - if (cram && big1) { - corner_x = 1; - } - - y0 += dpy_y; - if (nrand > 1) { - y0 += 2 * (nrand - 1) * dpy_y; - } - if (corner_y) { - y0 += dpy_y - h; - } - if (corner_x) { - x0 += dpy_x - w; - } - r1 = sraRgnCreateRect(x0, y0, x0+w, y0+h); - - for (i=0; i<cache_list_num; i++) { - int xb = cache_list[i].bs_x; - int yb = cache_list[i].bs_y; - int wb = cache_list[i].bs_w; - int hb = cache_list[i].bs_h; - if (xb < 0) { - continue; - } - if (nabs(yb - y0) > dpy_y) { - continue; - } - r2 = sraRgnCreateRect(xb, yb, xb+wb, yb+hb); - if (sraRgnAnd(r2, r1)) { - free_rect(i); - } - sraRgnDestroy(r2); - } - *x_hit = x0; - *y_hit = y0; - r3 = rect_reg[2*nrand-1]; - sraRgnSubtract(r3, r1); - sraRgnDestroy(r1); - -if (ncdb) fprintf(stderr, ">>**--**>> found rect via FORCE: %dx%d+%d+%d -- %d %d\n", w, h, x, y, *x_hit, *y_hit); - - fr_FORCE++; - fr_FORCEt++; - } -} - -void expire_rects2(int idx, int w, int h, int *x_hit, int *y_hit, int big1, int big2, int cram) { - sraRegionPtr r1, r2, r3; - int x = -1, y = -1, n, i, j, k; - int nwgt_max = 128, nwgt = 0; - int type[128]; - int val[4][128]; - double wgt[128], norm; - int Expire = 1, Force = 2; - int do_expire = 1; - int do_force = 1; - double now = dnow(), r; - double newest = -1.0, oldest = -1.0, basetime; - double map_factor = 0.25; - - for (i=0; i<cache_list_num; i++) { - double d, d1, d2; - - d1 = cache_list[i].bs_time; - d2 = cache_list[i].su_time; - - d = d1; - if (d2 > d) d = d2; - - if (d == 0.0) { - continue; - } - - if (oldest == -1.0 || d < oldest) { - oldest = d; - } - if (newest == -1.0 || d > newest) { - newest = d; - } - } - if (newest == -1.0) { - newest = now; - } - if (oldest == -1.0) { - oldest = newest - 1800; - } - - basetime = newest + 0.1 * (newest - oldest); - - if (do_expire) { - int old[10], N = 4; - double dold[10], fa, d, d1, d2; - int a0 = w * h, a1; - - for (k=1; k<=N; k++) { - old[k] = -1; - dold[k] = -1.0; - } - for (i=0; i<cache_list_num; i++) { - int wb = cache_list[i].bs_w; - int hb = cache_list[i].bs_h; - if (cache_list[i].bs_x < 0) { - continue; - } - if (w > wb || h > hb) { - continue; - } - if (wb == 0 || hb == 0) { - continue; - } - if (a0 == 0) { - continue; - } - if (i == idx) { - continue; - } - - a1 = wb * hb; - fa = ((double) a1) / a0; - k = (int) fa; - - if (k < 1) k = 1; - if (k > N) continue; - - d1 = cache_list[i].bs_time; - d2 = cache_list[i].su_time; - - d = d1; - if (d2 > d) d = d2; - if (d == 0.0) d = oldest; - - if (dold[k] == -1.0 || d < dold[k]) { - old[k] = i; - dold[k] = d; - } - } - - for (k=1; k<=N; k++) { - if (old[k] >= 0) { - int ik = old[k]; - int k_w = cache_list[ik].bs_w; - int k_h = cache_list[ik].bs_h; - - wgt[nwgt] = (basetime - dold[k]) / (k_w * k_h); - if (cache_list[ik].map_state == IsViewable) { - wgt[nwgt] *= map_factor; - } - type[nwgt] = Expire; - val[0][nwgt] = ik; -if (ncdb) fprintf(stderr, "Expire[%02d] %9.5f age=%9.4f area=%8d need=%8d\n", nwgt, 10000 * wgt[nwgt], basetime - dold[k], k_w * k_h, w*h); - nwgt++; - if (nwgt >= nwgt_max) { - break; - } - } - } - } - - /* next, force ourselves into some corner, expiring many rect */ - if (do_force) { - int corner_x, corner_y; - int x0, y0; - - for (n = 1; n < ncache; n += 2) { - if (big1 && ncache > 2 && n == 1) { - continue; - } - if (big2 && ncache > 4 && n <= 3) { - continue; - } - for (corner_x = 0; corner_x < 2; corner_x++) { - if (cram && big1 && corner_x == 0) { - continue; - } - for (corner_y = 0; corner_y < 2; corner_y++) { - double age = 0.0, area = 0.0, amap = 0.0, a; - double d, d1, d2, score; - int nc = 0; - - x0 = 0; - y0 = 0; - y0 += n * dpy_y; - - if (corner_y) { - y0 += dpy_y - h; - } - if (corner_x) { - x0 += dpy_x - w; - } - r1 = sraRgnCreateRect(x0, y0, x0+w, y0+h); - - for (i=0; i<cache_list_num; i++) { - int xb = cache_list[i].bs_x; - int yb = cache_list[i].bs_y; - int wb = cache_list[i].bs_w; - int hb = cache_list[i].bs_h; - - if (xb < 0) { - continue; - } - if (nabs(yb - y0) > dpy_y) { - continue; - } - - r2 = sraRgnCreateRect(xb, yb, xb+wb, yb+hb); - if (! sraRgnAnd(r2, r1)) { - sraRgnDestroy(r2); - continue; - } - sraRgnDestroy(r2); - - a = wb * hb; - - d1 = cache_list[i].bs_time; - d2 = cache_list[i].su_time; - - d = d1; - if (d2 > d) d = d2; - if (d == 0.0) d = oldest; - - if (cache_list[i].map_state == IsViewable) { - amap += a; - } - area += a; - age += (basetime - d) * a; - nc++; - } - if (nc == 0) { - score = 999999.9; - } else { - double fac; - age = age / area; - score = age / area; - fac = 1.0 * (1.0 - amap/area) + map_factor * (amap/area); - score *= fac; - } - - wgt[nwgt] = score; - type[nwgt] = Force; - val[0][nwgt] = n; - val[1][nwgt] = x0; - val[2][nwgt] = y0; -if (ncdb) fprintf(stderr, "Force [%02d] %9.5f age=%9.4f area=%8d amap=%8d need=%8d\n", nwgt, 10000 * wgt[nwgt], age, (int) area, (int) amap, w*h); - nwgt++; - if (nwgt >= nwgt_max) break; - sraRgnDestroy(r1); - } - if (nwgt >= nwgt_max) break; - } - if (nwgt >= nwgt_max) break; - } - } - - if (nwgt == 0) { -if (ncdb) fprintf(stderr, "nwgt=0\n"); - *x_hit = -1; - return; - } - - norm = 0.0; - for (i=0; i < nwgt; i++) { - norm += wgt[i]; - } - for (i=0; i < nwgt; i++) { - wgt[i] /= norm; - } - - r = rfac(); - - norm = 0.0; - for (j=0; j < nwgt; j++) { - norm += wgt[j]; -if (ncdb) fprintf(stderr, "j=%2d acc=%.6f r=%.6f\n", j, norm, r); - if (r < norm) { - break; - } - } - if (j >= nwgt) { - j = nwgt - 1; - } - - if (type[j] == Expire) { - int ik = val[0][j]; - int k_x = cache_list[ik].bs_x; - int k_y = cache_list[ik].bs_y; - int k_w = cache_list[ik].bs_w; - int k_h = cache_list[ik].bs_h; - -if (ncdb) fprintf(stderr, ">>**--**>> found rect [%d] via RAN EXPIRE: %d 0x%lx -- %dx%d+%d+%d %d %d -- %dx%d+%d+%d A: %d/%d\n", - get_bs_n(*y_hit), ik, cache_list[ik].win, w, h, x, y, *x_hit, *y_hit, k_w, k_h, k_x, k_y, k_w * k_h, w * h); - - free_rect(ik); - fr_EXPIRE++; - fr_EXPIREt++; - *x_hit = k_x; - *y_hit = k_y; - n = get_bs_n(*y_hit); - if (n >= 0) { - r1 = rect_reg[n]; - r2 = sraRgnCreateRect(*x_hit, *y_hit, *x_hit + w, *y_hit + h); - sraRgnSubtract(r1, r2); - sraRgnDestroy(r2); - } else { - fprintf(stderr, "failure to find y n in find_rect\n"); - clean_up_exit(1); - } - - } else if (type[j] == Force) { - - int x0 = val[1][j]; - int y0 = val[2][j]; - n = val[0][j]; - - r1 = sraRgnCreateRect(x0, y0, x0+w, y0+h); - - for (i=0; i<cache_list_num; i++) { - int xb = cache_list[i].bs_x; - int yb = cache_list[i].bs_y; - int wb = cache_list[i].bs_w; - int hb = cache_list[i].bs_h; - if (xb < 0) { - continue; - } - if (nabs(yb - y0) > dpy_y) { - continue; - } - r2 = sraRgnCreateRect(xb, yb, xb+wb, yb+hb); - if (sraRgnAnd(r2, r1)) { - free_rect(i); - } - sraRgnDestroy(r2); - } - *x_hit = x0; - *y_hit = y0; - r3 = rect_reg[2*n-1]; - sraRgnSubtract(r3, r1); - sraRgnDestroy(r1); - -if (ncdb) fprintf(stderr, ">>**--**>> found rect [%d] via RAN FORCE: %dx%d+%d+%d -- %d %d\n", n, w, h, x, y, *x_hit, *y_hit); - - fr_FORCE++; - fr_FORCEt++; - } -} - -void expire_rects(int idx, int w, int h, int *x_hit, int *y_hit, int big1, int big2, int cram) { - int method = 2; - if (method == 1) { - expire_rects1(idx, w, h, x_hit, y_hit, big1, big2, cram); - } else if (method == 2) { - expire_rects2(idx, w, h, x_hit, y_hit, big1, big2, cram); - } -} - -int find_rect(int idx, int x, int y, int w, int h) { - sraRegionPtr r1, r2; - sraRectangleIterator *iter; - sraRect rt; - int n, x_hit = -1, y_hit = -1; - int big1 = 0, big2 = 0, cram = 0; - double fac1 = 0.1, fac2 = 0.25; - double last_clean = 0.0; - double now = dnow(); - static int nobigs = -1; - - if (rect_reg[1] == NULL) { - for (n = 1; n <= ncache; n++) { - rect_reg[n] = sraRgnCreateRect(0, n * dpy_y, dpy_x, (n+1) * dpy_y); - } - } else if (now > last_clean + 60) { - last_clean = now; - for (n = 1; n < ncache; n += 2) { - int i, n2 = n+1; - - /* n */ - sraRgnDestroy(rect_reg[n]); - r1 = sraRgnCreateRect(0, n * dpy_y, dpy_x, (n+1) * dpy_y); - for (i=0; i<cache_list_num; i++) { - int bs_x = cache_list[i].bs_x; - int bs_y = cache_list[i].bs_y; - int bs_w = cache_list[i].bs_w; - int bs_h = cache_list[i].bs_h; - if (bs_x < 0) { - continue; - } - if (get_bs_n(bs_y) != n) { - continue; - } - r2 = sraRgnCreateRect(bs_x, bs_y, bs_x+bs_w, bs_y+bs_h); - sraRgnSubtract(r1, r2); - } - rect_reg[n] = r1; - - /* n+1 */ - sraRgnDestroy(rect_reg[n2]); - r1 = sraRgnCreateRect(0, n2 * dpy_y, dpy_x, (n2+1) * dpy_y); - for (i=0; i<cache_list_num; i++) { - int bs_x = cache_list[i].bs_x; - int su_x = cache_list[i].su_x; - int su_y = cache_list[i].su_y; - int su_w = cache_list[i].su_w; - int su_h = cache_list[i].su_h; - if (bs_x < 0) { - continue; - } - if (get_bs_n(su_y) != n2) { - continue; - } - r2 = sraRgnCreateRect(su_x, su_y, su_x+su_w, su_y+su_h); - sraRgnSubtract(r1, r2); - } - rect_reg[n2] = r1; - } - } - - if (idx < 0 || idx >= cache_list_num) { -if (ncdb) fprintf(stderr, "free_rect: bad index: %d\n", idx); - clean_up_exit(1); - } - - cache_list[idx].bs_x = -1; - cache_list[idx].su_x = -1; - cache_list[idx].bs_time = 0.0; - cache_list[idx].su_time = 0.0; - - if (ncache_pad) { - x -= ncache_pad; - y -= ncache_pad; - w += 2 * ncache_pad; - h += 2 * ncache_pad; - } - - if (ncache <= 2) { - cram = 1; - fac2 = 0.45; - } else if (ncache <= 4) { - fac1 = 0.18; - fac2 = 0.35; - } - if (macosx_console && !macosx_ncache_macmenu) { - if (cram) { - fac1 *= 1.5; - fac2 *= 1.5; - } else { - fac1 *= 2.5; - fac2 *= 2.5; - } - } - if (w * h > fac1 * (dpy_x * dpy_y)) { - big1 = 1; - } - if (w * h > fac2 * (dpy_x * dpy_y)) { - big2 = 1; - } - - if (nobigs < 0) { - if (getenv("NOBIGS")) { - nobigs = 1; - } else { - nobigs = 0; - } - } - if (nobigs) { - big1 = big2 = 0; - } - - if (w > dpy_x || h > dpy_y) { -if (ncdb) fprintf(stderr, ">>**--**>> BIG1 rect: %dx%d+%d+%d -- %d %d\n", w, h, x, y, x_hit, y_hit); - fr_BIG1++; - fr_BIG1t++; - return 0; - } - if (w == dpy_x && h == dpy_y) { -if (ncdb) fprintf(stderr, ">>**--**>> BIG1 rect: %dx%d+%d+%d -- %d %d (FULL DISPLAY)\n", w, h, x, y, x_hit, y_hit); - fr_BIG1++; - fr_BIG1t++; - return 0; - } - if (cram && big2) { -if (ncdb) fprintf(stderr, ">>**--**>> BIG2 rect: %dx%d+%d+%d -- %d %d\n", w, h, x, y, x_hit, y_hit); - fr_BIG2++; - fr_BIG2t++; - return 0; - } - - /* first try individual rects of unused region */ - for (n = 1; n < ncache; n += 2) { - r1 = rect_reg[n]; - r2 = NULL; - if (big1 && n == 1 && ncache > 2) { - continue; - } - if (big2 && n <= 3 && ncache > 4) { - continue; - } - iter = sraRgnGetIterator(r1); - while (sraRgnIteratorNext(iter, &rt)) { - int rw = rt.x2 - rt.x1; - int rh = rt.y2 - rt.y1; - if (cram && big1 && rt.x1 < dpy_x/4) { - continue; - } - if (rw >= w && rh >= h) { - x_hit = rt.x1; - y_hit = rt.y1; - if (cram && big1) { - x_hit = rt.x2 - w; - } - r2 = sraRgnCreateRect(x_hit, y_hit, x_hit + w, y_hit + h); - break; - } - } - sraRgnReleaseIterator(iter); - if (r2 != NULL) { -if (ncdb) fprintf(stderr, ">>**--**>> found rect via REGION: %dx%d+%d+%d -- %d %d\n", w, h, x, y, x_hit, y_hit); - fr_REGION++; - fr_REGIONt++; - sraRgnSubtract(r1, r2); - sraRgnDestroy(r2); - break; - } - } - - - /* next try moving corner to grid points */ - if (x_hit < 0) { - for (n = 1; n < ncache; n += 2) { - int rx, ry, Nx = 48, Ny = 24, ny = n * dpy_y; - - if (big1 && n == 1 && ncache > 2) { - continue; - } - if (big2 && n == 3 && ncache > 4) { - continue; - } - - r1 = sraRgnCreateRect(0, n * dpy_y, dpy_x, (n+1) * dpy_y); - sraRgnSubtract(r1, rect_reg[n]); - r2 = NULL; - - rx = 0; - while (rx + w <= dpy_x) { - ry = 0; - if (cram && big1 && rx < dpy_x/4) { - rx += dpy_x/Nx; - continue; - } - while (ry + h <= dpy_y) { - r2 = sraRgnCreateRect(rx, ry+ny, rx + w, ry+ny + h); - if (sraRgnAnd(r2, r1)) { - sraRgnDestroy(r2); - r2 = NULL; - } else { - sraRgnDestroy(r2); - r2 = sraRgnCreateRect(rx, ry+ny, rx + w, ry+ny + h); - x_hit = rx; - y_hit = ry+ny; - } - ry += dpy_y/Ny; - if (r2) break; - } - rx += dpy_x/Nx; - if (r2) break; - } - sraRgnDestroy(r1); - if (r2 != NULL) { - sraRgnSubtract(rect_reg[n], r2); - sraRgnDestroy(r2); -if (ncdb) fprintf(stderr, ">>**--**>> found rect via GRID: %dx%d+%d+%d -- %d %d\n", w, h, x, y, x_hit, y_hit); - fr_GRID++; - fr_GRIDt++; - break; - } - } - } - - /* next, try expiring the oldest/smallest used bs/su rectangle we fit in */ - - if (x_hit < 0) { - expire_rects(idx, w, h, &x_hit, &y_hit, big1, big2, cram); - } - - cache_list[idx].bs_x = x_hit; - cache_list[idx].bs_y = y_hit; - cache_list[idx].bs_w = w; - cache_list[idx].bs_h = h; - - cache_list[idx].su_x = x_hit; - cache_list[idx].su_y = y_hit + dpy_y; - cache_list[idx].su_w = w; - cache_list[idx].su_h = h; - - if (x_hit < 0) { - /* bad news, can it still happen? */ - if (ncdb) fprintf(stderr, ">>**--**>> *FAIL rect: %dx%d+%d+%d -- %d %d\n", w, h, x, y, x_hit, y_hit); - fr_FAIL++; - fr_FAILt++; - return 0; - } else { - if (0) fprintf(stderr, ">>**--**>> found rect: %dx%d+%d+%d -- %d %d\n", w, h, x, y, x_hit, y_hit); - } - - if (zero_rects) { - r1 = sraRgnCreateRect(x_hit, y_hit, x_hit+w, y_hit+h); - sraRgnSubtract(zero_rects, r1); - sraRgnDestroy(r1); - r1 = sraRgnCreateRect(x_hit, y_hit+dpy_y, x_hit+w, y_hit+dpy_y+h); - sraRgnSubtract(zero_rects, r1); - sraRgnDestroy(r1); - } - - return 1; -} - -static void cache_cr(sraRegionPtr r, int dx, int dy, double d0, double d1, int *nbatch) { - if (sraRgnEmpty(r)) { - return; - } - if (nbatch == NULL) { - if (!fb_push_wait(d0, FB_COPY)) { - fb_push_wait(d0/2, FB_COPY); - } - do_copyregion(r, dx, dy, 0); - if (!fb_push_wait(d1, FB_COPY)) { - fb_push_wait(d1/2, FB_COPY); - } - } else { - batch_dxs[*nbatch] = dx; - batch_dys[*nbatch] = dy; - batch_reg[*nbatch] = sraRgnCreateRgn(r); - (*nbatch)++; - } -} - -double save_delay0 = 0.02; -double restore_delay0 = 0.02; -double save_delay1 = 0.05; -double restore_delay1 = 0.05; -static double dtA, dtB; - -int valid_wr(int idx, Window win, XWindowAttributes *attr) { -#ifdef MACOSX - if (macosx_console) { - /* this is all to avoid animation changing WxH+X+Y... */ - if (idx >= 0) { - int rc = valid_window(win, attr, 1); - attr->x = cache_list[idx].x; - attr->y = cache_list[idx].y; - attr->width = cache_list[idx].width; - attr->height = cache_list[idx].height; - return rc; - } else { - return valid_window(win, attr, 1); - } - } -#else - if (!idx) {} -#endif - return valid_window(win, attr, 1); -} - -int clipped(int idx) { - int ic; - sraRegionPtr r0, r1, r2; - int x1, y1, w1, h1; - Window win; - int clip = 0; - - if (idx < 0) { - return 0; - } - r0 = sraRgnCreateRect(0, 0, dpy_x, dpy_y); - - x1 = cache_list[idx].x; - y1 = cache_list[idx].y; - w1 = cache_list[idx].width; - h1 = cache_list[idx].height; - - win = cache_list[idx].win; - - r1 = sraRgnCreateRect(x1, y1, x1+w1, y1+h1); - sraRgnAnd(r1, r0); - - for (ic = old_stack_n - 1; ic >= 0; ic--) { - int xc, yc, wc, hc, idx2; - - if (old_stack[ic] == win) { - break; - } - if (old_stack_mapped[ic] == 0) { - continue; - } - idx2 = lookup_old_stack_index(ic); - if (idx2 < 0) { - continue; - } - if (cache_list[idx2].win == win) { - break; - } - if (cache_list[idx2].map_state != IsViewable) { - continue; - } - xc = cache_list[idx2].x; - yc = cache_list[idx2].y; - wc = cache_list[idx2].width; - hc = cache_list[idx2].height; - - r2 = sraRgnCreateRect(xc, yc, xc+wc, yc+hc); - sraRgnAnd(r2, r0); - if (sraRgnAnd(r2, r1)) { -if (0) fprintf(stderr, "clip[0x%lx]: 0x%lx, %d/%d\n", win, cache_list[idx2].win, ic, idx2); - clip = 1; - } - sraRgnDestroy(r2); - if (clip) { - break; - } - } - sraRgnDestroy(r0); - sraRgnDestroy(r1); -if (0) fprintf(stderr, "clip[0x%lx]: %s\n", win, clip ? "clipped" : "no-clipped"); - return clip; -} - -void clip_region(sraRegionPtr r, Window win) { - int ic, idx2; - sraRegionPtr r1; - for (ic = old_stack_n - 1; ic >= 0; ic--) { - int xc, yc, wc, hc; - -if (0) fprintf(stderr, "----[0x%lx]: 0x%lx, %d %d\n", win, old_stack[ic], ic, old_stack_mapped[ic]); - if (old_stack[ic] == win) { - break; - } - if (old_stack_mapped[ic] == 0) { - continue; - } - idx2 = lookup_old_stack_index(ic); - if (idx2 < 0) { - continue; - } - if (cache_list[idx2].win == win) { - break; - } - if (cache_list[idx2].map_state != IsViewable) { - continue; - } - xc = cache_list[idx2].x; - yc = cache_list[idx2].y; - wc = cache_list[idx2].width; - hc = cache_list[idx2].height; - r1 = sraRgnCreateRect(xc, yc, xc+wc, yc+hc); - if (sraRgnAnd(r1, r)) { - sraRgnSubtract(r, r1); -if (0) fprintf(stderr, "clip[0x%lx]: 0x%lx, %d/%d\n", win, cache_list[idx2].win, ic, idx2); - } - sraRgnDestroy(r1); - } -} - -int bs_save(int idx, int *nbatch, XWindowAttributes *attr, int clip, int only_if_tracking, int *valid, int verb) { - Window win = cache_list[idx].win; - int x1, y1, w1, h1; - int x2, y2, w2, h2; - int x, y, w, h; - int dx, dy, rc = 1; - sraRegionPtr r, r0; - - x1 = cache_list[idx].x; - y1 = cache_list[idx].y; - w1 = cache_list[idx].width; - h1 = cache_list[idx].height; - -if (ncdb && verb) fprintf(stderr, "backingstore save: 0x%lx %3d clip=%d\n", win, idx, clip); - - X_LOCK; - if (*valid) { - attr->x = x1; - attr->y = y1; - attr->width = w1; - attr->height = h1; - } else if (! valid_wr(idx, win, attr)) { -if (ncdb) fprintf(stderr, "bs_save: not a valid X window: 0x%lx\n", win); - X_UNLOCK; - *valid = 0; - cache_list[idx].valid = 0; - return 0; - } else { - *valid = 1; - } - X_UNLOCK; - - if (only_if_tracking && cache_list[idx].bs_x < 0) { - return 0; - } - - x2 = attr->x; - y2 = attr->y; - w2 = attr->width; - h2 = attr->height; - - if (cache_list[idx].bs_x < 0) { - rc = find_rect(idx, x2, y2, w2, h2); - } else if (w2 > cache_list[idx].bs_w || h2 > cache_list[idx].bs_h) { - free_rect(idx); - rc = find_rect(idx, x2, y2, w2, h2); - } - - x = cache_list[idx].bs_x; - y = cache_list[idx].bs_y; - w = cache_list[idx].bs_w; - h = cache_list[idx].bs_h; - - if (x < 0 || ! rc) { -if (ncdb) fprintf(stderr, "BS_save: FAIL FOR: %d\n", idx); - return 0; - } - - if (ncache_pad) { - x2 -= ncache_pad; - y2 -= ncache_pad; - w2 += 2 * ncache_pad; - h2 += 2 * ncache_pad; - } - - if (clipshift) { - x2 -= coff_x; - y2 -= coff_y; - } - - r0 = sraRgnCreateRect(0, 0, dpy_x, dpy_y); - r = sraRgnCreateRect(x2, y2, x2+w2, y2+h2); - sraRgnAnd(r, r0); - - if (clip) { - clip_region(r, win); - } - - if (sraRgnEmpty(r)) { -if (ncdb && verb) fprintf(stderr, "BS_save: Region Empty: %d\n", idx); - sraRgnDestroy(r0); - sraRgnDestroy(r); - return 0; - } - - dx = x - x2; - dy = y - y2; - - sraRgnOffset(r, dx, dy); - - dtA = dnowx(); -if (ncdb && verb) fprintf(stderr, "BS_save: %.4f %d dx=%d dy=%d\n", dtA, idx, dx, dy); - if (w2 > 0 && h2 > 0) { - cache_cr(r, dx, dy, save_delay0, save_delay1, nbatch); - } - dtB = dnowx(); -if (ncdb && verb) fprintf(stderr, "BS_save: %.4f %.2f %d done. %dx%d+%d+%d %dx%d+%d+%d %.2f %.2f\n", dtB, dtB-dtA, idx, w1, h1, x1, y1, w2, h2, x2, y2, cache_list[idx].bs_time - x11vnc_start, dnowx()); - - sraRgnDestroy(r0); - sraRgnDestroy(r); - - last_bs_save = cache_list[idx].bs_time = dnow(); - - return 1; -} - -int su_save(int idx, int *nbatch, XWindowAttributes *attr, int clip, int *valid, int verb) { - Window win = cache_list[idx].win; - int x1, y1, w1, h1; - int x2, y2, w2, h2; - int x, y, w, h; - int dx, dy, rc = 1; - sraRegionPtr r, r0; - -if (ncdb && verb) fprintf(stderr, "save-unders save: 0x%lx %3d \n", win, idx); - - x1 = cache_list[idx].x; - y1 = cache_list[idx].y; - w1 = cache_list[idx].width; - h1 = cache_list[idx].height; - - X_LOCK; - if (*valid) { - attr->x = x1; - attr->y = y1; - attr->width = w1; - attr->height = h1; - } else if (! valid_wr(idx, win, attr)) { -if (ncdb) fprintf(stderr, "su_save: not a valid X window: 0x%lx\n", win); - X_UNLOCK; - *valid = 0; - cache_list[idx].valid = 0; - return 0; - } else { - *valid = 1; - } - X_UNLOCK; - - x2 = attr->x; - y2 = attr->y; - w2 = attr->width; - h2 = attr->height; - - if (cache_list[idx].bs_x < 0) { - rc = find_rect(idx, x2, y2, w2, h2); - } else if (w2 > cache_list[idx].su_w || h2 > cache_list[idx].su_h) { - free_rect(idx); - rc = find_rect(idx, x2, y2, w2, h2); - } - x = cache_list[idx].su_x; - y = cache_list[idx].su_y; - w = cache_list[idx].su_w; - h = cache_list[idx].su_h; - - if (x < 0 || ! rc) { -if (ncdb) fprintf(stderr, "SU_save: FAIL FOR: %d\n", idx); - return 0; - } - - if (ncache_pad) { - x2 -= ncache_pad; - y2 -= ncache_pad; - w2 += 2 * ncache_pad; - h2 += 2 * ncache_pad; - } - - if (clipshift) { - x2 -= coff_x; - y2 -= coff_y; - } - - r0 = sraRgnCreateRect(0, 0, dpy_x, dpy_y); - r = sraRgnCreateRect(x2, y2, x2+w2, y2+h2); - sraRgnAnd(r, r0); - - if (clip) { - clip_region(r, win); - } - - if (sraRgnEmpty(r)) { -if (ncdb && verb) fprintf(stderr, "SU_save: Region Empty: %d\n", idx); - sraRgnDestroy(r0); - sraRgnDestroy(r); - return 0; - } - - - dx = x - x2; - dy = y - y2; - - sraRgnOffset(r, dx, dy); - - dtA = dnowx(); -if (ncdb && verb) fprintf(stderr, "SU_save: %.4f %d dx=%d dy=%d\n", dtA, idx, dx, dy); - if (w2 > 0 && h2 > 0) { - cache_cr(r, dx, dy, save_delay0, save_delay1, nbatch); - } - dtB = dnowx(); -if (ncdb && verb) fprintf(stderr, "SU_save: %.4f %.2f %d done. %dx%d+%d+%d %dx%d+%d+%d %.2f %.2f\n", dtB, dtB-dtA, idx, w1, h1, x1, y1, w2, h2, x2, y2, cache_list[idx].su_time - x11vnc_start, dnowx()); - - sraRgnDestroy(r0); - sraRgnDestroy(r); - - last_su_save = cache_list[idx].su_time = dnow(); - - return 1; -} - -int bs_restore(int idx, int *nbatch, sraRegionPtr rmask, XWindowAttributes *attr, int clip, int nopad, int *valid, int verb) { - Window win = cache_list[idx].win; - int x1, y1, w1, h1; - int x2, y2, w2, h2; - int x, y, w, h; - int dx, dy; - sraRegionPtr r, r0; - -if (ncdb && verb) fprintf(stderr, "backingstore restore: 0x%lx %3d \n", win, idx); - - x1 = cache_list[idx].x; - y1 = cache_list[idx].y; - w1 = cache_list[idx].width; - h1 = cache_list[idx].height; - - X_LOCK; - if (*valid) { - attr->x = x1; - attr->y = y1; - attr->width = w1; - attr->height = h1; - } else if (! valid_wr(idx, win, attr)) { -if (ncdb) fprintf(stderr, "BS_restore: not a valid X window: 0x%lx\n", win); - *valid = 0; - X_UNLOCK; - return 0; - } else { - *valid = 1; - } - X_UNLOCK; - - x2 = attr->x; - y2 = attr->y; - w2 = attr->width; - h2 = attr->height; - - x = cache_list[idx].bs_x; - y = cache_list[idx].bs_y; - w = cache_list[idx].bs_w; - h = cache_list[idx].bs_h; - - if (x < 0 || cache_list[idx].bs_time == 0.0) { - return 0; - } - - if (ncache_pad) { - if (nopad) { - x += ncache_pad; - y += ncache_pad; - w -= 2 * ncache_pad; - h -= 2 * ncache_pad; - } else { - x2 -= ncache_pad; - y2 -= ncache_pad; - w2 += 2 * ncache_pad; - h2 += 2 * ncache_pad; - } - } - - if (clipshift) { - x2 -= coff_x; - y2 -= coff_y; - } - - if (w2 > w) { - w2 = w; - } - if (h2 > h) { - h2 = h; - } - - r0 = sraRgnCreateRect(0, 0, dpy_x, dpy_y); - r = sraRgnCreateRect(x, y, x+w2, y+h2); - - dx = x2 - x; - dy = y2 - y; - - sraRgnOffset(r, dx, dy); - sraRgnAnd(r, r0); - - if (clip) { - clip_region(r, win); - } - if (rmask != NULL) { - sraRgnAnd(r, rmask); - } - - dtA = dnowx(); -if (ncdb && verb) fprintf(stderr, "BS_rest: %.4f %d dx=%d dy=%d\n", dtA, idx, dx, dy); - if (w2 > 0 && h2 > 0) { - cache_cr(r, dx, dy, restore_delay0, restore_delay1, nbatch); - } - dtB = dnowx(); -if (ncdb && verb) fprintf(stderr, "BS_rest: %.4f %.2f %d done. %dx%d+%d+%d %dx%d+%d+%d %.2f %.2f\n", dtB, dtB-dtA, idx, w1, h1, x1, y1, w2, h2, x2, y2, cache_list[idx].bs_time - x11vnc_start, dnowx()); - - sraRgnDestroy(r0); - sraRgnDestroy(r); - - last_bs_restore = dnow(); - - return 1; -} - -int su_restore(int idx, int *nbatch, sraRegionPtr rmask, XWindowAttributes *attr, int clip, int nopad, int *valid, int verb) { - Window win = cache_list[idx].win; - int x1, y1, w1, h1; - int x2 = 0, y2 = 0, w2 = 0, h2 = 0; - int x, y, w, h; - int dx, dy; - sraRegionPtr r, r0; - -if (ncdb && verb) fprintf(stderr, "save-unders restore: 0x%lx %3d \n", win, idx); - - x1 = cache_list[idx].x; - y1 = cache_list[idx].y; - w1 = cache_list[idx].width; - h1 = cache_list[idx].height; - - X_LOCK; - if (*valid) { - attr->x = x1; - attr->y = y1; - attr->width = w1; - attr->height = h1; - x2 = attr->x; - y2 = attr->y; - w2 = attr->width; - h2 = attr->height; - } else if (! valid_wr(idx, win, attr)) { -if (ncdb) fprintf(stderr, "SU_restore: not a valid X window: 0x%lx\n", win); - *valid = 0; - x2 = x1; - y2 = y1; - w2 = w1; - h2 = h1; - } else { - x2 = attr->x; - y2 = attr->y; - w2 = attr->width; - h2 = attr->height; - *valid = 1; - } - X_UNLOCK; - - x = cache_list[idx].su_x; - y = cache_list[idx].su_y; - w = cache_list[idx].su_w; - h = cache_list[idx].su_h; - - if (x < 0 || cache_list[idx].bs_x < 0 || cache_list[idx].su_time == 0.0) { -if (ncdb) fprintf(stderr, "SU_rest: su_x/bs_x/su_time: %d %d %.3f\n", x, cache_list[idx].bs_x, cache_list[idx].su_time); - return 0; - } - - if (ncache_pad) { - if (nopad) { - x += ncache_pad; - y += ncache_pad; - w -= 2 * ncache_pad; - h -= 2 * ncache_pad; - } else { - x2 -= ncache_pad; - y2 -= ncache_pad; - w2 += 2 * ncache_pad; - h2 += 2 * ncache_pad; - } - } - - if (clipshift) { - x2 -= coff_x; - y2 -= coff_y; - } - - if (w2 > w) { - w2 = w; - } - if (h2 > h) { - h2 = h; - } - - r0 = sraRgnCreateRect(0, 0, dpy_x, dpy_y); - r = sraRgnCreateRect(x, y, x+w2, y+h2); - - dx = x2 - x; - dy = y2 - y; - - sraRgnOffset(r, dx, dy); - sraRgnAnd(r, r0); - - if (clip) { - clip_region(r, win); - } - if (rmask != NULL) { - sraRgnAnd(r, rmask); - } - - dtA = dnowx(); -if (ncdb && verb) fprintf(stderr, "SU_rest: %.4f %d dx=%d dy=%d\n", dtA, idx, dx, dy); - if (w2 > 0 && h2 > 0) { - cache_cr(r, dx, dy, restore_delay0, restore_delay1, nbatch); - } - dtB = dnowx(); -if (ncdb && verb) fprintf(stderr, "SU_rest: %.4f %.2f %d done. %dx%d+%d+%d %dx%d+%d+%d %.2f %.2f\n", dtB, dtB-dtA, idx, w1, h1, x1, y1, w2, h2, x2, y2, cache_list[idx].su_time - x11vnc_start, dnowx()); - - sraRgnDestroy(r0); - sraRgnDestroy(r); - - last_su_restore = dnow(); - - return 1; -} - -void check_zero_rects(void) { - sraRect rt; - sraRectangleIterator *iter; - if (! zero_rects) { - zero_rects = sraRgnCreate(); - } - if (sraRgnEmpty(zero_rects)) { - return; - } - - iter = sraRgnGetIterator(zero_rects); - while (sraRgnIteratorNext(iter, &rt)) { - zero_fb(rt.x1, rt.y1, rt.x2, rt.y2); - mark_rect_as_modified(rt.x1, rt.y1, rt.x2, rt.y2, 0); - } - sraRgnReleaseIterator(iter); - sraRgnMakeEmpty(zero_rects); -} - -void block_stats(void) { - int n, k, s1, s2; - static int t = -1; - int vcnt, icnt, tcnt, vtot = 0, itot = 0, ttot = 0; - t++; - for (n = 1; n < ncache+1; n += 2) { - double area = 0.0, frac; - vcnt = 0; - icnt = 0; - tcnt = 0; - for(k=0; k<cache_list_num; k++) { - XWindowAttributes attr; - int x = cache_list[k].bs_x; - int y = cache_list[k].bs_y; - int w = cache_list[k].bs_w; - int h = cache_list[k].bs_h; - int rc = 0; - Window win = cache_list[k].win; - - if (win == None) { - continue; - } - if (n == 1) { - X_LOCK; - rc = valid_window(win, &attr, 1); - X_UNLOCK; - if (rc) { - vtot++; - } else { - itot++; - } - if (x >= 0) { - ttot++; - } - } - if (y < n*dpy_y || y > (n+1)*dpy_y) { - continue; - } - if (n != 1) { - X_LOCK; - rc = valid_window(win, &attr, 1); - X_UNLOCK; - } - if (rc) { - vcnt++; - } else { - icnt++; - } - if (x >= 0) { - tcnt++; - } - if (x < 0) { - continue; - } - area += cache_list[k].width * cache_list[k].height; - if (! rc && ! macosx_console) { - char *u = getenv("USER"); - if (u && !strcmp(u, "runge")) fprintf(stderr, "\a"); - if (ncdb) fprintf(stderr, "\n *** UNRECLAIMED WINDOW: 0x%lx %dx%d+%d+%d\n\n", win, w, h, x, y); - DELETE(k); - } - if (t < 3 || (t % 4) == 0 || hack_val || macosx_console) { - double t1 = cache_list[k].su_time; - double t2 = cache_list[k].bs_time; - if (t1 > 0.0) {t1 = dnow() - t1;} else {t1 = -1.0;} - if (t2 > 0.0) {t2 = dnow() - t2;} else {t2 = -1.0;} - if (ncdb) fprintf(stderr, " [%02d] %04d 0x%08lx bs: %04dx%04d+%04d+%05d vw: %04dx%04d+%04d+%04d cl: %04dx%04d+%04d+%04d map=%d su=%9.3f bs=%9.3f cnt=%d/%d\n", - n, k, win, w, h, x, y, attr.width, attr.height, attr.x, attr.y, - cache_list[k].width, cache_list[k].height, cache_list[k].x, cache_list[k].y, - attr.map_state == IsViewable, t1, t2, cache_list[k].create_cnt, cache_list[k].map_cnt); - } - } - frac = area /(dpy_x * dpy_y); - if (ncdb) fprintf(stderr, "block[%02d] %.3f %8d trak/val/inval: %d/%d/%d of %d\n", n, frac, (int) area, tcnt, vcnt, icnt, vcnt+icnt); - } - - if (ncdb) fprintf(stderr, "\n"); - if (ncdb) fprintf(stderr, "block: trak/val/inval %d/%d/%d of %d\n", ttot, vtot, itot, vtot+itot); - - s1 = fr_REGION + fr_GRID + fr_EXPIRE + fr_FORCE + fr_BIG1 + fr_BIG2 + fr_FAIL; - s2 = fr_REGIONt + fr_GRIDt + fr_EXPIREt + fr_FORCEt + fr_BIG1t + fr_BIG2t + fr_FAILt; - if (ncdb) fprintf(stderr, "\n"); - if (ncdb) fprintf(stderr, "find_rect: REGION/GRID/EXPIRE/FORCE - BIG1/BIG2/FAIL %d/%d/%d/%d - %d/%d/%d of %d\n", - fr_REGION, fr_GRID, fr_EXPIRE, fr_FORCE, fr_BIG1, fr_BIG2, fr_FAIL, s1); - if (ncdb) fprintf(stderr, " totals: %d/%d/%d/%d - %d/%d/%d of %d\n", - fr_REGIONt, fr_GRIDt, fr_EXPIREt, fr_FORCEt, fr_BIG1t, fr_BIG2t, fr_FAILt, s2); - - fr_BIG1 = 0; - fr_BIG2 = 0; - fr_REGION = 0; - fr_GRID = 0; - fr_EXPIRE = 0; - fr_FORCE = 0; - fr_FAIL = 0; - if (ncdb) fprintf(stderr, "\n"); -} - -#define NSCHED 128 -Window sched_bs[NSCHED]; -double sched_tm[NSCHED]; -double last_sched_bs = 0.0; - -#define SCHED(w, v) \ -{ \ - int k, save = -1, empty = 1; \ - for (k=0; k < NSCHED; k++) { \ - if (sched_bs[k] == None) { \ - save = k; \ - } \ - if (sched_bs[k] == w) { \ - save = k; \ - empty = 0; \ - break; \ - } \ - } \ - if (save >= 0) { \ - sched_bs[save] = w; \ - if (empty) { \ - sched_tm[save] = dnow(); \ - if (v && ncdb) fprintf(stderr, "SCHED: %d %f\n", save, dnowx()); \ - } \ - } \ -} - -void xselectinput(Window w, unsigned long evmask, int sync) { -#if NO_X11 - trapped_xerror = 0; - trapped_xioerror = 0; - if (!evmask) {} -#else - XErrorHandler old_handler1; - XIOErrorHandler old_handler2; - - if (macosx_console || !dpy) { - return; - } - - old_handler1 = XSetErrorHandler(trap_xerror); - old_handler2 = XSetIOErrorHandler(trap_xioerror); - trapped_xerror = 0; - trapped_xioerror = 0; - - XSelectInput(dpy, w, evmask); - - /* - * We seem to need to synchronize right away since the window - * might go away quickly. - */ - if (sync) { - XSync(dpy, False); - } else { - XFlush_wr(dpy); - } - - XSetErrorHandler(old_handler1); - XSetIOErrorHandler(old_handler2); -#endif - - if (trapped_xerror) { - if (ncdb) fprintf(stderr, "XSELECTINPUT: trapped X Error."); - } - if (trapped_xioerror) { - if (ncdb) fprintf(stderr, "XSELECTINPUT: trapped XIO Error."); - } -if (sync && ncdb) fprintf(stderr, "XSELECTINPUT: 0x%lx sync=%d err=%d/%d\n", w, sync, trapped_xerror, trapped_xioerror); -} - -Bool xcheckmaskevent(Display *d, long mask, XEvent *ev) { -#ifdef MACOSX - if (macosx_console) { - if (macosx_checkevent(ev)) { - return True; - } else { - return False; - } - } -#endif - RAWFB_RET(False); - -#if NO_X11 - if (!d || !mask) {} - return False; -#else - return XCheckMaskEvent(d, mask, ev); -#endif -} - -#include <rfb/default8x16.h> - -#define EVMAX 2048 -XEvent Ev[EVMAX]; -int Ev_done[EVMAX]; -int Ev_order[EVMAX]; -int Ev_area[EVMAX]; -int Ev_tmp[EVMAX]; -int Ev_tmp2[EVMAX]; -Window Ev_tmpwin[EVMAX]; -Window Ev_win[EVMAX]; -Window Ev_map[EVMAX]; -Window Ev_unmap[EVMAX]; -sraRect Ev_rects[EVMAX]; - -int tmp_stack[STACKMAX]; -sraRegionPtr tmp_reg[STACKMAX]; - -#define CLEAN_OUT \ - for (i=0; i < n; i++) { \ - sraRgnDestroy(tmp_reg[i]); \ - } \ - if (r1) sraRgnDestroy(r1); \ - if (r0) sraRgnDestroy(r0); - -int try_to_fix_resize_su(Window orig_frame, int orig_x, int orig_y, int orig_w, int orig_h, - int x, int y, int w, int h, int try_batch) { - - int idx = lookup_win_index(orig_frame); - sraRegionPtr r0, r1, r2, r3; - int sx1, sy1, sw1, sh1, dx, dy; - int bx1, by1, bw1, bh1; - int nr = 0, *nbat = NULL; - - if (idx < 0) { - return 0; - } - if (cache_list[idx].bs_x < 0 || cache_list[idx].su_time == 0.0) { - return 0; - } - - r0 = sraRgnCreateRect(0, 0, dpy_x, dpy_y); - r1 = sraRgnCreateRect(orig_x, orig_y, orig_x+orig_w, orig_y+orig_h); - r2 = sraRgnCreateRect(x, y, x+w, y+h); - - sraRgnAnd(r1, r0); - sraRgnAnd(r2, r0); - - if (try_batch) { - nbat = &nr; - } - - if (orig_w >= w && orig_h >= h) { - -if (0) fprintf(stderr, "Shrinking resize %d %dx%d+%d+%d -> %dx%d+%d+%d\n", idx, orig_w, orig_h, orig_x, orig_y, w, h, x, y); - r3 = sraRgnCreateRgn(r1); - sraRgnSubtract(r3, r2); - - sx1 = cache_list[idx].su_x; - sy1 = cache_list[idx].su_y; - sw1 = cache_list[idx].su_w; - sh1 = cache_list[idx].su_h; - - dx = orig_x - sx1; - dy = orig_y - sy1; - - cache_cr(r3, dx, dy, 0.075, 0.05, nbat); - sraRgnDestroy(r3); - - r3 = sraRgnCreateRgn(r1); - sraRgnAnd(r3, r2); - - dx = sx1 - orig_x; - dy = sy1 - orig_y; - sraRgnOffset(r3, dx, dy); - - dx = orig_x - x; - dy = orig_y - y; - sraRgnOffset(r3, dx, dy); - - cache_cr(r3, dx, dy, 0.075, 0.05, nbat); - sraRgnDestroy(r3); - - if (nr) { - batch_push(nr, -1.0); - } - - cache_list[idx].x = x; - cache_list[idx].y = y; - cache_list[idx].width = w; - cache_list[idx].height = h; - - cache_list[idx].bs_w = w; - cache_list[idx].bs_h = h; - cache_list[idx].su_w = w; - cache_list[idx].su_h = h; - - cache_list[idx].bs_time = 0.0; - /* XXX Y */ - if (0) cache_list[idx].su_time = dnow(); - } else { -if (0) fprintf(stderr, "Growing resize %d %dx%d+%d+%d -> %dx%d+%d+%d\n", idx, orig_w, orig_h, orig_x, orig_y, w, h, x, y); - - sx1 = cache_list[idx].su_x; - sy1 = cache_list[idx].su_y; - sw1 = cache_list[idx].su_w; - sh1 = cache_list[idx].su_h; - - bx1 = cache_list[idx].bs_x; - by1 = cache_list[idx].bs_y; - bw1 = cache_list[idx].bs_w; - bh1 = cache_list[idx].bs_h; - - if (find_rect(idx, x, y, w, h)) { - r3 = sraRgnCreateRgn(r2); - sraRgnAnd(r3, r1); - - dx = cache_list[idx].su_x - x; - dy = cache_list[idx].su_y - y; - - sraRgnOffset(r3, dx, dy); - - dx = dx - (sx1 - orig_x); - dy = dy - (sy1 - orig_y); - - cache_cr(r3, dx, dy, 0.075, 0.05, nbat); - sraRgnDestroy(r3); - - r3 = sraRgnCreateRgn(r2); - sraRgnSubtract(r3, r1); - - dx = cache_list[idx].su_x - x; - dy = cache_list[idx].su_y - y; - - sraRgnOffset(r3, dx, dy); - - cache_cr(r3, dx, dy, 0.075, 0.05, nbat); - sraRgnDestroy(r3); - - if (nr) { - batch_push(nr, -1.0); - } - - cache_list[idx].bs_time = 0.0; - /* XXX Y */ - if (0) cache_list[idx].su_time = dnow(); - } - } - - sraRgnDestroy(r0); - sraRgnDestroy(r1); - sraRgnDestroy(r2); - - return 1; -} - -int try_to_fix_su(Window win, int idx, Window above, int *nbatch, char *mode) { - int i, idx2, n = 0, found = 0, found_above = 0; - sraRegionPtr r0, r1, r2; - Window win2; - int x, y, w, h, on = 0; - int x0, y0, w0, h0; - int x1, y1, w1, h1; - int x2, y2, w2, h2; - int unmapped = 0; - int moved = 0; - - - if (mode && !strcmp(mode, "unmapped")) { - unmapped = 1; - } else if (mode && !strcmp(mode, "moved")) { - moved = 1; - } - if (idx < 0) { - return 0; - } -if (ncdb) fprintf(stderr, "TRY_TO_FIX_SU(%d) 0x%lx 0x%lx was_unmapped=%d map_state=%s\n", idx, win, above, unmapped, MState(cache_list[idx].map_state)); - - if (cache_list[idx].map_state != IsViewable && !unmapped) { - return 0; - } - if (cache_list[idx].su_time == 0.0) { - return 0; - } - if (cache_list[idx].bs_x < 0) { - return 0; - } - - r0 = sraRgnCreateRect(0, 0, dpy_x, dpy_y); - - x = cache_list[idx].x; - y = cache_list[idx].y; - w = cache_list[idx].width; - h = cache_list[idx].height; - - r1 = sraRgnCreateRect(x, y, x+w, y+h); - - sraRgnAnd(r1, r0); - - if (sraRgnEmpty(r1)) { - CLEAN_OUT - return 0; - } - - if (unmapped) { - on = 1; - } - if (above == 0x1) { - on = 1; - } - for (i = old_stack_n - 1; i >= 0; i--) { - win2 = old_stack[i]; - if (win2 == above) { -if (0) fprintf(stderr, "0x%lx turn on: 0x%lx i=%d\n", win, win2, i); - on = 1; - found_above = 1; - } - if (win2 == win) { -if (0) fprintf(stderr, "0x%lx turn off: 0x%lx i=%d\n", win, win2, i); - found = 1; - on = 0; - break; - } - if (! on) { - continue; - } - idx2 = lookup_win_index(win2); - if (idx2 < 0) { - continue; - } - if (cache_list[idx2].map_state != IsViewable) { - continue; - } - if (cache_list[idx2].bs_x < 0) { - continue; - } - /* XXX Invalidate? */ - - x2 = cache_list[idx2].x; - y2 = cache_list[idx2].y; - w2 = cache_list[idx2].width; - h2 = cache_list[idx2].height; - - r2 = sraRgnCreateRect(x2, y2, x2+w2, y2+h2); - sraRgnAnd(r2, r0); - if (! sraRgnAnd(r2, r1)) { - sraRgnDestroy(r2); - continue; - } - - tmp_reg[n] = r2; - tmp_stack[n++] = idx2; - } - - if (! found) { - CLEAN_OUT - return 0; - } - - for (i = n - 1; i >= 0; i--) { - int i2; - r2 = sraRgnCreateRgn(tmp_reg[i]); - for (i2 = i + 1; i2 < n; i2++) { - sraRgnSubtract(r2, tmp_reg[i2]); - } - idx2 = tmp_stack[i]; - if (!sraRgnEmpty(r2)) { - int dx, dy; - int dx2, dy2; - - x0 = cache_list[idx2].x; - y0 = cache_list[idx2].y; - w0 = cache_list[idx2].width; - h0 = cache_list[idx2].height; - - x1 = cache_list[idx].su_x; /* SU -> SU */ - y1 = cache_list[idx].su_y; - w1 = cache_list[idx].su_w; - h1 = cache_list[idx].su_h; - - x2 = cache_list[idx2].su_x; - y2 = cache_list[idx2].su_y; - w2 = cache_list[idx2].su_w; - h2 = cache_list[idx2].su_h; - - dx = x2 - x0; - dy = y2 - y0; - sraRgnOffset(r2, dx, dy); - - dx2 = x1 - x; - dy2 = y1 - y; - dx = dx - dx2; - dy = dy - dy2; - cache_cr(r2, dx, dy, save_delay0, save_delay1, nbatch); - } - sraRgnDestroy(r2); - } - - if (unmapped) { - CLEAN_OUT - return found_above; - } - - for (i = n - 1; i >= 0; i--) { - r2 = sraRgnCreateRgn(tmp_reg[i]); - idx2 = tmp_stack[i]; - if (!sraRgnEmpty(r2)) { - int dx, dy; - int dx2, dy2; - - x0 = cache_list[idx2].x; - y0 = cache_list[idx2].y; - w0 = cache_list[idx2].width; - h0 = cache_list[idx2].height; - - x1 = cache_list[idx].su_x; /* BS -> SU */ - y1 = cache_list[idx].su_y; - w1 = cache_list[idx].su_w; - h1 = cache_list[idx].su_h; - - x2 = cache_list[idx2].bs_x; - y2 = cache_list[idx2].bs_y; - w2 = cache_list[idx2].bs_w; - h2 = cache_list[idx2].bs_h; - - dx = x1 - x; - dy = y1 - y; - sraRgnOffset(r2, dx, dy); - - dx2 = x2 - x0; - dy2 = y2 - y0; - dx = dx - dx2; - dy = dy - dy2; - cache_cr(r2, dx, dy, save_delay0, save_delay1, nbatch); - } - sraRgnDestroy(r2); - } - - CLEAN_OUT - return found_above; -} - -void idx_add_rgn(sraRegionPtr r, sraRegionPtr r0, int idx) { - int x, y, w, h; - sraRegionPtr rtmp; - - if (idx < 0) { - return; - } - x = cache_list[idx].x; - y = cache_list[idx].y; - w = cache_list[idx].width; - h = cache_list[idx].height; - - rtmp = sraRgnCreateRect(x, y, w, h); - if (r0) { - sraRgnAnd(rtmp, r0); - } - sraRgnOr(r, rtmp); - sraRgnDestroy(rtmp); -} - -sraRegionPtr idx_create_rgn(sraRegionPtr r0, int idx) { - int x, y, w, h; - sraRegionPtr rtmp; - - if (idx < 0) { - return NULL; - } - x = cache_list[idx].x; - y = cache_list[idx].y; - w = cache_list[idx].width; - h = cache_list[idx].height; - - rtmp = sraRgnCreateRect(x, y, w, h); - if (r0) { - sraRgnAnd(rtmp, r0); - } - return rtmp; -} - -void scale_mark_xrootpmap(void) { - char *dst_fb, *src_fb = main_fb; - int dst_bpl, Bpp = bpp/8, fac = 1; - int yn = (ncache+1) * dpy_y; - int yfac = (ncache+2); - int mark = 1; - - if (!scaling || !rfb_fb || rfb_fb == main_fb) { - mark_rect_as_modified(0, yn, dpy_x, yn + dpy_y, 0); - return; - } - - if (cmap8to24 && cmap8to24_fb) { - src_fb = cmap8to24_fb; - if (scaling) { - if (depth <= 8) { - fac = 4; - } else if (depth <= 16) { - fac = 2; - } - } - } - dst_fb = rfb_fb; - dst_bpl = rfb_bytes_per_line; - - scale_rect(scale_fac_x, scale_fac_y, scaling_blend, scaling_interpolate, fac * Bpp, - src_fb, fac * main_bytes_per_line, dst_fb, dst_bpl, dpy_x, yfac * dpy_y, - scaled_x, yfac * scaled_y, 0, yn, dpy_x, yn + dpy_y, mark); -} - -void set_ncache_xrootpmap(void) { - Atom pmap, type; - int format; - unsigned long length, after; - XImage *image = NULL; - XErrorHandler old_handler; - - RAWFB_RET_VOID -#if !NO_X11 - if (!ncache) { - return; - } - X_LOCK; - old_handler = XSetErrorHandler(trap_xerror); - trapped_xerror = 0; - pmap = XInternAtom(dpy, "_XROOTPMAP_ID", True); - - if (use_solid_bg) { - image = solid_image(NULL); - if (!quiet) { - rfbLog("set_ncache_xrootpmap: solid_image\n"); - } - } else if (pmap != None) { - Pixmap pixmap = None; - unsigned char *d_pmap; - - XGetWindowProperty(dpy, rootwin, pmap, 0L, 1L, False, - AnyPropertyType, &type, &format, &length, &after, &d_pmap); - - if (length != 0) { - pixmap = *((Pixmap *) d_pmap); - if (pixmap != None) { - image = XGetImage(dpy, pixmap, 0, 0, dpy_x, dpy_y, AllPlanes, ZPixmap); - } - } - if (!quiet) { - rfbLog("set_ncache_xrootpmap: loading background pixmap: 0x%lx\n", pixmap); - } - } else { - if (!quiet) { - rfbLog("set_ncache_xrootpmap: trying root background\n"); - } - } - if (image == NULL) { - image = solid_root((char *) 0x1); - } - if (image != NULL) { - char *src, *dst; - int line; - int pixelsize = bpp/8; - int y1 = dpy_y * (ncache+1); - - src = image->data; - dst = main_fb + y1 * main_bytes_per_line; - line = 0; - while (line++ < dpy_y) { - memcpy(dst, src, dpy_x * pixelsize); - src += image->bytes_per_line; - dst += main_bytes_per_line; - } - XDestroyImage(image); - X_UNLOCK; - scale_mark_xrootpmap(); - X_LOCK; - } else { - int yn = (ncache+1) * dpy_y; - zero_fb(0, yn, dpy_x, yn + dpy_y); - } - XSetErrorHandler(old_handler); - X_UNLOCK; -#endif -} - -#define EVLISTMAX 256 -#define EV_RESET 0 -#define EV_CREATE 1 -#define EV_DESTROY 2 -#define EV_UNMAP 3 -#define EV_MAP 4 -#define EV_REPARENT 5 -#define EV_CONFIGURE 6 -#define EV_CONFIGURE_SIZE 7 -#define EV_CONFIGURE_POS 8 -#define EV_CONFIGURE_STACK 9 -#define EV_VISIBILITY_UNOBS 10 -#define EV_VISIBILITY_OBS 11 -#define EV_PROPERTY 12 -#define EV_OLD_WM_MAP 13 -#define EV_OLD_WM_UNMAP 14 -#define EV_OLD_WM_OFF 15 -#define EV_OLD_WM_NOTMAPPED 16 -Window _ev_list[EVLISTMAX]; -int _ev_case[EVLISTMAX]; -int _ev_list_cnt; - -int n_CN = 0, n_RN = 0, n_DN = 0, n_ON = 0, n_MN = 0, n_UN = 0; -int n_VN = 0, n_VN_p = 0, n_VN_u = 0, n_ST = 0, n_PN = 0, n_DC = 0; -int n_ON_sz = 0, n_ON_po = 0, n_ON_st = 0; - -int ev_store(Window win, int type) { - if (type == EV_RESET) { - n_CN = 0; n_RN = 0; n_DN = 0; n_ON = 0; n_MN = 0; n_UN = 0; - n_VN = 0; n_VN_p = 0; n_VN_u = 0; n_ST = 0; n_PN = 0; n_DC = 0; - n_ON_sz = 0; n_ON_po = 0; n_ON_st = 0; - _ev_list_cnt = 0; - return 1; - } - if (_ev_list_cnt >= EVLISTMAX) { - return 0; - } - _ev_list[_ev_list_cnt] = win; - _ev_case[_ev_list_cnt++] = type; - return 1; -} - -int ev_lookup(Window win, int type) { - int i; - for(i=0; i < _ev_list_cnt; i++) { - if (_ev_list[i] == win && _ev_case[i] == type) { - return 1; - } - } - return 0; -} - -unsigned long all_ev = SubstructureNotifyMask|StructureNotifyMask|VisibilityChangeMask; -unsigned long win_ev = StructureNotifyMask|VisibilityChangeMask; - -void read_events(int *n_in) { - int n = *n_in; - Window win, win2; - XEvent ev; - - while (xcheckmaskevent(dpy, all_ev, &Ev[n])) { - int cfg_size = 0; - int cfg_pos = 0; - int cfg_stack = 0; - int type = Ev[n].type; - Window w = None; - - win = Ev[n].xany.window; - Ev_done[n] = 0; - Ev_area[n] = 0; - Ev_win[n] = win; - Ev_map[n] = None; - Ev_unmap[n] = None; - Ev_order[n] = n; - - ev = Ev[n]; - - if (type == DestroyNotify) w = Ev[n].xcreatewindow.window; - if (type == CreateNotify) w = Ev[n].xdestroywindow.window; - if (type == ReparentNotify) w = Ev[n].xreparent.window; - if (type == UnmapNotify) w = Ev[n].xunmap.window; - if (type == MapNotify) w = Ev[n].xmap.window; - if (type == Expose) w = Ev[n].xexpose.window; - if (type == ConfigureNotify) w = Ev[n].xconfigure.window; - if (type == VisibilityNotify) w = win; - if (n == *n_in && ncdb) fprintf(stderr, "\n"); - if (1) { - char *msg = ""; - int idx = -1, x = 0, y = 0, wd = 0, ht = 0; - if (w != None) { - idx = lookup_win_index(w); - if (idx >= 0) { - x = cache_list[idx].x; - y = cache_list[idx].y; - wd = cache_list[idx].width; - ht = cache_list[idx].height; - } - } - if (type == VisibilityNotify) { - msg = VState(Ev[n].xvisibility.state); - } else if (type == ConfigureNotify) { - int x_new = Ev[n].xconfigure.x; - int y_new = Ev[n].xconfigure.y; - int w_new = Ev[n].xconfigure.width; - int h_new = Ev[n].xconfigure.height; - if (idx >= 0) { - if (w_new != wd || h_new != ht) { - msg = "change size"; - cfg_size = 1; - } - if (x_new != x || y_new != y) { - if (!strcmp(msg, "")) { - msg = "change position"; - } - cfg_pos = 1; - } else if (! cfg_size) { - msg = "change stacking"; - cfg_stack = 1; - } - } - } - - if (ncdb) fprintf(stderr, "----- %02d inputev 0x%08lx w: 0x%08lx %04dx%04d+%04d+%04d %s %s\n", n, win, w, wd, ht, x, y, Etype(type), msg); - } - - if (win == rootwin) { - if (type == CreateNotify) { - win2 = ev.xcreatewindow.window; - ev_store(win2, EV_CREATE); - n++; - n_CN++; - } else if (type == ReparentNotify) { - if (ev.xreparent.parent != rootwin) { - win2 = ev.xreparent.window; - if (win2 != rootwin) { - ev_store(win2, EV_REPARENT); - } - } - n++; - n_RN++; - } else if (type == PropertyNotify) { - set_prop_atom(Ev[n].xproperty.atom); - n++; - n_PN++; - } else if (type == MapNotify) { - win2 = ev.xmap.window; - ev_store(win2, EV_MAP); - n++; - n_CN++; - } else { - /* skip rest */ -#if 0 - Window w = None; -if (type == DestroyNotify) w = Ev[n].xdestroywindow.window; -if (type == UnmapNotify) w = Ev[n].xunmap.window; -if (type == MapNotify) w = Ev[n].xmap.window; -if (type == Expose) w = Ev[n].xexpose.window; -if (type == ConfigureNotify) w = Ev[n].xconfigure.window; -if (type != ConfigureNotify) fprintf(stderr, "root: skip %s for 0x%lx\n", Etype(type), w); -#endif - - } - } else { - if (type == ReparentNotify) { - ev_store(win, EV_REPARENT); - n++; - n_RN++; - } else if (type == DestroyNotify) { - ev_store(win, EV_DESTROY); - n++; - n_DN++; - } else if (type == ConfigureNotify) { - ev_store(win, EV_CONFIGURE); - if (cfg_size) { - ev_store(win, EV_CONFIGURE_SIZE); - n_ON_sz++; - } - if (cfg_pos) { - ev_store(win, EV_CONFIGURE_POS); - n_ON_po++; - } - if (cfg_stack) { - ev_store(win, EV_CONFIGURE_STACK); - n_ON_st++; - } - n++; - n_ON++; - } else if (type == VisibilityNotify) { - if (Ev[n].xvisibility.state == VisibilityUnobscured) { - ev_store(win, EV_VISIBILITY_UNOBS); - n_VN_u++; - } else { - ev_store(win, EV_VISIBILITY_OBS); - n_VN_p++; - } - n++; - n_VN++; - } else if (type == MapNotify) { - ev_store(win, EV_MAP); - Ev_map[n] = win; - n++; - n_MN++; - } else if (type == UnmapNotify) { - ev_store(win, EV_UNMAP); - Ev_unmap[n] = win; - n++; - n_UN++; - } else { - /* skip rest */ -if (ncdb) fprintf(stderr, "----- skip %s\n", Etype(type)); - } - } - if (n >= EVMAX) { - break; - } - } - *n_in = n; -} - -int try_to_synthesize_su(int force, int urgent, int *nbatch) { - int i, idx, idx2, n = 0; - sraRegionPtr r0, r1, r2; - Window win = None; - int x0, y0, w0, h0; - int x1, y1, w1, h1; - int x2, y2, w2, h2; - int x3, y3, w3, h3; - XWindowAttributes attr; - - r0 = sraRgnCreateRect(0, 0, dpy_x, dpy_y); - - snap_old(); - - X_LOCK; - for (i = old_stack_n - 1; i >= 0; i--) { - win = old_stack[i]; - if (urgent) { /* XXX Y resp */ - if (!valid_window(win, &attr, 1)) { - continue; - } - idx = lookup_win_index(win); - if (idx >= 0) { - STORE(idx, win, attr); - } - } else { - idx = lookup_win_index(win); - if (idx >= 0) { - attr.map_state = cache_list[idx].map_state; - attr.x = cache_list[idx].x; - attr.y = cache_list[idx].y; - attr.width = cache_list[idx].width; - attr.height = cache_list[idx].height; - } else { - attr.map_state = IsUnmapped; - attr.x = 0; - attr.y = 0; - attr.width = 0; - attr.height = 0; - } - - } - if (attr.map_state != IsViewable) { - continue; - } -if (0) fprintf(stderr, "win: 0x%lx %d idx=%d\n", win, i, idx); - - x2 = attr.x; - y2 = attr.y; - w2 = attr.width; - h2 = attr.height; - - r2 = sraRgnCreateRect(x2, y2, x2+w2, y2+h2); - sraRgnAnd(r2, r0); - - tmp_reg[n] = r2; - tmp_stack[n++] = idx; - } - X_UNLOCK; - - if (! n) { - r1 = NULL; - CLEAN_OUT - return 0; - } - - for (i = 0; i < n; i++) { - int i2, cnt = 0; - idx = tmp_stack[i]; - if (idx < 0 || cache_list[idx].bs_x < 0) { - continue; - } - r1 = tmp_reg[i]; - if (r1 == NULL || sraRgnEmpty(r1)) { - continue; - } - if (cache_list[idx].su_time > 0.0) { - if (force) { -if (ncdb) fprintf(stderr, "forcing synth: 0x%lx %d\n", cache_list[idx].win, idx); - } else { - continue; - } - } - if (ncache_xrootpmap) { - int dx, dy; - - x0 = cache_list[idx].x; - y0 = cache_list[idx].y; - w0 = cache_list[idx].width; - h0 = cache_list[idx].height; - - x1 = cache_list[idx].su_x; - y1 = cache_list[idx].su_y; - w1 = cache_list[idx].su_w; - h1 = cache_list[idx].su_h; - - r2 = sraRgnCreateRgn(tmp_reg[i]); - dx = x1 - x0; - dy = y1 - y0; - - sraRgnOffset(r2, dx, dy); - - x2 = x0; - y2 = y0 + (ncache+1) * dpy_y; - - dx = x1 - x2; - dy = y1 - y2; - cache_cr(r2, dx, dy, save_delay0, save_delay1, nbatch); - cnt++; - - sraRgnDestroy(r2); - } - - for (i2 = n - 1; i2 > i; i2--) { - r2 = sraRgnCreateRgn(tmp_reg[i2]); - if (sraRgnAnd(r2, r1)) { - int dx, dy; - int dx2, dy2; - - idx2 = tmp_stack[i2]; - /* XXX Y */ - if (idx2 < 0 || cache_list[idx2].bs_x < 0 || cache_list[idx2].bs_time == 0.0) { - continue; - } - - x0 = cache_list[idx].x; - y0 = cache_list[idx].y; - w0 = cache_list[idx].width; - h0 = cache_list[idx].height; - - x1 = cache_list[idx].su_x; - y1 = cache_list[idx].su_y; - w1 = cache_list[idx].su_w; - h1 = cache_list[idx].su_h; - - x2 = cache_list[idx2].x; - y2 = cache_list[idx2].y; - w2 = cache_list[idx2].width; - h2 = cache_list[idx2].height; - - x3 = cache_list[idx2].bs_x; - y3 = cache_list[idx2].bs_y; - w3 = cache_list[idx2].bs_w; - h3 = cache_list[idx2].bs_h; - - dx = x1 - x0; - dy = y1 - y0; - sraRgnOffset(r2, dx, dy); - - dx2 = x3 - x2; - dy2 = y3 - y2; - dx = dx - dx2; - dy = dy - dy2; - cache_cr(r2, dx, dy, save_delay0, save_delay1, nbatch); - cnt++; - } - sraRgnDestroy(r2); - } - if (cnt) { - cache_list[idx].su_time = dnow(); - } -if (ncdb) fprintf(stderr, " try_to_synth_su: 0x%lx %d idx=%d cnt=%d\n", win, i, idx, cnt); - } - - r1 = NULL; - CLEAN_OUT - return 1; -} - -static double last_vis_unobs_time = 0.0; -static double last_vis_obs_time = 0.0; - -static int saw_desktop_change = 0; - -void check_sched(int try_batch, int *did_sched) { - static double last_root = 0.0; - static double last_pixmap = 0.0; - double refresh = 60.0; - int i, k, valid; - Window win; - XWindowAttributes attr; - double now = dnow(); - - if (now > last_root + refresh) { - -if (ncdb) fprintf(stderr, "\n**** checking cache_list[%d]\n\n", cache_list_num); - block_stats(); - - for(k=0; k<cache_list_num; k++) { - valid = 0; - win = cache_list[k].win; - X_LOCK; - if (win == None) { - ; - } else if (cache_list[k].selectinput && cache_list[k].time > now - refresh) { - valid = 1; - } else if (valid_window(win, &attr, 1)) { - STORE(k, win, attr); - if (! cache_list[k].selectinput) { - xselectinput(win, win_ev, 0); - CLEAR(k); - cache_list[k].selectinput = 1; - } - valid = 1; - } else { -if (ncdb) fprintf(stderr, "DELETE(%d) %dx%d+%d+%d\n", k, cache_list[k].width, cache_list[k].height, cache_list[k].x, cache_list[k].y); - DELETE(k); - } - X_UNLOCK; -/* XXX Y */ - if (valid) { - if (cache_list[k].create_cnt && cache_list[k].map_state != IsViewable && cache_list[k].map_cnt == 0) { - if (cache_list[k].bs_x >= 0) { -if (ncdb) fprintf(stderr, "Created window never mapped: freeing(%d) 0x%lx\n", k, win); - free_rect(k); - } - } - } - } - last_root = dnow(); - } - - if (now > last_sched_bs + 0.30) { - static double last_sched_vis = 0.0; - int nr = 0, *bat = NULL; - - if (try_batch) { - bat = &nr; - } - if (now < last_wireframe + 2.0) { - for (i=0; i < NSCHED; i++) { - sched_bs[i] = None; - } - } - if (now < last_get_wm_frame_time + 1.0) { - if (last_get_wm_frame != None) { - int idx = lookup_win_index(last_get_wm_frame); - if (idx >= 0) { - if (cache_list[idx].bs_x < 0) { - int x = cache_list[idx].x; - int y = cache_list[idx].y; - int w = cache_list[idx].width; - int h = cache_list[idx].height; - if (find_rect(idx, x, y, w, h)) { - SCHED(last_get_wm_frame, 1); - } - } - } - } - } - - for (i=0; i < NSCHED; i++) { - if (sched_bs[i] != None) { - int idx; - win = sched_bs[i]; - if (now < sched_tm[i] + 0.55) { - continue; - } - if (n_MN || n_UN || n_ST || n_DC) { - sched_tm[i] = now; - continue; - } - idx = lookup_win_index(win); - if (idx >= 0) { - int aw = cache_list[idx].width; - int ah = cache_list[idx].height; - if (cache_list[idx].map_state != IsViewable) { - ; - } else if (cache_list[idx].vis_state != VisibilityUnobscured) { - ; - } else if (aw * ah < 64 * 64) { - ; - } else { -if (ncdb) fprintf(stderr, "*SNAP BS_save: 0x%lx %d %d %d\n", win, aw, ah, cache_list[idx].map_state); - valid = 0; - bs_save(idx, bat, &attr, 1, 0, &valid, 0); - if (valid) { - STORE(idx, win, attr); - } else { - DELETE(idx); - } - } - } else { -if (ncdb) fprintf(stderr, "*SCHED LOOKUP FAIL: i=%d 0x%lx\n", i, win); - } - } - sched_bs[i] = None; - } - *did_sched = 1; - - if (n_MN || n_UN || n_ST || n_DC) { - if (last_sched_vis < now) { - last_sched_vis += 1.0; - } - } else if (now > last_sched_vis + 3.0 && now > last_wireframe + 2.0) { - static double last_vis = 0.0; - int vis_now[32], top_now[32]; - static int vis_prev[32], freq = 0; - int diff, nv = 32, vis_now_n = 0; - Window win; - - freq++; - - for (i=0; i < cache_list_num; i++) { - int ok = 0; - int top_only = 1; - int aw = cache_list[i].width; - int ah = cache_list[i].height; - int map_prev = cache_list[i].map_state; - - win = cache_list[i].win; - - if (saw_desktop_change) { - top_only = 0; - } - - if (win == None) { - continue; - } - /* XXX Y resp */ - if (saw_desktop_change || freq % 5 == 0) { - int vret = 0; - X_LOCK; - vret = valid_window(win, &attr, 1); - X_UNLOCK; - if (!vret) { - continue; - } - STORE(i, win, attr); - } - if (!cache_list[i].valid) { - continue; - } - if (cache_list[i].map_state != IsViewable) { - continue; - } - if (cache_list[i].vis_state == VisibilityFullyObscured) { - continue; - } - if (map_prev != IsViewable) { - /* we hope to catch it below in the normal event processing */ - continue; - } - if (aw * ah < 64 * 64) { - continue; - } - if (top_only) { - if (cache_list[i].vis_state == VisibilityUnobscured) { - ok = 1; - } else if (!clipped(i)) { - ok = 1; - } - } else { - ok = 1; - } - if (ok) { - if (vis_now_n < nv) { - vis_now[vis_now_n] = i; - top_now[vis_now_n++] = top_only; - } - } - } - diff = 0; - for (k = 0; k < vis_now_n; k++) { - if (vis_now[k] != vis_prev[k]) { - diff = 1; - } - } - if (diff == 0) { - if (now > last_vis + 45.0) { - diff = 1; - } - } - if (diff) { -if (ncdb && vis_now_n) fprintf(stderr, "*VIS snapshot all %.4f\n", dnowx()); - for (k = 0; k < vis_now_n; k++) { - i = vis_now[k]; - win = cache_list[i].win; - valid = 0; -if (ncdb) fprintf(stderr, "*VIS BS_save: 0x%lx %d %d %d\n", win, cache_list[i].width, cache_list[i].height, cache_list[i].map_state); - if (now < cache_list[i].vis_unobs_time + 0.75 && now < cache_list[i].vis_obs_time + 0.75) { - continue; - } - bs_save(i, bat, &attr, !top_now[k], 0, &valid, 1); - if (valid) { - STORE(i, win, attr); - } else { - DELETE(i); - } - vis_prev[k] = vis_now[k]; - } - last_vis = dnow(); - } - last_sched_vis = dnow(); - if (! n_DC) { - saw_desktop_change = 0; - } - /* XXX Y */ - try_to_synthesize_su(0, 0, bat); - } - - if (nr) { - batch_push(nr, -1.0); - } - last_sched_bs = dnow(); - } -#if !NO_X11 - if (dpy && atom_XROOTPMAP_ID == None && now > last_pixmap + 5.0) { - atom_XROOTPMAP_ID = XInternAtom(dpy, "_XROOTPMAP_ID", True); - last_pixmap = now; - } -#endif - if (got_XROOTPMAP_ID > 0.0) { -if (ncdb) fprintf(stderr, "got_XROOTPMAP_ID\n"); - if (ncache_xrootpmap) { - set_ncache_xrootpmap(); - } - got_XROOTPMAP_ID = 0.0; - } -} - -int check_ncache(int reset, int mode) { - static int first = 1; - static int last_client_count = -1; - int i, k, n; - int did_sched = 0; - - Window win, win2; - XWindowAttributes attr; - int valid; - int try_batch = 1; /* XXX Y */ - int use_batch = 0; - int nreg = 0, *nbatch; - int create_cnt; - int su_fix_cnt; - int pixels = 0, ttot; - int desktop_change = 0, n1, n2; - int desktop_change_old_wm = 0; - int missed_su_restore = 0; - int missed_bs_restore = 0; - sraRegionPtr r0, r; - sraRegionPtr missed_su_restore_rgn; - sraRegionPtr missed_bs_restore_rgn; - sraRegionPtr unmapped_rgn; - - int nrects = 0; - int nsave, nxsel; - double now; - - int skipwins_n = 0; - int skipwins_max = 256; - Window skipwins[256]; - - static char *dt_guess = NULL; - static double dt_last = 0.0; - int dt_gnome = 0, gnome_animation = 0; - int dt_kde = 0; - - if (unixpw_in_progress) return -1; - -#ifdef MACOSX - if (! macosx_console) { - RAWFB_RET(-1) - } - if (! screen) { - return -1; - } -#else - RAWFB_RET(-1) - if (! screen || ! dpy) { - return -1; - } -#endif - - now = dnow(); - -#ifdef NO_NCACHE - ncache = 0; -#endif - - if (reset && (first || cache_list_len == 0)) { - return -1; - } - if (use_threads) { - try_batch = 0; - } - - if (ncache0) { - if (reset) { - ; - } else if (!client_count || !ncache || nofb) { - static double last_purge = 0.0; - double delay = client_count ? 0.5 : 2.0; - if (now > last_purge + delay) { - int c = 0; - XEvent ev; - X_LOCK; - while (xcheckmaskevent(dpy, all_ev, &ev)) { - c++; - } - X_UNLOCK; - last_purge = dnow(); -if (ncdb && c) fprintf(stderr, "check_ncache purged %d events\n", c); - } - if (!client_count && last_client_count >= 0 && - client_count != last_client_count) { - /* this should use less RAM when no clients */ - do_new_fb(1); - } - last_client_count = client_count; - return -1; - } - } - last_client_count = client_count; - - if (ncache && ! ncache0) { - ncache0 = ncache; - } - - if (! ncache || ! ncache0) { - return -1; - } - if (subwin) { - return -1; - } - if (nofb) { - return -1; - } - if (now < last_client + 4) { - return -1; - } - if (! all_clients_initialized()) { - /* play it safe */ - return -1; - } - - - - if (reset) { - rfbLog("check_ncache: resetting cache: %d/%d %d %d\n", cache_list_num, cache_list_len, ncache, first); - for (i=0; i < cache_list_num; i++) { - free_rect(i); - } - for (n = 1; n <= ncache; n++) { - if (rect_reg[n] != NULL) { - sraRgnDestroy(rect_reg[n]); - rect_reg[n] = NULL; - } - } - zero_fb(0, dpy_y, dpy_x, (ncache+1)*dpy_y); - mark_rect_as_modified(0, dpy_y, dpy_x, (ncache+1)*dpy_y, 0); - - if (ncache_xrootpmap) { - set_ncache_xrootpmap(); - } - - snap_old(); - return -1; - } - - if (first) { - int dx = 10, dy = 24, ds = 0; - int Dx = dpy_x, Dy = dpy_y; - first = 0; - for (i=0; i < NRECENT; i++) { - recent[i] = None; - } - for (i=0; i < NSCHED; i++) { - sched_bs[i] = None; - } - rlast = 0; - - X_LOCK; - /* event leak with client_count == 0 */ - xselectinput_rootwin |= SubstructureNotifyMask; - XSelectInput_wr(dpy, rootwin, xselectinput_rootwin); - X_UNLOCK; - - if (scaling) { - Dx = scaled_x; - Dy = scaled_y; - } - if (!rotating_same) { - int t = Dx; - Dx = Dy; - Dy = t; - } - - for (i = 0; i < 3; i++) { - rfbDrawString(screen, &default8x16Font, dx, ds + Dy+1*dy, - "This is the Pixel buffer cache region. Your VNC Viewer is not hiding it from you.", - white_pixel()); - rfbDrawString(screen, &default8x16Font, dx, ds + Dy+2*dy, - "Try resizing your VNC Viewer so you don't see it!!", - white_pixel()); - rfbDrawString(screen, &default8x16Font, dx, ds + Dy+3*dy, - "Pay no attention to the man behind the curtain...", - white_pixel()); - rfbDrawString(screen, &default8x16Font, dx, ds + Dy+4*dy, - "To disable caching run the server with: x11vnc -noncache ...", - white_pixel()); - rfbDrawString(screen, &default8x16Font, dx, ds + Dy+5*dy, - "If there are painting errors press 3 Alt_L's (Left \"Alt\" key) in a row to repaint the screen.", - white_pixel()); - rfbDrawString(screen, &default8x16Font, dx, ds + Dy+6*dy, - "More info: http://www.karlrunge.com/x11vnc/faq.html#faq-client-caching", - white_pixel()); - - ds += 11 * dy; - } - - snapshot_cache_list(0, 100.0); - for (i=0; i < cache_list_num; i++) { - CLEAR(i); - } - for (n = 1; n <= ncache; n++) { - rect_reg[n] = NULL; - } - - if (ncache_xrootpmap) { - set_ncache_xrootpmap(); - } - - snap_old(); - } - - check_zero_rects(); - -if (hack_val == 2) { - block_stats(); - hack_val = 1; -} -#ifdef MACOSX - if (macosx_console) { - static double last_all_windows = 0.0; - if (! macosx_checkevent(NULL)) { - if (now > last_all_windows + 0.05) { - macosxCGS_get_all_windows(); - last_all_windows = dnow(); - } - } - /* XXX Y */ - rootwin = -1; - } -#endif - - n = 0; - ttot = 0; - - if (dt_guess == NULL || now > dt_last + 60) { - static char *dt_prev = NULL; - dt_prev = dt_guess; - dt_guess = strdup(guess_desktop()); - if (ncache_xrootpmap && dt_prev && dt_guess) { - if (strcmp(dt_prev, dt_guess)) { - set_ncache_xrootpmap(); - } - } - dt_last = now; - if (dt_prev) { - free(dt_prev); - } - } - if (dt_guess && !strcmp(dt_guess, "gnome")) { - dt_gnome = 1; - } else if (dt_guess && !strcmp(dt_guess, "kde")) { - dt_kde = 1; - } - if (dt_kde) { - kde_no_animate(0); - } - - ev_store(None, EV_RESET); - - X_LOCK; - for (k = 1; k <= 3; k++) { - int j, retry = 0; - - if (retry) {} - - nsave = n; - - if (k > 1 && ncdb) fprintf(stderr, "read_events-%d\n", k); - read_events(&n); - -#if 0 - if (dt_gnome && (n_MN || n_UN)) { - retry = 1; - } else if (ncache_old_wm && n_ON_po >= 2) { - retry = 1; - } else if (n > nsave) { - /* XXX Y */ - retry = 1; - } - - if (retry) { - int n0 = n; - usleep(25 * 1000); - XFlush_wr(dpy); - read_events(&n); - if (ncdb) fprintf(stderr, "read_events retry: %d -> %d\n", n0, n); - } -#endif - - if (n > nsave) { - int n0 = n; - - for (j=0; j<4; j++) { - if (j < 2) { - usleep(30 * 1000); - } else { - usleep(10 * 1000); - } - XFlush_wr(dpy); - read_events(&n); - if (ncdb) fprintf(stderr, "read_events retry: %d -> %d\n", n0, n); - if (n == n0) { - break; - } - n0 = n; - } - } - - nxsel = 0; - - /* handle creates and reparenting: */ - for (n1 = nsave; n1 < n; n1++) { - Window win2; - int idx; - XEvent ev = Ev[n1]; - win = Ev_win[n1]; - if (ev.type == CreateNotify) { - win2 = ev.xcreatewindow.window; - if (ev_lookup(win2, EV_REPARENT) || ev_lookup(win2, EV_DESTROY)) { - if (skipwins_n < skipwins_max) { -if (ncdb) fprintf(stderr, "SKIPWINS: CreateNotify: 0x%lx %d\n", win2, n1); - skipwins[skipwins_n++] = win2; - } - } else { - idx = lookup_win_index(win); - if (idx < 0) { - idx = lookup_free_index(); - if (idx < 0) { - continue; - } - CLEAR(idx); - } -if (ncdb) fprintf(stderr, "PRELOOP: CreateNotify: 0x%lx %d valid_window\n", win2, n1); - if (valid_window(win2, &attr, 1)) { - STORE(idx, win2, attr); - CLEAR(idx); - cache_list[idx].selectinput = 1; - cache_list[idx].create_cnt = 1; -if (ncdb) fprintf(stderr, "PRELOOP: CreateNotify: 0x%lx %d xselectinput\n", win2, n1); - xselectinput(win2, win_ev, 1); - nxsel++; - } else { - DELETE(idx); - } - nxsel++; - } - } else if (ev.type == ReparentNotify) { - if (ev.xreparent.parent != rootwin) { - win2 = ev.xreparent.window; - if (win2 != rootwin) { - idx = lookup_win_index(win2); -if (ncdb) fprintf(stderr, "PRELOOP: RepartNotify: 0x%lx %d idx=%d\n", win2, n1, idx); - if (idx >= 0) { - DELETE(idx); - } - if (! ev_lookup(win2, EV_CREATE)) { - xselectinput(win2, 0, 1); - nxsel++; - } - } - } - } - } - if (nxsel == 0) { - break; - } - } - - X_UNLOCK; - - if (got_NET_CURRENT_DESKTOP > 0.0) { - if (dnow() < got_NET_CURRENT_DESKTOP + 0.25) { - if (ncdb) fprintf(stderr, "***got_NET_CURRENT_DESKTOP n=%d\n", n); - desktop_change = 1; - n_DC++; - } else { - if (ncdb) fprintf(stderr, "***got_NET_CURRENT_DESKTOP n=%d STALE\n", n); - } - got_NET_CURRENT_DESKTOP = 0.0; - } - - if (n == 0) { - check_sched(try_batch, &did_sched); - return 0; - } -if (ncdb) fprintf(stderr, "\n"); if (ncdb) rfbLog("IN check_ncache() %d events. %.4f\n", n, now - x11vnc_start); - - if (try_batch) { - use_batch = 1; - } - - if (rotating) { - use_batch = 0; - } - if (cursor_noshape_updates_clients(screen)) { - use_batch = 0; - } - - if (! use_batch) { - nbatch = NULL; - } else { - nreg = 0; - nbatch = &nreg; - } - - /* XXX Y */ - for (n1 = 0; n1 < n; n1++) { - Window twin = Ev_map[n1]; - if (twin == None || twin == rootwin) { - continue; - } - for (n2 = 0; n2 < n; n2++) { - if (Ev_unmap[n2] == twin) { - if (skipwins_n < skipwins_max) { -if (ncdb) fprintf(stderr, "SKIPWINS: Ev_unmap/map: 0x%lx %d\n", twin, n2); - skipwins[skipwins_n++] = twin; - break; - } - } - } - } - - if (!desktop_change) { - if (skipwins_n) { - if (n_MN + n_UN >= 2 + 2*skipwins_n) { - desktop_change = 1; - n_DC++; - } - } else { - if (n_MN + n_UN >= 3) { - desktop_change = 1; - n_DC++; - } - } - } - if (ncache_old_wm) { - int shifts = 0; - for (i=0; i < n; i++) { - XEvent ev; - int type, idx = -1; - int ik = Ev_order[i]; - int x_new, y_new, w_new, h_new; - int x_old, y_old, w_old, h_old; - int old_wm = 0; - - if (Ev_done[ik]) continue; - win = Ev_win[ik]; - - ev = Ev[ik]; - type = ev.type; - if (type != ConfigureNotify) { - continue; - } - if (ev_lookup(win, EV_MAP)) { - continue; - } else if (ev_lookup(win, EV_UNMAP)) { - continue; - } else if (ev_lookup(win, EV_DESTROY)) { - continue; - } - - idx = lookup_win_index(win); - if (idx < 0) { - continue; - } - x_new = ev.xconfigure.x; - y_new = ev.xconfigure.y; - w_new = ev.xconfigure.width; - h_new = ev.xconfigure.height; - - x_old = cache_list[idx].x; - y_old = cache_list[idx].y; - w_old = cache_list[idx].width; - h_old = cache_list[idx].height; - - if (w_new == w_old && h_new == h_old) { - if (nabs(x_new - x_old) >= dpy_x || nabs(y_new - y_old) >= dpy_y) { - sraRegionPtr r_old, r_new, r0; - r0 = sraRgnCreateRect(0, 0, dpy_x, dpy_y); - r_old = sraRgnCreateRect(x_old, y_old, x_old+w_old, y_old+h_old); - sraRgnAnd(r_old, r0); - r_new = sraRgnCreateRect(x_new, y_new, x_new+w_new, y_new+h_new); - sraRgnAnd(r_new, r0); - if (cache_list[idx].map_state != IsViewable) { - ev_store(win, EV_OLD_WM_NOTMAPPED); - } else if (sraRgnEmpty(r_old) && !sraRgnEmpty(r_new)) { - old_wm = 1; - ev_store(win, EV_OLD_WM_MAP); - Ev_map[i] = win; - } else if (!sraRgnEmpty(r_old) && sraRgnEmpty(r_new)) { - ev_store(win, EV_OLD_WM_UNMAP); - old_wm = -1; - Ev_unmap[i] = win; - } else { - ev_store(win, EV_OLD_WM_OFF); - } - sraRgnDestroy(r_old); - sraRgnDestroy(r_new); - sraRgnDestroy(r0); - shifts++; -if (ncdb) fprintf(stderr, "old_wm[%d] +%04d+%04d +%04d+%04d old_wm: %d\n", i, x_old, y_old, x_new, y_new, old_wm); - } - } - } - if (shifts >= 3) { -if (ncdb) fprintf(stderr, "DESKTOP_CHANGE_OLD_WM: %d\n", shifts); - desktop_change = 1; - desktop_change_old_wm = 1; - } - } - -#define SKIPUMS \ - ok = 1; \ - if (twin == None || twin == rootwin) { \ - continue; \ - } \ - for (ns = 0; ns < skipwins_n; ns++) { \ - if (skipwins[ns] == twin) { \ - ok = 0; \ - break; \ - } \ - } - - if (desktop_change) { - Window twin; - int ok, s, k, add, cnt, ns; - - cnt = 0; - add = 0; - for (i=0; i < n; i++) { - twin = Ev_unmap[i]; - SKIPUMS - if (ok) { -if (ncdb) fprintf(stderr, "U Ev_tmp[%d] = %d\n", cnt, i); - Ev_tmp[cnt++] = i; - } - } - for (i=0; i < n; i++) { - twin = Ev_map[i]; - SKIPUMS - if (ok) { -if (ncdb) fprintf(stderr, "M Ev_tmp[%d] = %d\n", cnt, i); - Ev_tmp[cnt++] = i; - } - } - for (k = 0; k < cnt; k++) { - Ev_tmp2[k] = -1; - } - /* unmap from top to bottom */ - for (s = old_stack_n - 1; s >= 0; s--) { - twin = old_stack[s]; - if (twin == None || twin == rootwin) { - continue; - } - for (k = 0; k < cnt; k++) { - i = Ev_tmp[k]; - if (twin == Ev_unmap[i]) { -if (ncdb) fprintf(stderr, "U Ev_tmp2[%d] = %d\n", add, i); - Ev_tmp2[add++] = i; - break; - } - } - } - /* map from bottom to top */ - for (s = 0; s < old_stack_n; s++) { - twin = old_stack[s]; - if (twin == None || twin == rootwin) { - continue; - } - for (k = 0; k < cnt; k++) { - i = Ev_tmp[k]; - if (twin == Ev_map[i]) { -if (ncdb) fprintf(stderr, "M Ev_tmp2[%d] = %d\n", add, i); - Ev_tmp2[add++] = i; - break; - } - } - } - k = 0; - for (i=0; i < n; i++) { - Window wu, wm; - int j; - int oku = 0, okm = 0; - wu = Ev_unmap[i]; - wm = Ev_map[i]; - ok = 0; - if (wu != None && wu != rootwin) oku = 1; - if (wm != None && wm != rootwin) okm = 1; - if (!oku && !okm) { - continue; - } - if (oku) { - twin = wu; - SKIPUMS - if (!ok) { - oku = 0; - } - } - if (okm) { - twin = wm; - SKIPUMS - if (!ok) { - okm = 0; - } - } - if (!oku && !okm) { - continue; - } - j = Ev_tmp2[k++]; - if (j >= 0) { -if (ncdb) fprintf(stderr, "UM Ev_order[%d] = %d oku=%d okm=%d\n", i, j, oku, okm); - Ev_order[i] = j; - } - } - } - -#if 0 - if (desktop_change) { - Window twin; - int ok, s, k, add, cnt, ns; - - cnt = 0; - add = 0; - for (i=0; i < n; i++) { - twin = Ev_unmap[i]; - SKIPUMS - if (ok) { - Ev_tmp[cnt++] = i; - } - } - for (k = 0; k < cnt; k++) { - Ev_tmp2[k] = -1; - } - /* unmap from top to bottom */ - for (s = old_stack_n - 1; s >= 0; s--) { - twin = old_stack[s]; - for (k = 0; k < cnt; k++) { - i = Ev_tmp[k]; - if (twin == Ev_unmap[i]) { - Ev_tmp2[add++] = i; - break; - } - } - } - k = 0; - for (i=0; i < n; i++) { - int j; - twin = Ev_unmap[i]; - SKIPUMS - if (ok) { - j = Ev_tmp2[k++]; - if (j >= 0) { - Ev_order[i] = j; - } - } - } - - cnt = 0; - add = 0; - for (i=0; i < n; i++) { - twin = Ev_map[i]; - SKIPUMS - if (ok) { - Ev_tmp[cnt++] = i; - } - } - for (k = 0; k < cnt; k++) { - Ev_tmp2[k] = -1; - } - /* map from bottom to top */ - for (s = 0; s < old_stack_n; s++) { - twin = old_stack[s]; - for (k = 0; k < cnt; k++) { - i = Ev_tmp[k]; - if (twin == Ev_map[i]) { - Ev_tmp2[add++] = i; - break; - } - } - } - k = 0; - for (i=0; i < n; i++) { - int j; - twin = Ev_map[i]; - SKIPUMS - if (ok) { - j = Ev_tmp2[k++]; - if (j >= 0) { - Ev_order[i] = j; - } - } - } - } -#endif - - if (!desktop_change && (n_VN_p && !n_UN && (n_MN || n_ON_st))) { - if (now < last_vis_unobs_time + 0.75 || now < last_vis_obs_time + 0.75) { - ; - } else if (n_MN <= 2 && n_ON_st <= 1) { - for (i=0; i < n; i++) { - XEvent ev; - int type, idx = -1, state, valid; - int ik = Ev_order[i]; - - if (Ev_done[ik]) continue; - win = Ev_win[ik]; - - ev = Ev[ik]; - type = ev.type; - if (type != VisibilityNotify) { - continue; - } - - state = ev.xvisibility.state; - if (state == VisibilityUnobscured) { - continue; - } - if (ev_lookup(win, EV_MAP)) { - continue; - } else if (ev_lookup(win, EV_UNMAP)) { - continue; - } else if (ev_lookup(win, EV_DESTROY)) { - continue; - } - idx = lookup_win_index(win); - - if (idx < 0) { - continue; - } - if (cache_list[idx].vis_state == VisibilityFullyObscured) { - continue; - } - if (now < cache_list[idx].vis_unobs_time + 3.00 || now < cache_list[idx].vis_obs_time + 3.00) { - continue; - } - -if (ncdb) fprintf(stderr, "----%02d: VisibilityNotify 0x%lx %3d (*PRELOOP*) state: %s U/P %d/%d\n", ik, win, idx, VState(state), n_VN_u, n_VN_p); - valid = 0; - bs_save(idx, nbatch, &attr, 1, 0, &valid, 1); - if (valid) { - STORE(idx, win, attr); - } else { - DELETE(idx); - } - - cache_list[idx].vis_state = state; - cache_list[idx].vis_obs_time = last_vis_obs_time = dnow(); - Ev_done[ik] = 1; - } - } - } - if (desktop_change) { - if (ncache_dt_change) { - if (ncdb) fprintf(stderr, "GUESSED DESKTOP CHANGE.\n"); - saw_desktop_change = 1; - } else { - if (ncdb) fprintf(stderr, "GUESSED DESKTOP CHANGE. Skipping.\n"); - desktop_change = 0; - } - } - - - create_cnt = 0; - missed_su_restore = 0; - missed_bs_restore = 0; - missed_su_restore_rgn = sraRgnCreate(); - missed_bs_restore_rgn = sraRgnCreate(); - r0 = sraRgnCreateRect(0, 0, dpy_x, dpy_y); - unmapped_rgn = sraRgnCreate(); - su_fix_cnt = 0; - -for (k = 0; k < skipwins_n; k++) { - if (ncdb) fprintf(stderr, "skipwins[%d] 0x%lx\n", k, skipwins[k]); -} - - X_LOCK; - for (i=0; i < n; i++) { - XEvent ev; - int ns, skip = 0, type, idx = -1; - int ik = Ev_order[i]; - - if (Ev_done[ik]) continue; - win = Ev_win[ik]; - - ev = Ev[ik]; - type = ev.type; - Ev_done[ik] = 1; - - win2 = win; - if (win == rootwin) { - if (type == CreateNotify) { - win2 = ev.xcreatewindow.window; - } else if (type == ReparentNotify) { - win2 = ev.xreparent.window; - } - } - for (ns = 0; ns < skipwins_n; ns++) { - if (win2 == skipwins[ns]) { - skip = 1; - break; - } - } - if (skip) { -if (ncdb) fprintf(stderr, "skip%02d: ** SpecialSkip 0x%lx/0x%lx type: %s\n", ik, win, win2, Etype(type)); - continue; - } - - if (win == rootwin) { - if (type == CreateNotify) { - int x=0, y=0, w=0, h=0; - valid = 0; - win2 = ev.xcreatewindow.window; - idx = lookup_win_index(win2); - if (idx < 0) { - continue; - } - if (cache_list[idx].valid) { - valid = 1; - x=cache_list[idx].x; - y=cache_list[idx].y; - w=cache_list[idx].width; - h=cache_list[idx].height; - if (w*h > 64 * 64 && ev_lookup(win2, EV_MAP)) { - X_UNLOCK; - valid = 1; - su_save(idx, nbatch, &attr, 0, &valid, 1); - STORE(idx, win2, attr); - - X_LOCK; - - if (! desktop_change) { - SCHED(win2, 1) - } - create_cnt++; - } - } -if (ncdb) fprintf(stderr, "root%02d: ** CreateNotify 0x%lx %3d -- %dx%d+%d+%d valid=%d\n", ik, win2, idx, w, h, x, y, valid); - - } else if (type == ReparentNotify) { - if (ev.xreparent.parent != rootwin) { - win2 = ev.xreparent.window; - idx = lookup_win_index(win2); -if (ncdb) fprintf(stderr, "root%02d: ReparentNotifyRM 0x%lx %3d\n", ik, win2, idx); - } - } else { -if (ncdb) fprintf(stderr, "root%02d: ** IgnoringRoot 0x%lx type: %s\n", ik, win, Etype(type)); - } - } else { - if (type == ConfigureNotify) { - int x_new, y_new, w_new, h_new; - int x_old, y_old, w_old, h_old; - int stack_change, old_wm = 0; - Window oabove = None; - - idx = lookup_win_index(win); - - if (idx >= 0) { - oabove = cache_list[idx].above; - } - -if (ncdb) fprintf(stderr, "----%02d: ConfigureNotify 0x%lx %3d -- above: 0x%lx -> 0x%lx %dx%d+%d+%d\n", ik, win, idx, - oabove, ev.xconfigure.above, ev.xconfigure.width, ev.xconfigure.height, ev.xconfigure.x, ev.xconfigure.y); - - if (idx < 0) { - continue; - } - - x_new = ev.xconfigure.x; - y_new = ev.xconfigure.y; - w_new = ev.xconfigure.width; - h_new = ev.xconfigure.height; - - x_old = cache_list[idx].x; - y_old = cache_list[idx].y; - w_old = cache_list[idx].width; - h_old = cache_list[idx].height; - - if (desktop_change_old_wm) { - if (ev_lookup(win, EV_OLD_WM_MAP)) { - if (Ev_map[ik] == win) { - old_wm = 1; - } else { - old_wm = 2; - } - } else if (ev_lookup(win, EV_OLD_WM_UNMAP)) { - if (Ev_unmap[ik] == win) { - old_wm = -1; - } else { - old_wm = 2; - } - } else if (ev_lookup(win, EV_OLD_WM_OFF)) { - old_wm = 2; - } else if (ev_lookup(win, EV_OLD_WM_NOTMAPPED)) { - old_wm = 3; - } - } - - if (!old_wm) { - if (x_old != x_new || y_old != y_new) { - /* invalidate su */ - cache_list[idx].su_time = 0.0; -if (ncdb) fprintf(stderr, " INVALIDATE su: 0x%lx xy: +%d+%d +%d+%d \n", win, x_old, y_old, x_new, y_new); - } - if (w_old != w_new || h_old != h_new) { - /* invalidate bs */ - cache_list[idx].bs_time = 0.0; -if (ncdb) fprintf(stderr, " INVALIDATE bs: 0x%lx wh: %dx%d %dx%d \n", win, w_old, h_old, w_new, h_new); - } - } else { - int valid; - X_UNLOCK; - if (old_wm == 1) { - /* XXX Y */ -if (ncdb) fprintf(stderr, " OLD_WM_MAP: 0x%lx wh: %dx%d+%d+%d %dx%d+%d+%d \n", win, w_old, h_old, x_old, y_old, w_new, h_new, x_new, y_new); - valid = 0; - bs_restore(idx, nbatch, NULL, &attr, 0, 0, &valid, 1); - - } else if (old_wm == -1) { -if (ncdb) fprintf(stderr, " OLD_WM_UNMAP: 0x%lx wh: %dx%d+%d+%d %dx%d+%d+%d \n", win, w_old, h_old, x_old, y_old, w_new, h_new, x_new, y_new); - valid = 1; - su_restore(idx, nbatch, NULL, &attr, 1, 0, &valid, 1); - } else { -if (ncdb) fprintf(stderr, " OLD_WM_OFF:: 0x%lx wh: %dx%d+%d+%d %dx%d+%d+%d old_wm=%d\n", win, w_old, h_old, x_old, y_old, w_new, h_new, x_new, y_new, old_wm); - } - X_LOCK; - } - - stack_change = 0; - if (old_wm) { - ; - } else if (cache_list[idx].above != ev.xconfigure.above) { - stack_change = 1; - } else if (x_new == x_old && y_new == y_old && w_new == w_old && h_new == h_old) { - stack_change = 1; - } - if (stack_change) { - int i2, ok = 1; - for (i2=0; i2 < n; i2++) { - if (Ev_map[i2] == win) { - ok = 0; - break; - } - } - if (ok) { - if (n_MN == 0 && n_UN == 0) { - if (su_fix_cnt > 0) { - ok = 0; -if (ncdb) fprintf(stderr, " CONF_IGNORE: Too many stacking changes: 0x%lx\n", win); - } - } - - } - if (ok) { - if (ev_lookup(ev.xconfigure.above, EV_UNMAP)) { - if (ncdb) fprintf(stderr, " skip try_to_fix_su for GNOME deiconify #1\n"); - if (dt_gnome) { - gnome_animation = 1; - } - ok = 0; - } - } - if (ok && dt_gnome) { - if (valid_window(ev.xconfigure.above, &attr, 1)) { - if (attr.map_state != IsViewable) { - if (ncdb) fprintf(stderr, " skip try_to_fix_su for GNOME deiconify #2\n"); - gnome_animation = 1; - ok = 0; - } - } - } - if (ok) { - int rc = try_to_fix_su(win, idx, ev.xconfigure.above, nbatch, NULL); - if (rc == 0 && su_fix_cnt == 0 && n_MN == 0 && n_UN == 0) { - X_UNLOCK; - try_to_synthesize_su(1, 1, nbatch); - X_LOCK; - } - n_ST++; - su_fix_cnt++; - } - } - - cache_list[idx].x = x_new; - cache_list[idx].y = y_new; - cache_list[idx].width = w_new; - cache_list[idx].height = h_new; - - cache_list[idx].above = ev.xconfigure.above; - cache_list[idx].time = dnow(); - - } else if (type == VisibilityNotify) { - int state = ev.xvisibility.state; - idx = lookup_win_index(win); -if (ncdb) fprintf(stderr, "----%02d: VisibilityNotify 0x%lx %3d state: %s U/P %d/%d\n", ik, win, idx, VState(state), n_VN_u, n_VN_p); - - if (idx < 0) { - continue; - } - if (desktop_change) { - ; - } else if (macosx_console && n_VN_p == 0) { - ; /* XXXX not working well yet with UnmapNotify ... */ - } else if (state == VisibilityUnobscured) { - int ok = 1; - if (ncache <= 2) { - ok = 0; - } else if (ev_lookup(win, EV_MAP)) { - ok = 0; - } else if (ev_lookup(win, EV_UNMAP)) { - ok = 0; - } else if (ev_lookup(win, EV_DESTROY)) { - ok = 0; - } else if (gnome_animation) { - ok = 0; - } else { - /* this is for gnome iconify */ - int i2; - for (i2=i+1; i2 < n; i2++) { - int idx2, ik2 = Ev_order[i2]; - sraRegionPtr ro1, ro2; - Window win2 = Ev_unmap[ik2]; - - if (win2 == None) { - continue; - } - idx2 = lookup_win_index(win2); - if (idx2 < 0) { - continue; - } - - ro1 = idx_create_rgn(r0, idx); - ro2 = idx_create_rgn(r0, idx2); - - if (sraRgnAnd(ro1, ro2)) { - if (ncdb) fprintf(stderr, " skip VisibilityUnobscured for GNOME iconify.\n"); - ok = 0; - } - sraRgnDestroy(ro1); - sraRgnDestroy(ro2); - if (! ok) { - break; - } - } - } - if (ok) { - int x2, y2, w2, h2; - sraRegionPtr rmask = NULL; - valid = 0; - if (dnow() < cache_list[idx].vis_unobs_time + 3.00 && !sraRgnEmpty(unmapped_rgn)) { - x2 = cache_list[idx].x; - y2 = cache_list[idx].y; - w2 = cache_list[idx].width; - h2 = cache_list[idx].height; - rmask = sraRgnCreateRect(x2, y2, x2+w2, y2+h2); - sraRgnAnd(rmask, unmapped_rgn); - if (sraRgnEmpty(rmask)) { - sraRgnDestroy(rmask); - rmask = NULL; - } - } - if (ev_lookup(win, EV_CONFIGURE_SIZE)) { - valid = valid_window(win, &attr, 1); - } else { - X_UNLOCK; - bs_restore(idx, nbatch, rmask, &attr, 0, 1, &valid, 1); - X_LOCK; - } - if (rmask != NULL) { - sraRgnDestroy(rmask); - } - if (valid) { - STORE(idx, win, attr); - - cache_list[idx].time = dnow(); - cache_list[idx].vis_cnt++; - Ev_map[ik] = win; - Ev_rects[nrects].x1 = cache_list[idx].x; - Ev_rects[nrects].y1 = cache_list[idx].y; - Ev_rects[nrects].x2 = cache_list[idx].width; - Ev_rects[nrects].y2 = cache_list[idx].height; - nrects++; - SCHED(win, 1) - } else { - DELETE(idx); - } - } - } - if (state == VisibilityUnobscured) { - cache_list[idx].vis_unobs_time = last_vis_unobs_time = dnow(); - } else if (cache_list[idx].vis_state == VisibilityUnobscured) { - cache_list[idx].vis_obs_time = last_vis_obs_time = dnow(); - } - cache_list[idx].vis_state = state; - - } else if (type == MapNotify) { - idx = lookup_win_index(win); -if (ncdb) fprintf(stderr, "----%02d: MapNotify 0x%lx %3d\n", ik, win, idx); - - if (idx < 0) { - continue; - } - -#if 0 -/* - if (cache_list[idx].map_state == IsUnmapped || desktop_change || macosx_console) - */ -#endif - if (1) { - X_UNLOCK; - if (desktop_change) { - /* XXX Y */ - int save = 1; - sraRegionPtr r; - if (cache_list[idx].su_time != 0.0) { - save = 0; - } else if (missed_su_restore) { - r = idx_create_rgn(r0, idx); - if (sraRgnAnd(r, missed_su_restore_rgn)) { - save = 0; - } - sraRgnDestroy(r); - } - if (missed_bs_restore) { - r = idx_create_rgn(r0, idx); - if (sraRgnAnd(r, missed_bs_restore_rgn)) { - save = 0; - } - sraRgnDestroy(r); - } - if (save) { - valid = 0; - su_save(idx, nbatch, &attr, 1, &valid, 1); - if (valid) { - STORE(idx, win, attr); - } - } - } else { - valid = 0; - su_save(idx, nbatch, &attr, 0, &valid, 1); - if (valid) { - STORE(idx, win, attr); - } - } - valid = 0; - if (ev_lookup(win, EV_CONFIGURE_SIZE)) { - X_LOCK; - valid = valid_window(win, &attr, 1); - X_UNLOCK; - idx_add_rgn(missed_bs_restore_rgn, r0, idx); - missed_bs_restore++; - } else if (bs_restore(idx, nbatch, NULL, &attr, 0, 0, &valid, 1)) { /* XXX clip? */ - ; - } else { - idx_add_rgn(missed_bs_restore_rgn, r0, idx); - missed_bs_restore++; - } - if (valid) { - STORE(idx, win, attr); - } - - if (macosx_console) { -#ifdef MACOSX - macosxCGS_follow_animation_win(win, -1, 1); - if (valid_window(win, &attr, 1)) { - STORE(idx, win, attr); - SCHED(win, 1); - } - /* XXX Y */ - if (cache_list[idx].vis_state == -1) { - cache_list[idx].vis_state = VisibilityUnobscured; - } -#endif - } - X_LOCK; - pixels += cache_list[idx].width * cache_list[idx].height; - cache_list[idx].time = dnow(); - cache_list[idx].map_cnt++; - Ev_map[ik] = win; - Ev_rects[nrects].x1 = cache_list[idx].x; - Ev_rects[nrects].y1 = cache_list[idx].y; - Ev_rects[nrects].x2 = cache_list[idx].width; - Ev_rects[nrects].y2 = cache_list[idx].height; - nrects++; - - if (! valid) { - DELETE(idx); - } - } - cache_list[idx].map_state = IsViewable; - - } else if (type == UnmapNotify) { - int x2, y2, w2, h2; - idx = lookup_win_index(win); -if (ncdb) fprintf(stderr, "----%02d: UnmapNotify 0x%lx %3d\n", ik, win, idx); - - if (idx < 0) { - continue; - } - if (macosx_console) { - if (mode == 2) { - cache_list[idx].map_state = IsViewable; - } - } - -#if 0 -/* - if (cache_list[idx].map_state == IsViewable || desktop_change || macosx_console) - */ -#endif - if (1) { - X_UNLOCK; - if (desktop_change) { - int save = 1; - sraRegionPtr r; - if (cache_list[idx].bs_time > 0.0) { - save = 0; - } else if (missed_su_restore) { - r = idx_create_rgn(r0, idx); - if (sraRgnAnd(r, missed_su_restore_rgn)) { - save = 0; - } - sraRgnDestroy(r); - } - if (missed_bs_restore) { - r = idx_create_rgn(r0, idx); - if (sraRgnAnd(r, missed_bs_restore_rgn)) { - save = 0; - } - sraRgnDestroy(r); - } - if (save) { - valid = 0; - bs_save(idx, nbatch, &attr, 1, 0, &valid, 1); - } - } else { - valid = 0; - bs_save(idx, nbatch, &attr, 1, 0, &valid, 1); - } - valid = 0; - if (su_restore(idx, nbatch, NULL, &attr, 1, 0, &valid, 1)) { - try_to_fix_su(win, idx, None, nbatch, "unmapped"); - if (valid) { - STORE(idx, win, attr); - } else { - DELETE(idx); - } - } else { - idx_add_rgn(missed_su_restore_rgn, r0, idx); - missed_su_restore++; - } - X_LOCK; - - pixels += cache_list[idx].width * cache_list[idx].height; - cache_list[idx].time = dnow(); - cache_list[idx].unmap_cnt++; - Ev_unmap[ik] = win; - Ev_rects[nrects].x1 = cache_list[idx].x; - Ev_rects[nrects].y1 = cache_list[idx].y; - Ev_rects[nrects].x2 = cache_list[idx].width; - Ev_rects[nrects].y2 = cache_list[idx].height; - nrects++; - } - - x2 = cache_list[idx].x; - y2 = cache_list[idx].y; - w2 = cache_list[idx].width; - h2 = cache_list[idx].height; - r = sraRgnCreateRect(x2, y2, x2+w2, y2+h2); - sraRgnAnd(r, r0); - sraRgnOr(unmapped_rgn, r); - sraRgnDestroy(r); - - cache_list[idx].map_state = IsUnmapped; - - } else if (type == ReparentNotify) { - if (ev.xreparent.parent != rootwin) { - win2 = ev.xreparent.window; - if (win2 != rootwin) { - idx = lookup_win_index(win2); -if (ncdb) fprintf(stderr, "----%02d: ReparentNotifyRM 0x%lx %3d\n", ik, win2, idx); - } - } - - } else if (type == DestroyNotify) { - win2 = ev.xdestroywindow.window; - idx = lookup_win_index(win2); -if (ncdb) fprintf(stderr, "----%02d: DestroyNotify 0x%lx %3d\n", ik, win2, idx); - - if (idx >= 0) { - DELETE(idx); - } - } else { -if (ncdb) fprintf(stderr, "igno%02d: ** Ignoring 0x%lx type: %s\n", ik, win, Etype(type)); - } - - } - } - X_UNLOCK; - - if (use_batch && nreg) { - batch_push(nreg, -1.0); - } - if (nrects) { - if (scaling) { - push_borders(Ev_rects, nrects); - } - } - - check_sched(try_batch, &did_sched); - - if (n_CN || n_RN || n_DN || n_MN || n_UN || n_ST || n_DC || did_sched) { - snap_old(); - } - - sraRgnDestroy(r0); - sraRgnDestroy(missed_su_restore_rgn); - sraRgnDestroy(missed_bs_restore_rgn); - -if (ncdb) rfbLog("OUT check_ncache(): %.4f %.6f events: %d pixels: %d\n", dnowx(), dnow() - now, n, pixels); -if (ncdb) fprintf(stderr, "\n"); - return pixels; -} -#endif - |