#include <X11/extensions/XTest.h>
#include <X11/keysym.h>
-#define NUM_PAGES 25
+CanonImage *page_images[MAX_PAGES];
+int npages;
+static Window id;
static Display *disp;
+static struct timeval tv_startup;
static KeyCode keycode(KeySym sym) {
return XKeysymToKeycode(disp,sym);
}
-static CanonImage *screenshot_now(Window id) {
+static CanonImage *screenshot_now(void) {
char *cmd;
CanonImage *ci;
int r;
return ci;
}
-static void read_pages(Window id) {
+static void screenshot_startup(void) {
+ int r;
+ disp= XOpenDisplay(0); eassert(disp);
+ r= gettimeofday(&tv_startup,0); eassert(!r);
+}
+
+#if 0
+static CanonImage *single_page(void) {
+ int r;
+ r= XRaiseWindow(disp, id); eassert(r);
+ r= XSync(disp, False); eassert(r);
+ return screenshot_now();
+}
+#endif
+
+static void raise_and_set_focus(void) {
int r;
XWindowAttributes attr;
int xpos,ypos, evbase,errbase,majver,minver;
unsigned width,height,bd,depth;
Window dummy;
- disp= XOpenDisplay(0); eassert(disp);
+ fprintf(stderr,"PAGING raise_and_set_focus\n");
r= XTestQueryExtension(disp, &evbase,&errbase,&majver,&minver);
eassert(r==True);
int screen= XScreenNumberOfScreen(attr.screen);
XTestFakeMotionEvent(disp,screen, xpos, ypos, 0);
- XTestFakeButtonEvent(disp,1,1, 0);
+ XTestFakeButtonEvent(disp,1,1, 50);
XTestFakeButtonEvent(disp,1,0, 50);
+ r= XSync(disp, False); eassert(r);
- XTestFakeKeyEvent(disp, keycode(XK_Next),1, 50);
- XTestFakeKeyEvent(disp, keycode(XK_Next),0, 50);
-
+ fprintf(stderr,"PAGING raise_and_set_focus done.\n");
+}
+
+static void send_key(KeySym sym) {
+ int r;
+ XTestFakeKeyEvent(disp, keycode(sym),1, 10);
+ XTestFakeKeyEvent(disp, keycode(sym),0, 10);
r= XSync(disp, False); eassert(r);
}
+static void send_pgup(void) {
+ fprintf(stderr,"PAGING PageUp\n");
+ send_key(XK_Prior);
+}
+static void send_pgdown(void) {
+ fprintf(stderr,"PAGING PageDown\n");
+ send_key(XK_Next);
+}
+
+static double timestamp(void) {
+ struct timeval tv;
+ 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;
+}
+
+static double worst_snapshot= 0.050, worst_stabilise= 0.100;
+
+static void snapshot(CanonImage **output) {
+ free(*output);
+ double a= timestamp();
+ *output= screenshot_now();
+ fprintf(stderr,"PAGING snapshot\n");
+ 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;
+}
+
+static void snapshot_idle(void) {
+ int r;
+ r= usleep(worst_snapshot * 1e6 * 2);
+ /* spend no more than 1/3 of our time constantly snapshotting */
+ eassert(!r);
+}
+
+static int identical(const CanonImage *a, const CanonImage *b) {
+ return !(memcmp(a, b, sizeof(*a)) ||
+ memcmp(a->d, b->d, a->w * a->h));
+}
+
+static void wait_for_stability(CanonImage **output,
+ const CanonImage *previously,
+ void (*with_keypress)(void)) {
+ CanonImage *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 when_started= timestamp();
+ double last_change= when_started;
+ double it_took= -1;
+
+ fprintf(stderr,"PAGING wait_for_stability"
+ " worst_snapshot=%f worst_stabilise=%f\n",
+ worst_snapshot, worst_stabilise);
+
+ for (;;) {
+ snapshot(output);
+ double right_now= timestamp();
+
+ if (!last || !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;
+
+ double threshold= (worst_stabilise + worst_snapshot) * 3;
+ 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",
+ worst_snapshot, worst_stabilise,
+ stable_for, threshold);
+
+ if (stable_for > threshold)
+ break;
+ }
+ if (with_keypress)
+ with_keypress();
+ snapshot_idle();
+ }
+
+ if (it_took > worst_stabilise)
+ worst_stabilise= it_took;
+
+ free(last);
+ fprintf(stderr,"PAGING wait_for_stability done.\n");
+}
+
+static void read_pages(void) {
+ CanonImage *current=0, *last;
+
+ raise_and_set_focus();
+
+ /* page to the top - keep pressing page up until the image stops changing */
+ wait_for_stability(¤t,0, send_pgup);
+
+ /* now to actually page down */
+ for (;;) {
+ fprintf(stderr,"PAGING page %d\n",npages);
+ eassert(npages < MAX_PAGES);
+ page_images[npages++]= last= current;
+ send_pgdown();
+ wait_for_stability(¤t,last, 0);
+ if (npages && /* first pagedown doesn't do much */
+ identical(current,last)) {
+ free(current);
+ break;
+ }
+ }
+ fprintf(stderr,"PAGING all done.\n");
+}
+
int main(int argc, char **argv) {
- Window id;
- CanonImage *ci;
+ screenshot_startup();
id= strtoul(*++argv,0,0);
- read_pages(id);
- ci= screenshot_now(id);
+
+ read_pages();
return 0;
}
+