void CarioQImageMainWindow::on_draw_widget_button_clicked()
{
    int height = ui->label->height();
    int width = ui->label->width();
    const QX11Info& info = ui->label->x11Info();
    Drawable drawable = ui->label->handle();
    Display* display = info.display();
    Screen* screen = XScreenOfDisplay(display, info.screen());
    Visual* visual = reinterpret_cast<Visual*>(info.visual());
    XRenderPictFormat *format = XRenderFindVisualFormat(display, visual);

    //cairo_surface_t * pCairoSurface = cairo_xlib_surface_create_with_xrender_format(
    //            display, drawable, screen, format, width, height);
    cairo_surface_t * pCairoSurface = cairo_xlib_surface_create(
        display, drawable, visual,
                width, height);

    cairo_t* pCairoContext = cairo_create(pCairoSurface);
    cairo_surface_destroy(pCairoSurface);
    if(pCairoContext)
    {
        cairo_set_source_rgb (pCairoContext, 0.627, 0, 0);
        cairo_set_font_size (pCairoContext, 24.0);

        cairo_move_to (pCairoContext, 10.0, 34.0);
        cairo_show_text (pCairoContext, "Using X11 Surface");

        cairo_destroy(pCairoContext);
    }
//    ui->label->update();
}
Пример #2
0
void
x11_draw_glyphs( Drawable            drawable,
                 GC                  gc,
                 PangoFont          *font,
                 int                 x,
                 int                 y,
                 PangoGlyphString   *glyphs,
                 wxColour           &colour )
{
    if (PANGO_XFT_IS_FONT (font))
    {
        Display* xdisplay = wxGlobalDisplay();
        int xscreen = DefaultScreen( xdisplay );
        Visual* xvisual = DefaultVisual( xdisplay, xscreen );

        Colormap xcolormap = DefaultColormapOfScreen( XScreenOfDisplay( xdisplay, xscreen ) );

        XftDraw *draw = XftDrawCreate( xdisplay, drawable, xvisual, xcolormap );
        XftColor color;
        color.pixel = 0;
        color.color.red = colour.Red() << 8;
        color.color.green = colour.Green() << 8;
        color.color.blue = colour.Blue() << 8;
        color.color.alpha = 65000;
        pango_xft_render( draw, &color, font, glyphs, x, y );

        XftDrawDestroy( draw );
    }
}
Пример #3
0
static cairo_bool_t
_cairo_boilerplate_xlib_check_screen_size (Display *dpy,
					   int	    screen,
					   int	    width,
					   int	    height)
{
    Screen *scr = XScreenOfDisplay (dpy, screen);
    return width <= WidthOfScreen (scr) && height <= HeightOfScreen (scr);
}
Пример #4
0
Screen *
XpGetScreenOfContext (
    Display    *dpy,
    XPContext  print_context
)
{
    xPrintGetContextScreenReq     *req;
    xPrintGetContextScreenReply   rep;
    XExtensionVersion             *ext;
    XExtDisplayInfo *info = (XExtDisplayInfo *) xp_find_display (dpy);

    int    i;
    Screen *checkScr;
    Screen *screen;
    int    ok;


    if (XpCheckExtInit(dpy, XP_DONT_CHECK) == -1)
        return ( (Screen *) NULL ); /* No such extension */

    LockDisplay (dpy);

    GetReq(PrintGetContextScreen,req);
    req->reqType = info->codes->major_opcode;
    req->printReqType = X_PrintGetContextScreen;

    req->printContext = print_context;

    if (! _XReply (dpy, (xReply *) &rep, 0, xTrue)) {
        UnlockDisplay(dpy);
        SyncHandle();
        return ( (Screen *) NULL ); /* No such extension */
    }

    /*
     * Pull rootWindow ID and convert to the corresponding
     * Screen rec.
     */
    ok = False;

    for ( i = 0; i < XScreenCount(dpy); i++ ) {
	checkScr = XScreenOfDisplay(dpy, i);
	if ( XRootWindowOfScreen( checkScr ) == (Window) rep.rootWindow  ) {
	    ok = True;
	    break;
	}
    }

    if (!ok)
	checkScr = (Screen *) NULL;

    UnlockDisplay(dpy);
    SyncHandle();

    return ( (Screen *) checkScr );
}
Пример #5
0
unsigned long X11Info::appRootWindow(int screen)
{
#ifdef HAVE_QT5
    return screen == -1?
           XDefaultRootWindow(display()) :
           XRootWindowOfScreen(XScreenOfDisplay(display(), screen));
#else
    return QX11Info::appRootWindow(screen);
#endif
}
Пример #6
0
    extern void wm_init_window(struct wm * wm,
                               struct window * w,
                               const char * name,
                               int x, int y, int width, int height,
                               unsigned options) {
        assert(wm);
        assert(w);
        assert(name);

        const bool is_double_buffered = false;//WINDOW_OPTION_DOUBLE_BUFFERED & options;
        XVisualInfo * vinfo = glXChooseVisual(wm->display, wm->default_screen, is_double_buffered ? VI_ATTR : VI_ATTR_SINGLE_BUFFERED);
        assert(vinfo);

        Window root = XRootWindow(wm->display, vinfo->screen);
        assert(root);

        if(WINDOW_OPTION_FULLSCREEN & options) {
            const Screen * s = XScreenOfDisplay(wm->display, wm->default_screen);
            x = 0;
            y = 0;
            width = s->width;
            height = s->height;
        }

        Colormap cmap = XCreateColormap(wm->display, root, vinfo->visual, AllocNone);
        XSetWindowAttributes attr;
        attr.background_pixel = 0;
        attr.border_pixel = 0;
        attr.colormap = cmap;
        attr.event_mask = EVENT_MASK;

        ::Window window = XCreateWindow(
                wm->display,
                root,
                x, y, static_cast<unsigned>(width), static_cast<unsigned>(height),
                0,  /* no border */
                vinfo->depth,
                InputOutput,
                vinfo->visual,
                VALUE_MASK,
                &attr
        );
        assert(window);

        w->display = wm->display;
        w->w = window;
        w->colormap = cmap;
        w->vinfo = vinfo;

        if(WINDOW_OPTION_FULLSCREEN & options) _set_fullscreen(w);
        if(name) window_set_name(w, name);
        if(!(WINDOW_OPTION_HIDDEN & options)) XMapWindow(wm->display, window);

        XFlush(wm->display);
    }
Пример #7
0
gboolean xdk_display_open(XdkDisplay * self)
{
	g_return_val_if_fail(self, FALSE);
	
	XdkDisplayPrivate * priv = self->priv;
	
	if(! priv->peer) {
		priv->peer = XOpenDisplay(priv->display_string);
		priv->own_peer = TRUE;
	}
	if(! priv->peer) {
		goto end;
	}
	
	priv->n_screens = XScreenCount(priv->peer);
	
	int i;
	for(i = 0; i < priv->n_screens; i ++) {
		g_ptr_array_add(
			priv->screens,
			g_object_new(
				XDK_TYPE_SCREEN,
				"peer", XScreenOfDisplay(priv->peer, i),
				"display", self,
				NULL));
	}

	if(! priv->event_retrieval_disabled) {
		xdk_display_add_watch(self);
	}

	Atom atom = XInternAtom(priv->peer, "WM_DELETE_WINDOW", FALSE);
	g_object_set_qdata(
		G_OBJECT(self),
		XDK_ATOM_WM_DELETE_WINDOW,
		GUINT_TO_POINTER(atom));
	
	if(g_getenv("XDK_DUMP_EVENT")) {
		xdk_display_add_event_filter(
			self,
			(XdkEventFilter) xdk_display_dump_event,
			NULL);
	}

	goto end;
	
close_display:
	XCloseDisplay(priv->peer);
	priv->peer = NULL;
end:
	return NULL != priv->peer;
}
Пример #8
0
int main() {
    // Open $DISPLAY
    Display *display = XOpenDisplay(NULL);
    // Get screen 0
    Screen *screen = XScreenOfDisplay(display, 0);
    int screen_w = XWidthOfScreen(screen);
    int screen_h = XHeightOfScreen(screen);

    printf("width\t: %i\n", screen_w);
    printf("height\t: %i\n", screen_h);

    return 0;
}
Пример #9
0
IMAGE_CONTEXT *new_window( char *wnd_name, int x, int y, int width, int height )
{
    IMAGE_CONTEXT *img_ctx;
    img_ctx = new IMAGE_CONTEXT;

    g_width = width;
    g_height = height;

    // First we are creating the window
    if ( ( img_ctx->display = XOpenDisplay(NULL) ) == NULL )
    {
        printf("Error: XOpenDisplay failed.\n");
        exit(1);
    }

    img_ctx->screenNumber = DefaultScreen( img_ctx->display );
    img_ctx->screen = XScreenOfDisplay( img_ctx->display, img_ctx->screenNumber );


    img_ctx->window = XCreateSimpleWindow (
			img_ctx->display,
			RootWindowOfScreen( img_ctx->screen ),
			0,
			0,
			g_width,
			g_height,
			0,
			BlackPixelOfScreen( img_ctx->screen ),
			BlackPixelOfScreen( img_ctx->screen )
    );


    img_ctx->xImage = NULL;
    if( image_create( img_ctx, g_width, g_height ) < 0 )
    {
        printf("Error: image_create() failed\n");
        exit(1);
    }

    XSelectInput( img_ctx->display, img_ctx->window, ButtonPressMask | KeyPressMask );
    XMapRaised( img_ctx->display, img_ctx->window );
    XStoreName( img_ctx->display, img_ctx->window, wnd_name );
	XGetWindowAttributes( img_ctx->display, img_ctx->window, &(img_ctx->windowAttributes ) );

	XMoveWindow( img_ctx->display, img_ctx->window, x, y );


    return img_ctx;
}
Пример #10
0
WXColormap wxApp::GetMainColormap(WXDisplay* display)
{
    if (!display) /* Must be called first with non-NULL display */
        return m_mainColormap;

    int defaultScreen = DefaultScreen((Display*) display);
    Screen* screen = XScreenOfDisplay((Display*) display, defaultScreen);

    Colormap c = DefaultColormapOfScreen(screen);

    if (!m_mainColormap)
        m_mainColormap = (WXColormap) c;

    return (WXColormap) c;
}
Пример #11
0
 void screenMetrics(int *x_org, int *y_org, int *width, int *height){
     // Open the X Display; passing NULL returns the default display.
     Display* display = XOpenDisplay(NULL);
     
     // Raw screen information from the X server.
     Screen* screen = XScreenOfDisplay(display, DefaultScreen(display));
     
     // Xinerama screen information; if available, this info is more accurate.
     // This is especially important for multi-monitor configurations.
     int screen_count = 0;
     XineramaScreenInfo *screen_info = XineramaQueryScreens(display, &screen_count);
 
     // If screen_info is not NULL, we got preferred measurements from Xinerama,
     // otherwise we use the measurements from the X server.
     if(screen_info != NULL){
         // screen_info is an array of length screen_count
         // Index zero should hold the "default" or "primary"
         // screen as configured by the user.
         *x_org = screen_info[0].x_org;
         *y_org = screen_info[0].y_org;
         *width = screen_info[0].width;
         *height = screen_info[0].height;
     }else{
         // screen is a reference to the default X Server screen
         // Since we know Xinerama isn't running, this screen
         // should correspond to exactly one physical display.
         *x_org = 0;
         *y_org = 0;
         *width = screen->width;
         *height = screen->height;
     }
 
     // Release the Xinerama screen info, if we have it.
     if(screen_info != NULL){
         XFree(screen_info);
     }
     
     // Release the connection to the X Display
     XCloseDisplay(display);
     
     return;
 }
Пример #12
0
int_fast32_t x11_screen_geo(Display *dpy, const int_fast32_t screen,
	int_fast32_t *w, int_fast32_t *h)
{
	Screen *scr;

	if (!dpy || screen < 0 || screen >= XScreenCount(dpy))
		goto fail;

	scr = XScreenOfDisplay(dpy, screen);
	if (!scr)
		goto fail;

	*w = XWidthOfScreen(scr);
	*h = XHeightOfScreen(scr);

	return 0;
fail:
	*w = *h = 0;
	return -1;
}
Пример #13
0
/**
 * Update the capture
 *
 * @return < 0 on error, 0 when size is unchanged, > 1 on size change
 */
static int_fast32_t xshm_update_geometry(struct xshm_data *data,
	obs_data_t settings)
{
	int_fast32_t old_width = data->width;
	int_fast32_t old_height = data->height;
	int_fast32_t screen = obs_data_get_int(settings, "screen");

	if (data->use_xinerama) {
		if (xinerama_screen_geo(data->dpy, screen,
			&data->x_org, &data->y_org,
			&data->width, &data->height) < 0) {
			return -1;
		}
		data->screen = XDefaultScreenOfDisplay(data->dpy);
	}
	else {
		data->x_org = 0;
		data->y_org = 0;
		if (x11_screen_geo(data->dpy, screen,
			&data->width, &data->height) < 0) {
			return -1;
		}
		data->screen = XScreenOfDisplay(data->dpy, screen);
	}

	if (!data->width || !data->height) {
		blog(LOG_ERROR, "xshm-input: Failed to get geometry");
		return -1;
	}

	blog(LOG_INFO, "xshm-input: Geometry %"PRIdFAST32"x%"PRIdFAST32
		" @ %"PRIdFAST32",%"PRIdFAST32,
		data->width, data->height, data->x_org, data->y_org);

	if (old_width == data->width && old_height == data->height)
		return 0;

	return 1;
}
Пример #14
0
int main(int argc, char **argv) {
    // open display & screen
    auto display = XOpenDisplay(getenv("DISPLAY"));
    auto screen = XScreenOfDisplay(display, 0);

    if (display == NULL) {
        fprintf(stderr, "ERROR: Invalid display!\n");
        return 1;
    }
    if (screen == NULL) {
        fprintf(stderr, "ERROR: Invalid screen!\n");
        return 1;
    }

    // setup clock
    Clock::setup();

    // execute program
    run(display, screen);

    // close display
    XCloseDisplay(display);
    return 0;
}
Пример #15
0
int
ga_xwin_init(const char *displayname, gaImage *gaimg) {
	int ignore = 0;
	//
	bzero(&__xshminfo, sizeof(__xshminfo));
	// open display
	if((display = XOpenDisplay(displayname)) == NULL) {
		ga_error("cannot open display \"%s\"\n", displayname ? displayname : "DEFAULT");
		return -1;
	}
	// check MIT extension
	if(XQueryExtension(display, "MIT-SHM", &ignore, &ignore, &ignore) ) {
		int major, minor;
		Bool pixmaps;
		if(XShmQueryVersion(display, &major, &minor, &pixmaps) == True) {
			ga_error("XShm extention version %d.%d %s shared pixmaps\n",
					major, minor, (pixmaps==True) ? "with" : "without");
		} else {
			ga_error("XShm extension not supported.\n");
			goto xcap_init_error;
		}
	}
	// get default screen
	screenNumber = XDefaultScreen(display);
	if((screen = XScreenOfDisplay(display, screenNumber)) == NULL) {
		ga_error("cannot obtain screen #%d\n", screenNumber);
		goto xcap_init_error;
	}
	//
	width = XDisplayWidth(display, screenNumber);
	height = XDisplayHeight(display, screenNumber);
	depth = XDisplayPlanes(display, screenNumber);
	ga_error("X-Window-init: dimension: %dx%dx%d @ %d/%d\n",
			width, height, depth,
			screenNumber, XScreenCount(display));
	//
	if((image = XShmCreateImage(display,
			XDefaultVisual(display, screenNumber),
			depth, ZPixmap, NULL, &__xshminfo,
			width, height)) == NULL) {
		ga_error("XShmCreateImage failed.\n");
		goto xcap_init_error;
	}
	//
	if((__xshminfo.shmid = shmget(IPC_PRIVATE,
				image->bytes_per_line*image->height,
				IPC_CREAT | 0777)) < 0) {
		perror("shmget");
		goto xcap_init_error;
	}
	//
	__xshminfo.shmaddr = image->data = (char*) shmat(__xshminfo.shmid, 0, 0);
	__xshminfo.readOnly = False;
	if(XShmAttach(display, &__xshminfo) == 0) {
		ga_error("XShmAttach failed.\n");
		goto xcap_init_error;
	}
	//
	__xshmattached = true;
	rootWindow = XRootWindow(display, screenNumber);
	gaimg->width = image->width;
	gaimg->height = image->height;
	gaimg->bytes_per_line = image->bytes_per_line;
	//
	return 0;
	//
xcap_init_error:
	ga_xwin_deinit();
	return -1;
}
Пример #16
0
static int _gfx_x11_init_monitors(

		int  major,
		int  minor)
{
	/* Iterate over all screens */
	Screen* def = XDefaultScreenOfDisplay(_gfx_x11.display);
	unsigned int count = XScreenCount(_gfx_x11.display);

	while(count--)
	{
		/* Get screen resources */
		Screen* scr =
			XScreenOfDisplay(_gfx_x11.display, count);
		Window root =
			XRootWindowOfScreen(scr);
		XRRScreenResources* res =
			XRRGetScreenResources(_gfx_x11.display, root);
		RROutput prim =
			res->outputs[0];

		/* Get primary if RandR 1.3 is supported */
		if(major > 1 || (major == 1 && minor > 2))
			prim = XRRGetOutputPrimary(_gfx_x11.display, root);

		/* Insert the screen's display modes */
		size_t first = _gfx_x11_init_modes(scr, res);

		/* Iterate through outputs */
		unsigned int i;
		for(i = 0; i < res->noutput; ++i)
		{
			/* Validate output */
			XRROutputInfo* out =
				XRRGetOutputInfo(_gfx_x11.display, res, res->outputs[i]);

			if(out->connection != RR_Connected)
			{
				XRRFreeOutputInfo(out);
				continue;
			}

			/* Create new monitor */
			XRRCrtcInfo* crtc =
				XRRGetCrtcInfo(_gfx_x11.display, res, out->crtc);
			int rot =
				crtc->rotation & (RR_Rotate_90 | RR_Rotate_270);

			GFX_X11_Monitor mon =
			{
				.screen   = scr,
				.crtc     = out->crtc,
				.mode     = crtc->mode,
				.numModes = 0,
				.modes    = malloc(sizeof(size_t) * out->nmode),
				.x        = crtc->x,
				.y        = crtc->y,
				.width    = rot ? crtc->height : crtc->width,
				.height   = rot ? crtc->width : crtc->height
			};

			/* Retrieve output modes */
			unsigned int j;
			if(mon.modes) for(j = 0; j < out->nmode; ++j)
			{
				GFX_X11_Mode* mode;
				for(
					mode = gfx_vector_at(&_gfx_x11.modes, first);
					mode != _gfx_x11.modes.end;
					mode = gfx_vector_next(&_gfx_x11.modes, mode))
				{
					/* Also check if resolution isn't too big */
					if(
						mode->id == out->modes[j] &&
						mode->mode.width <= crtc->width &&
						mode->mode.height <= crtc->height)
					{
						mon.modes[mon.numModes++] = gfx_vector_get_index(
							&_gfx_x11.modes,
							mode
						);
						break;
					}
				}
			}

			/* Insert at beginning if primary */
			GFXVectorIterator monPos =
				scr == def && res->outputs[i] == prim ?
				_gfx_x11.monitors.begin : _gfx_x11.monitors.end;

			monPos = gfx_vector_insert(&_gfx_x11.monitors, &mon, monPos);
			if(monPos == _gfx_x11.monitors.end) free(mon.modes);

			XRRFreeCrtcInfo(crtc);
			XRRFreeOutputInfo(out);
		}

		XRRFreeScreenResources(res);
	}

	/* Need at least one monitor */
	return _gfx_x11.monitors.begin != _gfx_x11.monitors.end;
}

/******************************************************/
static GFXKey _gfx_x11_get_key(

		KeySym symbol)
{
	/* Unicode numbers */
	if(symbol >= XK_0 && symbol <= XK_9)
		return (GFXKey)(symbol - XK_0 + GFX_KEY_0);

	/* Keypad numbers */
	if(symbol >= XK_KP_0 && symbol <= XK_KP_9)
		return (GFXKey)(symbol - XK_KP_0 + GFX_KEY_KP_0);

	/* Unicode capitals */
	if(symbol >= XK_A && symbol <= XK_Z)
		return (GFXKey)(symbol - XK_A + GFX_KEY_A);

	/* Unicode lowercase */
	if(symbol >= XK_a && symbol <= XK_z)
		return (GFXKey)(symbol - XK_a + GFX_KEY_A);

	/* Function keys */
	if(symbol >= XK_F1 && symbol <= XK_F24)
		return (GFXKey)(symbol - XK_F1 + GFX_KEY_F1);

	/* Non-unicode */
	switch(symbol)
	{
		case XK_VoidSymbol   : return GFX_KEY_UNKNOWN;

		case XK_BackSpace    : return GFX_KEY_BACKSPACE;
		case XK_Tab          : return GFX_KEY_TAB;
		case XK_KP_Tab       : return GFX_KEY_TAB;
		case XK_Clear        : return GFX_KEY_CLEAR;
		case XK_Return       : return GFX_KEY_RETURN;
		case XK_Pause        : return GFX_KEY_PAUSE;
		case XK_Scroll_Lock  : return GFX_KEY_SCROLL_LOCK;
		case XK_Escape       : return GFX_KEY_ESCAPE;
		case XK_Delete       : return GFX_KEY_DELETE;
		case XK_KP_Delete    : return GFX_KEY_DELETE;

		case XK_Home         : return GFX_KEY_HOME;
		case XK_KP_Home      : return GFX_KEY_HOME;
		case XK_Left         : return GFX_KEY_LEFT;
		case XK_KP_Left      : return GFX_KEY_LEFT;
		case XK_Up           : return GFX_KEY_UP;
		case XK_KP_Up        : return GFX_KEY_UP;
		case XK_Right        : return GFX_KEY_RIGHT;
		case XK_KP_Right     : return GFX_KEY_RIGHT;
		case XK_Down         : return GFX_KEY_DOWN;
		case XK_KP_Down      : return GFX_KEY_DOWN;
		case XK_Page_Down    : return GFX_KEY_PAGE_DOWN;
		case XK_KP_Page_Down : return GFX_KEY_PAGE_DOWN;
		case XK_Page_Up      : return GFX_KEY_PAGE_UP;
		case XK_KP_Page_Up   : return GFX_KEY_PAGE_UP;
		case XK_End          : return GFX_KEY_END;
		case XK_KP_End       : return GFX_KEY_END;

		case XK_Select       : return GFX_KEY_SELECT;
		case XK_Print        : return GFX_KEY_PRINT;
		case XK_Execute      : return GFX_KEY_EXECUTE;
		case XK_Insert       : return GFX_KEY_INSERT;
		case XK_KP_Insert    : return GFX_KEY_INSERT;
		case XK_Menu         : return GFX_KEY_MENU;
		case XK_Cancel       : return GFX_KEY_CANCEL;
		case XK_Help         : return GFX_KEY_HELP;
		case XK_Num_Lock     : return GFX_KEY_NUM_LOCK;
		case XK_KP_Space     : return GFX_KEY_SPACE;
		case XK_space        : return GFX_KEY_SPACE;

		case XK_KP_Enter     : return GFX_KEY_KP_RETURN;
		case XK_KP_Multiply  : return GFX_KEY_KP_MULTIPLY;
		case XK_KP_Add       : return GFX_KEY_KP_ADD;
		case XK_KP_Separator : return GFX_KEY_KP_SEPARATOR;
		case XK_KP_Subtract  : return GFX_KEY_KP_SUBTRACT;
		case XK_KP_Decimal   : return GFX_KEY_KP_DECIMAL;
		case XK_KP_Divide    : return GFX_KEY_KP_DIVIDE;

		case XK_Shift_L      : return GFX_KEY_SHIFT_LEFT;
		case XK_Shift_R      : return GFX_KEY_SHIFT_RIGHT;
		case XK_Control_L    : return GFX_KEY_CONTROL_LEFT;
		case XK_Control_R    : return GFX_KEY_CONTROL_RIGHT;
		case XK_Alt_L        : return GFX_KEY_ALT_LEFT;
		case XK_Alt_R        : return GFX_KEY_ALT_RIGHT;
		case XK_Super_L      : return GFX_KEY_SUPER_LEFT;
		case XK_Super_R      : return GFX_KEY_SUPER_RIGHT;
	}

	return GFX_KEY_UNKNOWN;
}

/******************************************************/
static void _gfx_x11_create_key_table(void)
{
	/* Get permitted keycodes and their symbols */
	int minKey, maxKey;
	XDisplayKeycodes(_gfx_x11.display, &minKey, &maxKey);
	maxKey = maxKey > GFX_X11_MAX_KEYCODE ? GFX_X11_MAX_KEYCODE : maxKey;

	int numKeys = maxKey - minKey + 1;

	int symbolsPerKey;
	KeySym* symbols = XGetKeyboardMapping(
		_gfx_x11.display,
		minKey,
		numKeys,
		&symbolsPerKey
	);

	/* Use the first symbol of all keycodes */
	size_t i;
	for(i = minKey; i <= maxKey; ++i) _gfx_x11.keys[i] = _gfx_x11_get_key(
		symbols[(i - minKey) * symbolsPerKey]);

	XFree(symbols);
}
Пример #17
0
/**
 * @brief Return root window for a given X display
 * @param Screen number. If no value is passed, uses screen 1.
 * @return XID of the window
 */
unsigned long X11Extras::appRootWindow(int screen)
{
    return screen == -1 ? XDefaultRootWindow(display()) : XRootWindowOfScreen(XScreenOfDisplay(display(), screen));
}
Пример #18
0
int main(int argc, char** argv)
{
    int attrib[] = {
        GLX_RENDER_TYPE, GLX_RGBA_BIT,
        GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
        GLX_DOUBLEBUFFER, True,
        GLX_RED_SIZE, 8,
        GLX_GREEN_SIZE, 8,
        GLX_BLUE_SIZE, 8,
        GLX_ALPHA_SIZE, 8,
        GLX_DEPTH_SIZE, 24,
        None
    };
    
    PlatformContext context;

    context.MainDisplay = XOpenDisplay(NULL);
    int screenIndex = DefaultScreen(context.MainDisplay);
    Window root = RootWindow(context.MainDisplay, screenIndex);

    int fbcount;
    PFNGLXCHOOSEFBCONFIGPROC glXChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC)glXGetProcAddress((GLubyte*)"glXChooseFBConfig");
    GLXFBConfig *fbc = glXChooseFBConfig(context.MainDisplay, screenIndex, attrib, &fbcount);
    if (!fbc)
        pezFatal("Failed to retrieve a framebuffer config\n");

    PFNGLXGETVISUALFROMFBCONFIGPROC glXGetVisualFromFBConfig = (PFNGLXGETVISUALFROMFBCONFIGPROC) glXGetProcAddress((GLubyte*)"glXGetVisualFromFBConfig");
    if (!glXGetVisualFromFBConfig)
        pezFatal("Failed to get a GLX function pointer\n");

    PFNGLXGETFBCONFIGATTRIBPROC glXGetFBConfigAttrib = (PFNGLXGETFBCONFIGATTRIBPROC) glXGetProcAddress((GLubyte*)"glXGetFBConfigAttrib");
    if (!glXGetFBConfigAttrib)
        pezFatal("Failed to get a GLX function pointer\n");

    if (PezGetConfig().Multisampling) {
        int best_fbc = -1, worst_fbc = -1, best_num_samp = -1, worst_num_samp = 999;
        for ( int i = 0; i < fbcount; i++ ) {
            XVisualInfo *vi = glXGetVisualFromFBConfig( context.MainDisplay, fbc[i] );
            if (!vi) {
                continue;
            }
            int samp_buf, samples;
            glXGetFBConfigAttrib( context.MainDisplay, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf );
            glXGetFBConfigAttrib( context.MainDisplay, fbc[i], GLX_SAMPLES       , &samples  );
            //printf( "  Matching fbconfig %d, visual ID 0x%2x: SAMPLE_BUFFERS = %d,"
            //        " SAMPLES = %d\n", 
            //        i, (unsigned int) vi->visualid, samp_buf, samples );
            if ( best_fbc < 0 || (samp_buf && samples > best_num_samp) )
                best_fbc = i, best_num_samp = samples;
            if ( worst_fbc < 0 || !samp_buf || samples < worst_num_samp )
                worst_fbc = i, worst_num_samp = samples;
            XFree( vi );
        }
        fbc[0] = fbc[ best_fbc ];
    }

    XVisualInfo *visinfo = glXGetVisualFromFBConfig(context.MainDisplay, fbc[0]);
    if (!visinfo)
        pezFatal("Error: couldn't create OpenGL window with this pixel format.\n");

    XSetWindowAttributes attr;
    attr.background_pixel = 0;
    attr.border_pixel = 0;
    attr.colormap = XCreateColormap(context.MainDisplay, root, visinfo->visual, AllocNone);
    attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask | KeyReleaseMask |
                      PointerMotionMask | ButtonPressMask | ButtonReleaseMask;

    context.MainWindow = XCreateWindow(
        context.MainDisplay,
        root,
        0, 0,
        PezGetConfig().Width, PezGetConfig().Height, 0,
        visinfo->depth,
        InputOutput,
        visinfo->visual,
        CWBackPixel | /*CWBorderPixel |*/ CWColormap | CWEventMask,
        &attr
    );

    int borderless = 1;
    if (borderless) {
        Atom mwmHintsProperty = XInternAtom(context.MainDisplay, "_MOTIF_WM_HINTS", 0);
        MwmHints hints = {0};
        hints.flags = MWM_HINTS_DECORATIONS;
        hints.decorations = 0;
        XChangeProperty(context.MainDisplay, context.MainWindow, mwmHintsProperty, mwmHintsProperty, 32,
                        PropModeReplace, (unsigned char *)&hints, PROP_MWM_HINTS_ELEMENTS);
    }

    XMapWindow(context.MainDisplay, context.MainWindow);

    int centerWindow = 1;
    if (centerWindow) {
        Screen* pScreen = XScreenOfDisplay(context.MainDisplay, screenIndex);
        int left = XWidthOfScreen(pScreen)/2 - PezGetConfig().Width/2;
        int top = XHeightOfScreen(pScreen)/2 - PezGetConfig().Height/2;
        XMoveWindow(context.MainDisplay, context.MainWindow, left, top);
    }

    GLXContext glcontext = 0;
    if (PEZ_FORWARD_COMPATIBLE_GL) {
        PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((GLubyte*)"glXCreateContextAttribsARB");
        if (!glXCreateContextAttribs) {
            pezFatal("Your platform does not support OpenGL 4.0.\n"
                     "Try changing PEZ_FORWARD_COMPATIBLE_GL to 0.\n");
        }
        int attribs[] = {
            GLX_CONTEXT_MAJOR_VERSION_ARB, 4,
            GLX_CONTEXT_MINOR_VERSION_ARB, 0,
            GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
            GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
            0
        };
        glcontext = glXCreateContextAttribs(context.MainDisplay, fbc[0], NULL, True, attribs);
    } else {
        glcontext = glXCreateContext(context.MainDisplay, visinfo, NULL, True);
    }

    glXMakeCurrent(context.MainDisplay, context.MainWindow, glcontext);
    PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) glXGetProcAddress((GLubyte*)"glXSwapIntervalSGI");
    if (glXSwapIntervalSGI) {
        glXSwapIntervalSGI(PezGetConfig().VerticalSync ? 1 : 0);
    }
/*
    GLenum err = glewInit();
    if (GLEW_OK != err)
        pezFatal("GLEW Error: %s\n", glewGetErrorString(err));

    // Work around some GLEW issues:    
    #define glewGetProcAddress(name) (*glXGetProcAddressARB)(name)
    glPatchParameteri = (PFNGLPATCHPARAMETERIPROC)glewGetProcAddress((const GLubyte*)"glPatchParameteri");
    glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)glewGetProcAddress((const GLubyte*)"glBindVertexArray");
    glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC)glewGetProcAddress((const GLubyte*)"glDeleteVertexArrays");
    glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)glewGetProcAddress((const GLubyte*)"glGenVertexArrays");
    glIsVertexArray = (PFNGLISVERTEXARRAYPROC)glewGetProcAddress((const GLubyte*)"glIsVertexArray");
*/
    // Reset OpenGL error state:
    glGetError();

    // Lop off the trailing .c
    bstring name = bfromcstr(PezGetConfig().Title);
    bstring shaderPrefix = bmidstr(name, 0, blength(name) - 1);
    pezSwInit(bdata(shaderPrefix));
    bdestroy(shaderPrefix);

    // Set up the Shader Wrangler
    pezSwAddPath("./", ".glsl");
    pezSwAddPath("../", ".glsl");
    char qualifiedPath[128];
    strcpy(qualifiedPath, pezResourcePath());
    strcat(qualifiedPath, "/");
    pezSwAddPath(qualifiedPath, ".glsl");
    pezSwAddDirective("*", "#version 420");

    // Perform user-specified intialization
    pezPrintString("OpenGL Version: %s\n", glGetString(GL_VERSION));
    PezInitialize();
    bstring windowTitle = bmidstr(name, 5, blength(name) - 7);
    XStoreName(context.MainDisplay, context.MainWindow, bdata(windowTitle));
    bdestroy(windowTitle);
    bdestroy(name);
    
    // -------------------
    // Start the Game Loop
    // -------------------

    unsigned int previousTime = GetMicroseconds();
    int done = 0;
    while (!done) {
        
        if (glGetError() != GL_NO_ERROR)
            pezFatal("OpenGL error.\n");

        if (XPending(context.MainDisplay)) {
            XEvent event;
    
            XNextEvent(context.MainDisplay, &event);
            switch (event.type)
            {
                case Expose:
                    //redraw(display, event.xany.window);
                    break;
                
                case ConfigureNotify:
                    //resize(event.xconfigure.width, event.xconfigure.height);
                    break;
                
#ifdef PEZ_MOUSE_HANDLER
                case ButtonPress:
                    PezHandleMouse(event.xbutton.x, event.xbutton.y, PEZ_DOWN);
                    break;

                case ButtonRelease:
                    PezHandleMouse(event.xbutton.x, event.xbutton.y, PEZ_UP);
                    break;

                case MotionNotify:
                    PezHandleMouse(event.xmotion.x, event.xmotion.y, PEZ_MOVE);
                    break;
#endif

                case KeyRelease:
                case KeyPress: {
                    XComposeStatus composeStatus;
                    char asciiCode[32];
                    KeySym keySym;
                    int len;
                    
                    len = XLookupString(&event.xkey, asciiCode, sizeof(asciiCode), &keySym, &composeStatus);
                    switch (asciiCode[0]) {
                        case 'x': case 'X': case 'q': case 'Q':
                        case 0x1b:
                            done = 1;
                            break;
                    }
                }
            }
        }

        unsigned int currentTime = GetMicroseconds();
        unsigned int deltaTime = currentTime - previousTime;
        previousTime = currentTime;
        
        PezUpdate((float) deltaTime / 1000000.0f);

        PezRender(0);
        glXSwapBuffers(context.MainDisplay, context.MainWindow);
    }

    pezSwShutdown();

    return 0;
}
Пример #19
0
static DWORD
DrvCreateWindows(LPARAM dwParm1, LPARAM dwParm2, LPVOID lpStruct)
{
    LPWINCREATESTRUCT lpwcs = (LPWINCREATESTRUCT)lpStruct;
    UINT input_class;
    DWORD dwEventMask;
    DWORD dwCWMask;
    XSetWindowAttributes xattr;
    XSizeHints size_hints;
    XWMHints wm_hints;
    Window win_parent, frame_win;
    Pixmap icon_pixmap = None,icon_mask = None;
    DRVIMAGEDATA *lpimage;
    GC gc;
    PRIVATEDISPLAY *Disp = GETDP();
    WM_WINDOW_STATE WMWindowState;

    input_class = (lpwcs->dwExStyle & WS_EX_TRANSPARENT)?
		InputOnly:InputOutput;

    /* set general default values and mask for xattr */
    /* default white X background */
#ifdef	LATER
    these should call color subsystem
#endif
#ifdef TWIN_PALETTE
    xattr.background_pixel = DrvMakePixel(RGB(255,255,255), NULL);
    xattr.border_pixel = DrvMakePixel(RGB(0,0,0), NULL);
#else
    xattr.background_pixel = DrvMakePixel(RGB(255,255,255));
    xattr.border_pixel = DrvMakePixel(RGB(0,0,0));
#endif
    /* default NorthWestGravity */
    xattr.bit_gravity = NorthWestGravity;

#ifdef TWIN_PALETTE
    xattr.colormap = Disp->SystemPalette;
#else
    xattr.colormap = Disp->color_map;
#endif

    dwCWMask = CWBackPixel|CWBorderPixel|CWBitGravity|CWColormap;

	win_parent = RootWindow(Disp->display, Disp->screen);

	/* for top-level window without caption use override_redirect */
	if ((lpwcs->dwStyle & WS_CAPTION) != WS_CAPTION)
	    xattr.override_redirect = True;
	else
	    xattr.override_redirect = False;

	/* if SAVEBITS and server supports save_under, use it */
	if ((lpwcs->dwExStyle & WS_EX_SAVEBITS) &&
	    XDoesSaveUnders(XScreenOfDisplay(Disp->display,Disp->screen)))
	    xattr.save_under = True;
	else
	    xattr.save_under = False;

	if (lpwcs->Cursor) 
	    xattr.cursor = (Cursor)lpwcs->Cursor;
	else
	    xattr.cursor = None;


	/* X does not tolerate zero-size windows */
	lpwcs->rcFrame.right = max(lpwcs->rcFrame.right,1);
	lpwcs->rcFrame.bottom = max(lpwcs->rcFrame.bottom,1);

	if (input_class != InputOnly)
	    frame_win = XCreateWindow(Disp->display, win_parent,
		lpwcs->rcFrame.left,lpwcs->rcFrame.top,
		lpwcs->rcFrame.right,lpwcs->rcFrame.bottom,
		lpwcs->nBorder,
		CopyFromParent,
		input_class,
		CopyFromParent,
		dwCWMask | CWOverrideRedirect| CWSaveUnder | CWCursor,
		&xattr);
	else
	    frame_win = XCreateWindow(Disp->display, win_parent,
		lpwcs->rcFrame.left,lpwcs->rcFrame.top,
		lpwcs->rcFrame.right,lpwcs->rcFrame.bottom,
		0,
		CopyFromParent,
		InputOnly,
		CopyFromParent,
		CWOverrideRedirect,
		&xattr);

	if (frame_win == 0)
	    return 0L;

	/* save necessary contexts in the frame window */
	XSaveContext(Disp->display, frame_win, Disp->client_hwnd,
		(caddr_t)MAKELONG(lpwcs->hWndClient,lpwcs->hWndFrame));
	XSaveContext(Disp->display, frame_win, Disp->window_style,
		(caddr_t)lpwcs->dwStyle);
	XSaveContext(Disp->display, frame_win, Disp->window_ex_style,
		(caddr_t)lpwcs->dwExStyle);

#ifdef	LATER
	/* Use XSetWMProperties for top-level windows instead */
#endif
	/* Set standard hints for window manager */
#ifdef	LATER
	/* we can set user-specified values, min/maxsize, basesize etc. here */
#endif
	size_hints.flags = PPosition | PSize;
	size_hints.x = lpwcs->rcFrame.left;
	size_hints.y = lpwcs->rcFrame.top;
	size_hints.width = lpwcs->rcFrame.right;
	size_hints.height = lpwcs->rcFrame.bottom;

	if (lpwcs->lpIconANDData) {
	    XGCValues values;

	    lpimage = (DRVIMAGEDATA *)lpwcs->lpIconANDData;
	    if (lpimage->image) {
		icon_mask = XCreatePixmap(Disp->display,
				DefaultRootWindow(Disp->display),
				X_ICON_SIZE,X_ICON_SIZE,1);
		values.foreground = 0;
		values.background = 1;
		gc = XCreateGC(Disp->display,icon_mask,
				GCForeground|GCBackground,&values);
		XPutImage(Disp->display,
			  icon_mask,
			  gc,
			  lpimage->image,
			  0,0,0,0,
			  lpimage->nWidth,lpimage->nHeight);
		XFreeGC(Disp->display,gc);
	    }
	}

	if (lpwcs->lpIconXORData) {

	    lpimage = (DRVIMAGEDATA *)lpwcs->lpIconXORData;
	    if (lpimage->image) {
#if 1
		icon_pixmap = XCreateBitmapFromData(Disp->display, 
			DefaultRootWindow(Disp->display), lpimage->image->data,
			lpimage->nWidth, lpimage->nHeight);
#else
		{
	        int xOffset,yOffset;
		icon_pixmap = XCreatePixmap(Disp->display,
				DefaultRootWindow(Disp->display),
				X_ICON_SIZE,X_ICON_SIZE,1);
		gc = XCreateGC(Disp->display,icon_pixmap,0,0L);
		XSetForeground(Disp->display,gc,
				WhitePixel(Disp->display,Disp->screen));
		XFillRectangle(Disp->display,icon_pixmap,gc,0,0,
				X_ICON_SIZE,X_ICON_SIZE);
		xOffset = (X_ICON_SIZE - lpimage->nWidth)/2;
		yOffset = (X_ICON_SIZE - lpimage->nHeight)/2;
		XSetClipMask(Disp->display,gc,icon_mask);
		XSetClipOrigin(Disp->display,gc,xOffset,yOffset);
		XPutImage(Disp->display,
			  icon_pixmap,
			  gc,
			  lpimage->image,
			  0,0,xOffset,yOffset,
			  lpimage->nWidth,lpimage->nHeight);
		XFreeGC(Disp->display,gc);
		}
#endif
	    }
	}

	/* set properties for window manager */
	XSetStandardProperties(Disp->display, frame_win,
	    (HIWORD(lpwcs->lpszName))?lpwcs->lpszName:"",
	    (HIWORD(lpwcs->lpszName))?lpwcs->lpszName:"",
	    icon_pixmap,
#ifdef	LATER
	/* pass argv and argc here */
#else
	    0,0,
#endif
	    &size_hints);

#ifdef	LATER
	/* can this be False??? */
#endif
	wm_hints.input = True;
	wm_hints.icon_pixmap = icon_pixmap;
	wm_hints.icon_mask = icon_mask;
#ifdef	LATER
	/* we can set icon_window,icon position,initial state,group here */
#endif
	wm_hints.flags = InputHint | StateHint;
	if (icon_pixmap != None)
	    wm_hints.flags |= IconPixmapHint;
#ifdef LATER
    	if (lpwcs->dwStyle & WS_MINIMIZE)
		wm_hints.initial_state = IconicState;
	else
#endif
		wm_hints.initial_state = NormalState;
#ifdef LATER
	if ( XGetIconSizes ( Disp->display, frame_win, &pIconSizes, 
	                     &nIconSizes ) )
	{
		IconHeight = pIconSizes->max_height;
		IconWidth  = pIconSizes->max_width;
	}
	else
	{
		IconHeight = IconWidth = X_ICON_SIZE;
	}
	wm_hints.icon_window = XCreateSimpleWindow ( Disp->display,
	                                             win_parent, 0, 0,
	                                             IconWidth, IconHeight,
	                                             0, 0, 0xffffffff );
	xattr.override_redirect = True;
	xattr.background_pixmap = icon_pixmap;
	xattr.background_pixel  = DrvMakePixel(RGB(255,255,255), NULL);
	XChangeWindowAttributes ( Disp->display, wm_hints.icon_window,
	                          CWOverrideRedirect | CWBackPixel,
	                          &xattr );
#endif
	XSetWMHints(Disp->display, frame_win, &wm_hints);

	WMWindowState.State = wm_hints.initial_state;
	WMWindowState.IconWindow = wm_hints.icon_window;
	WMWindowState.PixmapWindow = icon_pixmap;
	DrvGetSetWMState ( frame_win, &WMWindowState, DRV_GETSET_SET );

#ifdef	LATER
	/* can other protocols (WM_TAKE_FOCUS etc.) be used??? */
#endif
	if (Disp->wm_delete_window != None)
	    XSetWMProtocols(Disp->display,frame_win,&Disp->wm_delete_window,1);

	dwEventMask = TOPLEVEL_EVENTS;

	/* Select event types wanted */
	XSelectInput(Disp->display, frame_win, dwEventMask);

    return (DWORD)frame_win;
}
Пример #20
0
int main(int argc, char **argv)

{
  Atom                atomWMDeleteWindow;
  int	              screenNumber;
  Screen              *screen;
  Window              window;
  XWindowAttributes   windowAttributes;
  Colormap            colormap;
  PaletteInfo         paletteInfo;
  Image               image;
  XImage              *xImage;
  int                 x, y;
  int                 captureFrame;
  XEvent              event;
  bool                sizeChanged;


  // ProgramExit initialization

  display = NULL;
  v4l = -1;
  captureBuf = NULL;

  on_exit(ProgramExit, NULL);

  // Get command line options

  magnification = 1;

  if (argc > 1) {
    magnification = atoi(argv[1]);
  } // end if

  magnification = max(1, magnification);

  printf("Magnification is %i\n", magnification);

  // Open display

  if ((display = XOpenDisplay(NULL)) == NULL) { // NULL for DISPLAY
    printf("Error: XOpenDisplay() failed\n");
    exit(1);
  } // end if

  screenNumber = DefaultScreen(display);

  screen = XScreenOfDisplay(display, screenNumber);

  // Obtain WM protocols atom for ClientMessage exit event

  if ((atomWMDeleteWindow = XInternAtom(display, AtomWMDeleteWindowName, True)) == None) {
    printf("Error: %s atom does not exist\n", AtomWMDeleteWindowName);
    exit(1);
  } // end if

  // Create window, inheriting depth and visual from root window

  window = XCreateSimpleWindow(
    display,
    RootWindowOfScreen(screen),
    0, // x
    0, // y
    640, // width
    480, // height
    0,                          // border width
    BlackPixelOfScreen(screen), // border
    BlackPixelOfScreen(screen)  // background
    );

  XStoreName(display, window, "V4L RGB Test");

  XGetWindowAttributes(display, window, &windowAttributes);

  if (((windowAttributes.depth == 8) && (windowAttributes.visual->c_class != PseudoColor)) ||
      ((windowAttributes.depth > 8) && (windowAttributes.visual->c_class != TrueColor))) {
    printf("Error: Visual not supported\n");
    exit(1);
  } // end if

  // Create PseudoColor HI240 colormap, if needed

  if (windowAttributes.depth == 8) {
    colormap = XCreateColormap(display, window, windowAttributes.visual, AllocAll);
    paletteInfo.display = display;
    paletteInfo.colormap = colormap;
    Hi240BuildPalette((ulong) 0x10000, (Hi240StorePaletteEntry *) StoreColormapEntry, &paletteInfo);
    XSetWindowColormap(display, window, colormap);
  } // end if

  // Create image

  if (image.Create(
    display,
    window, // Defines visual, depth
    MaxImageWidth,
    MaxImageHeight,
    True // MITSHM
    ) < 0) {
    printf("Error: image.Create() failed\n");
    exit(1);
  } // end if

  image.Clear();

#if (1)
  printf("\nDisplay:\n");
  printf("Image byte order = %s\n", ByteOrderName(ImageByteOrder(display)));
  printf("Bitmap unit      = %i\n", BitmapUnit(display));
  printf("Bitmap bit order = %s\n", ByteOrderName(BitmapBitOrder(display)));
  printf("Bitmap pad       = %i\n", BitmapPad(display));

  printf("\nWindow:\n");
  printf("Depth            = %i\n", windowAttributes.depth);
  printf("Visual ID        = 0x%02x\n", windowAttributes.visual->visualid);
  printf("Visual class     = %s\n", VisualClassName(windowAttributes.visual->c_class));
  printf("Red mask         = 0x%08lx\n", windowAttributes.visual->red_mask);
  printf("Green mask       = 0x%08lx\n", windowAttributes.visual->green_mask);
  printf("Blue mask        = 0x%08lx\n", windowAttributes.visual->blue_mask);
  printf("Bits per R/G/B   = %i\n", windowAttributes.visual->bits_per_rgb); // log2 # colors

  xImage = image.X();
  printf("\nImage:\n");
  printf("Image byte order = %s\n", ByteOrderName(xImage->byte_order));
  printf("Bitmap unit      = %i\n", xImage->bitmap_unit);
  printf("Bitmap bit order = %s\n", ByteOrderName(xImage->bitmap_bit_order));
  printf("Bitmap pad       = %i\n", xImage->bitmap_pad);
  printf("Depth            = %i\n", xImage->depth);
  printf("Red mask         = 0x%08lx\n", xImage->red_mask);
  printf("Green mask       = 0x%08lx\n", xImage->green_mask);
  printf("Blue mask        = 0x%08lx\n", xImage->blue_mask);
  printf("Bits per pixel   = %i\n", xImage->bits_per_pixel); // ZPixmap
  printf("Bytes per line   = %i\n", xImage->bytes_per_line);
  printf("IsShared         = %s\n", image.IsShared() ? "True" : "False");
  printf("HasSharedPixmap  = %s\n", image.HasSharedPixmap() ? "True" : "False");
#endif

  // V4L stuff

  if ((v4l = open(BigPictureDevice, O_RDWR)) < 0) {
    printf("Error: Can't open %s: %s\n", BigPictureDevice, strerror(errno));
    exit(1);
  } // end if

  if (V4LMGetMMInfo(v4l, &v4lMMInfo) < 0) {
    printf("Error: V4LMGetMMInfo: %s\n", strerror(errno));
    exit(1);
  } // end if
#if (0)
  printf("Capture buffer size   = %i\n", v4lMMInfo.size);
  printf("Capture buffer frames = %i\n", v4lMMInfo.frames);
#endif
  if (v4lMMInfo.frames < 2) {
    printf("Error: V4LMGetMMInfo: frames < 2\n");
    exit(1);
  } // end if

  if ((captureBuf = (bits8 *) mmap(0, v4lMMInfo.size, PROT_READ | PROT_WRITE, MAP_SHARED, v4l, 0)) == MAP_FAILED) {
    printf("Error: mmap(): %s\n", strerror(errno));
    exit(1);
  } // end if

  if (V4LSetSource(v4l, BigPictureCompositeSource, VIDEO_MODE_NTSC) < 0) {
    printf("Error: V4LSetSource: %s\n", strerror(errno));
    exit(1);
  } // end if

  if (V4LGetCaps(v4l, &v4lCaps) < 0) {
    printf("Error: V4LGetCaps: %s\n", strerror(errno));
    exit(1);
  } // end if

  // Select V4L RGB capture format to exactly match image/visual (no LUTs!)

  if ((captureFormat = XImageCaptureFormat(image.X())) < 0) {
    printf("Error: No  match for visual/image\n");
    exit(1);
  } // end if

  // Initialize capture size based on window size

  windowWidth = windowAttributes.width;
  windowHeight = windowAttributes.height;;

  WindowResize(v4l, windowWidth, windowHeight, magnification); // Does V4LMSetFormat().

  // Initialize picture attributes to mid-range

  V4LSetBrightness(v4l, 65535 / 2);
  V4LSetContrast(v4l, 65535 / 2);
  V4LSetSaturation(v4l, 65535 / 2);
  V4LSetHue(v4l, 65535 / 2);

  // Ready to start: Display window, select events, and initiate capture sequence

  XMapRaised(display, window);

  XSetWMProtocols(display, window, &atomWMDeleteWindow, 1);

  XSelectInput(display, window, StructureNotifyMask | ExposureMask);

  captureFrame = 0;

  if (V4LMCapture(v4l, captureFrame) < 0) {
    printf("Error: V4LMCapture: %s\n", strerror(errno));
    exit(1);
  } // end if

  while (1) {

    if (XPending(display) > 0) {

      XNextEvent(display, &event);

      switch (event.type) {
      case ClientMessage: // From WM
	if (event.xclient.data.l[0] == atomWMDeleteWindow) {
	  exit(0);
	} // end if
	break;
      case ConfigureNotify:
	sizeChanged = false;
	if (event.xconfigure.width != windowWidth) {
	  sizeChanged = true;
	  windowWidth = event.xconfigure.width;
	} // end if
	if (event.xconfigure.height != windowHeight) {
	  sizeChanged = true;
	  windowHeight = event.xconfigure.height;
	} // end if
	if (sizeChanged) {
	  image.Clear();
	  XClearWindow(display, window);
	  WindowResize(v4l, windowWidth, windowHeight, magnification);
	} // end if
	break;
      case Expose:
	if (event.xexpose.count == 0) {
	  Put(window, image);
	} // end if
	break;
      } // end switch

    } else {

      // Wait for this frame

      if (V4LMSync(v4l, captureFrame) < 0) {
	printf("Error: V4LMSync: %s\n", strerror(errno));
	exit(1);
      } // end if

      // Start capture for next frame

      if (V4LMCapture(v4l, 1 - captureFrame) < 0) {
	printf("Error: V4LMCapture: %s\n", strerror(errno));
	exit(1);
      } // end if

      Draw(image, captureBuf + v4lMMInfo.offsets[captureFrame], magnification);

      Put(window, image);

      captureFrame = 1 - captureFrame; // 0<->1

    } // endif 

  } // end while

  printf("Error: Fell out of event loop!\n");

  exit(1);

} // end main