[Xcb] xcbrandr

Jim Gettys Jim.Gettys at hp.com
Wed Feb 9 13:12:50 PST 2005


On Wed, 2005-02-09 at 15:12 -0500, Jeremy Kolb wrote:
> Here's my port of xrandr.  My computer doesn't support rotations but 
> they should work, everything else worked fine on my machine.  Feel free 
> to test it.

A kdrive server should to able to test rotation easily.  Xvesa should
run on most hardware.

And jhbuild makes building  kdrive servers pretty painless.
			- Jim


> 
> I didn't change the copyright notice, not sure if I have to or not.
> 
> Should this be put in xcb-demos?
> 
> Jeremy
> plain text document attachment (xcbrandr.c)
> /*
>  * $XFree86: xc/programs/xrandr/xrandr.c,v 1.11 2002/10/14 18:01:43 keithp Exp $
>  *
>  * Copyright  2001 Keith Packard, member of The XFree86 Project, Inc.
>  * Copyright  2002 Hewlett Pacard Company, Inc.
>  *
>  * Permission to use, copy, modify, distribute, and sell this software and its
>  * documentation for any purpose is hereby granted without fee, provided that
>  * the above copyright notice appear in all copies and that both that
>  * copyright notice and this permission notice appear in supporting
>  * documentation, and that the name of Keith Packard or HP not be used in
>  * advertising or publicity pertaining to distribution of the software without
>  * specific, written prior permission.  Keith Packard and HP makes no
>  * representations about the suitability of this software for any purpose.  It
>  * is provided "as is" without express or implied warranty.
>  *
>  * KEITH PACKARD and HP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
>  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
>  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
>  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
>  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
>  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
>  * PERFORMANCE OF THIS SOFTWARE.
>  *
>  * Blame Jim Gettys for any bugs; he wrote most of the client side code,
>  * and part of the server code for randr.
>  *
>  * Ported to XCB by Jeremy Kolb 2/8/2005
>  */
> 
> #include <stdio.h>
> #include <X11/XCB/xcb.h>
> #include <X11/XCB/randr.h>
> #include <X11/XCB/render.h>	/* we share subpixel information */
> #include <string.h>
> #include <stdlib.h>
> 
> #define CurrentTime 0L /* special time apparently*/
> 
> static char *program_name;
> 
> static char *direction[5] = {
>   "normal", 
>   "left", 
>   "inverted", 
>   "right",
>   "\n"};
> 
> /* subpixel order */
> static char *order[6] = {
>   "unknown",
>   "horizontal rgb",
>   "horizontal bgr",
>   "vertical rgb",
>   "vertical bgr",
>   "no subpixels"};
> 
> 
> static void
> usage(void)
> {
>   fprintf(stderr, "usage: %s [options]\n", program_name);
>   fprintf(stderr, "  where options are:\n");
>   fprintf(stderr, "  -display <display> or -d <display>\n");
>   fprintf(stderr, "  -help\n");
>   fprintf(stderr, "  -o <normal,inverted,left,right,0,1,2,3>\n");
>   fprintf(stderr, "            or --orientation <normal,inverted,left,right,0,1,2,3>\n");
>   fprintf(stderr, "  -q        or --query\n");
>   fprintf(stderr, "  -s <size>/<width>x<height> or --size <size>/<width>x<height>\n");
>   fprintf(stderr, "  -r <rate> or --rate <rate>\n");
>   fprintf(stderr, "  -v        or --version\n");
>   fprintf(stderr, "  -x        (reflect in x)\n");
>   fprintf(stderr, "  -y        (reflect in y)\n");
>   fprintf(stderr, "  --screen <screen>\n");
>   fprintf(stderr, "  --verbose\n");
>   
>   exit(1);
>   /*NOTREACHED*/
> }
> 
> // Same idea as xc/lib/Xrandr.c (XRRConfigRates).
> // Returns the rates for a given screen.
> // Would be nice to put in another library or something.
> short*
> ConfigRates(XCBRandRGetScreenInfoRep *config, int sizeID, int *nrates)
> {
>     int i = 0;
>     short *ents;
>     XCBRandRRefreshRatesIter ri = XCBRandRGetScreenInfoRatesIter(config);
>     
>     while (i++ < sizeID) {
> 	XCBRandRRefreshRatesNext(&ri);
>     }
>     
>     ents = XCBRandRRefreshRatesRates(ri.data);
>     *nrates = XCBRandRRefreshRatesRatesLength(ri.data);
>     
>     if (!nrates) {
> 	*nrates = 0;
> 	return 0;
>     }
>     
>     return ents;
> }
> 
> int
> main (int argc, char **argv)
> {
>   XCBConnection  *c;
>   XCBRandRScreenSize *sizes;
>   XCBRandRGetScreenInfoRep *sc;
>   int		nsize;
>   int		nrate;
>   short		*rates;
>   XCBSCREEN	*root;
>   int		status = XCBRandRSetConfigFailed;
>   int		rot = -1;
>   int		verbose = 0, query = 0;
>   short		rotation, current_rotation, rotations;
>   XCBGenericEvent *event;
>   XCBRandRScreenChangeNotifyEvent *sce;
>   char          *display_name = NULL;
>   char		*host;
>   int		display;
>   int 		i, j;
>   int		current_size;
>   short		current_rate;
>   short		rate = -1;
>   short		size = -1;
>   int		dirind = 0;
>   static int	setit = 0;
>   int		screen = -1;
>   int		version = 0;
>   int		event_base, error_base;
>   short		reflection = 0;
>   int		width = 0, height = 0;
>   int		have_pixel_size = 0;
>   XCBGenericError *err;
> 
>   program_name = argv[0];
>   if (argc == 1) query = 1;
>   for (i = 1; i < argc; i++) {
>     if (!strcmp ("-display", argv[i]) || !strcmp ("-d", argv[i])) {
>       if (++i>=argc) usage ();
>       display_name = argv[i];
>       continue;
>     }
>     if (!strcmp("-help", argv[i])) {
>       usage();
>       continue;
>     }
>     if (!strcmp ("--verbose", argv[i])) {
>       verbose = 1;
>       continue;
>     }
> 
>     if (!strcmp ("-s", argv[i]) || !strcmp ("--size", argv[i])) {
>       if (++i>=argc) usage ();
>       if (sscanf (argv[i], "%dx%d", &width, &height) == 2)
> 	have_pixel_size = 1;
>       else {
> 	size = atoi (argv[i]);
> 	if (size < 0) usage();
>       }
>       setit = 1;
>       continue;
>     }
> 
>     if (!strcmp ("-r", argv[i]) || !strcmp ("--rate", argv[i])) {
>       if (++i>=argc) usage ();
>       rate = atoi (argv[i]);
>       if (rate < 0) usage();
>       setit = 1;
>       continue;
>     }
> 
>     if (!strcmp ("-v", argv[i]) || !strcmp ("--version", argv[i])) {
>       version = 1;
>       continue;
>     }
> 
>     if (!strcmp ("-x", argv[i])) {
>       reflection |= XCBRandRRotationReflect_X;
>       setit = 1;
>       continue;
>     }
>     if (!strcmp ("-y", argv[i])) {
>       reflection |= XCBRandRRotationReflect_Y;
>       setit = 1;
>       continue;
>     }
>     if (!strcmp ("--screen", argv[i])) {
>       if (++i>=argc) usage ();
>       screen = atoi (argv[i]);
>       if (screen < 0) usage();
>       continue;
>     }
>     if (!strcmp ("-q", argv[i]) || !strcmp ("--query", argv[i])) {
>       query = 1;
>       continue;
>     }
>     if (!strcmp ("-o", argv[i]) || !strcmp ("--orientation", argv[i])) {
>       char *endptr;
>       if (++i>=argc) usage ();
>       dirind = strtol(argv[i], &endptr, 0);
>       if (*endptr != '\0') {
> 	for (dirind = 0; dirind < 4; dirind++) {
> 	  if (strcmp (direction[dirind], argv[i]) == 0) break;
> 	}
> 	if ((dirind < 0) || (dirind > 3))  usage();
>       }
>       rot = dirind;
>       setit = 1;
>       continue;
>     }
>     
>     usage();
>   }
>  
>   if (verbose) query = 1;
> 
>   if (!XCBParseDisplay(display_name, &host, &display, &screen)) {
>       fprintf(stderr, "Invalid DISPLAY\n");
>       exit(1);
>   }
> 
>   int fd = XCBOpen(host, display);
>   free(host);
>   if (fd == -1) {
>       fprintf(stderr, "Error: XCBOpen\n");
>       exit(1);
>   }
> 
>   /* Now we open the connection */
>   XCBAuthInfo auth;
>   XCBGetAuthInfo(fd, &auth);
>   c = XCBConnect(fd, &auth);
> 
>   /* Free auth data */
>   free(auth.name);
>   free(auth.data);
>   
>   if (!c) {
>       fprintf (stderr, "Can't open display %s\n", display_name);
>       exit (1);
>   }
>   if (screen < 0)
>     screen = 0;
> 
> /* TODO: Figure out a way to do this later...
>   if (screen >= ScreenCount (c)) {
>     fprintf (stderr, "Invalid screen number %d (display has %d)\n",
> 	     screen, ScreenCount (c));
>     exit (1);
>   }
> */
> 		
>   root = XCBConnSetupSuccessRepRootsIter(XCBGetSetup(c)).data;
>   XCBRandRGetScreenInfoCookie scookie;
> 
>   int major_version, minor_version;
>   XCBRandRQueryVersionRep *rr_version;
>   rr_version = XCBRandRQueryVersionReply(c, XCBRandRQueryVersion(c, 1, 1), &err);
>   major_version = rr_version->major_version;
>   minor_version = rr_version->minor_version;
> 
>   scookie = XCBRandRGetScreenInfo(c, root->root);
>   sc = XCBRandRGetScreenInfoReply(c, scookie, &err);
> 
>   if (sc == NULL || err) {
> 	fprintf(stderr, "Can't get screen info.\n");
> 	exit (1);
>   }
> 
>   current_rotation = sc->rotation;
>   current_size = sc->sizeID;
>   
>   nsize = sc->nSizes;
>   sizes = XCBRandRGetScreenInfoSizes(sc);
> 
>   if (have_pixel_size) {
>     for (size = 0; size < nsize; size++)
>     {
>       if (sizes[size].width == width && sizes[size].height == height)
> 	break;
>     }
>   }
>   else if (size < 0)
>     size = current_size;
> 
>   if (size >= nsize) usage();
> 
>   if (rot < 0)
>   {
>     for (rot = 0; rot < 4; rot++)
> 	if (1 << rot == (current_rotation & 0xf))
> 	    break;
>   }
> 
>   current_rate = sc->rate;
>   
>   if (rate < 0)
>   {
>     if (size == current_size)
> 	rate = current_rate;
>     else
> 	rate = 0;
>   }
> 
>   if (version) {
>     printf("Server reports RandR version %d.%d\n", 
> 	   major_version, minor_version);
>   }
>   
>   if (query) {
>     printf(" SZ:    Pixels          Physical       Refresh\n");
>     for (i = 0; i < nsize; i++) {
>       printf ("%c%-2d %5d x %-5d  (%4dmm x%4dmm )",
> 	   i == current_size ? '*' : ' ',
> 	   i, sizes[i].width, sizes[i].height,
> 	   sizes[i].mwidth, sizes[i].mheight);
>       rates = ConfigRates (sc, i, &nrate);
> 
>       if (nrate) printf ("  ");
>       for (j = 0; j < nrate; j++)
> 	printf ("%c%-4d",
> 		i == current_size && rates[j] == current_rate ? '*' : ' ',
> 		rates[j]);
>       printf ("\n");
>     }
>   }
> 
>   //rotations = XRRConfigRotations(sc, &current_rotation);
>   rotations = sc->rotation;
> 
>   rotation = 1 << rot ;
>   if (query) {
>     for (i = 0; i < 4; i ++) {
>       if ((current_rotation >> i) & 1) 
> 	printf("Current rotation - %s\n", direction[i]);
>     }
> 
>     printf("Current reflection - ");
>     if (current_rotation & (XCBRandRRotationReflect_X|XCBRandRRotationReflect_Y))
>     {
> 	if (current_rotation & XCBRandRRotationReflect_X) printf ("X Axis ");
> 	if (current_rotation & XCBRandRRotationReflect_Y) printf ("Y Axis");
>     }
>     else
> 	printf ("none");
>     printf ("\n");
>     
> 
>     printf ("Rotations possible - ");
>     for (i = 0; i < 4; i ++) {
>       if ((rotations >> i) & 1)  printf("%s ", direction[i]);
>     }
>     printf ("\n");
> 
>     printf ("Reflections possible - ");
>     if (rotations & (XCBRandRRotationReflect_X|XCBRandRRotationReflect_Y))
>     {
>         if (rotations & XCBRandRRotationReflect_X) printf ("X Axis ");
> 	if (rotations & XCBRandRRotationReflect_Y) printf ("Y Axis");
>     }
>     else
> 	printf ("none");
>     printf ("\n");
>   }
> 
>   if (verbose) { 
>     printf("Setting size to %d, rotation to %s\n",  size, direction[rot]);
> 
>     printf ("Setting reflection on ");
>     if (reflection)
>     {
> 	if (reflection & XCBRandRRotationReflect_X) printf ("X Axis ");
> 	if (reflection & XCBRandRRotationReflect_Y) printf ("Y Axis");
>     }
>     else
> 	printf ("neither axis");
>     printf ("\n");
> 
>     if (reflection & XCBRandRRotationReflect_X) printf("Setting reflection on X axis\n");
> 
>     if (reflection & XCBRandRRotationReflect_Y) printf("Setting reflection on Y axis\n");
>   }
> 
>   /* we should test configureNotify on the root window */
>   CARD16 mask = (CARD16) StructureNotifyMask;
>   CARD32 values[1];
>   values[0] = 1;
>   XCBConfigureWindow(c, root->root, mask, values);
> 
>   if (setit) XCBRandRSelectInput (c, root->root, XCBRandRSMScreenChangeNotify);
> 
>   if (setit) {
>     XCBRandRSetScreenConfigCookie sscc;
>     sscc = XCBRandRSetScreenConfig(c, root->root, CurrentTime, sc->config_timestamp, size,
> 	    (short) (rotation | reflection), rate);
>     status = XCBRandRSetScreenConfigReply(c, sscc, &err)->status;
>     
>     if (err && status) {
> 	fprintf(stderr, "Can't set the screen. Error Code: %i Status:%i\n",
> 		err->error_code, status);
> 	exit(1);
>     }
>   }
>     
>   const XCBQueryExtensionRep *qrre_rep = XCBRandRInit(c);
>   event_base = qrre_rep->first_event;
>   error_base = qrre_rep->first_error;
>   
>   if (verbose && setit) {
>     if (status == XCBRandRSetConfigSuccess)
>       {
> 	while (1) {
> 	int spo;
> 	event = XCBWaitEvent(c);
> 	
> 	printf ("Event received, type = %d\n", event->response_type);
> 	//update Xlib's knowledge of the event
> 	////Not sure what the equiv of this is or if we need it.
> 	//XRRUpdateConfiguration (&event);
> 	
> 	if (event->response_type == ConfigureNotify)
> 	  printf("Received ConfigureNotify Event!\n");
> 	
> 	switch (event->response_type - event_base) {
> 	case XCBRandRScreenChangeNotify:
> 	  sce = (XCBRandRScreenChangeNotifyEvent *) event;
> 
> 	  printf("Got a screen change notify event!\n");
> 	  printf(" window = %d\n root = %d\n size_index = %d\n rotation %d\n", 
> 	       (int) sce->request_window.xid, (int) sce->root.xid, 
> 	       sce->sizeID,  sce->rotation);
> 	  printf(" timestamp = %ld, config_timestamp = %ld\n",
> 	       sce->timestamp, sce->config_timestamp);
> 	  printf(" Rotation = %x\n", sce->rotation);
> 	  printf(" %d X %d pixels, %d X %d mm\n",
> 		 sce->width, sce->height, sce->mwidth, sce->mheight);
> 	  
> 	  printf("Display width   %d, height   %d\n",
> 		 root->width_in_pixels, root->height_in_pixels);
> 	  printf("Display widthmm %d, heightmm %d\n", 
> 		 root->width_in_millimeters, root->height_in_millimeters);
> 	  
> 	  spo = sce->subpixel_order;
> 	  if ((spo < 0) || (spo > 5))
> 	    printf ("Unknown subpixel order, value = %d\n", spo);
> 	  else printf ("new Subpixel rendering model is %s\n", order[spo]);
> 	  break;
> 	default:
> 	  if (event->response_type != ConfigureNotify) 
> 	    printf("unknown event received, type = %d!\n", event->response_type);
> 	}
> 	}
>       }
>   }
>   //XRRFreeScreenConfigInfo(sc);
>   free(sc);
>   free(c);
>   return(0);
> }
> _______________________________________________
> xcb mailing list
> xcb at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/xcb



More information about the xcb mailing list