#ifdef HAVE_XNEST_CONFIG_H
#include <xnest-config.h>
#endif
#include <X11/X.h>
#include <X11/Xproto.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;
XColor *colors;
int i, ncolors;
Pixel red, green, blue;
Pixel redInc, greenInc, blueInc;
pVisual = pCmap->pVisual;
ncolors = pVisual->ColormapEntries;
pCmap->devPriv = (pointer)xalloc(sizeof(xnestPrivColormap));
xnestColormapPriv(pCmap)->colormap =
XCreateColormap(xnestDisplay,
xnestDefaultWindows[pCmap->pScreen->myNum],
xnestVisual(pVisual),
(pVisual->class & DynamicClass) ?
AllocAll : AllocNone);
switch (pVisual->class) {
case StaticGray:
colors = (XColor *)xalloc(ncolors * sizeof(XColor));
for (i = 0; i < ncolors; i++)
colors[i].pixel = i;
XQueryColors(xnestDisplay, xnestColormap(pCmap), colors, ncolors);
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);
break;
case StaticColor:
colors = (XColor *)xalloc(ncolors * sizeof(XColor));
for (i = 0; i < ncolors; i++)
colors[i].pixel = i;
XQueryColors(xnestDisplay, xnestColormap(pCmap), colors, ncolors);
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);
break;
case TrueColor:
colors = (XColor *)xalloc(ncolors * sizeof(XColor));
red = green = blue = 0L;
redInc = lowbit(pVisual->redMask);
greenInc = lowbit(pVisual->greenMask);
blueInc = lowbit(pVisual->blueMask);
for (i = 0; i < ncolors; i++) {
colors[i].pixel = 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;
}
XQueryColors(xnestDisplay, xnestColormap(pCmap), colors, ncolors);
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;
}
xfree(colors);
break;
case GrayScale:
break;
case PseudoColor:
break;
case DirectColor:
break;
}
return True;
}
void
xnestDestroyColormap(ColormapPtr pCmap)
{
XFreeColormap(xnestDisplay, xnestColormap(pCmap));
xfree(pCmap->devPriv);
}
#define SEARCH_PREDICATE \
(xnestWindow(pWin) != None && wColormap(pWin) == icws->cmapIDs[i])
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 Window *xnestOldInstalledColormapWindows = NULL;
static int xnestNumOldInstalledColormapWindows = 0;
static Bool
xnestSameInstalledColormapWindows(Window *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(Window)))
return False;
return True;
}
void
xnestSetInstalledColormapWindows(ScreenPtr pScreen)
{
xnestInstalledColormapWindows icws;
int numWindows;
icws.cmapIDs = (Colormap *)xalloc(pScreen->maxInstalledCmaps *
sizeof(Colormap));
icws.numCmapIDs = xnestListInstalledColormaps(pScreen, icws.cmapIDs);
icws.numWindows = 0;
WalkTree(pScreen, xnestCountInstalledColormapWindows, (pointer)&icws);
if (icws.numWindows) {
icws.windows = (Window *)xalloc((icws.numWindows + 1) * sizeof(Window));
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);
#ifdef _XSERVER64
{
int i;
Window64 *windows = (Window64 *)xalloc(numWindows * sizeof(Window64));
for(i = 0; i < numWindows; ++i)
windows[i] = icws.windows[i];
XSetWMColormapWindows(xnestDisplay, xnestDefaultWindows[pScreen->myNum],
windows, numWindows);
xfree(windows);
}
#else
XSetWMColormapWindows(xnestDisplay, xnestDefaultWindows[pScreen->myNum],
icws.windows, numWindows);
#endif
xnestOldInstalledColormapWindows = icws.windows;
xnestNumOldInstalledColormapWindows = icws.numWindows;
#ifdef DUMB_WINDOW_MANAGERS
if (icws.numWindows)
{
WindowPtr pWin;
Visual *visual;
ColormapPtr pCmap;
pWin = xnestWindowPtr(icws.windows[0]);
visual = xnestVisualFromID(pScreen, wVisual(pWin));
if (visual == xnestDefaultVisual(pScreen))
pCmap = (ColormapPtr)LookupIDByType(wColormap(pWin),
RT_COLORMAP);
else
pCmap = (ColormapPtr)LookupIDByType(pScreen->defColormap,
RT_COLORMAP);
XSetWindowColormap(xnestDisplay,
xnestDefaultWindows[pScreen->myNum],
xnestColormap(pCmap));
}
#endif
}
else
if (icws.windows) xfree(icws.windows);
}
void
xnestSetScreenSaverColormapWindow(ScreenPtr pScreen)
{
if (xnestOldInstalledColormapWindows)
xfree(xnestOldInstalledColormapWindows);
#ifdef _XSERVER64
{
Window64 window;
window = xnestScreenSaverWindows[pScreen->myNum];
XSetWMColormapWindows(xnestDisplay, xnestDefaultWindows[pScreen->myNum],
&window, 1);
xnestScreenSaverWindows[pScreen->myNum] = window;
}
#else
XSetWMColormapWindows(xnestDisplay, xnestDefaultWindows[pScreen->myNum],
&xnestScreenSaverWindows[pScreen->myNum], 1);
#endif
xnestOldInstalledColormapWindows = NULL;
xnestNumOldInstalledColormapWindows = 0;
xnestDirectUninstallColormaps(pScreen);
}
void
xnestDirectInstallColormaps(ScreenPtr pScreen)
{
int i, n;
Colormap pCmapIDs[MAXCMAPS];
if (!xnestDoDirectColormaps) return;
n = (*pScreen->ListInstalledColormaps)(pScreen, pCmapIDs);
for (i = 0; i < n; i++) {
ColormapPtr pCmap;
pCmap = (ColormapPtr)LookupIDByType(pCmapIDs[i], RT_COLORMAP);
if (pCmap)
XInstallColormap(xnestDisplay, xnestColormap(pCmap));
}
}
void
xnestDirectUninstallColormaps(ScreenPtr pScreen)
{
int i, n;
Colormap pCmapIDs[MAXCMAPS];
if (!xnestDoDirectColormaps) return;
n = (*pScreen->ListInstalledColormaps)(pScreen, pCmapIDs);
for (i = 0; i < n; i++) {
ColormapPtr pCmap;
pCmap = (ColormapPtr)LookupIDByType(pCmapIDs[i], RT_COLORMAP);
if (pCmap)
XUninstallColormap(xnestDisplay, xnestColormap(pCmap));
}
}
void
xnestInstallColormap(ColormapPtr pCmap)
{
int index;
ColormapPtr pOldCmap;
index = pCmap->pScreen->myNum;
pOldCmap = InstalledMaps[index];
if(pCmap != pOldCmap)
{
xnestDirectUninstallColormaps(pCmap->pScreen);
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, Colormap *pCmapIDs)
{
if (xnestInstalledDefaultColormap) {
*pCmapIDs = InstalledMaps[pScreen->myNum]->mid;
return 1;
}
else
return 0;
}
void
xnestStoreColors(ColormapPtr pCmap, int nColors, xColorItem *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;
}
XStoreColors(xnestDisplay, xnestColormap(pCmap), pColors64, nColors);
xfree(pColors64);
}
#else
XStoreColors(xnestDisplay, xnestColormap(pCmap),
(XColor *)pColors, nColors);
#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))
{
*pRed = ((*pRed >> shift) * 65535) / lim;
*pGreen = ((*pGreen >> shift) * 65535) / lim;
*pBlue = ((*pBlue >> shift) * 65535) / lim;
}
else if (pVisual->class == GrayScale)
{
*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;
*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;
*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;
}