return XKeysymToKeycode(disp,sym);
}
+static void check_pclose(FILE *f, char *cmd) {
+ int r;
+ eassert(!ferror(f));
+ r= fgetc(f); eassert(r==EOF); eassert(feof(f));
+ r= pclose(f); eassert(r>=0); eassert(WIFEXITED(r) && !WEXITSTATUS(r));
+ free(cmd);
+}
+
+#if 0
static CanonImage *screenshot_now(void) {
char *cmd;
CanonImage *ci;
eassert(r>=0);
FILE *f= popen(cmd,"r"); eassert(f);
ci= file_read_image(f);
- r= fgetc(f); eassert(r==EOF); eassert(feof(f));
- r= pclose(f); eassert(r>=0); eassert(WIFEXITED(r) && !WEXITSTATUS(r));
- free(cmd);
+ check_pclose(f, cmd);
return ci;
}
+#endif
static void screenshot_startup(void) {
int r;
fprintf(stderr,"PAGING raise_and_set_focus done.\n");
}
+/*---------- pager ----------*/
+
+typedef struct {
+ size_t len;
+ unsigned char d[];
+} Snapshot;
+
static void send_key(KeySym sym) {
int r;
XTestFakeKeyEvent(disp, keycode(sym),1, 10);
r= XSync(disp, False); eassert(r);
}
-static void send_pgup(void) {
+static void send_pgup_many(void) {
+ int i;
fprintf(stderr,"PAGING PageUp\n");
- send_key(XK_Prior);
+ for (i=0; i<25; i++)
+ send_key(XK_Prior);
}
static void send_pgdown(void) {
fprintf(stderr,"PAGING PageDown\n");
int r;
r= gettimeofday(&tv,0); eassert(!r);
- return (tv.tv_sec - tv_startup.tv_sec) +
- (tv.tv_usec - tv_startup.tv_usec) * 1e-6;
+ double t= (tv.tv_sec - tv_startup.tv_sec) +
+ (tv.tv_usec - tv_startup.tv_usec) * 1e-6;
+ fprintf(stderr,"%f\n",t);
+ return t;
}
-static double worst_snapshot= 0.050, worst_stabilise= 0.100;
+static double worst_snapshot= 0.050;
+static double worst_stabilise= 0.100;
+static size_t snapshot_alloc= 1024;
-static void snapshot(CanonImage **output) {
- free(*output);
+static void snapshot(Snapshot **output) {
+ char *cmd;
+ int r;
+
+ free(*output); *output=0;
double a= timestamp();
- *output= screenshot_now();
+
fprintf(stderr,"PAGING snapshot\n");
+
+ r= asprintf(&cmd, "xwd -silent -id 0x%lx", (unsigned long)id); eassert(r>=0);
+ FILE *f= popen(cmd,"r"); eassert(f);
+
+ int need_alloc=1;
+ size_t used=0;
+ for (;;) {
+ size_t allow= snapshot_alloc - used;
+ if (!allow) {
+ snapshot_alloc <<= 1;
+ need_alloc= 1;
+ fprintf(stderr,"PAGING snapshot grow %ld\n", (long)snapshot_alloc);
+ continue;
+ }
+ if (need_alloc) {
+ *output= realloc(*output, sizeof(**output) + snapshot_alloc);
+ eassert(*output);
+ need_alloc= 0;
+ }
+ size_t got= fread((*output)->d, 1, allow, f);
+ if (got==0) break;
+ used += got;
+ }
+ check_pclose(f,cmd);
+
+ (*output)->len= used;
+ snapshot_alloc= used+1;
+ *output= realloc(*output, sizeof(**output) + snapshot_alloc);
+ eassert(*output);
+
double b= timestamp();
double it_took= b-a;
- fprintf(stderr,"PAGING snapshot took=%f\n",it_took);
if (it_took > worst_snapshot)
worst_snapshot= it_took;
+
+ fprintf(stderr,"PAGING snapshot took=%f len=%ld\n",
+ it_took, (long)used);
}
static void snapshot_idle(void) {
int r;
- r= usleep(worst_snapshot * 1e6 * 2);
- /* spend no more than 1/3 of our time constantly snapshotting */
+ r= usleep(worst_snapshot * 1e6 * 0.5);
+ /* spend no more than 2/3 of our time constantly snapshotting */
eassert(!r);
}
-static int identical(const CanonImage *a, const CanonImage *b) {
+static int identical(const Snapshot *a, const Snapshot *b) {
return !(memcmp(a, b, sizeof(*a)) ||
- memcmp(a->d, b->d, a->w * a->h));
+ memcmp(a->d, b->d, a->len));
}
-static void wait_for_stability(CanonImage **output,
- const CanonImage *previously,
+static void wait_for_stability(Snapshot **output,
+ const Snapshot *previously,
void (*with_keypress)(void)) {
- CanonImage *last=0;
+ Snapshot *last=0;
/* waits longer if we're going to return an image identical to previously
* if previously==0, all images are considered identical to it */
double it_took= -1;
fprintf(stderr,"PAGING wait_for_stability"
- " worst_snapshot=%f worst_stabilise=%f\n",
- worst_snapshot, worst_stabilise);
+ " worst_snapshot=%f worst_stabilise=%f previously=%p\n",
+ worst_snapshot, worst_stabilise, previously);
for (;;) {
+ double at_snapshot= timestamp();
snapshot(output);
double right_now= timestamp();
- if (!last || !identical(*output,last)) {
+ if (!last) {
+ fprintf(stderr,"PAGING wait_for_stability first...\n");
+ last_change= when_started= right_now;
+ last=*output; *output=0;
+ } else if (!identical(*output,last)) {
fprintf(stderr,"PAGING wait_for_stability changed...\n");
last_change= right_now;
free(last); last=*output; *output=0;
it_took= -1;
} else {
if (it_took<0)
- it_took= right_now - when_started;
+ it_took= at_snapshot - when_started;
- double threshold= (worst_stabilise + worst_snapshot) * 3;
+ double threshold= worst_stabilise + worst_snapshot;
if (!previously || identical(*output,previously))
threshold *= 2; threshold += 1.5;
double stable_for= right_now - last_change;
fprintf(stderr,"PAGING wait_for_stability"
" worst_snapshot=%f worst_stabilise=%f"
- " stable for %f thresh %f...\n",
+ " it_took=%f stable_for=%f threshold=%f...\n",
worst_snapshot, worst_stabilise,
- stable_for, threshold);
+ it_took, stable_for, threshold);
if (stable_for > threshold)
break;
snapshot_idle();
}
- if (it_took > worst_stabilise)
+ if (!with_keypress && it_took > worst_stabilise)
worst_stabilise= it_took;
free(last);
}
static void read_pages(void) {
- CanonImage *current=0, *last;
+ Snapshot *current=0, *last=0;
raise_and_set_focus();
/* page to the top - keep pressing page up until the image stops changing */
- wait_for_stability(¤t,0, send_pgup);
+ wait_for_stability(&last,0, send_pgup_many);
/* now to actually page down */
for (;;) {
fprintf(stderr,"PAGING page %d\n",npages);
- eassert(npages < MAX_PAGES);
- page_images[npages++]= last= current;
- send_pgdown();
+ //eassert(npages < MAX_PAGES);
+ //page_images[npages++]=
+ npages++;
+
wait_for_stability(¤t,last, 0);
if (npages && /* first pagedown doesn't do much */
identical(current,last)) {
free(current);
break;
}
+
+ free(last); last=current; current=0;
+
+ send_pgdown();
}
fprintf(stderr,"PAGING all done.\n");
}