Edit

IABSD.fr/xenocara/lib/libXrandr/src/XrrConfig.c

Branch :

  • Show log

    Commit

  • Author : matthieu
    Date : 2023-07-03 08:31:22
    Hash : dca2d3dc
    Message : Update to libXrandr 1.5.3

  • lib/libXrandr/src/XrrConfig.c
  • /*
     * Copyright © 2000 Compaq Computer Corporation, Inc.
     * Copyright © 2002 Hewlett Packard Company, Inc.
     * Copyright © 2006 Keith Packard
     *
     * 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 the copyright holders not be used in advertising or
     * publicity pertaining to distribution of the software without specific,
     * written prior permission.  The copyright holders make no representations
     * about the suitability of this software for any purpose.  It is provided "as
     * is" without express or implied warranty.
     *
     * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     * EVENT SHALL THE COPYRIGHT HOLDERS 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.
     *
     * Author:  Jim Gettys, HP Labs, HP.
     * Author:  Keith Packard, Intel Corporation
     */
    
    #ifdef HAVE_CONFIG_H
    #include <config.h>
    #endif
    
    #include <limits.h>
    #include <stdio.h>
    #include <X11/Xlib.h>
    /* we need to be able to manipulate the Display structure on events */
    #include <X11/Xlibint.h>
    #include <X11/extensions/render.h>
    #include <X11/extensions/Xrender.h>
    #include "Xrandrint.h"
    
    static XRRScreenConfiguration *_XRRGetScreenInfo (Display *dpy,
    						  XExtDisplayInfo *info,
    						  Window window);
    
    Rotation XRRConfigRotations(XRRScreenConfiguration *config, Rotation *current_rotation)
    {
      *current_rotation = config->current_rotation;
      return config->rotations;
    }
    
    XRRScreenSize *XRRConfigSizes(XRRScreenConfiguration *config, int *nsizes)
    {
       *nsizes = config->nsizes;
      return config->sizes;
    }
    
    short *XRRConfigRates (XRRScreenConfiguration *config, int sizeID, int *nrates)
    {
        short   *r = config->rates;
        int	    nents = config->nrates;
    
        /* Skip over the intervening rate lists */
        while (sizeID > 0 && nents > 0)
        {
    	int i = (*r + 1);
    	r += i;
    	nents -= i;
    	sizeID--;
        }
        if (!nents)
        {
    	*nrates = 0;
    	return NULL;
        }
        *nrates = (int) *r;
        return r + 1;
    }
    
    Time XRRConfigTimes (XRRScreenConfiguration *config, Time *config_timestamp)
    {
        *config_timestamp = config->config_timestamp;
        return config->timestamp;
    }
    
    
    SizeID XRRConfigCurrentConfiguration (XRRScreenConfiguration *config,
    			      Rotation *rotation)
    {
        *rotation = (Rotation) config->current_rotation;
        return (SizeID) config->current_size;
    }
    
    short XRRConfigCurrentRate (XRRScreenConfiguration *config)
    {
        return config->current_rate;
    }
    
    /*
     * Go get the screen configuration data and salt it away for future use;
     * returns NULL if extension not supported
     */
    static XRRScreenConfiguration *_XRRValidateCache (Display *dpy,
    						  XExtDisplayInfo *info,
    						  int screen)
    {
        if ((screen >= 0) && (screen < ScreenCount(dpy)) && XextHasExtension(info)) {
    	XRandRInfo *xrri = (XRandRInfo *) info->data;
    	XRRScreenConfiguration **configs = xrri->config;
    
    	if (configs[screen] == NULL)
    	    configs[screen] = _XRRGetScreenInfo (dpy, info, RootWindow(dpy, screen));
    	return configs[screen];
        } else {
    	return NULL;
        }
    }
    
    /* given a screen, return the information from the (possibly) cached data */
    Rotation XRRRotations(Display *dpy, int screen, Rotation *current_rotation)
    {
      XRRScreenConfiguration *config;
      XExtDisplayInfo *info = XRRFindDisplay(dpy);
    
      LockDisplay(dpy);
      if ((config = _XRRValidateCache(dpy, info, screen))) {
        Rotation cr = config->rotations;
        *current_rotation = config->current_rotation;
        UnlockDisplay(dpy);
        return cr;
      }
      else {
        UnlockDisplay(dpy);
        *current_rotation = RR_Rotate_0;
        return 0;	/* no rotations supported */
      }
    }
    
    /* given a screen, return the information from the (possibly) cached data */
    XRRScreenSize *XRRSizes(Display *dpy, int screen, int *nsizes)
    {
      XRRScreenConfiguration *config;
      XExtDisplayInfo *info = XRRFindDisplay(dpy);
    
      LockDisplay(dpy);
      if ((config = _XRRValidateCache(dpy, info, screen))) {
        XRRScreenSize *sizes = config->sizes;
        *nsizes = config->nsizes;
        UnlockDisplay(dpy);
        return sizes;
        }
      else {
        UnlockDisplay(dpy);
        *nsizes = 0;
        return NULL;
      }
    }
    
    short *XRRRates (Display *dpy, int screen, int sizeID, int *nrates)
    {
      XRRScreenConfiguration *config;
      XExtDisplayInfo *info = XRRFindDisplay(dpy);
    
      LockDisplay(dpy);
      if ((config = _XRRValidateCache(dpy, info, screen))) {
        short *rates = XRRConfigRates (config, sizeID, nrates);
        UnlockDisplay(dpy);
        return rates;
        }
      else {
        UnlockDisplay(dpy);
        *nrates = 0;
        return NULL;
      }
    }
    
    /* given a screen, return the information from the (possibly) cached data */
    Time XRRTimes (Display *dpy, int screen, Time *config_timestamp)
    {
      XRRScreenConfiguration *config;
      XExtDisplayInfo *info = XRRFindDisplay(dpy);
    
      LockDisplay(dpy);
      if ((config = _XRRValidateCache(dpy, info, screen))) {
          Time ts = config->timestamp;
          *config_timestamp = config->config_timestamp;
          UnlockDisplay(dpy);
          return ts;
        } else {
          UnlockDisplay(dpy);
    	return CurrentTime;
        }
    }
    
    /* need a version that does not hold the display lock */
    static XRRScreenConfiguration *_XRRGetScreenInfo (Display *dpy,
    						  XExtDisplayInfo *info,
    						  Window window)
    {
        xRRGetScreenInfoReply   rep;
        xRRGetScreenInfoReq	    *req;
        _XAsyncHandler 	    async;
        _XRRVersionState	    async_state;
        int			    nbytes, nbytesRead, rbytes;
        xScreenSizes	    size;
        struct _XRRScreenConfiguration  *scp;
        XRRScreenSize	    *ssp;
        short    		    *rates;
        XRandRInfo		    *xrri;
        Bool		    getting_version = False;
    
        xrri = (XRandRInfo *) info->data;
        if (!xrri)
    	return NULL;
    
        if (xrri->major_version == -1)
        {
    	xRRQueryVersionReq	*vreq;
    
    	/* hide a version query in the request */
    	GetReq (RRQueryVersion, vreq);
    	vreq->reqType = info->codes->major_opcode;
    	vreq->randrReqType = X_RRQueryVersion;
    	vreq->majorVersion = RANDR_MAJOR;
    	vreq->minorVersion = RANDR_MINOR;
    
    	async_state.version_seq = dpy->request;
    	async_state.error = False;
    	async.next = dpy->async_handlers;
    	async.handler = _XRRVersionHandler;
    	async.data = (XPointer) &async_state;
    	dpy->async_handlers = &async;
    
    	getting_version = True;
        }
    
        GetReq (RRGetScreenInfo, req);
        req->reqType = info->codes->major_opcode;
        req->randrReqType = X_RRGetScreenInfo;
        req->window = window;
    
        if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
        {
    	if (getting_version)
    	    DeqAsyncHandler (dpy, &async);
    	SyncHandle ();
    	return NULL;
        }
        if (getting_version)
        {
    	DeqAsyncHandler (dpy, &async);
    	if (async_state.error)
    	{
    	    UnlockDisplay (dpy);
    	    SyncHandle();
    	    LockDisplay (dpy);
    	}
    	xrri->major_version = async_state.major_version;
    	xrri->minor_version = async_state.minor_version;
    	xrri->has_rates = _XRRHasRates (xrri->minor_version, xrri->major_version);
        }
    
        /*
         * Make the reply compatible with v1.1
         */
        if (!xrri->has_rates)
        {
    	rep.rate = 0;
    	rep.nrateEnts = 0;
        }
        if (rep.length < INT_MAX >> 2) {
    	nbytes = (long) rep.length << 2;
    
    	nbytesRead = (long) (rep.nSizes * SIZEOF (xScreenSizes) +
    			    ((rep.nrateEnts + 1)& ~1) * 2 /* SIZEOF(CARD16) */);
    
    	/*
    	 * first we must compute how much space to allocate for
    	 * randr library's use; we'll allocate the structures in a single
    	 * allocation, on cleanlyness grounds.
    	 */
    
    	rbytes = sizeof (XRRScreenConfiguration) +
    	  (rep.nSizes * sizeof (XRRScreenSize) +
    	   rep.nrateEnts * sizeof (int));
    
    	scp = Xmalloc(rbytes);
        } else {
    	nbytes = 0;
    	nbytesRead = 0;
    	rbytes = 0;
    	scp = NULL;
        }
    
        if (scp == NULL) {
    	_XEatData (dpy, (unsigned long) nbytes);
    	return NULL;
        }
    
    
        ssp = (XRRScreenSize *)(scp + 1);
        rates = (short *) (ssp + rep.nSizes);
    
        /* set up the screen configuration structure */
        scp->screen =
          ScreenOfDisplay (dpy, XRRRootToScreen(dpy, rep.root));
    
        scp->sizes = ssp;
        scp->rates = rates;
        scp->rotations = rep.setOfRotations;
        scp->current_size = rep.sizeID;
        scp->current_rate = rep.rate;
        scp->current_rotation = rep.rotation;
        scp->timestamp = rep.timestamp;
        scp->config_timestamp = rep.configTimestamp;
        scp->nsizes = rep.nSizes;
        scp->nrates = rep.nrateEnts;
    
        /*
         * Time to unpack the data from the server.
         */
    
        /*
         * First the size information
         */
        for (unsigned int i = 0; i < rep.nSizes; i++)  {
    	_XReadPad (dpy, (char *) &size, SIZEOF (xScreenSizes));
    
            ssp[i].width = size.widthInPixels;
    	ssp[i].height = size.heightInPixels;
    	ssp[i].mwidth = size.widthInMillimeters;
    	ssp[i].mheight = size.heightInMillimeters;
        }
        /*
         * And the rates
         */
        _XRead16Pad (dpy, rates, 2 /* SIZEOF (CARD16) */ * rep.nrateEnts);
    
        /*
         * Skip any extra data
         */
        if (nbytes > nbytesRead)
    	_XEatData (dpy, (unsigned long) (nbytes - nbytesRead));
    
        return (XRRScreenConfiguration *)(scp);
    }
    
    XRRScreenConfiguration *XRRGetScreenInfo (Display *dpy, Window window)
    {
        XRRScreenConfiguration *config;
        XExtDisplayInfo *info = XRRFindDisplay(dpy);
        XRRFindDisplay(dpy);
        LockDisplay (dpy);
        config = _XRRGetScreenInfo(dpy, info, window);
        UnlockDisplay (dpy);
        SyncHandle ();
        return config;
    }
    
    
    void XRRFreeScreenConfigInfo (XRRScreenConfiguration *config)
    {
        Xfree (config);
    }
    
    Status XRRSetScreenConfigAndRate (Display *dpy,
    				  XRRScreenConfiguration *config,
    				  Drawable draw,
    				  int size_index,
    				  Rotation rotation,
    				  short rate,
    				  Time timestamp)
    {
        XExtDisplayInfo *info = XRRFindDisplay (dpy);
        xRRSetScreenConfigReply rep;
        XRandRInfo *xrri;
        int major, minor;
    
        RRCheckExtension (dpy, info, 0);
    
        /* Make sure has_rates is set */
        if (!XRRQueryVersion (dpy, &major, &minor))
    	return 0;
    
        LockDisplay (dpy);
        xrri = (XRandRInfo *) info->data;
        if (xrri->has_rates)
        {
    	xRRSetScreenConfigReq  *req;
    	GetReq (RRSetScreenConfig, req);
    	req->reqType = info->codes->major_opcode;
    	req->randrReqType = X_RRSetScreenConfig;
    	req->drawable = draw;
    	req->sizeID = size_index;
    	req->rotation = rotation;
    	req->timestamp = timestamp;
    	req->configTimestamp = config->config_timestamp;
    	req->rate = rate;
        }
        else
        {
    	xRR1_0SetScreenConfigReq  *req;
    	GetReq (RR1_0SetScreenConfig, req);
    	req->reqType = info->codes->major_opcode;
    	req->randrReqType = X_RRSetScreenConfig;
    	req->drawable = draw;
    	req->sizeID = size_index;
    	req->rotation = rotation;
    	req->timestamp = timestamp;
    	req->configTimestamp = config->config_timestamp;
        }
    
        (void) _XReply (dpy, (xReply *) &rep, 0, xTrue);
    
        /* actually .errorCode in struct xError */
        if (rep.status == RRSetConfigSuccess) {
          /* if we succeed, set our view of reality to what we set it to */
          config->config_timestamp = rep.newConfigTimestamp;
          config->timestamp = rep.newTimestamp;
          config->screen = ScreenOfDisplay (dpy, XRRRootToScreen(dpy, rep.root));
          config->current_size = size_index;
          config->current_rotation = rotation;
        }
        UnlockDisplay (dpy);
        SyncHandle ();
        return(rep.status);
    }
    
    Status XRRSetScreenConfig (Display *dpy,
    			   XRRScreenConfiguration *config,
    			   Drawable draw,
    			   int size_index,
    			   Rotation rotation, Time timestamp)
    {
        return XRRSetScreenConfigAndRate (dpy, config, draw, size_index,
    				      rotation, 0, timestamp);
    }