00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "Image/Image.H"
00039 #include "Image/Pixels.H"
00040 #include "GUI/AutomateXWin.H"
00041
00042
00043
00044 #define SHIFTL(x,i) (((i) >= 0) ? ((x) << (i)) : ((x) >> (-i)))
00045
00046
00047 AutomateXWin::AutomateXWin(const char* win_name) :
00048 itsDisplay(NULL),
00049 itsScreen(0),
00050 itsImage(NULL),
00051 itsWidth(0),
00052 itsHeight(0),
00053 itsDepth(0)
00054
00055 {
00056 char *dispName = XDisplayName(NULL);
00057 unsigned num_tries;
00058 int event_base, error_base;
00059 int major_version, minor_version;
00060
00061 itsDisplay = XOpenDisplay(dispName);
00062 if(!itsDisplay)
00063 LFATAL("XOpenDisplay(%s) failed\n", dispName);
00064
00065 if (!XTestQueryExtension (itsDisplay, &event_base, &error_base, &major_version, &minor_version)) {
00066 XCloseDisplay(itsDisplay);
00067 LFATAL("XTest extension not supported on server");
00068 }
00069
00070 LINFO("XTestQueryExtension passed.");
00071 LINFO("XTest information for server \"%s\":", DisplayString(itsDisplay));
00072 LINFO(" Major version: %d", major_version);
00073 LINFO(" Minor version: %d", minor_version);
00074 LINFO(" First event number: %d", event_base);
00075 LINFO(" First error number: %d", error_base);
00076
00077
00078 itsScreen = DefaultScreen(itsDisplay);
00079
00080 itsRootWin = RootWindow(itsDisplay, itsScreen);
00081
00082 for(num_tries=0;;)
00083 {
00084 itsWindow = XWindowByName(itsDisplay, itsRootWin, win_name);
00085 if(itsWindow) break;
00086 if(++num_tries == 100)
00087 LFATAL("XWindowByName\n");
00088 usleep(20000);
00089 }
00090
00091 XFlush(itsDisplay);
00092 XSync(itsDisplay, False);
00093 #ifdef USE_SHM
00094 if(!XShmQueryExtension(itsDisplay))
00095 LFATAL("XShmQueryExtension");
00096 #endif
00097 GetWindowGeometry();
00098
00099 if(!XMatchVisualInfo(itsDisplay, itsScreen, itsDepth, DirectColor, &itsVInfo))
00100 {
00101 return;
00102 }
00103
00104 }
00105
00106
00107
00108 AutomateXWin::~AutomateXWin()
00109 {
00110 if(!itsImage) return;
00111
00112 #ifdef USE_SHM
00113 XShmDetach(itsDisplay, &itsShminfo);
00114 XDestroyImage(itsImage);
00115 itsImage = NULL;
00116 shmdt(itsShminfo.shmaddr);
00117 #endif
00118
00119 }
00120
00121
00122 void AutomateXWin::setFocus()
00123 {
00124 XSetInputFocus(itsDisplay, itsWindow, RevertToNone, CurrentTime);
00125 }
00126
00127
00128 Image<PixRGB<byte> > AutomateXWin::getImage()
00129 {
00130
00131
00132 DeleteImage();
00133 #ifdef USE_SHM
00134 if(!itsImage)
00135 {
00136 itsImage = XShmCreateImage(itsDisplay, itsVInfo.visual,
00137 itsDepth,
00138 ZPixmap,
00139 NULL,
00140 &itsShminfo,
00141 itsWidth,
00142 itsHeight);
00143 if(!itsImage)
00144 {
00145 LERROR("XShmCreateImage");
00146 return Image<PixRGB<byte> >();
00147 }
00148
00149 itsShminfo.shmid = shmget(IPC_PRIVATE,
00150 itsImage->bytes_per_line * itsImage->height,
00151 IPC_CREAT | 0777);
00152 if(itsShminfo.shmid < 0)
00153 {
00154 LERROR("shmget");
00155 XDestroyImage(itsImage);
00156 itsImage=NULL;
00157 return Image<PixRGB<byte> >();
00158 }
00159 itsShminfo.shmaddr = (char *) shmat(itsShminfo.shmid, 0, 0);
00160 if(itsShminfo.shmaddr == (char *)-1)
00161 {
00162 LERROR("shmat");
00163 XDestroyImage(itsImage);
00164 return Image<PixRGB<byte> >();
00165 }
00166 shmctl(itsShminfo.shmid, IPC_RMID, 0),
00167 itsImage->data = itsShminfo.shmaddr;
00168 itsShminfo.readOnly = False;
00169 XShmAttach(itsDisplay, &itsShminfo);
00170
00171 XSync(itsDisplay, False);
00172 }
00173 #endif
00174
00175 if(!itsImage)
00176 {
00177 itsImage = XGetImage(itsDisplay, itsWindow,
00178 0, 0,
00179 itsWidth,
00180 itsHeight,
00181 AllPlanes,
00182 XYPixmap);
00183 if(!itsImage)
00184 LERROR("XGetImage\n");
00185 }
00186 #ifdef USE_SHM
00187 if(!XShmGetImage(itsDisplay, itsWindow, itsImage,
00188 0, 0,
00189 AllPlanes))
00190 LERROR("XSHMGetImage");
00191 #endif
00192
00193 Image<PixRGB<byte> > img(itsWidth,itsHeight,NO_INIT);
00194 int rshift = 7 - getHighBitIndex (itsImage->red_mask);
00195 int gshift = 7 - getHighBitIndex (itsImage->green_mask);
00196 int bshift = 7 - getHighBitIndex (itsImage->blue_mask);
00197
00198 for (int y=0; y<itsImage->height; y++) {
00199 for (int x=0; x<itsImage->width; x++) {
00200 unsigned long pixel = XGetPixel (itsImage,x,y);
00201 PixRGB<byte> pixVal(
00202 SHIFTL(pixel & itsImage->red_mask,rshift),
00203 SHIFTL(pixel & itsImage->green_mask,gshift),
00204 SHIFTL(pixel & itsImage->blue_mask,bshift)
00205 );
00206 img.setVal(x,y, pixVal);
00207 }
00208 }
00209
00210 return img;
00211
00212 }
00213
00214 void AutomateXWin::DeleteImage(void)
00215 {
00216 if(!itsImage) return;
00217
00218 #ifndef USE_SHM
00219 XDestroyImage(itsImage);
00220 itsImage = NULL;
00221 #endif
00222 }
00223
00224
00225 void AutomateXWin::sendKey(const int key)
00226 {
00227 XTestFakeKeyEvent(itsDisplay, key, True, CurrentTime);
00228 XTestFakeKeyEvent(itsDisplay, key, False, CurrentTime);
00229 XSync(itsDisplay, True);
00230 }
00231
00232
00233
00234
00235 int AutomateXWin::getHighBitIndex (unsigned int x)
00236 {
00237 int i = 0;
00238 while (x) {
00239 i++;
00240 x >>= 1;
00241 }
00242 return i-1;
00243 }
00244
00245
00246 void AutomateXWin::GetWindowGeometry()
00247 {
00248 unsigned border_width;
00249 int xpos, ypos;
00250 Window root;
00251
00252 if(!XGetGeometry(
00253 itsDisplay, itsWindow, &root,
00254 &xpos, &ypos,
00255 &itsWidth, &itsHeight,
00256 &border_width,
00257 &itsDepth))
00258 {
00259 LERROR("XGetGeometry\n");
00260 }
00261 LINFO("width=%u, height=%u, depth=%u\n", itsWidth, itsHeight, itsDepth);
00262
00263 }
00264
00265
00266 Window AutomateXWin::XWindowByName(Display *display, const Window rootwin, const char *name)
00267 {
00268 unsigned int num_children;
00269 Window *children, child, window;
00270 XTextProperty windowname;
00271
00272 if(XGetWMName(display, rootwin, &windowname) != 0)
00273 {
00274 LINFO("Window='%s'\n", (const char *)windowname.value);
00275 if(!strcmp((const char *)windowname.value, name))
00276 return rootwin;
00277 }
00278
00279 window = (Window) NULL;
00280
00281 if(XQueryTree(display, rootwin, &child, &child, &children, &num_children))
00282 {
00283 unsigned i;
00284 for(i=0; i < num_children; ++i)
00285 {
00286
00287 window = XWindowByName(display, children[i], name);
00288 if(window != (Window) NULL)
00289 break;
00290 }
00291 if (children != (Window *)NULL)
00292 XFree((void *)children);
00293 }
00294 return window;
00295 }
00296
00297
00298 void AutomateXWin::XListWindows(Display *display, const Window rootwin)
00299 {
00300 unsigned int num_children;
00301 Window *children, child;
00302 XTextProperty windowname;
00303
00304 if(XGetWMName(display, rootwin, &windowname) != 0)
00305 LINFO(" '%s'\n", (const char *)windowname.value);
00306
00307 if(XQueryTree(display, rootwin, &child, &child, &children, &num_children))
00308 {
00309 unsigned i;
00310 for(i=0; i < num_children; ++i)
00311 {
00312
00313 XListWindows(display, children[i]);
00314 }
00315 if (children != (Window *)NULL)
00316 XFree((void *)children);
00317 }
00318 }
00319
00320
00321
00322
00323
00324
00325
00326