Blame clients/mwm/WmColormap.c

Packit b099d7
/* 
Packit b099d7
 * Motif
Packit b099d7
 *
Packit b099d7
 * Copyright (c) 1987-2012, The Open Group. All rights reserved.
Packit b099d7
 *
Packit b099d7
 * These libraries and programs are free software; you can
Packit b099d7
 * redistribute them and/or modify them under the terms of the GNU
Packit b099d7
 * Lesser General Public License as published by the Free Software
Packit b099d7
 * Foundation; either version 2 of the License, or (at your option)
Packit b099d7
 * any later version.
Packit b099d7
 *
Packit b099d7
 * These libraries and programs are distributed in the hope that
Packit b099d7
 * they will be useful, but WITHOUT ANY WARRANTY; without even the
Packit b099d7
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
Packit b099d7
 * PURPOSE. See the GNU Lesser General Public License for more
Packit b099d7
 * details.
Packit b099d7
 *
Packit b099d7
 * You should have received a copy of the GNU Lesser General Public
Packit b099d7
 * License along with these librararies and programs; if not, write
Packit b099d7
 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
Packit b099d7
 * Floor, Boston, MA 02110-1301 USA
Packit b099d7
*/ 
Packit b099d7
/* 
Packit b099d7
 * Motif Release 1.2.3
Packit b099d7
*/ 
Packit b099d7
#ifdef HAVE_CONFIG_H
Packit b099d7
#include <config.h>
Packit b099d7
#endif
Packit b099d7
Packit b099d7
Packit b099d7
#ifdef REV_INFO
Packit b099d7
#ifndef lint
Packit b099d7
static char rcsid[] = "$XConsortium: WmColormap.c /main/5 1996/10/30 11:14:44 drk $"
Packit b099d7
#endif
Packit b099d7
#endif
Packit b099d7
/*
Packit b099d7
 * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * Included Files:
Packit b099d7
 */
Packit b099d7
Packit b099d7
#include "WmGlobal.h"
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * include extern functions
Packit b099d7
 */
Packit b099d7
Packit b099d7
#include "WmColormap.h"
Packit b099d7
#include "WmKeyFocus.h"
Packit b099d7
Packit b099d7
static Bool ProcessEvents(Display *dpy, XEvent *Event, char *c_pCD);
Packit b099d7
Packit b099d7
Packit b099d7
/* Global variables */
Packit b099d7
	static unsigned long firstRequest, lastRequest;
Packit b099d7
Packit b099d7

Packit b099d7
/*************************************<->*************************************
Packit b099d7
 *
Packit b099d7
 *  InitWorkspaceColormap ()
Packit b099d7
 *
Packit b099d7
 *
Packit b099d7
 *  Description:
Packit b099d7
 *  -----------
Packit b099d7
 *  This function sets up the default workspace colormap and prepares for
Packit b099d7
 *  workspace colormap processing.
Packit b099d7
 *
Packit b099d7
 *
Packit b099d7
 *  Inputs:
Packit b099d7
 *  -------
Packit b099d7
 *  pSD = ptr to screen data
Packit b099d7
 * 
Packit b099d7
 *  Outputs:
Packit b099d7
 *  -------
Packit b099d7
 *  wmGD = (workspaceColormap)
Packit b099d7
 * 
Packit b099d7
 *************************************<->***********************************/
Packit b099d7
Packit b099d7
void InitWorkspaceColormap (WmScreenData *pSD)
Packit b099d7
{
Packit b099d7
    /*
Packit b099d7
     * Setup the default (workspace) colormap:
Packit b099d7
     * !!! this should be made more general to get the colormap for the !!!
Packit b099d7
     * !!! workspace (root) and then track colormap changes             !!!
Packit b099d7
     */
Packit b099d7
Packit b099d7
    pSD->workspaceColormap = DefaultColormap (DISPLAY, pSD->screen);
Packit b099d7
Packit b099d7
} /* END OF FUNCTION InitWorkspaceColormap */
Packit b099d7
Packit b099d7
Packit b099d7

Packit b099d7
/*************************************<->*************************************
Packit b099d7
 *
Packit b099d7
 *  InitColormapFocus (pSD)
Packit b099d7
 *
Packit b099d7
 *
Packit b099d7
 *  Description:
Packit b099d7
 *  -----------
Packit b099d7
 *  This function prepares for managing the colormap focus and sets the
Packit b099d7
 *  initial colormap focus (if the focus policy is "keyboard" - i.e. the
Packit b099d7
 *  colormap focus tracks the keyboard focus) the initial colormap
Packit b099d7
 *  installation is done in InitKeyboardFocus.
Packit b099d7
 *
Packit b099d7
 *  Inputs:
Packit b099d7
 *  -------
Packit b099d7
 *  pSD = pointer to screen data
Packit b099d7
 *
Packit b099d7
 *  Outputs:
Packit b099d7
 *  -------
Packit b099d7
 *  *pSD = (colormapFocus)
Packit b099d7
 * 
Packit b099d7
 *************************************<->***********************************/
Packit b099d7
Packit b099d7
void InitColormapFocus (WmScreenData *pSD)
Packit b099d7
{
Packit b099d7
    ClientData *pCD;
Packit b099d7
    Boolean sameScreen;
Packit b099d7
Packit b099d7
Packit b099d7
    /*
Packit b099d7
     * Set up the initial colormap focus.  If the colormapFocusPolicy is
Packit b099d7
     * "keyboard" or it is "pointer" and the keyboard input focus policy
Packit b099d7
     * is "pointer" then set up the initial colormap focus when the
Packit b099d7
     * initial keyboard input focus is set up.
Packit b099d7
     */
Packit b099d7
Packit b099d7
    pSD->colormapFocus = NULL;
Packit b099d7
Packit b099d7
    if (wmGD.colormapFocusPolicy == CMAP_FOCUS_POINTER)
Packit b099d7
    {
Packit b099d7
	if (wmGD.keyboardFocusPolicy != KEYBOARD_FOCUS_POINTER)
Packit b099d7
	{
Packit b099d7
	    if ((pCD = GetClientUnderPointer (&sameScreen)) != NULL)
Packit b099d7
	    {
Packit b099d7
	        SetColormapFocus (pSD, pCD);
Packit b099d7
	    }
Packit b099d7
	    else
Packit b099d7
	    {
Packit b099d7
	        WmInstallColormap (pSD, pSD->workspaceColormap);
Packit b099d7
	    }
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
    else
Packit b099d7
    {
Packit b099d7
	WmInstallColormap (pSD, pSD->workspaceColormap);
Packit b099d7
    }
Packit b099d7
Packit b099d7
} /* END OF FUNCTION InitColormapFocus */
Packit b099d7
Packit b099d7
Packit b099d7

Packit b099d7
#ifndef OLD_COLORMAP
Packit b099d7
/*************************************<->*************************************
Packit b099d7
 *
Packit b099d7
 *  ForceColormapFocus (pSD, pCD)
Packit b099d7
 *
Packit b099d7
 *
Packit b099d7
 *  Description:
Packit b099d7
 *  -----------
Packit b099d7
 * ForceColormapFocus is the working part of the original SetColormapFocus.
Packit b099d7
 * This function is used to unconditionally set the colormap focus to a
Packit b099d7
 * particular client window or to clear the colormap focus (set focus to
Packit b099d7
 * the root window).
Packit b099d7
 *
Packit b099d7
 * The reason is to permit focus to be dtrced.  We need to do this because
Packit b099d7
 * we can already have colormap focus, but still need to set the colormaps.
Packit b099d7
 * Examples of when this occurs are:
Packit b099d7
 *
Packit b099d7
 *	* after the window manager itself has forced a colormap,
Packit b099d7
 *	  as happens when it draws transients in the overlay planes.
Packit b099d7
 *	* when WM_COLORMAP_WINDOWS changes.
Packit b099d7
 *	* when a ColormapNotify (new) event is received.
Packit b099d7
 *
Packit b099d7
 *
Packit b099d7
 *  Inputs:
Packit b099d7
 *  ------
Packit b099d7
 *  pSD = pointer to Screen Data
Packit b099d7
 *  pCD = pointer to client data (clientColormap ...)
Packit b099d7
 *
Packit b099d7
 *************************************<->***********************************/
Packit b099d7
Packit b099d7
void ForceColormapFocus (WmScreenData *pSD, ClientData *pCD)
Packit b099d7
{
Packit b099d7
    if (pCD && ((pCD->clientState == NORMAL_STATE) ||
Packit b099d7
		(pCD->clientState == MAXIMIZED_STATE)))
Packit b099d7
    {
Packit b099d7
	pSD->colormapFocus = pCD;
Packit b099d7
#ifndef OLD_COLORMAP /* colormaps */
Packit b099d7
	ProcessColormapList (pSD, pCD);
Packit b099d7
#else /* OSF original */
Packit b099d7
	WmInstallColormap (pSD, pCD->clientColormap);
Packit b099d7
#endif
Packit b099d7
    }
Packit b099d7
    else
Packit b099d7
    {
Packit b099d7
	/*
Packit b099d7
	 * The default colormap is installed for minimized windows that have
Packit b099d7
	 * the colormap focus.
Packit b099d7
	 * !!! should colormaps be installed for icons with client      !!!
Packit b099d7
	 * !!! icon windows?  should the client colormap be installed ? !!!
Packit b099d7
	 */
Packit b099d7
Packit b099d7
	pSD->colormapFocus = NULL;
Packit b099d7
	WmInstallColormap (pSD, pSD->workspaceColormap);
Packit b099d7
    }
Packit b099d7
Packit b099d7
} /* END OF FUNCTION ForceColormapFocus */
Packit b099d7
#endif
Packit b099d7
Packit b099d7
Packit b099d7

Packit b099d7
/*************************************<->*************************************
Packit b099d7
 *
Packit b099d7
 *  SetColormapFocus (pSD, pCD)
Packit b099d7
 *
Packit b099d7
 *
Packit b099d7
 *  Description:
Packit b099d7
 *  -----------
Packit b099d7
 *  This function is used to set the colormap focus to a particular client
Packit b099d7
 *  window or to clear the colormap focus (set focus to the root window).
Packit b099d7
 *
Packit b099d7
 *
Packit b099d7
 *  Inputs:
Packit b099d7
 *  ------
Packit b099d7
 *  pSD = pointer to Screen Data
Packit b099d7
 *  pCD = pointer to client data (clientColormap ...)
Packit b099d7
 *
Packit b099d7
 *************************************<->***********************************/
Packit b099d7
Packit b099d7
void SetColormapFocus (WmScreenData *pSD, ClientData *pCD)
Packit b099d7
{
Packit b099d7
    if (pCD == pSD->colormapFocus)
Packit b099d7
    {
Packit b099d7
	/*
Packit b099d7
	 * The focus is already set to the right place.
Packit b099d7
	 */
Packit b099d7
Packit b099d7
	return;
Packit b099d7
    }
Packit b099d7
#ifndef OLD_COLORMAP
Packit b099d7
    ForceColormapFocus (pSD, pCD);
Packit b099d7
#else /* OSF original */
Packit b099d7
Packit b099d7
    if (pCD && ((pCD->clientState == NORMAL_STATE) ||
Packit b099d7
		(pCD->clientState == MAXIMIZED_STATE)))
Packit b099d7
    {
Packit b099d7
	pSD->colormapFocus = pCD;
Packit b099d7
#ifndef OLD_COLORMAP /* colormaps */
Packit b099d7
	ProcessColormapList (pSD, pCD);
Packit b099d7
#else /* OSF original */
Packit b099d7
	WmInstallColormap (pSD, pCD->clientColormap);
Packit b099d7
#endif
Packit b099d7
    }
Packit b099d7
    else
Packit b099d7
    {
Packit b099d7
	/*
Packit b099d7
	 * The default colormap is installed for minimized windows that have
Packit b099d7
	 * the colormap focus.
Packit b099d7
	 * !!! should colormaps be installed for icons with client      !!!
Packit b099d7
	 * !!! icon windows?  should the client colormap be installed ? !!!
Packit b099d7
	 */
Packit b099d7
Packit b099d7
	pSD->colormapFocus = NULL;
Packit b099d7
	WmInstallColormap (pSD, pSD->workspaceColormap);
Packit b099d7
    }
Packit b099d7
#endif
Packit b099d7
Packit b099d7
} /* END OF FUNCTION SetColormapFocus */
Packit b099d7
Packit b099d7
Packit b099d7

Packit b099d7
/*************************************<->*************************************
Packit b099d7
 *
Packit b099d7
 *  WmInstallColormap (pSD, colormap)
Packit b099d7
 *
Packit b099d7
 *
Packit b099d7
 *  Description:
Packit b099d7
 *  -----------
Packit b099d7
 *  This function installs colormaps for the window manager.  It trys to be
Packit b099d7
 *  intelligent and avoid unnecessary installations.  It assumes that no
Packit b099d7
 *  other program is installing colormaps.
Packit b099d7
 *
Packit b099d7
 *
Packit b099d7
 *  Inputs:
Packit b099d7
 *  ------
Packit b099d7
 *  pSD = ptr to screen data
Packit b099d7
 *  colormap = the id for the colormap to be installed
Packit b099d7
 *
Packit b099d7
 *************************************<->***********************************/
Packit b099d7
Packit b099d7
void WmInstallColormap (WmScreenData *pSD, Colormap colormap)
Packit b099d7
{
Packit b099d7
    /*
Packit b099d7
     * !!! this could be generalized to work better for systems that !!!
Packit b099d7
     * !!! support multiple installed colormaps                      !!!
Packit b099d7
     */
Packit b099d7
Packit b099d7
    if (colormap != pSD->lastInstalledColormap)
Packit b099d7
    {
Packit b099d7
	XInstallColormap (DISPLAY, colormap);
Packit b099d7
	pSD->lastInstalledColormap = colormap;
Packit b099d7
    }
Packit b099d7
Packit b099d7
} /* END OF FUNCTION WmInstallColormap */
Packit b099d7
Packit b099d7
Packit b099d7

Packit b099d7
/*************************************<->*************************************
Packit b099d7
 *
Packit b099d7
 *  ResetColormapData (pCD, pWindows, count)
Packit b099d7
 *
Packit b099d7
 *
Packit b099d7
 *  Description:
Packit b099d7
 *  -----------
Packit b099d7
 *  This function is used to release old colormap data (contexts, malloc'ed
Packit b099d7
 *  space).
Packit b099d7
 *
Packit b099d7
 *
Packit b099d7
 *  Inputs:
Packit b099d7
 *  ------
Packit b099d7
 *  pCD = pointer to client data (cmapWindows ...)
Packit b099d7
 *
Packit b099d7
 *  pWindows = new list of colormap windows
Packit b099d7
 *
Packit b099d7
 *  count = number of windows in new colormap windows list
Packit b099d7
 *
Packit b099d7
 *************************************<->***********************************/
Packit b099d7
Packit b099d7
void ResetColormapData (ClientData *pCD, Window *pWindows, int count)
Packit b099d7
{
Packit b099d7
    int i;
Packit b099d7
Packit b099d7
Packit b099d7
    if (pCD->clientCmapCount)
Packit b099d7
    {
Packit b099d7
	if (count == 0)
Packit b099d7
	{
Packit b099d7
	    /* reset the client colormap to the toplevel window colormap */
Packit b099d7
	    for (i = 0; i < pCD->clientCmapCount; i++)
Packit b099d7
	    {
Packit b099d7
		if (pCD->cmapWindows[i] == pCD->client)
Packit b099d7
		{
Packit b099d7
		    pCD->clientColormap = pCD->clientCmapList[i];
Packit b099d7
		    break;
Packit b099d7
		}
Packit b099d7
	    }
Packit b099d7
	}
Packit b099d7
Packit b099d7
	/*
Packit b099d7
	 * Free up old contexts.
Packit b099d7
	 */
Packit b099d7
Packit b099d7
	for (i = 0; i < pCD->clientCmapCount; i++)
Packit b099d7
	{
Packit b099d7
	    if (pCD->cmapWindows[i] != pCD->client)
Packit b099d7
	    {
Packit b099d7
#ifndef	IBM_169380
Packit b099d7
		RemoveColormapWindowReference(pCD, pCD->cmapWindows[i]);
Packit b099d7
#else
Packit b099d7
		XDeleteContext (DISPLAY, pCD->cmapWindows[i],
Packit b099d7
		    wmGD.windowContextType);
Packit b099d7
#endif
Packit b099d7
	    }
Packit b099d7
	}
Packit b099d7
Packit b099d7
	/*
Packit b099d7
	 * Free up old colormap data.
Packit b099d7
	 */
Packit b099d7
Packit b099d7
	XtFree ((char *)(pCD->cmapWindows));
Packit b099d7
	XtFree ((char *)(pCD->clientCmapList));
Packit b099d7
	pCD->clientCmapCount = 0;
Packit b099d7
#ifndef OLD_COLORMAP /* colormap */
Packit b099d7
	XtFree ((char  *)(pCD->clientCmapFlags));
Packit b099d7
	pCD->clientCmapFlags = 0;		/* DEBUG: */
Packit b099d7
	pCD->clientCmapFlagsInitialized = 0;
Packit b099d7
#endif
Packit b099d7
    }
Packit b099d7
Packit b099d7
    if (count)
Packit b099d7
    {
Packit b099d7
	/*
Packit b099d7
	 * Set new contexts.
Packit b099d7
	 */
Packit b099d7
Packit b099d7
	for (i = 0; i < count; i++)
Packit b099d7
	{
Packit b099d7
	    if (pWindows[i] != pCD->client)
Packit b099d7
	    {
Packit b099d7
#ifndef	IBM_169380
Packit b099d7
		AddColormapWindowReference(pCD, pWindows[i]);
Packit b099d7
#else
Packit b099d7
		XSaveContext (DISPLAY, pWindows[i], wmGD.windowContextType,
Packit b099d7
		    (caddr_t)pCD);
Packit b099d7
#endif
Packit b099d7
	    }
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
Packit b099d7
} /* END OF FUNCTION ResetColormapData */
Packit b099d7
Packit b099d7
#ifndef IBM_169380
Packit b099d7
/*************************************<->*************************************
Packit b099d7
 *
Packit b099d7
 *  AddColormapWindowReference (pCD, window)
Packit b099d7
 *
Packit b099d7
 *  Description:
Packit b099d7
 *  -----------
Packit b099d7
 *  This function is used to update (or create, if necessary) the structure
Packit b099d7
 *  that keeps track of all references to a Window from a toplevel window
Packit b099d7
 *  WM_COLORMAP_DATA property.
Packit b099d7
 *
Packit b099d7
 *************************************<->***********************************/
Packit b099d7
Packit b099d7
void AddColormapWindowReference (ClientData *pCD, Window window)
Packit b099d7
{
Packit b099d7
    ClientData          **cmap_window_data;
Packit b099d7
    Boolean             context_exists;
Packit b099d7
    int                 i;
Packit b099d7
    ClientData          **new_cmap_window_data;
Packit b099d7
Packit b099d7
    context_exists = (!XFindContext (DISPLAY, window,
Packit b099d7
                        wmGD.cmapWindowContextType,
Packit b099d7
                        (XPointer *) &cmap_window_data));
Packit b099d7
    if (context_exists)
Packit b099d7
    {
Packit b099d7
        for (i = 0; cmap_window_data[i] != NULL; i++)
Packit b099d7
        {
Packit b099d7
            if (cmap_window_data[i] == pCD)
Packit b099d7
            {
Packit b099d7
                /* Reference already exists - return */
Packit b099d7
                return;
Packit b099d7
            }
Packit b099d7
        }
Packit b099d7
        new_cmap_window_data = (ClientData **)
Packit b099d7
                                XtMalloc((i + 2 ) * sizeof(ClientData *));
Packit b099d7
        memcpy((void *)new_cmap_window_data,(void *)cmap_window_data,
Packit b099d7
                        (i + 1) * sizeof(ClientData *));
Packit b099d7
        XtFree((char *) cmap_window_data);
Packit b099d7
        XDeleteContext(DISPLAY, window, wmGD.cmapWindowContextType);
Packit b099d7
    }
Packit b099d7
    else
Packit b099d7
    {
Packit b099d7
        i = 0;
Packit b099d7
        new_cmap_window_data = (ClientData **)
Packit b099d7
                                XtMalloc(2 * sizeof(ClientData *));
Packit b099d7
    }
Packit b099d7
    new_cmap_window_data[i] = pCD;
Packit b099d7
    new_cmap_window_data[i + 1] = NULL;
Packit b099d7
    XSaveContext (DISPLAY, window, wmGD.cmapWindowContextType,
Packit b099d7
                        (caddr_t)new_cmap_window_data);
Packit b099d7
}
Packit b099d7
Packit b099d7
/*************************************<->*************************************
Packit b099d7
 *
Packit b099d7
 *  RemoveColormapWindowReference (pCD, window)
Packit b099d7
 *
Packit b099d7
 *  Description:
Packit b099d7
 *  -----------
Packit b099d7
 *  This function is used to update (or delete, if necessary) the structure
Packit b099d7
 *  that keeps track of all references to a Window from a toplevel window
Packit b099d7
 *  WM_COLORMAP_DATA property.
Packit b099d7
 *
Packit b099d7
 *************************************<->***********************************/
Packit b099d7
Packit b099d7
void RemoveColormapWindowReference (ClientData *pCD, Window window)
Packit b099d7
{
Packit b099d7
    ClientData  **cmap_window_data;
Packit b099d7
    Boolean     context_exists;
Packit b099d7
    int         i;
Packit b099d7
    int         reference_idx = -1;
Packit b099d7
    ClientData  **new_cmap_window_data;
Packit b099d7
Packit b099d7
    context_exists = (!XFindContext (DISPLAY, window,
Packit b099d7
                        wmGD.cmapWindowContextType,
Packit b099d7
                        (XPointer *) &cmap_window_data));
Packit b099d7
    if (context_exists)
Packit b099d7
    {
Packit b099d7
        for (i = 0; cmap_window_data[i] != NULL; i++)
Packit b099d7
        {
Packit b099d7
            if (cmap_window_data[i] == pCD)
Packit b099d7
                reference_idx = i;
Packit b099d7
        }
Packit b099d7
        if (reference_idx < 0)
Packit b099d7
            return;
Packit b099d7
Packit b099d7
        if (i > 1)
Packit b099d7
        {
Packit b099d7
        int     j,idx;
Packit b099d7
Packit b099d7
            new_cmap_window_data = (ClientData **)
Packit b099d7
                                        XtMalloc(i * sizeof(ClientData *));
Packit b099d7
            idx = 0;
Packit b099d7
            for (j = 0; cmap_window_data[j] != NULL; j++)
Packit b099d7
            {
Packit b099d7
                if (j != reference_idx)
Packit b099d7
                {
Packit b099d7
                    new_cmap_window_data[idx] = cmap_window_data[j];
Packit b099d7
                    idx++;
Packit b099d7
                }
Packit b099d7
            }
Packit b099d7
            new_cmap_window_data[idx] = NULL;
Packit b099d7
        }
Packit b099d7
        XtFree((char *) cmap_window_data);
Packit b099d7
        XDeleteContext(DISPLAY, window, wmGD.cmapWindowContextType);
Packit b099d7
        if (i > 1)
Packit b099d7
        {
Packit b099d7
            XSaveContext (DISPLAY, window,
Packit b099d7
                        wmGD.cmapWindowContextType,
Packit b099d7
                        (caddr_t)new_cmap_window_data);
Packit b099d7
        }
Packit b099d7
    }
Packit b099d7
}
Packit b099d7
#endif	/* IBM_169380 */
Packit b099d7
Packit b099d7
/*******************************************************************************
Packit b099d7
 **
Packit b099d7
 ** The rest of this module contains the SGI-added colormap handling.
Packit b099d7
 **
Packit b099d7
 ** mwm 1.1.3 didn't even try to deal with multiple colormaps, except to rotate
Packit b099d7
 ** them.  We need to see that all of the colormaps from WM_COLORMAP_WINDOWS
Packit b099d7
 ** are installed when a window gets colormap focus.
Packit b099d7
 **
Packit b099d7
 ** The general idea is to keep track of which colormaps bounce which other
Packit b099d7
 ** ones, so we only flash the first time (usually not even then).
Packit b099d7
 **
Packit b099d7
 ** The conflict record of a window is cleared whenever:
Packit b099d7
 **	* WM_COLORMAP_WINDOWS property changes
Packit b099d7
 **	* ColormapNotify for a new colormap happens
Packit b099d7
 **	* windows are rotated (prev_cmap, next_cmap)
Packit b099d7
 ** This is because with a changed colormap list, we need to recalculate
Packit b099d7
 ** which ones get bounced out during a full colormap installation.
Packit b099d7
 **
Packit b099d7
 ** We don't just lift the twm code because, after carefully looking over
Packit b099d7
 ** the twm code, it appears to have some problems of its own.  In
Packit b099d7
 ** particular, it assumes that if a given colormap displaces another one
Packit b099d7
 ** once, it will always do so.  This isn't necessarily so for a multiple
Packit b099d7
 ** hardware colormaps machine.
Packit b099d7
 **
Packit b099d7
 ** We still need to add code to keep track of which color maps are really
Packit b099d7
 ** installed at any one time.  The current code is ready for this, but it has
Packit b099d7
 ** not yet been done.  Then we could do two things:
Packit b099d7
 **
Packit b099d7
 **	* refrain from installing a colormap if it is already installed
Packit b099d7
 **
Packit b099d7
 **	* have a way to restore all installed colormaps after the window
Packit b099d7
 **	  manager overwrites with it's own.
Packit b099d7
 **
Packit b099d7
 ******************************************************************************/
Packit b099d7
Packit b099d7
Packit b099d7
void
Packit b099d7
ProcessColormapList (WmScreenData *pSD, ClientData *pCD)
Packit b099d7
Packit b099d7
{
Packit b099d7
	register int i;
Packit b099d7
	XEvent event;
Packit b099d7
Packit b099d7
Packit b099d7
    /*
Packit b099d7
     * If there is no client, return.  This can happen when the root gets focus.
Packit b099d7
     */
Packit b099d7
	if (!pCD) return;
Packit b099d7
Packit b099d7
    /*
Packit b099d7
     * If the window does not have colormap focus, return.  We only install
Packit b099d7
     * colormaps for windows with focus.  We'll get another chance when the
Packit b099d7
     * window does get focus.
Packit b099d7
     */
Packit b099d7
	if (pCD != pSD->colormapFocus) return;
Packit b099d7
Packit b099d7
    /*
Packit b099d7
     * If window is iconified, return.
Packit b099d7
     */
Packit b099d7
	if (   (pCD->clientState != NORMAL_STATE) 
Packit b099d7
	    && (pCD->clientState != MAXIMIZED_STATE)
Packit b099d7
	   ) return;
Packit b099d7
Packit b099d7
    /*
Packit b099d7
     * If the list doesn't exist, or has just a single item, no conflicts
Packit b099d7
     * exist -- just go ahead and install the indicated colormap.
Packit b099d7
     */
Packit b099d7
	if (pCD->clientCmapCount == 0) {
Packit b099d7
		WmInstallColormap (pSD, pCD->clientColormap);
Packit b099d7
		return;
Packit b099d7
	}
Packit b099d7
	if (pCD->clientCmapCount == 1) {
Packit b099d7
		WmInstallColormap (pSD, pCD->clientCmapList[0]);
Packit b099d7
		return;
Packit b099d7
	}
Packit b099d7
Packit b099d7
    /*
Packit b099d7
     * If the list has already been initialized, we just need to do installs.
Packit b099d7
     * Separate out these loops for performance, and because it isn't nice
Packit b099d7
     * to grab the server unnecessarily.
Packit b099d7
     *
Packit b099d7
     * This code should also check for already-installed, once we put in that
Packit b099d7
     * capability.
Packit b099d7
     */
Packit b099d7
	if (pCD->clientCmapFlagsInitialized) {
Packit b099d7
Packit b099d7
	    /* Do the part between the index and zero */
Packit b099d7
		for (i=pCD->clientCmapIndex; --i>=0; ) {
Packit b099d7
			if (pCD->clientCmapFlags[i] == ColormapInstalled) {
Packit b099d7
				WmInstallColormap (pSD, pCD->clientCmapList[i]);
Packit b099d7
			   }
Packit b099d7
		};
Packit b099d7
	
Packit b099d7
	    /* Do the part from the end of the list to the index */
Packit b099d7
		for (i=pCD->clientCmapCount; --i>= pCD->clientCmapIndex; ) {
Packit b099d7
			if (pCD->clientCmapFlags[i] == ColormapInstalled) {
Packit b099d7
				WmInstallColormap (pSD, pCD->clientCmapList[i]);
Packit b099d7
			}
Packit b099d7
		}
Packit b099d7
Packit b099d7
	    /**/
Packit b099d7
		return;
Packit b099d7
	}
Packit b099d7
Packit b099d7
    /*
Packit b099d7
     * If we get this far, the list has not yet been initialized.
Packit b099d7
     *
Packit b099d7
     * Stabilize the input queue -- the issue is that we need to know
Packit b099d7
     * which colormap notify install and uninstall events are ours.
Packit b099d7
     */
Packit b099d7
	XGrabServer (DISPLAY);	/* Ensure no one else's events for awhile */
Packit b099d7
	XSync (DISPLAY, FALSE);	/* Let pending events settle */
Packit b099d7
	firstRequest = NextRequest (DISPLAY); /* First one that can be ours */
Packit b099d7
Packit b099d7
    /*
Packit b099d7
     * Install the colormaps from last to first -- first is the "highest
Packit b099d7
     * priority".  "First" is pCD->clientCmapIndex.
Packit b099d7
     *
Packit b099d7
     * If the list has not been proocessed before, we need to unconditionally
Packit b099d7
     * install each colormap.  Colormap flashing is possible this once.
Packit b099d7
     *
Packit b099d7
     * If the list has already been processed once, all conflict checking
Packit b099d7
     * was done then.  All we need to do this time is to install the colormaps
Packit b099d7
     * we know we need.
Packit b099d7
     */
Packit b099d7
Packit b099d7
	/* Do the part between the index and zero */
Packit b099d7
	for (i=pCD->clientCmapIndex; --i>=0; ) {
Packit b099d7
		WmInstallColormap (pSD, pCD->clientCmapList[i]);
Packit b099d7
		pCD->clientCmapFlags[i] = ColormapInstalled;
Packit b099d7
	};
Packit b099d7
Packit b099d7
	/* Do the part from the end of the list to the index */
Packit b099d7
	for (i=pCD->clientCmapCount; --i>= pCD->clientCmapIndex; ) {
Packit b099d7
		WmInstallColormap (pSD, pCD->clientCmapList[i]);
Packit b099d7
		pCD->clientCmapFlags[i] = ColormapInstalled;
Packit b099d7
	}
Packit b099d7
Packit b099d7
    /*
Packit b099d7
     * Stabilize the input queue again -- the issue is that we need to know
Packit b099d7
     * which colormap notify install and uninstall events we caused.
Packit b099d7
     */
Packit b099d7
	XSync (DISPLAY, FALSE);			/* Let pending events settle */
Packit b099d7
	lastRequest = NextRequest (DISPLAY);	/* Last one that can be ours */
Packit b099d7
	XUngrabServer (DISPLAY);		/* Let others use it again */
Packit b099d7
Packit b099d7
    /* Process the install & uninstall events */
Packit b099d7
	XCheckIfEvent (DISPLAY, (XEvent *) &event, ProcessEvents, (char *)pCD);
Packit b099d7
Packit b099d7
    /* Set that the list has been processed once */
Packit b099d7
	pCD->clientCmapFlagsInitialized = True;
Packit b099d7
}
Packit b099d7
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * Look over the queue for install and uninstall events on colormap/window
Packit b099d7
 * combinations we care about.  We don't actually disturb the queue, so
Packit b099d7
 * events can be delivered in undisturbed order to the normal event handling
Packit b099d7
 * routines.
Packit b099d7
 *
Packit b099d7
 * For each appropriate install/uninstall ColormapNotify event that is queued:
Packit b099d7
 *	   *) if uninstall event
Packit b099d7
 *		*) Set the conflict flag for this colormap window
Packit b099d7
 *	   else if install event
Packit b099d7
 *		*) Clear the conflict flag for this colormap window
Packit b099d7
 */
Packit b099d7
static Bool
Packit b099d7
ProcessEvents(Display *dpy, XEvent *Event, char *c_pCD)
Packit b099d7
{
Packit b099d7
	int i;
Packit b099d7
	XColormapEvent *pEvent = (XColormapEvent *) Event;
Packit b099d7
	ClientData *pCD = (ClientData *) c_pCD;
Packit b099d7
Packit b099d7
	if (   (pEvent->type == ColormapNotify)
Packit b099d7
	    && (pEvent->serial >= firstRequest)
Packit b099d7
	    && (pEvent->serial <  lastRequest)
Packit b099d7
	    && (pEvent->colormap != None)
Packit b099d7
	    && (!pEvent->new)
Packit b099d7
	   ) {
Packit b099d7
		switch (pEvent->state) {
Packit b099d7
		case ColormapInstalled:
Packit b099d7
			for (i=0; i<pCD->clientCmapCount; i++) {
Packit b099d7
				if (  (pCD->clientCmapList[i]==pEvent->colormap)
Packit b099d7
				    &&(pCD->cmapWindows[i]==pEvent->window)
Packit b099d7
				   ) {
Packit b099d7
					pCD->clientCmapFlags[i]
Packit b099d7
						= ColormapInstalled;
Packit b099d7
					break;
Packit b099d7
				}
Packit b099d7
			}
Packit b099d7
			break;
Packit b099d7
		case ColormapUninstalled:
Packit b099d7
			for (i=0; i<pCD->clientCmapCount; i++) {
Packit b099d7
				if (  (pCD->clientCmapList[i]==pEvent->colormap)
Packit b099d7
				    &&(pCD->cmapWindows[i]==pEvent->window)
Packit b099d7
				   ) {
Packit b099d7
					pCD->clientCmapFlags[i]
Packit b099d7
						= ColormapUninstalled;
Packit b099d7
					break;
Packit b099d7
				}
Packit b099d7
			}
Packit b099d7
			break;
Packit b099d7
		default:		/* Should never get here */
Packit b099d7
			break;
Packit b099d7
		}
Packit b099d7
	}
Packit b099d7
Packit b099d7
    /*
Packit b099d7
     * Always return false:
Packit b099d7
     *	* so that we get to search the entire queue -- it isn't very long
Packit b099d7
     *	* so all events remain on the queue to be handled normally elsewhere
Packit b099d7
     */
Packit b099d7
	return False;	/* Always, so no events are lost from the queue */
Packit b099d7
}