#include #include #include #include #include #include #include #include #include #include #include pid_t child_pid = 0; void die(int sig) { if (child_pid) kill(child_pid, SIGKILL); fprintf(stderr, "test died\n"); exit(0); } static void notify(const char * message) { printf("%d [%ld]: %s\n", getpid(), (long) time(NULL), message); fflush(stdout); } /* * The "main" display. */ Display * Dsp = NULL; /* * Two displays used for the test. */ Display * display = NULL; Display * client2 = NULL; /* * Creates a window with the default visual type. */ Window defwin(Display * disp) { XVisualInfo vi; XVisualInfo * vp; int Nvis = 0; Window w; XEvent event; XSetWindowAttributes atts; Colormap cmap; /* Find a default visual. */ vi.screen = DefaultScreen(disp); vp = XGetVisualInfo(disp, VisualScreenMask, &vi, &Nvis); if (vp == NULL || Nvis == 0) { fprintf(stderr, "XGetVisualInfo() did not return any valid format.\n"); return (Window) 0; } if (vp->visual == 0) { fprintf(stderr, "Default visual has no usable drawable.\n"); return (Window) 0; } atts.override_redirect = 0; atts.border_pixel = BlackPixel(disp, vp->screen); atts.background_pixel = WhitePixel(disp, vp->screen); switch (vp->class) { case StaticGray: case StaticColor: case TrueColor: cmap = XCreateColormap( disp, RootWindow(disp, vp->screen), vp->visual, AllocNone ); break; case GrayScale: case PseudoColor: case DirectColor: cmap = XCreateColormap( disp, RootWindow(disp, vp->screen), vp->visual, AllocAll ); break; default: fprintf(stderr, "Unrecognized color class.\n"); return (Window) 0; } atts.colormap = cmap; w = XCreateWindow( disp, RootWindow(disp, vp->screen), 0, 0, /* X and Y position (in pixels) */ 320, 240, /* width, height (in pixels) */ 1, /* border width (in pixels) */ vp->depth, InputOutput, vp->visual, CWOverrideRedirect | CWBorderPixel | CWBackPixel | CWColormap, &atts ); if (w == (Window) 0) { fprintf(stderr, "XCreateWindow() failed.\n"); return (Window) 0; } XSelectInput(disp, w, ExposureMask); XMapWindow(disp, w); XWindowEvent(disp, w, ExposureMask, &event); XSelectInput(disp, w, PropertyChangeMask); XSync(disp, True); return w; } Atom at; Window win; char *atname = "XT_TEST_Atom"; #define WAITTIME 3 static void t006p() { XEvent ev; display = XOpenDisplay(NULL); if (display == NULL) { fprintf(stderr, "XOpenDisplay() returned NULL.\n"); exit(1); } XSelectInput(display, win, PropertyChangeMask); XSync(display, False); notify("establishing a server grab"); XGrabServer(display); XSync(display, False); notify("giving the child time to post an event"); sleep(WAITTIME); if(XCheckWindowEvent(display, win, PropertyChangeMask, &ev) == True) notify("A request was processed for a non-grabbing client"); notify("the grab seems to work, now closing the display"); XCloseDisplay(display); display = NULL; notify("waiting for the child to react on the ungrab"); waitpid(child_pid, 0, 0); sleep(WAITTIME); if(XCheckWindowEvent(Dsp, win, PropertyChangeMask, &ev) == False) notify("could not ungrab the server"); notify("success"); } static void t006c() { long val = 1332; notify("child: trying to post an event (should block until the display is ungrabbed)"); XChangeProperty(client2, win, at, XA_INTEGER, 32, PropModeReplace, (unsigned char *) &val, 1); XSync(client2, False); notify("child: closing connection"); XCloseDisplay(client2); notify("child: exiting"); exit(0); } void do_test() { Dsp = XOpenDisplay(NULL); if (Dsp == NULL) { fprintf(stderr, "XOpenDisplay() returned NULL.\n"); goto cleanup; } win = defwin(Dsp); if (win == 0) { fprintf(stderr, "Could not open window.\n"); goto cleanup; } client2 = XOpenDisplay(NULL); if (client2 == NULL) { fprintf(stderr, "XOpenDisplay() returned NULL.\n"); XCloseDisplay(display); goto cleanup; } XSelectInput(client2, win, PropertyChangeMask); at = XInternAtom(Dsp, atname, False); notify("spawning a child process"); child_pid = fork(); if (child_pid < 0) { fprintf(stderr, "fork() failed.\n"); goto cleanup; } if (child_pid == 0) { /* This is the child process. */ notify("this is the child"); t006c(); notify("child function failed to exit"); abort(); } client2 = 0; /* This is the parent process. */ t006p(); cleanup: notify("cleaning up:"); if (display) { notify("(cleanup) closing the testing display #1"); XCloseDisplay(display); display = NULL; } if (client2) { notify("(cleanup) closing the testing display #2"); XCloseDisplay(client2); client2 = NULL; } if (Dsp) { notify("(cleanup) closing the main display"); XCloseDisplay(Dsp); Dsp = NULL; } } int main(int argc, char ** argv) { struct itimerval v = {{0, 0}, {0, 0}}; v.it_value.tv_sec = 15; setitimer(ITIMER_REAL, &v, 0); signal(SIGALRM, die); do_test(); notify("Test finished"); return 0; }