#include <sys/ipc.h>
#include <sys/shm.h>
-CanonImage *page_images[MAX_PAGES];
-int npages;
-RgbImage *page0_rgbimage;
-
const char *ocean, *pirate;
static XWindowAttributes attr;
static struct timeval tv_startup;
static unsigned wwidth, wheight;
static int max_relevant_y= -1;
+static Point commod_focus_point, commod_page_point, commod_focuslast_point;
static XImage *shmim;
static XShmSegmentInfo shminfo;
Window dummy;
xassert( XTranslateCoordinates(disp, id,attr.root, wx,wy, rx,ry, &dummy) );
}
+static void translate_coords_toroot_p(Point w, int *rx, int *ry) {
+ translate_coords_toroot(w.x, w.y, rx, ry);
+}
static void check_client_window_all_on_screen(void) {
Rect onroot;
}
static void mouse_1_updown_here(void) {
check_not_disturbed();
- XTestFakeButtonEvent(disp,1,1, 50);
- XTestFakeButtonEvent(disp,1,0, 50);
+ XTestFakeButtonEvent(disp,1,1, 10);
+ XTestFakeButtonEvent(disp,1,0, 10);
}
static void mouse_1_updown(int x, int y) {
check_not_disturbed();
XTestFakeMotionEvent(disp, screen, xpos,ypos, 0);
mouse_1_updown_here();
}
+static void pgdown_by_mouse(void) {
+ check_not_disturbed();
+ debugf("PAGING Mouse\n");
+ mouse_1_updown_here();
+ sync_after_input();
+}
static int pgupdown;
debugf("PAGING PageUp x %d\n",i);
sync_after_input();
}
-static void send_pgdown(void) {
- send_key(XK_Next);
- pgupdown++;
- debugf("PAGING PageDown\n");
- sync_after_input();
-}
static void send_pgdown_torestore(void) {
debugf("PAGING PageDown x %d\n", -pgupdown);
while (pgupdown < 0) {
}
assert(sm->lshift < LONG_BIT);
assert(sm->rshift < LONG_BIT);
+ debugf("SHIFTMASK %p={.lshift=%d, .rshift=%d} image_mask=%lx\n",
+ sm, sm->lshift, sm->rshift, ximage_mask);
}
static void rtimestamp(double *t, const char *wh) {
#define COMPUTE_SHIFT_MASK(ix, rgb) \
compute_shift_mask(&shiftmasks[ix], im_use->rgb##_mask)
- COMPUTE_SHIFT_MASK(0, red);
+ COMPUTE_SHIFT_MASK(0, blue);
COMPUTE_SHIFT_MASK(1, green);
- COMPUTE_SHIFT_MASK(2, blue);
+ COMPUTE_SHIFT_MASK(2, red);
if (!*output)
*output= alloc_rgb_image(wwidth, wheight);
rtimestamp(&begin, "compute_shift_masks+alloc_rgb_image");
int x,y,i;
- unsigned char *op= (*output)->data;
+ uint32_t *op32= (*output)->data;
for (y=0; y<wheight; y++) {
- for (x=0; x<wwidth; x++) {
- long xrgb= XGetPixel(im_use,x,y);
- for (i=0; i<3; i++) {
- unsigned long sample=
- ((xrgb << shiftmasks[i].lshift) >> shiftmasks[i].rshift)
- & SAMPLEMASK;
- *op++= sample;
+ if (im_use->xoffset == 0 &&
+ im_use->format == ZPixmap &&
+ im_use->byte_order == LSBFirst &&
+ im_use->depth == 24 &&
+ im_use->bits_per_pixel == 32 &&
+ im_use->red_mask == 0x0000ffU &&
+ im_use->green_mask == 0x00ff00U &&
+ im_use->blue_mask == 0xff0000U) {
+ const char *p= im_use->data + y * im_use->bytes_per_line;
+// debugf("optimised copy y=%d",y);
+ memcpy(op32, p, wwidth*sizeof(*op32));
+ op32 += wwidth;
+ } else {
+ for (x=0; x<wwidth; x++) {
+ long xrgb= XGetPixel(im_use,x,y);
+ Rgb sample= 0;
+ for (i=0; i<3; i++) {
+ sample <<= 8;
+ sample |=
+ ((xrgb << shiftmasks[i].lshift) >> shiftmasks[i].rshift)
+ & SAMPLEMASK;
+ }
+ *op32++= sample;
}
}
}
" last_input=%f previously=%p `%s'\n",
last_input, previously, doing);
- double min_interval= 25000; /*us*/
+ double min_interval= 0.025;
for (;;) {
progress_spinner("%s",doing);
double this_interval= min_interval - since_last_input;
if (this_interval >= 0)
- usleep(this_interval);
+ delay(this_interval);
snapshot(output);
last=*output; *output=0;
} else if (!identical(*output,last)) {
debugf("PAGING wait_for_stability changed...\n");
- free(last); last=*output; *output=0;
+ free_snapshot(&last); last=*output; *output=0;
nidentical=0;
if (!with_keypress) {
min_interval *= 3.0;
- min_interval += 0.5;
+ min_interval += 0.1;
}
} else {
nidentical++;
if (nidentical >= threshold)
break;
- min_interval += 0.5;
+ min_interval += 0.1;
min_interval *= 2.0;
}
if (!(wwidth >= 320 && wheight >= 320))
fatal("YPP client window is implausibly small?");
+ if (attr.depth < 24)
+ fatal("Display is not 24bpp.");
+
check_client_window_all_on_screen();
Bool shmpixmaps=0;
debugf("PAGING set_focus\n");
- mouse_1_updown(160,160);
+ mouse_1_updown(commod_focus_point.x, commod_focus_point.y);
sync_after_input();
delay(0.5);
) );
int xpos,ypos;
- translate_coords_toroot(10,10, &xpos,&ypos);
- XTestFakeMotionEvent(disp,screen, xpos,ypos, 0);
+ translate_coords_toroot_p(commod_page_point, &xpos,&ypos);
+ XTestFakeMotionEvent(disp, screen, xpos,ypos, 0);
sync_after_input();
debugf("PAGING raise_and_set_focus done.\n");
}
-static CanonImage *convert_page(Snapshot *sn, RgbImage *ri) {
+static CanonImage *convert_page(const Snapshot *sn, RgbImage **rgb_r) {
CanonImage *im;
+ RgbImage *ri;
fwrite_ppmraw(screenshot_file, sn);
- if (ri) memcpy(ri->data, sn->data, ri->h * ri->w * 3);
-
- unsigned char *pixel= sn->data;
- CANONICALISE_IMAGE(im, sn->w, sn->h, {
- rgb=
- (pixel[0] << 16) |
- (pixel[1] << 8) |
- (pixel[2] );
- pixel += 3;
+
+ const Rgb *pixel= sn->data;
+ CANONICALISE_IMAGE(im, sn->w, sn->h, ri, {
+ rgb= *pixel++;
});
-
+
sysassert(!ferror(screenshot_file));
sysassert(!fflush(screenshot_file));
+ if (rgb_r) *rgb_r= ri;
+ else free(ri);
+
return im;
}
raise_and_get_details();
wait_for_stability(¤t,0,0, "checking current YPP client screen...");
- test= convert_page(current, 0);
- find_structure(test, &max_relevant_y);
+ test= convert_page(current,0);
+ find_structure(test,0, &max_relevant_y,
+ &commod_focus_point,
+ &commod_page_point,
+ &commod_focuslast_point);
check_correct_commodities();
Rect sunshine= find_sunshine_widget();
free_snapshot(&status);
}
+static void convert_store_page(Snapshot *current) {
+ RgbImage *rgb;
+ CanonImage *ci;
+ PageStruct *pstruct;
+
+ progress("page %d prescanning ...",npages);
+ ci= convert_page(current,&rgb);
+
+ progress("page %d overview ...",npages);
+ find_structure(ci,&pstruct, 0,0,0,0);
+
+ store_current_page(ci,pstruct,rgb);
+}
+
void take_screenshots(void) {
Snapshot *current=0, *last=0;
/* now to actually page down */
for (;;) {
- debugf("paging page %d\n",npages);
+ debugf("page %d paging\n",npages);
if (!(npages < MAX_PAGES))
fatal("Paging down seems to generate too many pages - max is %d.",
MAX_PAGES);
-
- page_images[npages]= convert_page(current, 0);
+
+ convert_store_page(current);
free_snapshot(&last); last=current; current=0;
debugf("PAGING page %d converted\n",npages);
wait_for_stability(¤t,last, 0,
- "collecting screenshot of page %d...",
+ "page %d collecting ...",
npages+1);
if (npages && /* first pagedown doesn't do much */
break;
}
- send_pgdown();
+ pgdown_by_mouse();
npages++;
}
progress("finishing with the YPP client...");
+ mouse_1_updown(commod_focuslast_point.x, commod_focuslast_point.y);
+ sync_after_input();
send_pgdown_torestore();
+ sync_after_input();
debugf("PAGING all done.\n");
progress_log("collected %d screenshots.",npages);
prepare_ypp_client();
wait_for_stability(¤t,0,0, "taking screenshot...");
- page0_rgbimage= alloc_rgb_image(current->w, current->h);
- page_images[0]= convert_page(current, page0_rgbimage);
+ convert_store_page(current);
npages= 1;
progress_log("collected single screenshot.");
}
DEBUG_DEFINE_SOME_DEBUGF(findypp,debugfind)
-void find_yppclient_window(void) {
- Window root, gotroot, gotparent;
- int screen;
- int nfound=0;
-
- if (id) return;
-
- progress("looking for YPP client window...");
+static int nfound;
+static Atom wm_name;
+static int screen;
+
+static void findypp_recurse(int depth, int targetdepth, Window w) {
+ unsigned int nchildren;
+ int i;
+ Window *children=0;
+ Window gotroot, gotparent;
static const char prefix[]= "Puzzle Pirates - ";
static const char onthe[]= " on the ";
static const char suffix[]= " ocean";
-#define S(x) (sizeof((x))-1)
-
- Atom wm_name= XInternAtom(disp,"WM_NAME",True);
- xassert(wm_name != None);
-
- for (screen=0; screen<ScreenCount(disp); screen++) {
- debugfind("FINDYPP screen %d\n", screen);
- root= RootWindow(disp,screen);
- unsigned int nchildren1;
- Window *children1=0;
-
- xassert( XQueryTree(disp,root,
- &gotroot,&gotparent,
- &children1,&nchildren1) );
- debugfind("FINDYPP screen %d nchildren1=%d\n", screen, nchildren1);
-
- int i;
- for (i=0; i<nchildren1; i++) {
- Window w1= children1[i];
- unsigned int nchildren2;
- Window *children2=0;
-
- xassert( XQueryTree(disp,w1,
- &gotroot,&gotparent,
- &children2,&nchildren2) );
- debugfind("FINDYPP screen %d c1[%2d]=0x%08lx nchildren2=%d\n",
- screen, i, (unsigned long)w1, nchildren2);
-
- int j;
- for (j=-1; j<(int)nchildren2; j++) {
- Window w2= j<0 ? w1 : children2[j];
- debugfind("FINDYPP screen %d c1[%2d]=0x%08lx c2[%2d]=0x%08lx",
- screen, i, (unsigned long)w1, j, (unsigned long)w2);
-
- int gotfmt;
- Atom gottype;
- unsigned long len, gotbytesafter;
- char *title;
- unsigned char *gottitle=0;
- xassert( !XGetWindowProperty(disp,w2, wm_name,0,512, False,
- AnyPropertyType,&gottype, &gotfmt, &len,
- &gotbytesafter, &gottitle) );
- title= (char*)gottitle;
-
- if (DEBUGP(findypp)) {
- debugfind(" gf=%d len=%lu gba=%lu \"", gotfmt,len,gotbytesafter);
- char *p;
- for (p=title; p < title+len; p++) {
- char c= *p;
- if (c>=' ' && c<=126) fputc(c,debug);
- else fprintf(debug,"\\x%02x",c & 0xff);
- }
- fputs("\": ",debug);
- }
+#define S(x) ((int)sizeof((x))-1)
-#define REQUIRE(pred) \
- if (!(pred)) { debugfind(" failed test %s\n", #pred); continue; } \
- else
+ debugfind("FINDYPP %d/%d screen %d %*s %lx",
+ depth,targetdepth,screen,
+ depth,"",(unsigned long)w);
+
+ if (depth!=targetdepth) {
+ xassert( XQueryTree(disp,w,
+ &gotroot,&gotparent,
+ &children,&nchildren) );
+ debugfind(" nchildren=%d\n",nchildren);
+
+ for (i=0; i<nchildren; i++) {
+ Window child= children[i];
+ findypp_recurse(depth+1, targetdepth, child);
+ }
+ XFree(children);
+ return;
+ }
+
- REQUIRE( gottype!=None );
- REQUIRE( len );
- REQUIRE( gotfmt==8 );
+ int gotfmt;
+ Atom gottype;
+ unsigned long len, gotbytesafter;
+ char *title;
+ unsigned char *gottitle=0;
+ xassert( !XGetWindowProperty(disp,w, wm_name,0,512, False,
+ AnyPropertyType,&gottype, &gotfmt, &len,
+ &gotbytesafter, &gottitle) );
+ title= (char*)gottitle;
+
+ if (DEBUGP(findypp)) {
+ debugfind(" gf=%d len=%lu gba=%lu \"", gotfmt,len,gotbytesafter);
+ char *p;
+ for (p=title; p < title+len; p++) {
+ char c= *p;
+ if (c>=' ' && c<=126) fputc(c,debug);
+ else fprintf(debug,"\\x%02x",c & 0xff);
+ }
+ fputs("\": ",debug);
+ }
- REQUIRE( len >= S(prefix) + 1 + S(onthe) + 1 + S(suffix) );
+#define REQUIRE(pred) \
+ if (!(pred)) { debugfind(" failed test %s\n", #pred); return; } \
+ else
- char *spc1= strchr( title + S(prefix), ' '); REQUIRE(spc1);
- char *spc2= strrchr((title + len) - S(suffix), ' '); REQUIRE(spc2);
+ REQUIRE( gottype!=None );
+ REQUIRE( len );
+ REQUIRE( gotfmt==8 );
- REQUIRE( (title + len) - spc1 >= S(onthe) + S(suffix) );
- REQUIRE( spc2 - title >= S(prefix) + S(onthe) );
+ REQUIRE( len >= S(prefix) + 1 + S(onthe) + 1 + S(suffix) );
- REQUIRE( !memcmp(title, prefix, S(prefix)) );
- REQUIRE( !memcmp(title + len - S(suffix), suffix, S(suffix)) );
- REQUIRE( !memcmp(spc1, onthe, S(onthe)) );
+ char *spc1= strchr( title + S(prefix), ' '); REQUIRE(spc1);
+ char *spc2= strrchr((title + len) - S(suffix), ' '); REQUIRE(spc2);
-#define ASSIGN(what, start, end) \
- what= masprintf("%.*s", (end)-(start), start); \
- if (o_##what) REQUIRE( !strcasecmp(o_##what, what) ); \
- else
+ REQUIRE( (title + len) - spc1 >= S(onthe) + S(suffix) );
+ REQUIRE( spc2 - title >= S(prefix) + S(onthe) );
- ASSIGN(ocean, spc1 + S(onthe), (title + len) - S(suffix));
- ASSIGN(pirate, title + S(prefix), spc1);
+ REQUIRE( !memcmp(title, prefix, S(prefix)) );
+ REQUIRE( !memcmp(title + len - S(suffix), suffix, S(suffix)) );
+ REQUIRE( !memcmp(spc1, onthe, S(onthe)) );
- debugfind(" YES!\n");
- id= w2;
- nfound++;
- progress_log("found YPP client (0x%lx):"
- " %s ocean - %s.",
- (unsigned long)id, ocean, pirate);
- }
- if (children2) XFree(children2);
+#define ASSIGN(what, start, end) \
+ what= masprintf("%.*s", (int)((end)-(start)), start); \
+ if (o_##what) REQUIRE( !strcasecmp(o_##what, what) ); \
+ else
+
+ ASSIGN(ocean, spc1 + S(onthe), (title + len) - S(suffix));
+ ASSIGN(pirate, title + S(prefix), spc1);
+
+ debugfind(" YES!\n");
+ id= w;
+ nfound++;
+ progress_log("found YPP client (0x%lx):"
+ " %s ocean - %s.",
+ (unsigned long)id, ocean, pirate);
+}
+
+void find_yppclient_window(void) {
+ int targetdepth;
+
+ nfound=0;
+
+ if (id) return;
+
+ progress("looking for YPP client window...");
+
+ xassert( (wm_name= XInternAtom(disp,"WM_NAME",True)) != None);
+
+ for (targetdepth=1; targetdepth<4; targetdepth++) {
+ for (screen=0; screen<ScreenCount(disp); screen++) {
+ debugfind("FINDYPP screen %d\n", screen);
+ findypp_recurse(0,targetdepth, RootWindow(disp,screen));
}
- if (children1) XFree(children1);
+ if (nfound) break;
}
+
if (nfound>1)
fatal("Found several possible YPP clients. Close one,\n"
" disambiguate with --pirate or --ocean,"