From c88d830f5591913f2e5e763814978e2877f367ec Mon Sep 17 00:00:00 2001 From: runge Date: Tue, 2 Jan 2007 05:15:07 +0000 Subject: [PATCH] x11vnc: more -ncache improvements. --- x11vnc/ChangeLog | 3 + x11vnc/README | 92 +-- x11vnc/help.c | 30 +- x11vnc/options.c | 20 +- x11vnc/options.h | 9 + x11vnc/remote.c | 30 + x11vnc/scan.c | 2 +- x11vnc/ssltools.h | 2 +- x11vnc/tkx11vnc | 22 +- x11vnc/tkx11vnc.h | 22 +- x11vnc/user.c | 6 + x11vnc/userinput.c | 1370 ++++++++++++++++++++++++++++++++++++------ x11vnc/x11vnc.1 | 40 +- x11vnc/x11vnc.c | 16 +- x11vnc/x11vnc.h | 4 + x11vnc/x11vnc_defs.c | 6 +- x11vnc/xevents.c | 25 +- x11vnc/xevents.h | 1 + 18 files changed, 1437 insertions(+), 263 deletions(-) diff --git a/x11vnc/ChangeLog b/x11vnc/ChangeLog index cbcfa9d..f86d22c 100644 --- a/x11vnc/ChangeLog +++ b/x11vnc/ChangeLog @@ -1,3 +1,6 @@ +2007-01-01 Karl Runge + * x11vnc: more -ncache improvements. + 2006-12-28 Karl Runge * x11vnc: more work on -ncache, add macosx support, fix X errors and improve cache expiration algorithm. diff --git a/x11vnc/README b/x11vnc/README index 80eb701..1e3e08f 100644 --- a/x11vnc/README +++ b/x11vnc/README @@ -1,5 +1,5 @@ -x11vnc README file Date: Fri Dec 29 01:37:39 EST 2006 +x11vnc README file Date: Mon Jan 1 21:04:46 EST 2007 The following information is taken from these URLs: @@ -9262,7 +9262,7 @@ x11vnc: a VNC server for real X displays Here are all of x11vnc command line options: % x11vnc -opts (see below for -help long descriptions) -x11vnc: allow VNC connections to real X11 displays. 0.8.4 lastmod: 2006-12-29 +x11vnc: allow VNC connections to real X11 displays. 0.8.4 lastmod: 2007-01-01 x11vnc options: -display disp -auth file -id windowid @@ -9308,34 +9308,34 @@ x11vnc options: -noalphablend -nocursorshape -cursorpos -nocursorpos -xwarppointer -noxwarppointer -buttonmap string -nodragging -ncache n - -ncache_cr -ncache_pad n -wireframe [str] - -nowireframe -nowireframelocal -wirecopyrect mode - -nowirecopyrect -debug_wireframe -scrollcopyrect mode - -noscrollcopyrect -scr_area n -scr_skip list - -scr_inc list -scr_keys list -scr_term list - -scr_keyrepeat lo-hi -scr_parms string -fixscreen string - -debug_scroll -noxrecord -grab_buster - -nograb_buster -debug_grabs -debug_sel - -pointer_mode n -input_skip n -allinput - -speeds rd,bw,lat -wmdt string -debug_pointer - -debug_keyboard -defer time -wait time - -wait_ui factor -nowait_bog -slow_fb time - -readtimeout n -nap -nonap - -sb time -nofbpm -fbpm - -nodpms -dpms -noxdamage - -xd_area A -xd_mem f -sigpipe string - -threads -nothreads -fs f - -gaps n -grow n -fuzz n - -debug_tiles -snapfb -rawfb string - -freqtab file -pipeinput cmd -macnodim - -macnosleep -macnosaver -macnowait - -macwheel n -macnoswap -macnoresize - -maciconanim n -macmenu -gui [gui-opts] - -remote command -query variable -QD variable - -sync -noremote -yesremote - -unsafe -safer -privremote - -nocmds -allowedcmds list -deny_all - + -ncache_cr -ncache_no_moveraise -ncache_no_dtchange + -ncache_pad n -wireframe [str] -nowireframe + -nowireframelocal -wirecopyrect mode -nowirecopyrect + -debug_wireframe -scrollcopyrect mode -noscrollcopyrect + -scr_area n -scr_skip list -scr_inc list + -scr_keys list -scr_term list -scr_keyrepeat lo-hi + -scr_parms string -fixscreen string -debug_scroll + -noxrecord -grab_buster -nograb_buster + -debug_grabs -debug_sel -pointer_mode n + -input_skip n -allinput -speeds rd,bw,lat + -wmdt string -debug_pointer -debug_keyboard + -defer time -wait time -wait_ui factor + -nowait_bog -slow_fb time -readtimeout n + -nap -nonap -sb time + -nofbpm -fbpm -nodpms + -dpms -noxdamage -xd_area A + -xd_mem f -sigpipe string -threads + -nothreads -fs f -gaps n + -grow n -fuzz n -debug_tiles + -snapfb -rawfb string -freqtab file + -pipeinput cmd -macnodim -macnosleep + -macnosaver -macnowait -macwheel n + -macnoswap -macnoresize -maciconanim n + -macmenu -gui [gui-opts] -remote command + -query variable -QD variable -sync + -noremote -yesremote -unsafe + -safer -privremote -nocmds + -allowedcmds list -deny_all libvncserver options: -rfbport port TCP port for RFB protocol @@ -9369,7 +9369,7 @@ libvncserver-tight-extension options: % x11vnc -help -x11vnc: allow VNC connections to real X11 displays. 0.8.4 lastmod: 2006-12-29 +x11vnc: allow VNC connections to real X11 displays. 0.8.4 lastmod: 2007-01-01 (type "x11vnc -opts" to just list the options.) @@ -11388,7 +11388,7 @@ Options: better results than the 'Genie' one. Also, window event detection not as accurate as the X version. --ncache_cr In -nache mode, try do to copyrect opaque window +-ncache_cr In -ncache mode, try to do copyrect opaque window moves/drags instead of wireframes (this can induce painting errors). The wireframe will still be used when moving a window whose save-unders has not yet been set @@ -11399,7 +11399,18 @@ Options: smoother drags than tightvnc viewer. Response may also be choppy if the server side machine is too slow. --ncache_pad n In -nache mode, pad each window with n pixels for the +-ncache_no_moveraise In -ncache mode, do not assume that moving a window + will cause the window manager to raise it to the top + of the stack. The default is to assume it does, and + so at the beginning of any wireframe, etc, window moves + the window will be pushed to top in the VNC viewer. + +-ncache_no_dtchange In -ncache mode, do not try to guess when the desktop + (viewport) changes to another one (i.e. another + workarea). The default is to try to guess and when + detected try to make the transistion more smoothly. + +-ncache_pad n In -ncache mode, pad each window with n pixels for the caching rectangles. This can be used to try to improve the situation with dropshadows or other compositing (e.g. MacOS X window manager), although it could make @@ -12656,6 +12667,8 @@ n ncache_size:n set -ncache size to n. ncache_cr enable -ncache_cr mode. noncache_cr disable -ncache_cr mode. + ncache_no_moveraise enable no_moveraise mode. + noncache_no_moveraise disable no_moveraise mode. wireframe enable -wireframe mode. same as "wf" nowireframe disable -wireframe mode. same as "nowf" wireframe:str enable -wireframe mode string. @@ -12817,12 +12830,13 @@ n bell nobell sel nosel primary noprimary setprimary nosetprimary clipboard noclipboard setclipboard nosetclipboard seldir cursorshape nocursorshape - cursorpos nocursorpos cursor_drag nocursor_drag cursor - show_cursor noshow_cursor nocursor arrow xfixes noxfixes - xdamage noxdamage xd_area xd_mem alphacut alphafrac - alpharemove noalpharemove alphablend noalphablend - xwarppointer xwarp noxwarppointer noxwarp buttonmap - dragging nodragging ncache_cr noncache_cr ncache + cursorpos nocursorpos cursor_drag nocursor_drag + cursor show_cursor noshow_cursor nocursor arrow + xfixes noxfixes xdamage noxdamage xd_area xd_mem + alphacut alphafrac alpharemove noalpharemove alphablend + noalphablend xwarppointer xwarp noxwarppointer noxwarp + buttonmap dragging nodragging ncache_cr noncache_cr + ncache_no_moveraise noncache_no_moveraise ncache noncache ncache_size wireframe_mode wireframe wf nowireframe nowf wireframelocal wfl nowireframelocal nowfl wirecopyrect wcr nowirecopyrect nowcr scr_area diff --git a/x11vnc/help.c b/x11vnc/help.c index 6592407..d4c9aad 100644 --- a/x11vnc/help.c +++ b/x11vnc/help.c @@ -2053,7 +2053,7 @@ void print_help(int mode) { " better results than the 'Genie' one. Also, window event\n" " detection not as accurate as the X version.\n" "\n" -"-ncache_cr In -nache mode, try do to copyrect opaque window\n" +"-ncache_cr In -ncache mode, try to do copyrect opaque window\n" " moves/drags instead of wireframes (this can induce\n" " painting errors). The wireframe will still be used when\n" " moving a window whose save-unders has not yet been set\n" @@ -2064,7 +2064,18 @@ void print_help(int mode) { " smoother drags than tightvnc viewer. Response may also\n" " be choppy if the server side machine is too slow.\n" "\n" -"-ncache_pad n In -nache mode, pad each window with n pixels for the\n" +"-ncache_no_moveraise In -ncache mode, do not assume that moving a window\n" +" will cause the window manager to raise it to the top\n" +" of the stack. The default is to assume it does, and\n" +" so at the beginning of any wireframe, etc, window moves\n" +" the window will be pushed to top in the VNC viewer.\n" +"\n" +"-ncache_no_dtchange In -ncache mode, do not try to guess when the desktop\n" +" (viewport) changes to another one (i.e. another\n" +" workarea). The default is to try to guess and when\n" +" detected try to make the transistion more smoothly.\n" +"\n" +"-ncache_pad n In -ncache mode, pad each window with n pixels for the\n" " caching rectangles. This can be used to try to improve\n" " the situation with dropshadows or other compositing\n" " (e.g. MacOS X window manager), although it could make\n" @@ -3329,6 +3340,8 @@ void print_help(int mode) { " ncache_size:n set -ncache size to n.\n" " ncache_cr enable -ncache_cr mode.\n" " noncache_cr disable -ncache_cr mode.\n" +" ncache_no_moveraise enable no_moveraise mode.\n" +" noncache_no_moveraise disable no_moveraise mode.\n" " wireframe enable -wireframe mode. same as \"wf\"\n" " nowireframe disable -wireframe mode. same as \"nowf\"\n" " wireframe:str enable -wireframe mode string.\n" @@ -3488,12 +3501,13 @@ void print_help(int mode) { " bell nobell sel nosel primary noprimary setprimary\n" " nosetprimary clipboard noclipboard setclipboard\n" " nosetclipboard seldir cursorshape nocursorshape\n" -" cursorpos nocursorpos cursor_drag nocursor_drag cursor\n" -" show_cursor noshow_cursor nocursor arrow xfixes noxfixes\n" -" xdamage noxdamage xd_area xd_mem alphacut alphafrac\n" -" alpharemove noalpharemove alphablend noalphablend\n" -" xwarppointer xwarp noxwarppointer noxwarp buttonmap\n" -" dragging nodragging ncache_cr noncache_cr ncache\n" +" cursorpos nocursorpos cursor_drag nocursor_drag\n" +" cursor show_cursor noshow_cursor nocursor arrow\n" +" xfixes noxfixes xdamage noxdamage xd_area xd_mem\n" +" alphacut alphafrac alpharemove noalpharemove alphablend\n" +" noalphablend xwarppointer xwarp noxwarppointer noxwarp\n" +" buttonmap dragging nodragging ncache_cr noncache_cr\n" +" ncache_no_moveraise noncache_no_moveraise ncache\n" " noncache ncache_size wireframe_mode wireframe wf\n" " nowireframe nowf wireframelocal wfl nowireframelocal\n" " nowfl wirecopyrect wcr nowirecopyrect nowcr scr_area\n" diff --git a/x11vnc/options.c b/x11vnc/options.c index f25582f..fcb1961 100644 --- a/x11vnc/options.c +++ b/x11vnc/options.c @@ -197,16 +197,26 @@ int wireframe_local = 1; #ifndef NCACHE #define NCACHE -10 #endif -int ncache = NCACHE; -int ncache0 = 0; -int ncache_copyrect = 0; -int macosx_ncache_macmenu = 0; -int ncache_beta_tester = 0; #ifdef MACOSX +int ncache = 0; int ncache_pad = 24; #else +int ncache = NCACHE; int ncache_pad = 0; #endif +int ncache0 = 0; +int ncache_copyrect = 0; +int ncache_wf_raises = 1; +int ncache_dt_change = 1; +int macosx_ncache_macmenu = 0; +int ncache_beta_tester = 0; + +Atom atom_NET_ACTIVE_WINDOW = None; +Atom atom_NET_CURRENT_DESKTOP = None; +Atom atom_NET_CLIENT_LIST_STACKING = None; +double got_NET_ACTIVE_WINDOW = 0.0; +double got_NET_CURRENT_DESKTOP = 0.0; +double got_NET_CLIENT_LIST_STACKING = 0.0; /* T+B+L+R,tkey+presist_key,tmouse+persist_mouse */ char *scroll_copyrect_str = NULL; diff --git a/x11vnc/options.h b/x11vnc/options.h index 856df15..cc53a29 100644 --- a/x11vnc/options.h +++ b/x11vnc/options.h @@ -159,10 +159,19 @@ extern int wireframe_in_progress; extern int ncache; extern int ncache0; extern int ncache_copyrect; +extern int ncache_wf_raises; +extern int ncache_dt_change; extern int ncache_pad; extern int macosx_ncache_macmenu; extern int ncache_beta_tester; +extern Atom atom_NET_ACTIVE_WINDOW; +extern Atom atom_NET_CURRENT_DESKTOP; +extern Atom atom_NET_CLIENT_LIST_STACKING; +extern double got_NET_ACTIVE_WINDOW; +extern double got_NET_CURRENT_DESKTOP; +extern double got_NET_CLIENT_LIST_STACKING; + extern char *scroll_copyrect_str; extern char *scroll_copyrect; extern char *scroll_copyrect_default; diff --git a/x11vnc/remote.c b/x11vnc/remote.c index 775816c..64a6369 100644 --- a/x11vnc/remote.c +++ b/x11vnc/remote.c @@ -2748,6 +2748,36 @@ char *process_remote_cmd(char *cmd, int stringonly) { ncache_copyrect = 0; rfbLog("remote_cmd: disabled -ncache_cr %d\n", ncache_copyrect); + } else if (!strcmp(p, "ncache_no_moveraise")) { + if (query) { + snprintf(buf, bufn, "ans=%s:%d", p, !ncache_wf_raises); + goto qry; + } + ncache_wf_raises = 0; + rfbLog("remote_cmd: set -ncache_no_moveraise\n"); + } else if (!strcmp(p, "noncache_no_moveraise")) { + if (query) { + snprintf(buf, bufn, "ans=%s:%d", p, ncache_wf_raises); + goto qry; + } + ncache_wf_raises = 1; + rfbLog("remote_cmd: disabled -ncache_no_moveraise\n"); + + } else if (!strcmp(p, "ncache_no_dtchange")) { + if (query) { + snprintf(buf, bufn, "ans=%s:%d", p, !ncache_dt_change); + goto qry; + } + ncache_dt_change = 0; + rfbLog("remote_cmd: set -ncache_no_dt_change\n"); + } else if (!strcmp(p, "noncache_no_dtchange")) { + if (query) { + snprintf(buf, bufn, "ans=%s:%d", p, ncache_dt_change); + goto qry; + } + ncache_dt_change = 1; + rfbLog("remote_cmd: disabled -ncache_no_dt_change\n"); + } else if (!strcmp(p, "ncache")) { if (query) { snprintf(buf, bufn, "ans=%s:%d", p, !!ncache); diff --git a/x11vnc/scan.c b/x11vnc/scan.c index 7ffc24f..a05d063 100644 --- a/x11vnc/scan.c +++ b/x11vnc/scan.c @@ -2897,7 +2897,7 @@ if (ncache > 0) { nomsg = 0; } } else { -fprintf(stderr, "*** SCAN_DISPLAY CHECK_NCACHE/%d *** %d rescan=%d\n", gotone, y, rescan); +fprintf(stderr, "\n*** SCAN_DISPLAY CHECK_NCACHE/%d *** %d rescan=%d\n", gotone, y, rescan); } X_UNLOCK; check_ncache(0, 1); diff --git a/x11vnc/ssltools.h b/x11vnc/ssltools.h index 06520ab..dc38ef7 100644 --- a/x11vnc/ssltools.h +++ b/x11vnc/ssltools.h @@ -829,7 +829,7 @@ char find_display[] = char create_display[] = "#!/bin/sh\n" "\n" -"CREATE_DISPLAY_OUTPUT=/tmp/cdo.txt\n" +"#CREATE_DISPLAY_OUTPUT=/tmp/cdo.txt\n" "if [ \"X$CREATE_DISPLAY_EXEC\" = \"X\" ]; then\n" " CREATE_DISPLAY_EXEC=1\n" " export CREATE_DISPLAY_EXEC\n" diff --git a/x11vnc/tkx11vnc b/x11vnc/tkx11vnc index 6974778..d0ce05a 100755 --- a/x11vnc/tkx11vnc +++ b/x11vnc/tkx11vnc @@ -360,6 +360,13 @@ Tuning xd_area: xd_mem: =GAL LOFF + =GAL Ncache:: + ncache + ncache_size: + ncache_cr + ncache_no_moveraise + ncache_no_dtchange + =GAL LOFF -- =GAL SharedMemory:: noshm @@ -381,10 +388,6 @@ Tuning rfbwait: nodpms nofbpm - -- - ncache - ncache_size: - ncache_cr =GAL LOFF " } @@ -1054,6 +1057,17 @@ changed regions. Nevertheless, x11vnc uses the DAMAGE information very effectively as hints to improve its performance. The items in the sub-menu allow tweaking x11vnc's DAMAGE algorithm. +" + + set helptext(Ncache:) " +A simple client-side (viewer) caching scheme is enabled with the +\"-ncache n\" option. It simply uses \"n\" framebuffer sized areas +below the actual display for caching window pixel data. + +Drawbacks are it uses a lot of RAM (roughly n times more), and the +pixels cache area is visible in the viewers. + +The items in the sub-menu allow tweaking x11vnc's -ncache algorithm. " set helptext(SharedMemory:) " diff --git a/x11vnc/tkx11vnc.h b/x11vnc/tkx11vnc.h index 593637e..823e026 100644 --- a/x11vnc/tkx11vnc.h +++ b/x11vnc/tkx11vnc.h @@ -371,6 +371,13 @@ char gui_code[] = ""; " xd_area:\n" " xd_mem:\n" " =GAL LOFF\n" +" =GAL Ncache::\n" +" ncache\n" +" ncache_size:\n" +" ncache_cr\n" +" ncache_no_moveraise\n" +" ncache_no_dtchange\n" +" =GAL LOFF\n" " --\n" " =GAL SharedMemory::\n" " noshm\n" @@ -392,10 +399,6 @@ char gui_code[] = ""; " rfbwait:\n" " nodpms\n" " nofbpm\n" -" --\n" -" ncache\n" -" ncache_size:\n" -" ncache_cr\n" " =GAL LOFF\n" "\"\n" "}\n" @@ -1067,6 +1070,17 @@ char gui_code[] = ""; "The items in the sub-menu allow tweaking x11vnc's DAMAGE algorithm.\n" "\"\n" "\n" +" set helptext(Ncache:) \"\n" +"A simple client-side (viewer) caching scheme is enabled with the\n" +"\\\"-ncache n\\\" option. It simply uses \\\"n\\\" framebuffer sized areas\n" +"below the actual display for caching window pixel data. \n" +"\n" +"Drawbacks are it uses a lot of RAM (roughly n times more), and the\n" +"pixels cache area is visible in the viewers.\n" +"\n" +"The items in the sub-menu allow tweaking x11vnc's -ncache algorithm.\n" +"\"\n" +"\n" " set helptext(SharedMemory:) \"\n" "This sub-menu provides some options regarding SYSV shared memory usage\n" "(shm) by x11vnc. Usually you want shm turned on because the x11vnc\n" diff --git a/x11vnc/user.c b/x11vnc/user.c index cf7cbe4..1a2bbd8 100644 --- a/x11vnc/user.c +++ b/x11vnc/user.c @@ -1235,6 +1235,7 @@ int wait_for_client(int *argc, char** argv, int http) { char *create_cmd = NULL; char *users_list_save = NULL; int created_disp = 0; + int ncache_save; if (! use_dpy || strstr(use_dpy, "WAIT:") != use_dpy) { return 0; @@ -1341,6 +1342,9 @@ int wait_for_client(int *argc, char** argv, int http) { *argc = (*argc) + 1; } + ncache_save = ncache; + ncache = 0; + initialize_allowed_input(); if (! multiple_cursors_mode) { @@ -1745,6 +1749,8 @@ if (db) fprintf(stderr, "xauth_raw_len: %d\n", n); free(create_cmd); } + ncache = ncache_save; + return 1; } diff --git a/x11vnc/userinput.c b/x11vnc/userinput.c index 4099ca5..57a302a 100644 --- a/x11vnc/userinput.c +++ b/x11vnc/userinput.c @@ -80,8 +80,8 @@ 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 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 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); @@ -1369,7 +1369,7 @@ if (n) { \ int batch_dxs[], batch_dys[]; sraRegionPtr batch_reg[]; -void batch_copyregion(sraRegionPtr* region, int *dx, int *dy, int ncr, double delay); +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) { @@ -1568,7 +1568,7 @@ if (db > 1) fprintf(stderr, "------------ got: %d x: %4d y: %3d" if (fast_push) { int k, nbatch = 0; double delay, d1 = 0.1, d2 = 0.02; - rc = try_copyrect(frame, x, y, w, h, dx, dy, &obscured, + rc = try_copyrect(frame, frame, x, y, w, h, dx, dy, &obscured, tmpregion, waittime, &nbatch); if (first_push) { @@ -1577,13 +1577,10 @@ if (db > 1) fprintf(stderr, "------------ got: %d x: %4d y: %3d" delay = d2; } - batch_copyregion(batch_reg, batch_dxs, batch_dys, nbatch, delay); - for (k=0; k < nbatch; k++) { - sraRgnDestroy(batch_reg[k]); - } + batch_push(nbatch, delay); fb_push(); } else { - rc = try_copyrect(frame, x, y, w, h, dx, dy, &obscured, + rc = try_copyrect(frame, frame, x, y, w, h, dx, dy, &obscured, tmpregion, waittime, NULL); if (rc) { last_scroll_type = type; @@ -1972,19 +1969,43 @@ if (0) fprintf(stderr, "s... %d %d %d %d %d %d\n", sx1, sy1, sx2, sy2, sdx, sdy) void batch_copyregion(sraRegionPtr* region, int *dx, int *dy, int ncr, double delay) { rfbClientIteratorPtr i; rfbClientPtr cl; - int k, direct, mode, nrects = 0; + int k, direct, mode, nrects = 0, bad = 0; /* XXX Y */ + 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) { + 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) { + 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; } fb_push_wait(delay, FB_COPY|FB_MOD); - for (k=0; k < ncr; k++) { - nrects += sraRgnCountRects(region[k]); - } - i = rfbGetClientIterator(screen); while( (cl = rfbClientIteratorNext(i)) ) { rfbFramebufferUpdateMsg *fu = (rfbFramebufferUpdateMsg *)cl->updateBuf; @@ -2022,6 +2043,14 @@ fprintf(stderr, "batch_copyregion: nrects: %d nregions: %d\n", nrects, ncr); } +void batch_push(int nreg, double delay) { + int k; + batch_copyregion(batch_reg, batch_dxs, batch_dys, nreg, delay); + for (k=0; k < nreg; k++) { + sraRgnDestroy(batch_reg[k]); + } +} + void fb_push0(void) { char *httpdir = screen->httpDir; int defer = screen->deferUpdateTime; @@ -3041,8 +3070,8 @@ if (0) fprintf(stderr, "check_xrecord: button_mask: %d mouse_wants_back_in: %d\ int batch_dxs[NBATCHMAX], batch_dys[NBATCHMAX]; sraRegionPtr batch_reg[NBATCHMAX]; -static int try_copyrect(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 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; @@ -3075,7 +3104,7 @@ static int try_copyrect(Window frame, int x, int y, int w, int h, int dx, int dy */ if (time(NULL) > dt_bad_check + 5) { char *dt = guess_desktop(); - if (!strcmp(dt, "kde")) { + if (!strcmp(dt, "kde_maybe_is_ok_now...")) { dt_bad = 1; } else if (!strcmp(dt, "xfce")) { dt_bad = 1; @@ -3093,7 +3122,10 @@ static int try_copyrect(Window frame, int x, int y, int w, int h, int dx, int dy x -= off_x; y -= off_y; } -if (db2) fprintf(stderr, "try_copyrect: 0x%lx bad: %d stack_list_num: %d\n", frame, dt_bad, stack_list_num); +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; @@ -3171,16 +3203,13 @@ if (db2) fprintf(stderr, "moved_win: %4d %3d, %4d %3d 0x%lx ---\n", swin = stack_list[k].win; if (db2) fprintf(stderr, "sw: %d/%lx\n", k, swin); - if (swin == frame) { + if (swin == frame || swin == orig_frame) { if (db2) { saw_me = 1; fprintf(stderr, " ----------\n"); } else { break; } } -#if 0 -fprintf(stderr, "bo: %d/%lx\n", k, swin); -#endif /* skip some unwanted cases: */ #ifndef MACOSX @@ -3224,6 +3253,7 @@ fprintf(stderr, "bo: %d/%lx\n", k, swin); 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; @@ -3544,29 +3574,32 @@ static sraRegionPtr NPP_roffscreen = NULL; static sraRegionPtr NPP_r_bs_tmp = NULL; static Window NPP_nwin = None; -void clear_win_events(void) { +void clear_win_events(Window win, int vis) { #if !NO_X11 - if (dpy && NPP_nwin != None) { + if (dpy && win != None && ncache) { XEvent ev; XErrorHandler old_handler; old_handler = XSetErrorHandler(trap_xerror); trapped_xerror = 0; - while (XCheckTypedWindowEvent(dpy, NPP_nwin, ConfigureNotify, &ev)) { + while (XCheckTypedWindowEvent(dpy, win, ConfigureNotify, &ev)) { fprintf(stderr, "."); if (trapped_xerror) { break; } trapped_xerror = 0; } - while (XCheckTypedWindowEvent(dpy, NPP_nwin, VisibilityNotify, &ev)) { - fprintf(stderr, "+"); - if (trapped_xerror) { - break; +/* XXX Y */ + if (vis) { + while (XCheckTypedWindowEvent(dpy, win, VisibilityNotify, &ev)) { + fprintf(stderr, "+"); + if (trapped_xerror) { + break; + } + trapped_xerror = 0; } - trapped_xerror = 0; } XSetErrorHandler(old_handler); - fprintf(stderr, " 0x%x\n", (unsigned int) NPP_nwin); + fprintf(stderr, " 0x%x\n", (unsigned int) win); } #endif } @@ -3962,11 +3995,7 @@ void ncache_post_portions(int nidx, int use_batch, int orig_x, int orig_y, int o sraRgnDestroy(r1); if (use_batch) { - int k; - batch_copyregion(batch_reg, batch_dxs, batch_dys, NPP_nreg, batch_delay); - for (k=0; k < NPP_nreg; k++) { - sraRgnDestroy(batch_reg[k]); - } + batch_push(NPP_nreg, batch_delay); 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); } @@ -3978,11 +4007,7 @@ fprintf(stderr, "FB_COPY: %.4f XX did batch 0x%x %3d su: %dx%d+%d+%d bs: %dx%d+ } } else { if (use_batch) { - int k; - batch_copyregion(batch_reg, batch_dxs, batch_dys, NPP_nreg, batch_delay); - for (k=0; k < NPP_nreg; k++) { - sraRgnDestroy(batch_reg[k]); - } + batch_push(NPP_nreg, batch_delay); } } @@ -4126,6 +4151,58 @@ void check_macosx_click_frame(void) { #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; + + 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; +fprintf(stderr, "--YES, wf_raise\n"); + if (try_batch) { + nb = &nr; + } + bs_restore(idx, nb, 0, 1, 1, 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 (no) fprintf(stderr, "--NO, wf_raise: %s\n", no); + } + if (ncache_wf_raises) { + snapshot_stack_list(0, 0.0); + snap_old(); + } +} + +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 @@ -4244,7 +4321,11 @@ if (db) fprintf(stderr, "NO get_wm_frame_pos-1: 0x%lx\n", frame); return 0; } X_UNLOCK; -if (db) fprintf(stderr, "a: %d wf: %.3f A: %d frm: 0x%lx\n", w*h, wireframe_frac, (dpy_x*dpy_y), frame); + + 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 @@ -4378,7 +4459,7 @@ if (db) fprintf(stderr, "INTERIOR\n"); XFlush_wr(dpy); X_UNLOCK; - /* try do induce/waitfor some more user input */ + /* try to induce/waitfor some more user input */ if (use_threads) { usleep(1000); } else if (drew_box && do_copyrect_drag != 1) { @@ -4609,17 +4690,20 @@ fprintf(stderr, "*** NO GPI DRAW_BOX\n"); } else if (w != box_w || h != box_h) { do_copyrect_drag = 0; } else if (do_copyrect_drag < 0) { - int idx = lookup_win_index(orig_frame); + Window fr = orig_frame; + int idx = lookup_win_index(fr); if (idx < 0) { - idx = lookup_win_index(frame); + fr = frame; + idx = lookup_win_index(fr); } if (idx >= 0) { - if (cache_list[idx].su_time > 0.0) { - /* XXX Y */ + do_copyrect_drag = set_copyrect_drag(idx, fr, try_batch); + if (do_copyrect_drag) { min_draw *= 0.66; - do_copyrect_drag = 1; } nidx = idx; + } else { + do_copyrect_drag = 0; } now_x = orig_x; now_y = orig_y; @@ -4631,8 +4715,18 @@ fprintf(stderr, "*** NO GPI DRAW_BOX\n"); } } - drew_box = 1; if (do_copyrect_drag <= 0) { + 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); @@ -4648,6 +4742,8 @@ fprintf(stderr, "*** NO GPI DRAW_BOX\n"); } #endif } + drew_box = 1; + last_wireframe = dnow(); last_draw = spin; last_draw_cnt = cnt; @@ -4712,11 +4808,17 @@ if (db || db2) fprintf(stderr, "NO button_mask\n"); } 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); + clear_win_events(orig_frame, 1); + if (frame != orig_frame) { + clear_win_events(frame, 1); + } + } } else if (dx == 0 && dy == 0) { ; } else if (do_copyrect_drag > 0) { - clear_win_events(); + clear_win_events(NPP_nwin, 0); } else { int spin_ms = (int) (spin * 1000 * 1000); int obscured, sent_copyrect = 0; @@ -4758,16 +4860,16 @@ fprintf(stderr, "FB_COPY failed again! %.4f", dnow() - ntim); /* 2) try to send a clipped copyrect of translation: */ if (! try_batch) { - sent_copyrect = try_copyrect(frame, x, y, w, h, dx, dy, + sent_copyrect = try_copyrect(orig_frame, frame, x, y, w, h, dx, dy, &obscured, NULL, 0.15, NULL); } else { - try_copyrect(frame, x, y, w, h, dx, dy, + 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 (db) fprintf(stderr, "sent_copyrect: %d - obs: %d frame: 0x%lx\n", sent_copyrect, obscured, frame); +if (1 || db) 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) { @@ -4781,7 +4883,7 @@ if (db) fprintf(stderr, "sent_copyrect: %d - obs: %d frame: 0x%lx\n", sent_copy #ifndef NO_NCACHE ncache_post_portions(nidx, use_batch, orig_x, orig_y, orig_w, orig_h, x, y, w, h, -1.0, ntim); - clear_win_events(); + clear_win_events(NPP_nwin, 0); #endif if (scaling && !use_batch) { @@ -5415,10 +5517,8 @@ if (debug_scroll && rc > 1) fprintf(stderr, " CXR: check_user_input ret %d\n", if (wireframe) { if (check_wireframe()) { -fprintf(stderr, "check_wireframe: 1\n"); return 0; } -//fprintf(stderr, "check_wireframe: 0\n"); } if (pointer_mode == 1) { @@ -5583,6 +5683,56 @@ void snapshot_cache_list(int free_only, double allowed_age) { #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) { @@ -5698,6 +5848,63 @@ 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); + 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) \ cache_list[k].win = w; \ cache_list[k].fetched = 1; \ @@ -6292,7 +6499,6 @@ int find_rect(int idx, int x, int y, int w, int h) { rect_reg[n] = sraRgnCreateRect(0, n * dpy_y, dpy_x, (n+1) * dpy_y); } } else if (now > last_clean + 60) { -//fprintf(stderr, "free_rect: cleaning up regions:\n"); last_clean = now; for (n = 1; n < ncache; n += 2) { int i, n2 = n+1; @@ -6384,7 +6590,7 @@ fprintf(stderr, ">>**--**>> BIG1 rect: %dx%d+%d+%d -- %d %d\n", w, h, x, y, x_hi fr_BIG1t++; return 0; } - if (w == dpy_x && h && dpy_y) { + if (w == dpy_x && h == dpy_y) { 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++; @@ -6573,21 +6779,124 @@ int valid_wr(int idx, Window win, XWindowAttributes *attr) { return valid_window(win, attr, 1); } -int bs_save(int idx, int *nbatch, int verb) { +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)) { +//fprintf(stderr, "clip[0x%x]: 0x%x, %d/%d\n", win, cache_list[idx2].win, ic, idx2); + clip = 1; + } + sraRgnDestroy(r2); + if (clip) { + break; + } + } + sraRgnDestroy(r0); + sraRgnDestroy(r1); +//fprintf(stderr, "clip[0x%x]: %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; + +//fprintf(stderr, "----[0x%x]: 0x%x, %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); +//fprintf(stderr, "clip[0x%x]: 0x%x, %d/%d\n", win, cache_list[idx2].win, ic, idx2); + } + sraRgnDestroy(r1); + } +} + +int bs_save(int idx, int *nbatch, int clip, int only_if_tracking, int verb) { Window win = cache_list[idx].win; XWindowAttributes attr; int x1, y1, w1, h1; int x2, y2, w2, h2; int x, y, w, h; int dx, dy, rc = 1; - sraRegionPtr r, r0; + sraRegionPtr r, r0, r1; x1 = cache_list[idx].x; y1 = cache_list[idx].y; w1 = cache_list[idx].width; h1 = cache_list[idx].height; -if (verb) fprintf(stderr, "backingstore save: 0x%x %3d \n", (unsigned int) win, idx); + if (only_if_tracking && cache_list[idx].bs_x < 0) { + return; + } + +if (verb) fprintf(stderr, "backingstore save: 0x%x %3d clip=%d\n", (unsigned int) win, idx, clip); X_LOCK; if (! valid_wr(idx, win, &attr)) { @@ -6635,12 +6944,17 @@ fprintf(stderr, "BS_save: FAIL FOR: %d\n", idx); y2 -= coff_y; } - dx = x - x2; - dy = y - y2; - 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); + } + + dx = x - x2; + dy = y - y2; + sraRgnOffset(r, dx, dy); dtA = dnowx(); @@ -6660,7 +6974,7 @@ if (verb) fprintf(stderr, "BS_save: %.4f %.2f %d done. %dx%d+%d+%d %dx%d+%d+%d return 1; } -int su_save(int idx, int *nbatch, int verb) { +int su_save(int idx, int *nbatch, int clip, int verb) { Window win = cache_list[idx].win; XWindowAttributes attr; int x1, y1, w1, h1; @@ -6721,12 +7035,17 @@ fprintf(stderr, "SU_save: FAIL FOR: %d\n", idx); y2 -= coff_y; } - dx = x - x2; - dy = y - y2; - 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); + } + + dx = x - x2; + dy = y - y2; + sraRgnOffset(r, dx, dy); dtA = dnowx(); @@ -6746,7 +7065,7 @@ if (verb) fprintf(stderr, "SU_save: %.4f %.2f %d done. %dx%d+%d+%d %dx%d+%d+%d return 1; } -int bs_restore(int idx, int *nbatch, int nopad, int verb) { +int bs_restore(int idx, int *nbatch, int clip, int nopad, int novalidate, int verb) { Window win = cache_list[idx].win; XWindowAttributes attr; int x1, y1, w1, h1; @@ -6763,7 +7082,12 @@ if (verb) fprintf(stderr, "backingstore restore: 0x%x %3d \n", (unsigned int h1 = cache_list[idx].height; X_LOCK; - if (! valid_wr(idx, win, &attr)) { + if (novalidate) { + attr.x = x1; + attr.y = y1; + attr.width = w1; + attr.height = h1; + } else if (! valid_wr(idx, win, &attr)) { fprintf(stderr, "BS_restore: not a valid X window: 0x%x\n", (unsigned int) win); DELETE(idx); X_UNLOCK; @@ -6782,7 +7106,9 @@ fprintf(stderr, "BS_restore: not a valid X window: 0x%x\n", (unsigned int) win); h = cache_list[idx].bs_h; if (x < 0 || cache_list[idx].bs_time == 0.0) { - STORE(idx, win, attr); + if (!novalidate) { + STORE(idx, win, attr); + } return 0; } @@ -6805,9 +7131,6 @@ fprintf(stderr, "BS_restore: not a valid X window: 0x%x\n", (unsigned int) win); y2 -= coff_y; } - dx = x2 - x; - dy = y2 - y; - if (w2 > w) { w2 = w; } @@ -6817,9 +7140,17 @@ fprintf(stderr, "BS_restore: not a valid X window: 0x%x\n", (unsigned int) win); 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); + } + dtA = dnowx(); if (verb) fprintf(stderr, "BS_rest: %.4f %d dx=%d dy=%d\n", dtA, idx, dx, dy); if (w2 > 0 && h2 > 0) { @@ -6831,12 +7162,14 @@ if (verb) fprintf(stderr, "BS_rest: %.4f %.2f %d done. %dx%d+%d+%d %dx%d+%d+%d sraRgnDestroy(r0); sraRgnDestroy(r); - STORE(idx, win, attr); + if (!novalidate) { + STORE(idx, win, attr); + } return 1; } -int su_restore(int idx, int *nbatch, int nopad, int verb) { +int su_restore(int idx, int *nbatch, int clip, int nopad, int verb) { Window win = cache_list[idx].win; XWindowAttributes attr; int x1, y1, w1, h1; @@ -6901,9 +7234,6 @@ fprintf(stderr, "SU_rest: su_x/bs_x/su_time: %d %d %.3f\n", x, cache_list[idx].b y2 -= coff_y; } - dx = x2 - x; - dy = y2 - y; - if (w2 > w) { w2 = w; } @@ -6913,9 +7243,17 @@ fprintf(stderr, "SU_rest: su_x/bs_x/su_time: %d %d %.3f\n", x, cache_list[idx].b 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); + } + dtA = dnowx(); if (verb) fprintf(stderr, "SU_rest: %.4f %d dx=%d dy=%d\n", dtA, idx, dx, dy); if (w2 > 0 && h2 > 0) { @@ -6929,11 +7267,10 @@ if (verb) fprintf(stderr, "SU_rest: %.4f %.2f %d done. %dx%d+%d+%d %dx%d+%d+%d if (invalid) { DELETE(idx); - return 0; } else { STORE(idx, win, attr); - return 1; } + return 1; } void check_zero_rects(void) { @@ -7051,7 +7388,7 @@ void block_stats(void) { fprintf(stderr, "\n"); } -#define NSCHED 64 +#define NSCHED 128 Window sched_bs[NSCHED]; double sched_tm[NSCHED]; double last_sched_bs = 0.0; @@ -7142,40 +7479,419 @@ Bool xcheckmaskevent(Display *d, long mask, XEvent *ev) { #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_win[EVMAX]; Window Ev_map[EVMAX]; Window Ev_unmap[EVMAX]; sraRect Ev_rects[EVMAX]; -int check_ncache(int reset, int mode) { - static double last_root = 0.0; - static int first = 1; - static int last_client_count = -1; - int i, k, n; - 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; +int tmp_stack[STACKMAX]; +sraRegionPtr tmp_reg[STACKMAX]; - double now, refresh = 60.0; - Window win, win2; - XWindowAttributes attr; - unsigned long all_ev = SubstructureNotifyMask|StructureNotifyMask|VisibilityChangeMask; - unsigned long win_ev = StructureNotifyMask|VisibilityChangeMask; +#define CLEAN_OUT \ + for (i=0; i < n; i++) { \ + sraRgnDestroy(tmp_reg[i]); \ + } \ + sraRgnDestroy(r1); \ + sraRgnDestroy(r0); - int try_batch = 1; /* XXX Y */ - int use_batch = 0; - int nreg = 0, *nbatch; - static int didtopmost = 0; - int create_cnt, create_tot; - int pixels = 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) { - int nrects = 0; + int idx = lookup_win_index(orig_frame); + sraRegionPtr r0, r1, r2, r3; + int sx1, sy1, sw1, sh1, dx, dy; + int sx2, sy2, sw2, sh2; + int bx1, by1, bw1, bh1; + int bx2, by2, bw2, bh2; + int nr = 0, *nbat = NULL; -#ifdef MACOSX - if (! macosx_console) { - RAWFB_RET(-1) + if (idx < 0) { + return 0; } -#else + 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) { + +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; + cache_list[idx].su_time = dnow(); + } else { +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; + cache_list[idx].su_time = dnow(); + } + } + + sraRgnDestroy(r0); + sraRgnDestroy(r1); + sraRgnDestroy(r2); +} + +int try_to_fix_su(Window win, int idx, Window above, int *nbatch, char *mode) { + int i, idx2, n = 0, found = 0; + sraRegionPtr r0, r1, r2, r3; + 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; + +fprintf(stderr, "TRY_TO_FIX_SU(%d) 0x%x 0x%x unmapped=%d\n", idx, win, above, unmapped); + + if (mode && !strcmp(mode, "unmapped")) { + unmapped = 1; + } else if (mode && !strcmp(mode, "moved")) { + moved = 1; + } + + if (idx < 0) { + return 0; + } + 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) { +fprintf(stderr, "0x%x turn on: 0x%x\n", win, win2); + on = 1; + } + if (win2 == win) { +fprintf(stderr, "0x%x turn off: 0x%x\n", win, win2); + 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 1; + } + + 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 1; +} + +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; +} + +int check_ncache(int reset, int mode) { + static double last_root = 0.0; + static int first = 1; + static int last_client_count = -1; + int i, k, n; + 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; + int did_sched = 0; + + double now, refresh = 60.0; + Window win, win2; + XWindowAttributes attr; + unsigned long all_ev = SubstructureNotifyMask|StructureNotifyMask|VisibilityChangeMask; + unsigned long win_ev = StructureNotifyMask|VisibilityChangeMask; + + int try_batch = 1; /* XXX Y */ + int use_batch = 0; + int nreg = 0, *nbatch; + int create_cnt, create_tot; + int pixels = 0, ttot; + int desktop_change = 0, n1, n2; + static int saw_desktop_change = 0; + int missed_su_restore = 0; + int missed_bs_restore = 0; + sraRegionPtr r0, r; + sraRegionPtr missed_su_restore_rgn; + sraRegionPtr missed_bs_restore_rgn; + + int nrects = 0; + + int skipwins_n = 0; + int skipwins_max = 16; + Window skipwins[16]; + + if (unixpw_in_progress) return -1; + +#ifdef MACOSX + if (! macosx_console) { + RAWFB_RET(-1) + } +#else RAWFB_RET(-1) #endif @@ -7188,7 +7904,7 @@ int check_ncache(int reset, int mode) { if (ncache0) { if (reset) { ; - } else if (! client_count || !ncache || nofb) { + } 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) { @@ -7241,6 +7957,8 @@ if (c) fprintf(stderr, "check_ncache purged %d events\n", c); } 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); + + snap_old(); return -1; } @@ -7290,16 +8008,16 @@ if (c) fprintf(stderr, "check_ncache purged %d events\n", c); } snapshot_cache_list(0, 100.0); -fprintf(stderr, "cache_list_num: %d\n", cache_list_num); for (i=0; i < cache_list_num; i++) { CLEAR(i); } for (n = 1; n <= ncache; n++) { rect_reg[n] = NULL; } + snap_old(); } - if (now < last_client + 2) { + if (now < last_client + 4) { return -1; } @@ -7322,7 +8040,6 @@ if (hack_val == 2) { #endif if (now > last_root + refresh) { - Window topmapped = None; fprintf(stderr, "\n**** checking cache_list[%d]\n\n", cache_list_num); block_stats(); @@ -7337,7 +8054,6 @@ fprintf(stderr, "\n**** checking cache_list[%d]\n\n", cache_list_num); ; } else if (valid_window(win, &attr, 1)) { STORE(k, win, attr); -//fprintf(stderr, "STORE(%2d) %03dx%03d+%03d+%03d\n", k, cache_list[k].width, cache_list[k].height, cache_list[k].x, cache_list[k].y); if (! cache_list[k].selectinput) { xselectinput(win, win_ev, 0); CLEAR(k); @@ -7345,9 +8061,6 @@ fprintf(stderr, "\n**** checking cache_list[%d]\n\n", cache_list_num); } else { ; } - if (attr.map_state == IsViewable) { - topmapped = win; - } valid = 1; } else { 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); @@ -7365,32 +8078,44 @@ fprintf(stderr, "Created window never mapped: freeing(%d) 0x%x\n", k, (unsigned } } last_root = dnow(); - if (0 && ! didtopmost && topmapped != None) { - int idx = lookup_win_index(topmapped); - if (idx >= 0) { - if (! macosx_console) { - bs_save(idx, NULL, 1); - } - } - } - didtopmost = 1; } check_zero_rects(); - if (now > last_sched_bs + 0.2) { + 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.65) { + if (now < sched_tm[i] + 0.55) { continue; } idx = lookup_win_index(win); @@ -7404,39 +8129,68 @@ fprintf(stderr, "Created window never mapped: freeing(%d) 0x%x\n", k, (unsigned } else if (aw * ah < 64 * 64) { ; } else { -fprintf(stderr, "*SNAP BS_save: 0x%x %d %d %d\n", (unsigned int) win, aw, ah, cache_list[idx].map_state); - bs_save(idx, bat, 0); +//fprintf(stderr, "*SNAP BS_save: 0x%x %d %d %d\n", (unsigned int) win, aw, ah, cache_list[idx].map_state); + bs_save(idx, bat, 1, 0, 0); } } } sched_bs[i] = None; } - if (nr) { - int k; - batch_copyregion(batch_reg, batch_dxs, batch_dys, nr, -1.0); - for (k=0; k < nr; k++) { - sraRgnDestroy(batch_reg[k]); - } - } - last_sched_bs = dnow(); + did_sched = 1; - if (now > last_sched_vis + 3.0) { + if (now > last_sched_vis + 3.0 && now > last_wireframe + 2.0) { for (i=0; i < cache_list_num; i++) { - if (cache_list[i].map_state == IsViewable) { + Window win = cache_list[i].win; + int ok = 0; + int top_only = 1; + int aw = cache_list[i].width; + int ah = cache_list[i].height; + + if (saw_desktop_change) { + top_only = 0; + } + + if (win == None) { + continue; + } + if (!valid_window(win, &attr, 1)) { + continue; + } + STORE(i, win, attr); + if (!cache_list[i].valid) { + continue; + } + if (cache_list[i].map_state != IsViewable) { + continue; + } + if (aw * ah < 64 * 64) { + continue; + } + if (top_only) { if (cache_list[i].vis_state == VisibilityUnobscured) { - if (cache_list[i].valid) { - if (cache_list[i].win != None) { - SCHED(cache_list[i].win, 0) - } - } + ok = 1; + } else if (!clipped(i)) { + ok = 1; } + } else { + ok = 1; + } + if (ok) { + bs_save(i, bat, !top_only, 0, 0); } } last_sched_vis = dnow(); + saw_desktop_change = 0; + } + + if (nr) { + batch_push(nr, -1.0); } + last_sched_bs = dnow(); } n = 0; + ttot = 0; create_tot = 0; X_LOCK; @@ -7445,18 +8199,25 @@ fprintf(stderr, "*SNAP BS_save: 0x%x %d %d %d\n", (unsigned int) win, aw, ah, ca win = Ev[n].xany.window; Ev_done[n] = 0; Ev_area[n] = 0; - Ev_win[n] = None; + Ev_win[n] = win; Ev_map[n] = None; Ev_unmap[n] = None; + Ev_order[n] = n; + +//fprintf(stderr, "----- %d/%d inputev 0x%x %s\n", n, ttot++, win, Etype(type)); if (win == rootwin) { if (type == CreateNotify) { - n++; create_tot++; + n++; n_CN++; } else if (type == ReparentNotify) { n++; n_RN++; + } else if (type == PropertyNotify) { + set_prop_atom(Ev[n].xproperty.atom); + n++; + n_PN++; } else { /* skip rest */ #if 0 @@ -7489,9 +8250,11 @@ if (type != ConfigureNotify) fprintf(stderr, "root: skip %s for 0x%x\n", Etype( n++; n_VN++; } else if (type == MapNotify) { + Ev_map[n] = win; n++; n_MN++; } else if (type == UnmapNotify) { + Ev_unmap[n] = win; n++; n_UN++; } else { @@ -7505,16 +8268,21 @@ fprintf(stderr, "----- skip %s\n", Etype(type)); } X_UNLOCK; + if (got_NET_CURRENT_DESKTOP > 0.0) { + if (dnow() < got_NET_CURRENT_DESKTOP + 0.25) { + fprintf(stderr, "***got_NET_CURRENT_DESKTOP n=%d\n", n); + desktop_change = 1; + } else { + fprintf(stderr, "***got_NET_CURRENT_DESKTOP n=%d STALE\n", n); + } + got_NET_CURRENT_DESKTOP = 0.0; + } + if (n == 0) { return 0; } fprintf(stderr, "\n"); rfbLog("IN check_ncache() %d events.\n", n); - for (i=0; i < n; i++) { - XEvent ev = Ev[i]; - Ev_win[i] = ev.xany.window; - } - if (try_batch) { use_batch = 1; } @@ -7533,19 +8301,163 @@ fprintf(stderr, "\n"); rfbLog("IN check_ncache() %d events.\n", n); 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) { + skipwins[skipwins_n++] = twin; + break; + } + } + } + } + + if (!desktop_change) { + if (skipwins_n) { + if (n_MN + n_UN >= 2 + 2*skipwins_n) { + desktop_change = 1; + } + } else { + if (n_MN + n_UN >= 4) { + desktop_change = 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; \ + } \ + } + + /* XXX Y not working well */ + 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; + } + } + } + } + if (desktop_change) { + if (ncache_dt_change) { + fprintf(stderr, "GUESSED DESKTOP CHANGE.\n"); + saw_desktop_change = 1; + } else { + 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); X_LOCK; for (i=0; i < n; i++) { XEvent ev; - int type, idx = -1; + int ns, skip = 0, type, idx = -1; + int ik = Ev_order[i]; - if (Ev_done[i]) continue; - win = Ev_win[i]; + if (Ev_done[ik]) continue; + win = Ev_win[ik]; - ev = Ev[i]; + ev = Ev[ik]; type = ev.type; - Ev_done[i] = 1; + Ev_done[ik] = 1; + + for (ns = 0; ns < skipwins_n; ns++) { + if (win == skipwins[ns]) { + skip = 1; + break; + } + } + if (skip) { +fprintf(stderr, "skip%02d: ** SpecialSkip 0x%x type: %s\n", ik, (unsigned int) win, Etype(type)); + continue; + } if (win == rootwin) { if (type == CreateNotify) { @@ -7567,14 +8479,15 @@ fprintf(stderr, "\n"); rfbLog("IN check_ncache() %d events.\n", n); y=attr.y; w=attr.width; h=attr.height; -/* XXX Y */ if (create_tot <= 6 && create_cnt++ < 3) { if (w*h > 64 * 64) { X_UNLOCK; - su_save(idx, nbatch, 1); + su_save(idx, nbatch, 0, 1); X_LOCK; if (cache_list[idx].valid) { - SCHED(win2, 1) + if (! desktop_change) { + SCHED(win2, 1) + } } create_cnt++; } @@ -7588,25 +8501,28 @@ fprintf(stderr, "\n"); rfbLog("IN check_ncache() %d events.\n", n); DELETE(idx); } } -fprintf(stderr, "root%02d: ** CreateNotify 0x%x %3d -- %dx%d+%d+%d valid=%d\n", i, (unsigned int) win2, idx, w, h, x, y, valid); +fprintf(stderr, "root%02d: ** CreateNotify 0x%x %3d -- %dx%d+%d+%d valid=%d\n", ik, (unsigned int) win2, idx, w, h, x, y, valid); } else if (type == ReparentNotify) { if (ev.xreparent.parent != rootwin) { win2 = ev.xreparent.window; if (win2 != rootwin) { idx = lookup_win_index(win2); -fprintf(stderr, "root%02d: ReparentNotifyRM 0x%x %3d\n", i, (unsigned int) win2, idx); +fprintf(stderr, "root%02d: ReparentNotifyRM 0x%x %3d\n", ik, (unsigned int) win2, idx); if (idx >= 0) { DELETE(idx); } xselectinput(win2, 0, 1); } } + } else { +fprintf(stderr, "root%02d: ** IgnoringRoot 0x%x type: %s\n", ik, (unsigned int) 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; Window oabove = None; idx = lookup_win_index(win); @@ -7615,7 +8531,7 @@ fprintf(stderr, "root%02d: ReparentNotifyRM 0x%x %3d\n", i, (unsigned int) win2 oabove = cache_list[idx].above; } -fprintf(stderr, "----%02d: ConfigureNotify 0x%x %3d -- above: 0x%x -> 0x%x %dx%d+%d+%d\n", i, (unsigned int) win, idx, +fprintf(stderr, "----%02d: ConfigureNotify 0x%x %3d -- above: 0x%x -> 0x%x %dx%d+%d+%d\n", ik, (unsigned int) win, idx, (unsigned int) oabove, (unsigned int) ev.xconfigure.above, ev.xconfigure.width, ev.xconfigure.height, ev.xconfigure.x, ev.xconfigure.y); if (idx < 0) { @@ -7634,12 +8550,31 @@ fprintf(stderr, "----%02d: ConfigureNotify 0x%x %3d -- above: 0x%x -> 0x%x % if (x_old != x_new || y_old != y_new) { /* invalidate su */ cache_list[idx].su_time = 0.0; -fprintf(stderr, " invalidate su: 0x%x xy: %d/%d %d/%d \n", (unsigned int) win, x_old, y_old, x_new, y_new); +fprintf(stderr, " INVALIDATE su: 0x%x xy: %d/%d %d/%d \n", (unsigned int) 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; -fprintf(stderr, " invalidate bs: 0x%x wh: %d/%d %d/%d \n", (unsigned int) win, w_old, h_old, w_new, h_new); +fprintf(stderr, " INVALIDATE bs: 0x%x wh: %d/%d %d/%d \n", (unsigned int) win, w_old, h_old, w_new, h_new); + } + stack_change = 0; + 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) { + try_to_fix_su(win, idx, ev.xconfigure.above, nbatch, NULL); + n_ST++; + } } cache_list[idx].x = x_new; @@ -7652,12 +8587,14 @@ fprintf(stderr, " invalidate bs: 0x%x wh: %d/%d %d/%d \n", (unsigned i } else if (type == VisibilityNotify) { int state = ev.xvisibility.state; idx = lookup_win_index(win); -fprintf(stderr, "----%02d: VisibilityNotify 0x%x %3d state: %s U/P %d/%d\n", i, (unsigned int) win, idx, VState(state), n_VN_u, n_VN_p); +fprintf(stderr, "----%02d: VisibilityNotify 0x%x %3d state: %s U/P %d/%d\n", ik, (unsigned int) win, idx, VState(state), n_VN_u, n_VN_p); if (idx < 0) { continue; } - if (macosx_console && n_VN_p == 0) { + if (desktop_change) { + ; + } else if (macosx_console && n_VN_p == 0) { ; /* XXXX not working well yet with UnmapNotify ... */ } else if (state == VisibilityUnobscured) { int i2, ok = 1; @@ -7672,11 +8609,11 @@ fprintf(stderr, "----%02d: VisibilityNotify 0x%x %3d state: %s U/P %d/%d\n", i } if (ok) { X_UNLOCK; - bs_restore(idx, nbatch, 1, 1); + bs_restore(idx, nbatch, 0, 1, 0, 1); X_LOCK; cache_list[idx].time = dnow(); cache_list[idx].vis_cnt++; - Ev_map[i] = win; + 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; @@ -7689,16 +8626,47 @@ fprintf(stderr, "----%02d: VisibilityNotify 0x%x %3d state: %s U/P %d/%d\n", i } else if (type == MapNotify) { idx = lookup_win_index(win); -fprintf(stderr, "----%02d: MapNotify 0x%x %3d\n", i, (unsigned int) win, idx); +fprintf(stderr, "----%02d: MapNotify 0x%x %3d\n", ik, (unsigned int) win, idx); if (idx < 0) { continue; } - if (cache_list[idx].map_state == IsUnmapped || macosx_console) { + if (cache_list[idx].map_state == IsUnmapped || desktop_change || macosx_console) { X_UNLOCK; - su_save(idx, nbatch, 1); - bs_restore(idx, nbatch, 0, 1); + 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) { + su_save(idx, nbatch, 1, 1); + } + } else { + su_save(idx, nbatch, 0, 1); + } + if (bs_restore(idx, nbatch, 0, 0, 0, 1)) { /* XXX clip? */ + ; + } else { + idx_add_rgn(missed_bs_restore_rgn, r0, idx); + missed_bs_restore++; + } + if (macosx_console) { #ifdef MACOSX macosxCGS_follow_animation_win(win, -1, 1); @@ -7716,7 +8684,7 @@ fprintf(stderr, "----%02d: MapNotify 0x%x %3d\n", i, (unsigned int) win, pixels += cache_list[idx].width * cache_list[idx].height; cache_list[idx].time = dnow(); cache_list[idx].map_cnt++; - Ev_map[i] = win; + 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; @@ -7727,7 +8695,7 @@ fprintf(stderr, "----%02d: MapNotify 0x%x %3d\n", i, (unsigned int) win, } else if (type == UnmapNotify) { idx = lookup_win_index(win); -fprintf(stderr, "----%02d: UnmapNotify 0x%x %3d\n", i, (unsigned int) win, idx); +fprintf(stderr, "----%02d: UnmapNotify 0x%x %3d\n", ik, (unsigned int) win, idx); if (idx < 0) { continue; @@ -7738,15 +8706,45 @@ fprintf(stderr, "----%02d: UnmapNotify 0x%x %3d\n", i, (unsigned int) win, } } - if (cache_list[idx].map_state == IsViewable || macosx_console) { + if (cache_list[idx].map_state == IsViewable || desktop_change || macosx_console) { X_UNLOCK; - bs_save(idx, nbatch, 1); - su_restore(idx, nbatch, 0, 1); + 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) { + bs_save(idx, nbatch, 1, 0, 1); + } + } else { + bs_save(idx, nbatch, 1, 0, 1); + } + if (su_restore(idx, nbatch, 1, 0, 1)) { + try_to_fix_su(win, idx, None, nbatch, "unmapped"); + } 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[i] = win; + 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; @@ -7760,7 +8758,7 @@ fprintf(stderr, "----%02d: UnmapNotify 0x%x %3d\n", i, (unsigned int) win, win2 = ev.xreparent.window; if (win2 != rootwin) { idx = lookup_win_index(win2); -fprintf(stderr, "----%02d: ReparentNotifyRM 0x%x %3d\n", i, (unsigned int) win2, idx); +fprintf(stderr, "----%02d: ReparentNotifyRM 0x%x %3d\n", ik, (unsigned int) win2, idx); if (idx >= 0) { DELETE(idx); } @@ -7771,11 +8769,13 @@ fprintf(stderr, "----%02d: ReparentNotifyRM 0x%x %3d\n", i, (unsigned int) win2 } else if (type == DestroyNotify) { win2 = ev.xdestroywindow.window; idx = lookup_win_index(win2); -fprintf(stderr, "----%02d: DestroyNotify 0x%x %3d\n", i, (unsigned int) win2, idx); +fprintf(stderr, "----%02d: DestroyNotify 0x%x %3d\n", ik, (unsigned int) win2, idx); if (idx >= 0) { DELETE(idx); } + } else { +fprintf(stderr, "igno%02d: ** Ignoring 0x%x type: %s\n", ik, (unsigned int) win, Etype(type)); } } @@ -7783,11 +8783,7 @@ fprintf(stderr, "----%02d: DestroyNotify 0x%x %3d\n", i, (unsigned int) win2 X_UNLOCK; if (use_batch && nreg) { - int k; - batch_copyregion(batch_reg, batch_dxs, batch_dys, nreg, -1.0); - for (k=0; k < nreg; k++) { - sraRgnDestroy(batch_reg[k]); - } + batch_push(nreg, -1.0); } if (nrects) { if (scaling) { @@ -7795,6 +8791,14 @@ fprintf(stderr, "----%02d: DestroyNotify 0x%x %3d\n", i, (unsigned int) win2 } } + if (n_CN || n_RN || n_DN || n_MN || n_UN || n_ST || did_sched) { + snap_old(); + } + + sraRgnDestroy(r0); + sraRgnDestroy(missed_su_restore_rgn); + sraRgnDestroy(missed_bs_restore_rgn); + rfbLog("OUT check_ncache(): %.6f events: %d pixels: %d\n", dnow() - now, n, pixels); return pixels; } diff --git a/x11vnc/x11vnc.1 b/x11vnc/x11vnc.1 index 389fb12..a7ca7de 100644 --- a/x11vnc/x11vnc.1 +++ b/x11vnc/x11vnc.1 @@ -1,8 +1,8 @@ .\" This file was automatically generated from x11vnc -help output. -.TH X11VNC "1" "December 2006" "x11vnc " "User Commands" +.TH X11VNC "1" "January 2007" "x11vnc " "User Commands" .SH NAME x11vnc - allow VNC connections to real X11 displays - version: 0.8.4, lastmod: 2006-12-29 + version: 0.8.4, lastmod: 2007-01-01 .SH SYNOPSIS .B x11vnc [OPTION]... @@ -2418,7 +2418,7 @@ detection not as accurate as the X version. .PP \fB-ncache_cr\fR .IP -In \fB-nache\fR mode, try do to copyrect opaque window +In \fB-ncache\fR mode, try to do copyrect opaque window moves/drags instead of wireframes (this can induce painting errors). The wireframe will still be used when moving a window whose save-unders has not yet been set @@ -2429,9 +2429,24 @@ with this option. On Unix, realvnc viewer gives smoother drags than tightvnc viewer. Response may also be choppy if the server side machine is too slow. .PP +\fB-ncache_no_moveraise\fR +.IP +In \fB-ncache\fR mode, do not assume that moving a window +will cause the window manager to raise it to the top +of the stack. The default is to assume it does, and +so at the beginning of any wireframe, etc, window moves +the window will be pushed to top in the VNC viewer. +.PP +\fB-ncache_no_dtchange\fR +.IP +In \fB-ncache\fR mode, do not try to guess when the desktop +(viewport) changes to another one (i.e. another +workarea). The default is to try to guess and when +detected try to make the transistion more smoothly. +.PP \fB-ncache_pad\fR \fIn\fR .IP -In \fB-nache\fR mode, pad each window with n pixels for the +In \fB-ncache\fR mode, pad each window with n pixels for the caching rectangles. This can be used to try to improve the situation with dropshadows or other compositing (e.g. MacOS X window manager), although it could make @@ -4001,6 +4016,10 @@ ncache_cr enable \fB-ncache_cr\fR mode. .IP noncache_cr disable \fB-ncache_cr\fR mode. .IP +ncache_no_moveraise enable no_moveraise mode. +.IP +noncache_no_moveraise disable no_moveraise mode. +.IP wireframe enable \fB-wireframe\fR mode. same as "wf" .IP nowireframe disable \fB-wireframe\fR mode. same as "nowf" @@ -4277,12 +4296,13 @@ clear_keys noclear_keys remap repeat norepeat fb nofb bell nobell sel nosel primary noprimary setprimary nosetprimary clipboard noclipboard setclipboard nosetclipboard seldir cursorshape nocursorshape -cursorpos nocursorpos cursor_drag nocursor_drag cursor -show_cursor noshow_cursor nocursor arrow xfixes noxfixes -xdamage noxdamage xd_area xd_mem alphacut alphafrac -alpharemove noalpharemove alphablend noalphablend -xwarppointer xwarp noxwarppointer noxwarp buttonmap -dragging nodragging ncache_cr noncache_cr ncache +cursorpos nocursorpos cursor_drag nocursor_drag +cursor show_cursor noshow_cursor nocursor arrow +xfixes noxfixes xdamage noxdamage xd_area xd_mem +alphacut alphafrac alpharemove noalpharemove alphablend +noalphablend xwarppointer xwarp noxwarppointer noxwarp +buttonmap dragging nodragging ncache_cr noncache_cr +ncache_no_moveraise noncache_no_moveraise ncache noncache ncache_size wireframe_mode wireframe wf nowireframe nowf wireframelocal wfl nowireframelocal nowfl wirecopyrect wcr nowirecopyrect nowcr scr_area diff --git a/x11vnc/x11vnc.c b/x11vnc/x11vnc.c index 73adb8f..6a44907 100644 --- a/x11vnc/x11vnc.c +++ b/x11vnc/x11vnc.c @@ -1451,7 +1451,7 @@ char msg[] = "\n" "Hello! Exciting News!!\n" "\n" -"You have been selected at random to beta test the x11vnc '-ncache' VNC\n" +"You have been selected at random to beta-test the x11vnc '-ncache' VNC\n" "client-side pixel caching feature!\n" "\n" "This scheme stores pixel data offscreen on the VNC viewer side for faster\n" @@ -1468,12 +1468,13 @@ char msg[] = "would notice and use the -ncache option (e.g. the wireframe and scroll\n" "detection features are on by default). A couple things to note:\n" "\n" -" 1) It uses a large amount of RAM (on both viewer and server)\n" +" 1) It uses a large amount of RAM (on both viewer and server sides)\n" "\n" " 2) You can actually see the cached pixel data if you scroll down\n" " to it in your viewer; adjust your viewer's size to hide it.\n" "\n" "More info: http://www.karlrunge.com/x11vnc/#faq-client-caching\n" +"waiting for connections:\n" ; if (raw_fb_str && !macosx_console) { @@ -2161,6 +2162,10 @@ int main(int argc, char* argv[]) { } } else if (!strcmp(arg, "-ncache_cr")) { ncache_copyrect = 1; + } else if (!strcmp(arg, "-ncache_no_moveraise")) { + ncache_wf_raises = 1; + } else if (!strcmp(arg, "-ncache_no_dtchange")) { + ncache_dt_change = 0; } else if (!strcmp(arg, "-ncache_pad")) { CHECK_ARGC ncache_pad = atoi(argv[++i]); @@ -3249,6 +3254,7 @@ int main(int argc, char* argv[]) { multiple_cursors_mode = strdup("most"); if (! quiet && ! raw_fb_str) { + rfbLog("\n"); rfbLog("XFIXES available on display, resetting cursor mode\n"); rfbLog(" to: '-cursor most'.\n"); rfbLog(" to disable this behavior use: '-cursor arrow'\n"); @@ -3390,13 +3396,13 @@ int main(int argc, char* argv[]) { if (! quiet && ncache && ! raw_fb_str) { rfbLog("\n"); rfbLog("Client Side Caching: -ncache mode is in effect to provide\n"); - rfbLog(" some client-side pixel data caching. This speeds up\n"); + rfbLog(" client-side pixel data caching. This speeds up\n"); rfbLog(" iconifying/deiconifying windows, moving and raising\n"); rfbLog(" windows, and reposting menus. In the simple CopyRect\n"); rfbLog(" encoding scheme used (no compression) a huge amount\n"); rfbLog(" of extra memory (20-80MB) is used on both the server and\n"); - rfbLog(" client sides. This mode works with any VNC viewer,\n"); - rfbLog(" however in most you can actually see the cached pixel\n"); + rfbLog(" client sides. This mode works with any VNC viewer.\n"); + rfbLog(" However, in most you can actually see the cached pixel\n"); rfbLog(" data by scrolling down, so you need to re-adjust its size.\n"); rfbLog(" See http://www.karlrunge.com/x11vnc/#faq-client-caching.\n"); rfbLog(" If this mode yields undesired behavior (poor response,\n"); diff --git a/x11vnc/x11vnc.h b/x11vnc/x11vnc.h index 589736b..5dad134 100644 --- a/x11vnc/x11vnc.h +++ b/x11vnc/x11vnc.h @@ -464,9 +464,13 @@ extern double last_pointer_motion_time; extern double last_key_to_button_remap_time; extern double last_copyrect; extern double last_copyrect_fix; +extern double last_wireframe; extern double servertime_diff; extern double x11vnc_start; +extern double last_get_wm_frame_time; +extern Window last_get_wm_frame; + extern int hack_val; /* last client to move pointer */ diff --git a/x11vnc/x11vnc_defs.c b/x11vnc/x11vnc_defs.c index 170be87..78ebe42 100644 --- a/x11vnc/x11vnc_defs.c +++ b/x11vnc/x11vnc_defs.c @@ -15,7 +15,7 @@ int xtrap_base_event_type = 0; int xdamage_base_event_type = 0; /* date +'lastmod: %Y-%m-%d' */ -char lastmod[] = "0.8.4 lastmod: 2006-12-29"; +char lastmod[] = "0.8.4 lastmod: 2007-01-01"; /* X display info */ @@ -128,9 +128,13 @@ double last_pointer_motion_time = 0.0; double last_key_to_button_remap_time = 0.0; double last_copyrect = 0.0; double last_copyrect_fix = 0.0; +double last_wireframe = 0.0; double servertime_diff = 0.0; double x11vnc_start = 0.0; +double last_get_wm_frame_time = 0.0; +Window last_get_wm_frame = None; + int hack_val = 0; /* last client to move pointer */ diff --git a/x11vnc/xevents.c b/x11vnc/xevents.c index 5f22e9b..a9c6549 100644 --- a/x11vnc/xevents.c +++ b/x11vnc/xevents.c @@ -19,7 +19,7 @@ int grab_buster = 0; int grab_kbd = 0; int grab_ptr = 0; -int sync_tod_delay = 3; +int sync_tod_delay = 20; void initialize_vnc_connect_prop(void); void initialize_x11vnc_remote_prop(void); @@ -28,6 +28,7 @@ void spawn_grab_buster(void); void sync_tod_with_servertime(void); void check_keycode_state(void); void check_autorepeat(void); +void set_prop_atom(Atom atom); void check_xevents(int reset); void xcut_receive(char *text, int len, rfbClientPtr cl); @@ -600,6 +601,16 @@ void sync_tod_with_servertime(void) { RAWFB_RET_VOID + if (atom_NET_ACTIVE_WINDOW == None) { + atom_NET_ACTIVE_WINDOW = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); + } + if (atom_NET_CURRENT_DESKTOP == None) { + atom_NET_CURRENT_DESKTOP = XInternAtom(dpy, "_NET_CURRENT_DESKTOP", False); + } + if (atom_NET_CLIENT_LIST_STACKING == None) { + atom_NET_CLIENT_LIST_STACKING = XInternAtom(dpy, "_NET_CLIENT_LIST_STACKING", False); + } + if (! ticker_atom) { ticker_atom = XInternAtom(dpy, "X11VNC_TICKER", False); } @@ -609,7 +620,7 @@ void sync_tod_with_servertime(void) { XSync(dpy, False); while (XCheckTypedEvent(dpy, PropertyNotify, &xev)) { - ; + set_prop_atom(xev.xproperty.atom); } snprintf(diff, 128, "%d/%08d/%lu/%.6f", (int) getpid(), seq++, @@ -739,6 +750,13 @@ void check_autorepeat(void) { } } +void set_prop_atom(Atom atom) { + if (atom == None) return; + if (atom == atom_NET_ACTIVE_WINDOW) got_NET_ACTIVE_WINDOW = dnow(); + if (atom == atom_NET_CURRENT_DESKTOP) got_NET_CURRENT_DESKTOP = dnow(); + if (atom == atom_NET_CLIENT_LIST_STACKING) got_NET_CLIENT_LIST_STACKING = dnow(); +} + /* * This routine is periodically called to check for selection related * and other X11 events and respond to them as needed. @@ -871,7 +889,10 @@ void check_xevents(int reset) { * Go retrieve X11VNC_REMOTE string. */ read_x11vnc_remote_prop(0); + + } + set_prop_atom(xev.xproperty.atom); } } diff --git a/x11vnc/xevents.h b/x11vnc/xevents.h index 3200063..30c4c15 100644 --- a/x11vnc/xevents.h +++ b/x11vnc/xevents.h @@ -15,6 +15,7 @@ extern void spawn_grab_buster(void); extern void sync_tod_with_servertime(void); extern void check_keycode_state(void); extern void check_autorepeat(void); +extern void set_prop_atom(Atom atom); extern void check_xevents(int reset); extern void xcut_receive(char *text, int len, rfbClientPtr cl);