/* xfixindexwindow.c - This program automatically moves and resizes new */ /* FamilySearch indexing windows. It should be run in */ /* the background. */ /* */ /* Syntax: xfixindexwindow */ /* */ /* To compile this program, use the following command line: */ /* */ /* cc -Wall -o xfixindexwindow xfixindexwindow.c -B /usr/X11R6/lib -lX11 */ // Include header files #include #include #include #include #include #include // #include #include // #include #include #include // #include #include // Define macros // // 0=no debug; 1=usec only; 2=usec and move; 3=very verbose #define DEBUG 0 // #define DEBUGSTR "xfixindexwindow: dbg: " #define NEEDWIN1 1 #define NEEDWIN2 1 #define SLEEPUSEC 1000000 #define LENROTATION 4 #define MINSIZ 20 #define LINBUFSIZ 120 #define MINSCREEN 400 #define SIZEFRACTION 4 #define MOVEFRACTION 8 int screenwidth; // width of screen int screenheight; // height of screen int posrotation; // where in the rotation are we // arrays // // Based on the assumption that there is no such window ID as 0. // // Potentially useful prime sizes: 67, 131, 257, 521, 1031, 2053, 4099, 7919 // #define ARRAYSIZE 2053 #define ARRAYBYTES (ARRAYSIZE * sizeof(Window)) // Window arr1[ARRAYSIZE]; Window arr2[ARRAYSIZE]; Window * oldarr; Window * newarr; ///////////////////////////////////////////////////////////////////////////// // // Function capturescreensize() sets screenwidth and screenheight. // ///////////////////////////////////////////////////////////////////////////// void capturescreensize(Display * dpy) { Screen * scr; scr = DefaultScreenOfDisplay(dpy); if (NULL == scr) { // bad fprintf( stderr, "xfixindexwindow: DefaultScreenOfDisplay() returned NULL.\n" ); exit(1); } // bad screenwidth = WidthOfScreen(scr); screenheight = HeightOfScreen(scr); if ((MINSCREEN > screenwidth) || (MINSCREEN > screenheight)) { fprintf( stderr, "Warning: xfixindexwindow: Screen too small.\n" ); } } ///////////////////////////////////////////////////////////////////////////// // // Function checkwindow1() returns nonzero iff this first-level window is a // candidate window, 0 otherwise. // ///////////////////////////////////////////////////////////////////////////// int checkwindow1( Display * dpy, Window curwin) { int res; Window foundroot; int foundx; int foundy; unsigned int foundwidth; unsigned int foundheight; unsigned int foundborder; unsigned int founddepth; res = XGetGeometry( dpy, curwin, &foundroot, &foundx, &foundy, &foundwidth, &foundheight, &foundborder, &founddepth ); if (True != res) { // XGetGeometry failed fprintf( stderr, "xfixindexwindow: XGetGeometry 1 failed: win=%ld\n", curwin ); exit(1); } // XGetGeometry failed return( (MINSIZ > foundwidth) // too narrow || (MINSIZ > foundheight) // too short || (screenwidth < (foundx - MINSIZ)) // too far right || (screenheight < (foundy - MINSIZ)) // too far down || (MINSIZ > (foundx + foundwidth)) // too far left || (MINSIZ > (foundy + foundheight)) // too far up ); } ///////////////////////////////////////////////////////////////////////////// // // Function cleararray() clears an array. // ///////////////////////////////////////////////////////////////////////////// void cleararray(Window * arr) { memset( arr, 0, ARRAYBYTES); } ///////////////////////////////////////////////////////////////////////////// // // Function isnewrecord() records a first-level window, then it returns // nonzero iff this is a new first-level window, zero if it is old. // ///////////////////////////////////////////////////////////////////////////// int isnewrecord( Window * oldarr, Window * newarr, Window newone) { int startslot; int tryslot; Window oldval; startslot = (3 * newone) % ARRAYSIZE; // // record new entry // tryslot = startslot; while (0 != newarr[tryslot]) { // try to find an empty slot if (3 <= DEBUG) { printf( "%s %s %d\n", DEBUGSTR, "increment new slot: ", tryslot); fflush(stdout); } tryslot++; if (startslot == tryslot) { fprintf( stderr, "xfixindexwindow: failed to find new slot: %ld\n", newone ); exit(1); } if (ARRAYSIZE <= tryslot) { // need to wrap around tryslot = 0; } // need to wrap around } // try to find an empty slot newarr[tryslot] = newone; // // check old array // tryslot = startslot; for (;;) { // loop once per slot to try oldval = oldarr[tryslot]; if (oldval == newone) { // it's old return(0); } // it's old else if (0 == oldval) { // empty slot means it's new return(1); } // empty slot means it's new else { // need to try next slot if (3 <= DEBUG) { printf( "%s %s %d\n", DEBUGSTR, "increment old slot: ", tryslot); fflush(stdout); } tryslot++; if (startslot == tryslot) { fprintf( stderr, "xfixindexwindow: failed to find empty old slot: %ld\n", newone ); exit(1); } if (ARRAYSIZE <= tryslot) { // need to wrap around tryslot = 0; } // need to wrap around } // need to try next slot } // loop once per slot to try } ///////////////////////////////////////////////////////////////////////////// // // Function printwininfo() prints info about the target window. // ///////////////////////////////////////////////////////////////////////////// void printwininfo( Display * dpy, Window curwin) { int res; Window foundroot; int foundx; int foundy; unsigned int foundwidth; unsigned int foundheight; unsigned int foundborder; unsigned int founddepth; XTextProperty tp; char ** sarr; int nums; int j; char * s1; res = XGetGeometry( dpy, curwin, &foundroot, &foundx, &foundy, &foundwidth, &foundheight, &foundborder, &founddepth ); if (True != res) { // XGetGeometry failed fprintf( stderr, "xfixindexwindow: XGetGeometry 1 failed: win=%ld\n", curwin ); exit(1); } // XGetGeometry failed res = XGetWMName( dpy, curwin, &tp); if (DEBUG) { printf( "%s %s%d\n", DEBUGSTR, "printwininfo(): XGetWMName result:", res ); } res = XTextPropertyToStringList( &tp, &sarr, &nums); if (DEBUG) { printf( "%s %s %d, %s %d\n", DEBUGSTR, "printwininfo(): XTp2SL result:", res, "nums:", nums ); } if ((1 != res) || (0 >= nums)) { // no names printf( "%s win=%ld, x=%d, y=%d, wid=%d, hit=%d, no name\n", "printwininfo():", curwin, foundx, foundy, foundwidth, foundheight ); } // no names if (1 == res) { // check names for ( j = 0; nums > j; j++) { // per name s1 = sarr[j]; printf( "%s win=%ld, x=%d, y=%d, wid=%d, hit=%d, name=%s\n", "printwininfo():", curwin, foundx, foundy, foundwidth, foundheight, s1 ); } // per name } // check names } ///////////////////////////////////////////////////////////////////////////// // // Function movetoplace() moves a first-level window to its proper place. // ///////////////////////////////////////////////////////////////////////////// void movetoplace( Display * dpy, Window newone) { int want1width; int want1height; int targx; int targy; int res; want1width = screenwidth / SIZEFRACTION; want1height = screenheight / SIZEFRACTION; targx = posrotation * screenwidth / MOVEFRACTION; targy = posrotation * screenheight / MOVEFRACTION; posrotation++; if (LENROTATION < posrotation) { posrotation = 1; } res = XMoveWindow( dpy, newone, targx, targy); if (2 <= DEBUG) { printf( "%s %s %d\n", DEBUGSTR, "main(): XMoveWindow returned", res); fflush(stdout); } if (1 != res) { fprintf( stderr, "xfixindexwindow: XMoveWindow failed.\n"); exit(1); } res = XResizeWindow( dpy, newone, want1width, want1height); if (2 <= DEBUG) { printf( "%s %s %d\n", DEBUGSTR, "main(): XResizeWindow returned", res); fflush(stdout); } if (1 != res) { fprintf( stderr, "xfixindexwindow: XResizeWindow failed.\n"); exit(1); } } ///////////////////////////////////////////////////////////////////////////// // // Function main() is the top level. // ///////////////////////////////////////////////////////////////////////////// int main( int argc, char **argv) { Display * dpy; Window defroot; int firstpass; struct timeval timebuf; long startsec; long startusec; long endsec; long endusec; int res; Window foundroot; Window foundparent; Window * children1; unsigned int numchildren1; int i; Window curchild1; Window * tmparr; long spentusec; char linebuf[LINBUFSIZ]; // if (NULL == (dpy = XOpenDisplay(NULL))) { fprintf( stderr, "xfixindexwindow: can't open display.\n"); exit(1); } if (3 <= DEBUG) { printf( "%s %s\n", DEBUGSTR, "main(): display open."); fflush(stdout); } defroot = DefaultRootWindow(dpy); if (3 <= DEBUG) { printf( "%s %s %ld\n", DEBUGSTR, "main(): default root window:", defroot ); fflush(stdout); } // // initialize a few things // if (3 <= DEBUG) { printf( "%s %s %d\n", DEBUGSTR, "main(): array size: ", ARRAYSIZE); printf( "%s %s %d\n", DEBUGSTR, "main(): array bytes: ", ARRAYBYTES); fflush(stdout); } oldarr = arr1; newarr = arr2; cleararray(oldarr); firstpass = 1; capturescreensize(dpy); posrotation = 1; // // loop forever, looking for windows to move and moving them // for (;;) { // loop forever if (1 <= DEBUG) { // get start time printf("\n"); fflush(stdout); gettimeofday( &timebuf, NULL); startsec = timebuf.tv_sec; startusec = timebuf.tv_usec; } // get start time cleararray(newarr); res = XQueryTree( dpy, defroot, &foundroot, &foundparent, &children1, &numchildren1 ); if (1 != res) { // XQueryTree 1 failed fprintf( stderr, "xfixindexwindow: XQueryTree 1 failed.\n"); exit(1); } // XQueryTree 1 failed if (NEEDWIN1 > numchildren1) { // too few first-level windows fprintf( stderr, "xfixindexwindow: too few first-level windows.\n"); exit(1); } // too few first-level windows for ( i = 0; numchildren1 > i; i++) { // per first-level window curchild1 = children1[i]; if (3 <= DEBUG) { printf( "%s %s %ld\n", DEBUGSTR, "curchild1:", curchild1); fflush(stdout); } if (isnewrecord( oldarr, newarr, curchild1)) { // is new if (0 == firstpass) { // it's not the first pass if (2 <= DEBUG) { printf( "%s %s %ld\n", DEBUGSTR, "is new", curchild1); fflush(stdout); } if (0 != checkwindow1( dpy, curchild1)) { // it's good size if (3 <= DEBUG) { printf( "%s %s %ld\n", DEBUGSTR, "good size", curchild1); fflush(stdout); } printwininfo( dpy, curchild1); for (;;) { // ask and require an answer printf("Move/resize? (y/n) \n"); if (NULL == fgets( linebuf, LINBUFSIZ - 5, stdin)) { // error printf("xfixindexwindow: error reading input line.\n"); return(1); } // error else if ('y' == linebuf[0]) { // do move, break movetoplace( dpy, curchild1); break; // ask and require an answer } // do move, break else if ('n' == linebuf[0]) { // just break break; // ask and require an answer } // just break else { // tell user we're being picky printf("xfixindexwindow: incorrect answer, try again.\n"); } // tell user we're being picky } // ask and require an answer } // it's good size } // it's not the first pass } // is new } // per first-level window // XFree(children1); // tmparr = oldarr; // swap arrays oldarr = newarr; newarr = tmparr; firstpass = 0; if (1 <= DEBUG) { // get end time gettimeofday( &timebuf, NULL); endsec = timebuf.tv_sec; endusec = timebuf.tv_usec; spentusec = (1000000 * (endsec - startsec)) + (endusec - startusec); printf( "%s %s %ld\n", DEBUGSTR, "spent usec:", spentusec); printf("\n"); fflush(stdout); } // get end time // usleep(SLEEPUSEC); // sleep // } // loop forever }