// ###################################################################### AutomateXWin::AutomateXWin(const char* win_name) : itsDisplay(NULL), itsScreen(0), itsImage(NULL), itsWidth(0), itsHeight(0), itsDepth(0) { char *dispName = XDisplayName(NULL); unsigned num_tries; int event_base, error_base; int major_version, minor_version; itsDisplay = XOpenDisplay(dispName); if(!itsDisplay) LFATAL("XOpenDisplay(%s) failed\n", dispName); if (!XTestQueryExtension (itsDisplay, &event_base, &error_base, &major_version, &minor_version)) { XCloseDisplay(itsDisplay); LFATAL("XTest extension not supported on server"); } LINFO("XTestQueryExtension passed."); LINFO("XTest information for server \"%s\":", DisplayString(itsDisplay)); LINFO(" Major version: %d", major_version); LINFO(" Minor version: %d", minor_version); LINFO(" First event number: %d", event_base); LINFO(" First error number: %d", error_base); itsScreen = DefaultScreen(itsDisplay); itsRootWin = RootWindow(itsDisplay, itsScreen); for(num_tries=0;;) { itsWindow = XWindowByName(itsDisplay, itsRootWin, win_name); if(itsWindow) break; if(++num_tries == 100) LFATAL("XWindowByName\n"); usleep(20000); } XFlush(itsDisplay); XSync(itsDisplay, False); #ifdef USE_SHM if(!XShmQueryExtension(itsDisplay)) LFATAL("XShmQueryExtension"); #endif GetWindowGeometry(); if(!XMatchVisualInfo(itsDisplay, itsScreen, itsDepth, DirectColor, &itsVInfo)) { return; } }
/*********************************************************************** * Event Handler to reparent client window under plugin window ***********************************************************************/ /* static */ void SubstructureRedirectHandler ( Widget widget, XtPointer client_data, XEvent* event, Boolean* cont) { windowrec* new_list; PluginInstance* This = (PluginInstance*) client_data; #ifdef PLUGIN_TRACE fprintf (stderr, "%s\n", "SubstructureRedirectHandler"); fprintf (stderr, "This: 0x%x\n", This); #endif switch (event->type) { case ConfigureRequest: { XWindowChanges config; config.x = event->xconfigurerequest.x; config.y = event->xconfigurerequest.y; config.width = event->xconfigurerequest.width; config.height = event->xconfigurerequest.height; config.border_width = event->xconfigurerequest.border_width; config.sibling = event->xconfigurerequest.above; config.stack_mode = event->xconfigurerequest.detail; #if 0 fprintf (stderr, "configuring at %dx%d+%d+%d\n", config.width, config.height, config.x, config.y); #endif XConfigureWindow (RxGlobal.dpy, event->xconfigurerequest.window, event->xconfigurerequest.value_mask, &config); } break; case MapRequest: RxpSetStatusWidget(This, RUNNING); { Window for_win; int i; if (XGetTransientForHint (RxGlobal.dpy, event->xmaprequest.window, &for_win)) { for (i = 0; i < This->nclient_windows; i++) if (for_win == This->client_windows[i].win) XMapWindow (RxGlobal.dpy, event->xmaprequest.window); return; } } new_list = (windowrec*) NPN_MemAlloc (sizeof (windowrec) * (This->nclient_windows + 1)); if (new_list) { Position x, y; Dimension width, height; Dimension border_width; Colormap cmap; int n; Atom* wm_proto; windowrec* wp; Window destwin = XtWindow (This->plugin_widget); This->nclient_windows++; if (This->nclient_windows > 1) memcpy ((void*) new_list, (void*) This->client_windows, (This->nclient_windows - 1) * sizeof (windowrec)); if (This->client_windows) NPN_MemFree (This->client_windows); This->client_windows = new_list; x = y = 0; width = height = border_width = 0; GetWindowGeometry (RxGlobal.dpy, event->xmaprequest.window, &x, &y, &width, &height, &border_width, &cmap); wp = &This->client_windows[This->nclient_windows - 1]; wp->win = event->xmaprequest.window; wp->x = x; wp->y = y; wp->width = width; wp->height = height; wp->border_width = border_width; wp->flags = RxpMapped; wp->colormap = cmap; if (XGetWMProtocols (RxGlobal.dpy, wp->win, &wm_proto, &n)) { int i; Atom* ap; for (i = 0, ap = wm_proto; i < n; i++, ap++) { if (*ap == RxGlobal.wm_delete_window) wp->flags |= RxpWmDelWin; } if (wm_proto) XFree ((char*) wm_proto); } XSelectInput(RxGlobal.dpy, wp->win, EnterWindowMask | LeaveWindowMask); XtRegisterDrawable (RxGlobal.dpy, wp->win, This->plugin_widget); XReparentWindow (RxGlobal.dpy, wp->win, destwin, wp->x, wp->y); XMapWindow (RxGlobal.dpy, wp->win); } break; } }
// main entry point main(int argc, char **argv) { // get command line options int nextarg; if (cmdopts(argc, argv, nextarg) != OK) { fprintf(stderr, "invalid command line option [%s].\n", argv[nextarg]); return(2); } // get data if (getdata(argc, argv, nextarg) != OK) { fprintf(stderr, "unable to get data."); return(2); } // connect to server Display *xdisplay = NULL; if (OpenDisplay(display, xdisplay) != OK) { fprintf(stderr, "unable to open display to server %s.\n", XDisplayName(display)); return(2); } // get physical screen attributes int xscreen; unsigned int display_width, display_height; if (GetDisplayAttributes(xdisplay, xscreen, display_width, display_height) != OK) { fprintf(stderr, "unable to get display attributes.\n"); CloseDisplay(xdisplay); return(2); } // determine window geometry and location int window_width, window_height, window_x, window_y; if (GetWindowGeometry(display_width, display_height, window_width, window_height, window_x, window_y) != OK) { fprintf(stderr, "unable to get window geometry.\n"); CloseDisplay(xdisplay); return(2); } // default black and white pixels unsigned long black = BlackPixel(xdisplay, xscreen); unsigned long white = WhitePixel(xdisplay, xscreen); // get pseudo-color display, if any int window_depth; Visual *window_visual; if (GetPseudoColorVisual(xdisplay, xscreen, window_visual, window_depth) != OK) { fprintf(stderr, "unable to get a color visual.\n"); CloseDisplay(xdisplay); return(2); } // create a window unsigned int window_border_width = 4; Window root_window = RootWindow(xdisplay, xscreen); window_visual=CopyFromParent; window_depth=CopyFromParent; Window window = CreateWindow( xdisplay, root_window, window_x, window_y, window_width, window_height, black, white, EventMask, window_visual, window_border_width, window_depth); // set size hints if (SetSizeHints(xdisplay, window, window_x, window_y, window_width, window_height) != OK) { fprintf(stderr, "unable to set window size hints.\n"); CloseDisplay(xdisplay); return(2); } // set window name if (SetWindowName(xdisplay, window, title) != OK) { fprintf(stderr, "unable to set window title.\n"); CloseDisplay(xdisplay); return(2); } // set class hints if (SetClassHints(xdisplay, window, argv[0], argv[0]) != OK) { fprintf(stderr, "unable to set class hints.\n"); CloseDisplay(xdisplay); return(2); } // set other window manager hints int initstate = (strcmp(iconic, "YES") == 0) ? IconicState : NormalState; if (SetWMHints(xdisplay, window, initstate) != OK) { fprintf(stderr, "unable to set WM hints.\n"); CloseDisplay(xdisplay); return(2); } // set up color map for window Colormap window_colormap; if (SetUpColorMap(xdisplay, xscreen, window, window_visual, window_colormap) != OK) { fprintf(stderr, "unable to set up a color map.\n"); CloseDisplay(xdisplay); return(2); } // allocate colors for background and foreground unsigned long window_background = AllocateColorByName(xdisplay, window_colormap, background, white); unsigned long window_foreground = AllocateColorByName(xdisplay, window_colormap, foreground, black); // get font for writing XFontStruct *xfont = LoadFont(xdisplay, font, "fixed"); if (xfont == NULL) { fprintf(stderr, "unable to load font.\n"); CloseDisplay(xdisplay); return(2); } // create GC for drawing GC gc = CreateGC(xdisplay, window, xfont, window_foreground, window_background); GC xor_gc = CreateXorGC(xdisplay, window, xfont, window_foreground, window_background); // map window XMapRaised(xdisplay, window); XFlush(xdisplay); // event loop int start_x = -1; int start_y = -1; int last_x = -1; int last_y = -1; XEvent event; KeySym keysym; char string[BUFSIZ]; for (int done = 0; !done; ) { XNextEvent(xdisplay, &event); switch (event.type) { case Expose: if (event.xexpose.count == 0) { redraw(xdisplay, window, gc, xfont, window_width, window_height); } break; case ConfigureNotify: window_x = event.xconfigure.x; window_y = event.xconfigure.y; window_width = event.xconfigure.width; window_height = event.xconfigure.height; break; case KeyPress: done = DecodeKeyPress(&event.xkey, &keysym, string); break; case MappingNotify: XRefreshKeyboardMapping(&event.xmapping); break; case ButtonPress: if (event.xbutton.button == Button1) { start_x = event.xbutton.x; start_y = event.xbutton.y; last_x = start_x; last_y = start_y; DrawBox(xdisplay, window, xor_gc, start_x, start_y, last_x, last_y); XFlush(xdisplay); } break; case ButtonRelease: if (event.xbutton.button == Button1) { if (start_x != last_x && start_y != last_y) { DrawBox(xdisplay, window, xor_gc, start_x, start_y, last_x, last_y); XFlush(xdisplay); UpdateLimits(start_x, start_y, last_x, last_y, window_width, window_height); XClearWindow(xdisplay, window); XFlush(xdisplay); redraw(xdisplay, window, gc, xfont, window_width, window_height); XFlush(xdisplay); } start_x = -1; start_y = -1; last_x = -1; last_y = -1; } else { // reset to original values. rminxval = reset_rminxval; rmaxxval = reset_rmaxxval; rminyval = reset_rminyval; rmaxyval = reset_rmaxyval; XClearWindow(xdisplay, window); XFlush(xdisplay); redraw(xdisplay, window, gc, xfont, window_width, window_height); XFlush(xdisplay); } break; case MotionNotify: if (event.xbutton.button == Button1) { DrawBox(xdisplay, window, xor_gc, start_x, start_y, last_x, last_y); last_x = event.xmotion.x; last_y = event.xmotion.y; DrawBox(xdisplay, window, xor_gc, start_x, start_y, last_x, last_y); XFlush(xdisplay); } break; } } // close display CloseDisplay(xdisplay); // all done return(0); }
/* Main driver */ int main (int argc, char **argv) { xcb_connection_t *conn; int conn_screen; xcb_screen_t *root_screen; xcb_drawable_t root_window; xcb_connection_t *conn_two; int conn_two_screen; xcb_screen_t *root_two_screen; xcb_drawable_t root_two_window; xcb_drawable_t window; uint32_t mask; uint32_t values[1]; xcb_void_cookie_t cookie; xcb_get_geometry_reply_t *geom_reply; xcb_generic_event_t *event; image_data_t img_data; xcb_image_t *image; xcb_pixmap_t pixmap; xcb_gcontext_t gc; /* Check the first argument to see what display to connect to. If empty, then use default display. */ if (argc > 1) { conn = xcb_connect(argv[1], &conn_screen); } else { conn = xcb_connect(NULL, &conn_screen); } root_screen = xcb_aux_get_screen(conn, conn_screen); root_window = root_screen->root; /* Get the geometry of the root window */ geom_reply = GetWindowGeometry(conn, root_window); WriteWindowInfo(conn, root_window); WriteAllChildrenWindowInfo(conn, root_window); img_data = GetWindowImageData(conn, root_window); xcb_flush(conn); /* Get the image of the root window */ image = xcb_image_get(conn, root_window, geom_reply->x, geom_reply->y, geom_reply->width, geom_reply->height, (unsigned int) ~0L, XCB_IMAGE_FORMAT_Z_PIXMAP); /* Set up the events the window will recognize */ mask = XCB_CW_EVENT_MASK; values[0] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS; /* Create our new window on the default display. Make it half the size */ conn_two = xcb_connect(NULL, &conn_two_screen); root_two_screen = xcb_aux_get_screen(conn_two, conn_two_screen); root_two_window = root_two_screen->root; window = xcb_generate_id(conn_two); cookie = xcb_create_window_checked(conn_two, XCB_COPY_FROM_PARENT, window, root_two_window, geom_reply->x, geom_reply->y, geom_reply->width / 2, geom_reply->height / 2, geom_reply->border_width, XCB_WINDOW_CLASS_INPUT_OUTPUT, root_two_screen->root_visual, mask, values); if (RequestCheck(conn_two, cookie, "Falied to create new window")) { exit(1); } WriteWindowInfo(conn_two, window); /* Map the window and flush the connection so it draws to the screen */ xcb_map_window(conn_two, window); xcb_flush(conn_two); WriteWindowInfo(conn_two, window); /* Create the pixmap and associate it with our new window. */ pixmap = xcb_generate_id(conn_two); cookie = xcb_create_pixmap(conn_two, geom_reply->depth, pixmap, window, geom_reply->width, geom_reply->height); if (RequestCheck(conn_two, cookie, "Failed to create pixmap")) { exit(1); } /* Put the root_window image into the pixmap. Note that a gc is * created, but I believe it is ignored. */ gc = xcb_generate_id(conn_two); xcb_create_gc(conn_two, gc, window, 0, 0); cookie = xcb_image_put(conn_two, pixmap, gc, image, 0, 0, 0); if (RequestCheck(conn_two, cookie, "Failed to put image into pixmap")) { exit(1); } /* Copy the pixmap into the new window */ cookie = xcb_copy_area(conn_two, pixmap, window, gc, 0, 0, 0, 0, geom_reply->width / 2, geom_reply->height / 2); if (RequestCheck(conn_two, cookie, "Failed to put image into pixmap")) { exit(1); } xcb_flush(conn_two); WriteWindowInfo(conn_two, window); /* Enter infinte loop so the window stays open */ while (1) { } /* Never get here, but if we could, would still want to clean up memory */ free(geom_reply); xcb_disconnect(conn); xcb_disconnect(conn_two); return 0; }