mirror of
https://gitlab.freedesktop.org/xorg/xserver.git
synced 2026-05-24 05:28:12 +02:00
480 lines
15 KiB
C
480 lines
15 KiB
C
/* $Xorg: Color.c,v 1.3 2000/08/17 19:53:27 cpqbld Exp $ */
|
|
/*
|
|
|
|
Copyright 1993 by Davor Matic
|
|
|
|
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. Davor Matic makes no representations about
|
|
the suitability of this software for any purpose. It is provided "as
|
|
is" without express or implied warranty.
|
|
|
|
*/
|
|
/* $XFree86$ */
|
|
|
|
#ifdef HAVE_XNEST_CONFIG_H
|
|
#include <xnest-config.h>
|
|
#endif
|
|
|
|
#include <X11/Xmd.h>
|
|
#include <X11/XCB/xcb.h>
|
|
#include <X11/XCB/xproto.h>
|
|
#include <X11/XCB/xcb_aux.h>
|
|
#include "scrnintstr.h"
|
|
#include "window.h"
|
|
#include "windowstr.h"
|
|
#include "colormapst.h"
|
|
#include "resource.h"
|
|
|
|
#include "Xnest.h"
|
|
|
|
|
|
#include "Display.h"
|
|
#include "Screen.h"
|
|
#include "Color.h"
|
|
#include "Visual.h"
|
|
#include "XNWindow.h"
|
|
#include "Args.h"
|
|
|
|
static ColormapPtr InstalledMaps[MAXSCREENS];
|
|
|
|
Bool xnestCreateColormap(ColormapPtr pCmap)
|
|
{
|
|
VisualPtr pVisual;
|
|
XCBVISUALID vid;
|
|
XCBSCREEN *screen;
|
|
XCBGenericError *e;
|
|
XCBRGB *colors;
|
|
int i, ncolors;
|
|
CARD32 *pixels;
|
|
CARD32 red, green, blue;
|
|
CARD32 redInc, greenInc, blueInc;
|
|
XCBQueryColorsCookie c;
|
|
XCBQueryColorsRep *rep;
|
|
|
|
pVisual = pCmap->pVisual;
|
|
ncolors = pVisual->ColormapEntries;
|
|
|
|
pCmap->devPriv = (pointer)xalloc(sizeof(xnestPrivColormap));
|
|
screen = XCBSetupRootsIter (XCBGetSetup (xnestConnection)).data;
|
|
|
|
xnestColormapPriv(pCmap)->colormap = XCBCOLORMAPNew(xnestConnection);
|
|
vid = screen->root_visual;
|
|
XCBCreateColormap(xnestConnection,
|
|
(pVisual->class & DynamicClass) ? XCBColormapAllocAll : XCBColormapAllocNone,
|
|
xnestColormapPriv(pCmap)->colormap,
|
|
xnestDefaultWindows[pCmap->pScreen->myNum],
|
|
vid);
|
|
|
|
|
|
switch (pVisual->class) {
|
|
case XCBVisualClassStaticGray: /* read only */
|
|
colors = xalloc(ncolors * sizeof(XCBRGB));
|
|
pixels = xalloc(ncolors * sizeof(CARD32));
|
|
for (i = 0; i < ncolors; i++)
|
|
pixels[i] = i;
|
|
c = XCBQueryColors(xnestConnection, xnestColormap(pCmap), ncolors, pixels);
|
|
rep = XCBQueryColorsReply(xnestConnection, c, 0);
|
|
colors = XCBQueryColorsColors(rep);
|
|
for (i = 0; i < ncolors; i++) {
|
|
pCmap->red[i].co.local.red = colors[i].red;
|
|
pCmap->red[i].co.local.green = colors[i].red;
|
|
pCmap->red[i].co.local.blue = colors[i].red;
|
|
}
|
|
xfree(colors);
|
|
xfree(pixels);
|
|
break;
|
|
|
|
case XCBVisualClassStaticColor: /* read only */
|
|
colors = xalloc(ncolors * sizeof(XCBRGB));
|
|
pixels = xalloc(ncolors * sizeof(CARD32));
|
|
for (i = 0; i < ncolors; i++)
|
|
pixels[i] = i;
|
|
c = XCBQueryColors(xnestConnection, xnestColormap(pCmap), ncolors, pixels);
|
|
rep = XCBQueryColorsReply(xnestConnection, c, 0);
|
|
colors = XCBQueryColorsColors(rep);
|
|
for (i = 0; i < ncolors; i++) {
|
|
pCmap->red[i].co.local.red = colors[i].red;
|
|
pCmap->red[i].co.local.green = colors[i].green;
|
|
pCmap->red[i].co.local.blue = colors[i].blue;
|
|
}
|
|
xfree(colors);
|
|
xfree(pixels);
|
|
break;
|
|
|
|
case XCBVisualClassTrueColor: /* read only */
|
|
//colors = xalloc(ncolors * sizeof(XCBRGB));
|
|
pixels = xalloc(ncolors * sizeof(CARD32));
|
|
red = green = blue = 0L;
|
|
redInc = lowbit(pVisual->redMask);
|
|
greenInc = lowbit(pVisual->greenMask);
|
|
blueInc = lowbit(pVisual->blueMask);
|
|
for (i = 0; i < ncolors; i++) {
|
|
pixels[i] = red | green | blue;
|
|
red += redInc;
|
|
if (red > pVisual->redMask) red = 0L;
|
|
green += greenInc;
|
|
if (green > pVisual->greenMask) green = 0L;
|
|
blue += blueInc;
|
|
if (blue > pVisual->blueMask) blue = 0L;
|
|
}
|
|
c = XCBQueryColors(xnestConnection, xnestColormap(pCmap), ncolors, pixels);
|
|
xfree(pixels);
|
|
rep = XCBQueryColorsReply(xnestConnection, c, &e);
|
|
colors = XCBQueryColorsColors(rep);
|
|
for (i = 0; i < ncolors; i++) {
|
|
pCmap->red[i].co.local.red = colors[i].red;
|
|
pCmap->green[i].co.local.green = colors[i].green;
|
|
pCmap->blue[i].co.local.blue = colors[i].blue;
|
|
}
|
|
/*free(colors); FIXME: are we leaking? crash if I free it...*/
|
|
break;
|
|
|
|
case XCBVisualClassGrayScale: /* read and write */
|
|
break;
|
|
|
|
case XCBVisualClassPseudoColor: /* read and write */
|
|
break;
|
|
|
|
case XCBVisualClassDirectColor: /* read and write */
|
|
break;
|
|
}
|
|
|
|
return True;
|
|
}
|
|
|
|
void xnestDestroyColormap(ColormapPtr pCmap)
|
|
{
|
|
XCBFreeColormap(xnestConnection, xnestColormap(pCmap));
|
|
xfree(pCmap->devPriv);
|
|
}
|
|
|
|
#define SEARCH_PREDICATE \
|
|
(xnestWindow(pWin).xid != None && wColormap(pWin) == icws->cmapIDs[i].xid)
|
|
|
|
static int xnestCountInstalledColormapWindows(WindowPtr pWin, pointer ptr)
|
|
{
|
|
xnestInstalledColormapWindows *icws = (xnestInstalledColormapWindows *)ptr;
|
|
int i;
|
|
|
|
for (i = 0; i < icws->numCmapIDs; i++)
|
|
if (SEARCH_PREDICATE) {
|
|
icws->numWindows++;
|
|
return WT_DONTWALKCHILDREN;
|
|
}
|
|
|
|
return WT_WALKCHILDREN;
|
|
}
|
|
|
|
static int xnestGetInstalledColormapWindows(WindowPtr pWin, pointer ptr)
|
|
{
|
|
xnestInstalledColormapWindows *icws = (xnestInstalledColormapWindows *)ptr;
|
|
int i;
|
|
|
|
for (i = 0; i < icws->numCmapIDs; i++)
|
|
if (SEARCH_PREDICATE) {
|
|
icws->windows[icws->index++] = xnestWindow(pWin);
|
|
return WT_DONTWALKCHILDREN;
|
|
}
|
|
|
|
return WT_WALKCHILDREN;
|
|
}
|
|
|
|
static XCBWINDOW *xnestOldInstalledColormapWindows = NULL;
|
|
static int xnestNumOldInstalledColormapWindows = 0;
|
|
static Bool xnestSameInstalledColormapWindows(XCBWINDOW *windows, int numWindows)
|
|
{
|
|
if (xnestNumOldInstalledColormapWindows != numWindows)
|
|
return False;
|
|
|
|
if (xnestOldInstalledColormapWindows == windows)
|
|
return True;
|
|
|
|
if (xnestOldInstalledColormapWindows == NULL || windows == NULL)
|
|
return False;
|
|
|
|
if (memcmp(xnestOldInstalledColormapWindows, windows,
|
|
numWindows * sizeof(XCBWINDOW)))
|
|
return False;
|
|
|
|
return True;
|
|
}
|
|
|
|
static void xnestSetWmColormapWindows(XCBConnection *c, XCBWINDOW win, XCBWINDOW *wins, int numwin)
|
|
{
|
|
}
|
|
|
|
void xnestSetInstalledColormapWindows(ScreenPtr pScreen)
|
|
{
|
|
xnestInstalledColormapWindows icws;
|
|
XCBVISUALID vis;
|
|
XCBParamsCW params;
|
|
int numWindows;
|
|
|
|
icws.cmapIDs = (XCBCOLORMAP *)xalloc(pScreen->maxInstalledCmaps*sizeof(XCBCOLORMAP));
|
|
icws.numCmapIDs = xnestListInstalledColormaps(pScreen, icws.cmapIDs);
|
|
icws.numWindows = 0;
|
|
WalkTree(pScreen, xnestCountInstalledColormapWindows, (pointer)&icws);
|
|
if (icws.numWindows) {
|
|
icws.windows = xalloc((icws.numWindows + 1) * sizeof(XCBWINDOW));
|
|
icws.index = 0;
|
|
WalkTree(pScreen, xnestGetInstalledColormapWindows, (pointer)&icws);
|
|
icws.windows[icws.numWindows] = xnestDefaultWindows[pScreen->myNum];
|
|
numWindows = icws.numWindows + 1;
|
|
}
|
|
else {
|
|
icws.windows = NULL;
|
|
numWindows = 0;
|
|
}
|
|
|
|
xfree(icws.cmapIDs);
|
|
|
|
if (!xnestSameInstalledColormapWindows(icws.windows, icws.numWindows)) {
|
|
if (xnestOldInstalledColormapWindows)
|
|
xfree(xnestOldInstalledColormapWindows);
|
|
|
|
xnestSetWmColormapWindows(xnestConnection, xnestDefaultWindows[pScreen->myNum], icws.windows, numWindows);
|
|
|
|
xnestOldInstalledColormapWindows = icws.windows;
|
|
xnestNumOldInstalledColormapWindows = icws.numWindows;
|
|
|
|
#ifdef DUMB_WINDOW_MANAGERS
|
|
/*
|
|
This code is for dumb window managers.
|
|
This will only work with default local visual colormaps.
|
|
*/
|
|
if (icws.numWindows)
|
|
{
|
|
WindowPtr pWin;
|
|
XCBVISUALTYPE *visual;
|
|
ColormapPtr pCmap;
|
|
|
|
pWin = xnestWindowPtr(icws.windows[0]);
|
|
vis.id = wVisual(pWin);
|
|
visual = xnestVisualFromID(pScreen, vis);
|
|
|
|
if (visual == xnestGetDefaultVisual(pScreen))
|
|
pCmap = (ColormapPtr)LookupIDByType(wColormap(pWin),
|
|
RT_COLORMAP);
|
|
else
|
|
pCmap = (ColormapPtr)LookupIDByType(pScreen->defColormap,
|
|
RT_COLORMAP);
|
|
|
|
params.colormap = xnestColormap(pCmap).xid;
|
|
/*XCBAuxChangeWindowAttributes(xnestConnection,
|
|
xnestDefaultRoots[pScreen->myNum],
|
|
XCBCWColormap,
|
|
¶ms);*/
|
|
/* XSetWindowColormap(xnestDisplay,
|
|
xnestDefaultWindows[pScreen->myNum],
|
|
xnestColormap(pCmap));*/
|
|
}
|
|
#endif /* DUMB_WINDOW_MANAGERS */
|
|
}
|
|
else
|
|
if (icws.windows) xfree(icws.windows);
|
|
}
|
|
|
|
void xnestSetScreenSaverColormapWindow(ScreenPtr pScreen)
|
|
{
|
|
if (xnestOldInstalledColormapWindows)
|
|
xfree(xnestOldInstalledColormapWindows);
|
|
|
|
xnestSetWmColormapWindows(xnestConnection, xnestDefaultWindows[pScreen->myNum],
|
|
&xnestScreenSaverWindows[pScreen->myNum], 1);
|
|
|
|
xnestOldInstalledColormapWindows = NULL;
|
|
xnestNumOldInstalledColormapWindows = 0;
|
|
|
|
xnestDirectUninstallColormaps(pScreen);
|
|
}
|
|
void xnestDirectInstallColormaps(ScreenPtr pScreen)
|
|
{
|
|
int i, n;
|
|
XCBCOLORMAP pCmapIDs[MAXCMAPS];
|
|
|
|
if (!xnestDoDirectColormaps) return;
|
|
|
|
n = (*pScreen->ListInstalledColormaps)(pScreen, (XID *)pCmapIDs);
|
|
|
|
for (i = 0; i < n; i++) {
|
|
ColormapPtr pCmap;
|
|
|
|
pCmap = (ColormapPtr)LookupIDByType(pCmapIDs[i].xid, RT_COLORMAP);
|
|
if (pCmap)
|
|
XCBInstallColormap(xnestConnection, xnestColormap(pCmap));
|
|
}
|
|
}
|
|
void xnestDirectUninstallColormaps(ScreenPtr pScreen)
|
|
{
|
|
int i, n;
|
|
XCBCOLORMAP pCmapIDs[MAXCMAPS];
|
|
|
|
if (!xnestDoDirectColormaps) return;
|
|
|
|
n = (*pScreen->ListInstalledColormaps)(pScreen, (XID*)pCmapIDs);
|
|
|
|
for (i = 0; i < n; i++) {
|
|
ColormapPtr pCmap;
|
|
|
|
pCmap = (ColormapPtr)LookupIDByType(pCmapIDs[i].xid, RT_COLORMAP);
|
|
if (pCmap)
|
|
XCBUninstallColormap(xnestConnection, xnestColormap(pCmap));
|
|
}
|
|
}
|
|
void xnestInstallColormap(ColormapPtr pCmap)
|
|
{
|
|
int index;
|
|
ColormapPtr pOldCmap;
|
|
|
|
index = pCmap->pScreen->myNum;
|
|
pOldCmap = InstalledMaps[index];
|
|
|
|
if(pCmap != pOldCmap)
|
|
{
|
|
xnestDirectUninstallColormaps(pCmap->pScreen);
|
|
|
|
/* Uninstall pInstalledMap. Notify all interested parties. */
|
|
if(pOldCmap != (ColormapPtr)None)
|
|
WalkTree(pCmap->pScreen, TellLostMap, (pointer)&pOldCmap->mid);
|
|
|
|
InstalledMaps[index] = pCmap;
|
|
WalkTree(pCmap->pScreen, TellGainedMap, (pointer)&pCmap->mid);
|
|
|
|
xnestSetInstalledColormapWindows(pCmap->pScreen);
|
|
xnestDirectInstallColormaps(pCmap->pScreen);
|
|
}
|
|
}
|
|
void xnestUninstallColormap(ColormapPtr pCmap)
|
|
{
|
|
int index;
|
|
ColormapPtr pCurCmap;
|
|
|
|
index = pCmap->pScreen->myNum;
|
|
pCurCmap = InstalledMaps[index];
|
|
|
|
if(pCmap == pCurCmap)
|
|
{
|
|
if (pCmap->mid != pCmap->pScreen->defColormap)
|
|
{
|
|
pCurCmap = (ColormapPtr)LookupIDByType(pCmap->pScreen->defColormap,
|
|
RT_COLORMAP);
|
|
(*pCmap->pScreen->InstallColormap)(pCurCmap);
|
|
}
|
|
}
|
|
}
|
|
|
|
static Bool xnestInstalledDefaultColormap = False;
|
|
|
|
int xnestListInstalledColormaps(ScreenPtr pScreen, XCBCOLORMAP *pCmapIDs)
|
|
{
|
|
if (xnestInstalledDefaultColormap) {
|
|
pCmapIDs->xid = InstalledMaps[pScreen->myNum]->mid;
|
|
return 1;
|
|
}
|
|
else
|
|
return 0;
|
|
}
|
|
void xnestStoreColors(ColormapPtr pCmap, int nColors, XCBCOLORITEM *pColors)
|
|
{
|
|
if (pCmap->pVisual->class & DynamicClass)
|
|
/*#ifdef _XSERVER64
|
|
{
|
|
int i;
|
|
XColor *pColors64 = (XColor *)xalloc(nColors * sizeof(XColor) );
|
|
|
|
for(i = 0; i < nColors; ++i)
|
|
{
|
|
pColors64[i].pixel = pColors[i].pixel;
|
|
pColors64[i].red = pColors[i].red;
|
|
pColors64[i].green = pColors[i].green;
|
|
pColors64[i].blue = pColors[i].blue;
|
|
pColors64[i].flags = pColors[i].flags;
|
|
}
|
|
XCBStoreColors(xnestConnection, xnestColormap(pCmap), pColors64, nColors);
|
|
xfree(pColors64);
|
|
}
|
|
#else*/
|
|
XCBStoreColors(xnestConnection, xnestColormap(pCmap), nColors, pColors);
|
|
/*#endif*/
|
|
}
|
|
|
|
void xnestResolveColor(unsigned short *pRed, unsigned short *pGreen, unsigned short *pBlue, VisualPtr pVisual)
|
|
{
|
|
int shift;
|
|
unsigned int lim;
|
|
|
|
shift = 16 - pVisual->bitsPerRGBValue;
|
|
lim = (1 << pVisual->bitsPerRGBValue) - 1;
|
|
|
|
if ((pVisual->class == PseudoColor) || (pVisual->class == DirectColor))
|
|
{
|
|
/* rescale to rgb bits */
|
|
*pRed = ((*pRed >> shift) * 65535) / lim;
|
|
*pGreen = ((*pGreen >> shift) * 65535) / lim;
|
|
*pBlue = ((*pBlue >> shift) * 65535) / lim;
|
|
}
|
|
else if (pVisual->class == GrayScale)
|
|
{
|
|
/* rescale to gray then rgb bits */
|
|
*pRed = (30L * *pRed + 59L * *pGreen + 11L * *pBlue) / 100;
|
|
*pBlue = *pGreen = *pRed = ((*pRed >> shift) * 65535) / lim;
|
|
}
|
|
else if (pVisual->class == StaticGray)
|
|
{
|
|
unsigned int limg;
|
|
|
|
limg = pVisual->ColormapEntries - 1;
|
|
/* rescale to gray then [0..limg] then [0..65535] then rgb bits */
|
|
*pRed = (30L * *pRed + 59L * *pGreen + 11L * *pBlue) / 100;
|
|
*pRed = ((((*pRed * (limg + 1))) >> 16) * 65535) / limg;
|
|
*pBlue = *pGreen = *pRed = ((*pRed >> shift) * 65535) / lim;
|
|
}
|
|
else
|
|
{
|
|
unsigned limr, limg, limb;
|
|
|
|
limr = pVisual->redMask >> pVisual->offsetRed;
|
|
limg = pVisual->greenMask >> pVisual->offsetGreen;
|
|
limb = pVisual->blueMask >> pVisual->offsetBlue;
|
|
/* rescale to [0..limN] then [0..65535] then rgb bits */
|
|
*pRed = ((((((*pRed * (limr + 1)) >> 16) *
|
|
65535) / limr) >> shift) * 65535) / lim;
|
|
*pGreen = ((((((*pGreen * (limg + 1)) >> 16) *
|
|
65535) / limg) >> shift) * 65535) / lim;
|
|
*pBlue = ((((((*pBlue * (limb + 1)) >> 16) *
|
|
65535) / limb) >> shift) * 65535) / lim;
|
|
}
|
|
}
|
|
Bool xnestCreateDefaultColormap(ScreenPtr pScreen)
|
|
{
|
|
VisualPtr pVisual;
|
|
ColormapPtr pCmap;
|
|
unsigned short zero = 0, ones = 0xFFFF;
|
|
Pixel wp, bp;
|
|
|
|
for (pVisual = pScreen->visuals;
|
|
pVisual->vid != pScreen->rootVisual;
|
|
pVisual++);
|
|
|
|
if (CreateColormap(pScreen->defColormap, pScreen, pVisual, &pCmap,
|
|
(pVisual->class & DynamicClass) ? AllocNone : AllocAll, 0)
|
|
!= Success)
|
|
return False;
|
|
|
|
wp = pScreen->whitePixel;
|
|
bp = pScreen->blackPixel;
|
|
if ((AllocColor(pCmap, &ones, &ones, &ones, &wp, 0) !=
|
|
Success) ||
|
|
(AllocColor(pCmap, &zero, &zero, &zero, &bp, 0) !=
|
|
Success))
|
|
return FALSE;
|
|
pScreen->whitePixel = wp;
|
|
pScreen->blackPixel = bp;
|
|
(*pScreen->InstallColormap)(pCmap);
|
|
|
|
xnestInstalledDefaultColormap = True;
|
|
return True;
|
|
}
|