chiark / gitweb /
Merge branch 'master' of ijackson@chiark:things/ypp-sc-tools
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Mon, 15 Jun 2009 12:32:07 +0000 (13:32 +0100)
committerIan Jackson <Ian.Jackson@eu.citrix.com>
Mon, 15 Jun 2009 12:32:07 +0000 (13:32 +0100)
1  2 
pctb/pages.c

diff --combined pctb/pages.c
index 1fba5a64fccc2b6ccbacc952bd9efb29daa86c1f,dfa9108537bbf7b5a9c19d507a443f6caa13851c..56fb4092b8e35650586c35a4ffd18c3b400e1f70
  #include <X11/keysym.h>
  #include <X11/Xutil.h>
  
 +#include <X11/extensions/XShm.h>
 +#include <sys/ipc.h>
 +#include <sys/shm.h>
 +
  CanonImage *page_images[MAX_PAGES];
  int npages;
+ RgbImage *page0_rgbimage;
  
  char *ocean, *pirate;
  
@@@ -53,9 -50,6 +54,9 @@@ static struct timeval tv_startup
  static unsigned wwidth, wheight;
  static int max_relevant_y= -1;
  
 +static XImage *shmim;
 +static XShmSegmentInfo shminfo;
 +
  DEBUG_DEFINE_DEBUGF(pages)
  
  #define xassert(what)                                 \
@@@ -158,6 -152,19 +159,19 @@@ static void send_key(KeySym sym) 
    XTestFakeKeyEvent(disp, keycode(sym),1, 10);
    XTestFakeKeyEvent(disp, keycode(sym),0, 10);
  }
+ static void mouse_1_updown_here(void) {
+   check_not_disturbed();
+   XTestFakeButtonEvent(disp,1,1, 50);
+   XTestFakeButtonEvent(disp,1,0, 50);
+ }
+ static void mouse_1_updown(int x, int y) {
+   check_not_disturbed();
+   int screen= XScreenNumberOfScreen(attr.screen);
+   int xpos, ypos;
+   translate_coords_toroot(x,y, &xpos,&ypos);
+   XTestFakeMotionEvent(disp, screen, xpos,ypos, 0);
+   mouse_1_updown_here();
+ }
  
  static int pgupdown;
  
@@@ -314,71 -321,16 +328,65 @@@ static void raise_and_get_details(void
      fatal("YPP client window is implausibly small?");
  
    check_client_window_all_on_screen();
 +
 +  int shm= XShmQueryExtension(disp);
 +  if (shm) {
 +    xassert( shmim= XShmCreateImage(disp, attr.visual, attr.depth, ZPixmap,
 +                                  0,&shminfo, wwidth,wheight) );
 +
 +    sigset_t oldset, all;
 +    sigfillset(&all);
 +    sysassert(! sigprocmask(SIG_BLOCK,&all,&oldset) );
 +
 +    int pfd[2];
 +    pid_t cleaner;
 +    sysassert(! pipe(pfd) );
 +    sysassert( (cleaner= fork()) != -1 );
 +    if (!cleaner) {
 +      sysassert(! close(pfd[1]) );
 +      for (;;) {
 +      int r= read(pfd[0], &shminfo.shmid, sizeof(shminfo.shmid));
 +      if (!r) exit(0);
 +      if (r==sizeof(shminfo.shmid)) break;
 +      assert(r==-1 && errno==EINTR);
 +      }
 +      for (;;) {
 +      char bc;
 +      int r= read(pfd[0],&bc,1);
 +      if (r>=0) break;
 +      assert(r==-1 && errno==EINTR);
 +      }
 +      sysassert(! shmctl(shminfo.shmid,IPC_RMID,0) );
 +      exit(0);
 +    }
 +    sysassert(! close(pfd[0]) );
 +
 +    sysassert(! sigprocmask(SIG_SETMASK,&oldset,0) );
 +
 +    assert(shmim->height == wheight);
 +    sysassert( (shminfo.shmid=
 +              shmget(IPC_PRIVATE, shmim->bytes_per_line * wheight,
 +                     IPC_CREAT|0600)) >= 0 );
 +
 +    sysassert( write(pfd[1],&shminfo.shmid,sizeof(shminfo.shmid)) ==
 +             sizeof(shminfo.shmid) );
 +    sysassert( shminfo.shmaddr= shmat(shminfo.shmid,0,0) );
 +    shmim->data= shminfo.shmaddr;
 +    shminfo.readOnly= False;
 +    xassert( XShmAttach(disp,&shminfo) );
 +
 +    close(pfd[1]); /* causes IPC_RMID */
 +  }
  }
  
- static void set_focus(void) {
+ static void set_focus_commodity(void) {
    int screen= XScreenNumberOfScreen(attr.screen);
  
    progress("taking control of YPP client window...");
  
    debugf("PAGING set_focus\n");
  
-   int xpos, ypos;
-   translate_coords_toroot(160,160, &xpos,&ypos);
-   XTestFakeMotionEvent(disp,screen, xpos,ypos, 0);
-   XTestFakeButtonEvent(disp,1,1, 50);
-   XTestFakeButtonEvent(disp,1,0, 50);
+   mouse_1_updown(160,160);
    sync_after_input();
  
    delay(0.5);
                        FocusChangeMask
                        ) );
  
+   int xpos,ypos;
    translate_coords_toroot(10,10, &xpos,&ypos);
    XTestFakeMotionEvent(disp,screen, xpos,ypos, 0);
  
@@@ -420,7 -373,7 +429,7 @@@ static void compute_shift_mask(ShMask *
    assert(sm->rshift < LONG_BIT);
  }
  
- static CanonImage *convert_page(Snapshot *sn) {
+ static CanonImage *convert_page(Snapshot *sn, RgbImage *ri) {
    ShMask shiftmasks[3];
    CanonImage *im;
  
        rgb |= sample;
        fputc(sample, screenshot_file);
      }
+     if (ri)
+       CANONIMG_ALSO_STORERGB(ri);
    });
  
    sysassert(!ferror(screenshot_file));
    return im;
  }
  
- void take_screenshots(void) {
-   Snapshot *current=0, *last=0;
+ static void prepare_ypp_client(void) {
    CanonImage *test;
+   Snapshot *current=0;
+   
    /* find the window and check it's on the right kind of screen */
    raise_and_get_details();
    wait_for_stability(&current,0,0, "checking current YPP client screen...");
-   test= convert_page(current);
+   test= convert_page(current, 0);
    find_structure(test, &max_relevant_y);
    check_correct_commodities();
    free(test);
+   free_snapshot(&current);
+   progress("requesting status information...");
+   mouse_1_updown(250, wheight-10);
+   mouse_1_updown_here();
+   mouse_1_updown_here();
+   XSync(disp,False);
+   check_not_disturbed();
+   send_key(XK_slash);
+   send_key(XK_w);
+   send_key(XK_Return);
+   sync_after_input();
+ }
  
+ void take_screenshots(void) {
+   Snapshot *current=0, *last=0;
+   prepare_ypp_client();
+   
    /* page to the top - keep pressing page up until the image stops changing */
-   set_focus();
+   set_focus_commodity();
    wait_for_stability(&current,0, send_pgup_many,
                     "paging up to top of commodity list...");
  
        fatal("Paging down seems to generate too many pages - max is %d.",
            MAX_PAGES);
      
-     page_images[npages]= convert_page(current);
+     page_images[npages]= convert_page(current, 0);
      free_snapshot(&last); last=current; current=0;
  
      debugf("PAGING page %d converted\n",npages);
  
  void take_one_screenshot(void) {
    Snapshot *current=0;
-   
-   raise_and_get_details();
-   sync_after_input();
+   prepare_ypp_client();
    wait_for_stability(&current,0,0, "taking screenshot...");
-   page_images[0]= convert_page(current);
+   page0_rgbimage= alloc_rgb_image(current->width, current->height);
+   page_images[0]= convert_page(current, 0);
    npages= 1;
    progress_log("collected single screenshot.");
  }