[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, ¤t_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