diff options
author | runge <runge> | 2007-01-02 05:15:07 +0000 |
---|---|---|
committer | runge <runge> | 2007-01-02 05:15:07 +0000 |
commit | c88d830f5591913f2e5e763814978e2877f367ec (patch) | |
tree | 217ae1113daa5bced6f21c34eb1a923bcd8cec18 /x11vnc/userinput.c | |
parent | 833f06025fbd2fa8d4d83ccf8ab068c8060663de (diff) | |
download | libtdevnc-c88d830f5591913f2e5e763814978e2877f367ec.tar.gz libtdevnc-c88d830f5591913f2e5e763814978e2877f367ec.zip |
x11vnc: more -ncache improvements.
Diffstat (limited to 'x11vnc/userinput.c')
-rw-r--r-- | x11vnc/userinput.c | 1330 |
1 files changed, 1167 insertions, 163 deletions
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,19 +7479,386 @@ 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 tmp_stack[STACKMAX]; +sraRegionPtr tmp_reg[STACKMAX]; + +#define CLEAN_OUT \ + for (i=0; i < n; i++) { \ + sraRgnDestroy(tmp_reg[i]); \ + } \ + sraRgnDestroy(r1); \ + 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 sx2, sy2, sw2, sh2; + int bx1, by1, bw1, bh1; + int bx2, by2, bw2, bh2; + 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) { + +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; + 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; @@ -7165,12 +7869,24 @@ int check_ncache(int reset, int mode) { 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 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) @@ -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; } |