+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 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 REQUIRE(pred) \
+ if (!(pred)) { debugfind(" failed test %s\n", #pred); continue; } \
+ else
+
+ REQUIRE( gottype!=None );
+ REQUIRE( len );
+ REQUIRE( gotfmt==8 );
+
+ REQUIRE( len >= S(prefix) + 1 + S(onthe) + 1 + S(suffix) );
+
+ char *spc1= strchr( title + S(prefix), ' '); REQUIRE(spc1);
+ char *spc2= strrchr((title + len) - S(suffix), ' '); REQUIRE(spc2);
+
+ REQUIRE( (title + len) - spc1 >= S(onthe) + S(suffix) );
+ REQUIRE( spc2 - title >= S(prefix) + S(onthe) );
+
+ REQUIRE( !memcmp(title, prefix, S(prefix)) );
+ REQUIRE( !memcmp(title + len - S(suffix), suffix, S(suffix)) );
+ REQUIRE( !memcmp(spc1, onthe, S(onthe)) );
+
+#define ASSIGN(what, start, end) do { \
+ sysassert( asprintf(&what, "%.*s", (end)-(start), start) >0 ); \
+ }while(0)
+ ASSIGN(pirate, title + S(prefix), spc1);
+ ASSIGN(ocean, spc1 + S(onthe), (title + len) - S(suffix));
+
+ 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);
+ }
+ if (children1) XFree(children1);
+ }
+ if (nfound>1)
+ fatal("Found several YPP clients."
+ " Close one, or specify the windowid with --window-id.\n");
+ if (nfound<1)
+ fatal("Did not find YPP client."
+ " Use --window-id and/or report this as a fault.\n");
+}