[BACK]Return to cursor.c CVS log [TXT][DIR] Up to [Development] / performer / src / lib / libpfutil

File: [Development] / performer / src / lib / libpfutil / cursor.c (download)

Revision 1.1, Tue Nov 21 21:39:36 2000 UTC (16 years, 10 months ago) by flynnt
Branch: MAIN
CVS Tags: HEAD

Initial check-in based on OpenGL Performer 2.4 tree.
-flynnt

/*
 * Copyright 1993, 1994, 1995, Silicon Graphics, Inc.
 * ALL RIGHTS RESERVED
 *
 * UNPUBLISHED -- Rights reserved under the copyright laws of the United
 * States.   Use of a copyright notice is precautionary only and does not
 * imply publication or disclosure.
 *
 * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND:
 * Use, duplication or disclosure by the Government is subject to restrictions
 * as set forth in FAR 52.227.19(c)(2) or subparagraph (c)(1)(ii) of the Rights
 * in Technical Data and Computer Software clause at DFARS 252.227-7013 and/or
 * in similar or successor clauses in the FAR, or the DOD or NASA FAR
 * Supplement.  Contractor/manufacturer is Silicon Graphics, Inc.,
 * 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311.
 *
 * THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY
 * INFORMATION OF SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION,
 * DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY
 * PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SILICON
 * GRAPHICS, INC.
 */

#define KON_XVC_PLATFORM_PARAM_LOAD_DAC_CURSOR		-3


/*
 * file: cursor.c  
 * --------------
 * 
 * Support for X cursors
 * 
 * $Revision: 1.1 $
 * $Date: 2000/11/21 21:39:36 $
 *
 */

#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#ifndef __linux__
#include <bstring.h>
#else
#include <string.h>
#endif  /* __linux__ */

#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/cursorfont.h>

#include <Performer/pfutil.h>

#include "cursor.h"


/******************************************************************************
 *			    Static Declarations
 ******************************************************************************
 */

static void initCursorMgmt(void);
static void draw2DCursor(int mx, int my, int chxo, int chyo, int wxs, int wys, 
			    float pixXScale, float pixYScale);

static pfDataPool *CursorDP = NULL;
static pfuCursorMgmt *CM = NULL;


/******************************************************************************
 *			    Global Routines
 ******************************************************************************
 */

void
pfuCursorType(int val)
{
    if (!CM)
	initCursorMgmt();
	
    if (CM->type == val)
	return;
    CM->type = val;
    /* if want 3D cursor, must set main X cursor to OFF */
    CM->curXCursor = PFU_CURSOR_OFF;
    CM->dirty |= DIRTY_TYPE;
}

int
pfuGetCursorType(void)
{
    if (!CM)
	initCursorMgmt();
	
    return CM->type;
}

void
pfuSelCursor(int c)
{
    if (!CM)
	initCursorMgmt();
	
    if (CM->curXCursor == c)
	return;
    CM->curXCursor = c;
    CM->dirty |= DIRTY_SEL;
}

Cursor
pfuCreateCursor(Cursor c)
{
    Display *dsp = pfGetCurWSConnection();
    
    if (!CM)
	initCursorMgmt();
	
    if (c > 154 && c != PFU_CURSOR_OFF)
	    pfNotify(PFNFY_NOTICE, PFNFY_USAGE, 
		    "pfuLoadWinCursor - bad cursor index %d", c);
    if (c == PFU_CURSOR_OFF)
	    CM->XCursors[c] = pfuGetInvisibleCursor();
    else 
	CM->XCursors[c] = XCreateFontCursor(dsp, (unsigned int)c);
    XFlush(dsp);
    if (CM->dirty & DIRTY_COLOR)
    {
	XColor      c1, c2;
	c1.red = 0xffff * CM->fgColor[0];
	c1.green = 0xffff * CM->fgColor[1];
	c1.blue = 0xffff * CM->fgColor[2];
	c2.red = 0xffff * CM->bgColor[0];
	c2.green = 0xffff * CM->bgColor[1];
	c2.blue = 0xffff * CM->bgColor[2];
	XRecolorCursor( dsp, CM->XCursors[c], &c1, &c2 );
	CM->dirty &= ~DIRTY_COLOR;
    }
    return CM->XCursors[c];
}

void
pfuLoadWinCursor(pfWindow *w, int c)
{
    Window xwin;
    Display *dsp;
    
    if (!w)
    {
	pfNotify(PFNFY_WARN, PFNFY_USAGE, 
		    "pfuLoadWinCursor - NULL pfWindow*");
	return;
    }
    xwin = pfGetWinWSWindow(w);
    if (!xwin)
    {
	pfNotify(PFNFY_WARN, PFNFY_USAGE, 
		    "pfuLoadWinCursor - pfWindow has not been opened.");
	return;
    }
    if (!(pfGetWinType(w) & PFPWIN_TYPE_X))
	return;
    
    dsp = pfGetCurWSConnection();
    
    if (!CM)
	initCursorMgmt();
	
    if (!(CM->XCursors[c]) && ((c == PFU_CURSOR_OFF) || (c < XC_num_glyphs)))
    {
	pfuCreateCursor(c);
    }
    XDefineCursor(dsp, xwin, CM->XCursors[c]);
    XFlush(dsp);
}

void
pfuLoadPWinCursor(pfPipeWindow *w, int c)
{
    Window xwin;
    Display *dsp;
   
    if (!w)
    {
	pfNotify(PFNFY_WARN, PFNFY_USAGE, 
		    "pfuLoadWinCursor - NULL pfWindow*");
	return;
    }
    xwin = pfGetPWinWSWindow(w);
    if (!xwin)
    {
	pfNotify(PFNFY_WARN, PFNFY_USAGE, 
		    "pfuLoadWinCursor - pfWindow has not been opened.");
	return;
    }
    if (!(pfGetPWinType(w) & PFPWIN_TYPE_X))
	return;

    if (!CM)
	initCursorMgmt();
	
    dsp = pfGetCurWSConnection();
    if (!(CM->XCursors[c]) && ((c == PFU_CURSOR_OFF) || (c < XC_num_glyphs)))
    {
	pfuCreateCursor(c);
    }
    XDefineCursor(dsp, xwin, CM->XCursors[c]);
    XFlush(dsp);
}

void 
pfuLoadChanCursor(pfChannel *chan, int c)
{
    if (!CM)
	initCursorMgmt();
	
    switch(CM->type)
    {
    case PFU_CURSOR_X:
	{
	    pfPipeWindow *pw = pfGetChanPWin(chan);
	    pfuLoadPWinCursor(pw, c);
	    break;
	}
    }
}

Cursor
pfuGetInvisibleCursor(void)
{
    Cursor curs;
    /* cursor mask for invisible cursor */
    XColor xclr = {0,0,0,0,0,0};
    char *cursoffdata = calloc(1, 16*16*(sizeof(char)));
    Pixmap pix;
    Display		*dsp;
    
    if (!CM)
	initCursorMgmt();
	
    if (CM->invisibleCursor)
	return CM->invisibleCursor;

    dsp = pfGetCurWSConnection();
    pix = XCreateBitmapFromData(dsp, 
		RootWindow(dsp, DefaultScreen(dsp)),
		cursoffdata, 16, 16);
    curs = XCreatePixmapCursor(dsp, pix, pix, 
		    &xclr, &xclr, 0, 0);
    XFreePixmap(dsp, pix);
    free(cursoffdata);
    CM->invisibleCursor = curs;
    return curs;
}

void
pfuCursor(Cursor c, int index)
{
    if (!CM)
	initCursorMgmt();
	
    CM->XCursors[index] = c;
}

Cursor
pfuGetCursor(int index)
{
    if (!CM)
	initCursorMgmt();
	
    return CM->XCursors[index];
}

void	
pfuDrawPWin2DCursor(pfPipeWindow *pw, int mx, int my)
{
    pfPipeVideoChannel *vc = pfGetPWinPosPVChan(pw, mx, my);

    if (!vc)
	vc = pfGetPWinPVChan(pw, 0);
    
    pfuDrawPVChan2DCursor(vc, mx, my);
}

void	
pfuDrawPVChan2DCursor(pfPipeVideoChannel *pVChan, int mx, int my)
{
    float xs, ys;
    int xo, yo, wxs, wys;
    pfPipeWindow *pwin =  pfGetPVChanPWin(pVChan);

    if (!CM)
	initCursorMgmt();
	
    pfGetPVChanScale(pVChan, &xs, &ys);
    pfGetPVChanOrigin(pVChan, &xo, &yo);
    pfGetPWinSize(pwin, &wxs, &wys);
    draw2DCursor(mx, my, xo, yo, wxs, wys, xs, ys);
}

void	
pfuDrawVChan2DCursor(pfVideoChannel *vChan, int mx, int my)
{
    float xs, ys;
    int xo, yo, wxs, wys;
    pfWindow *win;

    if (!CM)
	initCursorMgmt();
	
    pfGetVChanScale(vChan, &xs, &ys);
    pfGetVChanOrigin(vChan, &xo, &yo);
    if ((win = pfGetCurWin()) && pfIsWinOpen(win))
	pfGetWinSize(win, &wxs, &wys);
    else
	pfGetVChanSize(vChan, &wxs, &wys);
    draw2DCursor(mx, my, xo, yo, wxs, wys, xs, ys);
}

void	
pfuDrawChan2DCursor(pfChannel *chan, int mx, int my)
{
    float xs, ys;
    int wxs, wys;
    int   chxo, chyo, chxs, chys;
    pfPipeVideoChannel *vc = pfGetChanPVChan(chan);
    pfPipeWindow *pwin =  pfGetChanPWin(chan);
    
    if (!CM)
	initCursorMgmt();
    
    /* get channel origin and size to test mouse against */
    pfGetChanOutputOrigin(chan,  &chxo,  &chyo);
    pfGetChanOutputSize(chan,  &chxs,  &chys);
    pfGetPWinSize(pwin, &wxs, &wys);
    /* if mouse is not in channel, don't draw it */
    if (!((mx > chxo) && (my > chyo) && 
	(mx < chxo + chxs) && (my < chyo + chys)))
	return;
    
    pfGetPVChanScale(vc, &xs, &ys);
    draw2DCursor(mx, my, chxo, chyo, wxs, wys, xs, ys);
}

void	
pfuDraw2DCursor(int mx, int my)
{
    if (!CM)
	initCursorMgmt();
	
    draw2DCursor(mx, my, 0, 0, 0, 0, 1.0f, 1.0f);
}


void	
pfuCursorColor(pfVec3 fg, pfVec3 bg)
{
    if (!CM)
	initCursorMgmt();
	
    PFCOPY_VEC3(CM->fgColor, fg);
    PFCOPY_VEC3(CM->bgColor, bg);
    CM->dirty |= DIRTY_COLOR;
}


/******************************************************************************
 *			    Static Routines
 ******************************************************************************
 */


static void
initCursorMgmt(void)
{
    if (!CursorDP)
	CursorDP = pfuGetUtilDPool();

    if (!(CM = (pfuCursorMgmt *)  pfDPoolFind(CursorDP, PFU_CURSOR_DATA_DPID)))
    {
	pfNotify(PFNFY_FATAL, PFNFY_SYSERR, 
	    "initCursorMgmt - didn't find pfuCursorMnger in Util Data Pool.");
	return;
    }
    PFSET_VEC3(CM->bgColor, 1.0f, 0.0f, 0.0f);
    PFSET_VEC3(CM->fgColor, 1.0f, 1.0f, 1.0f);

}

#define CURSOR_3D_SIZE 12
#define CURSOR_3D_HALFSIZE (CURSOR_3D_SIZE >> 1)
static void
draw2DCursor(int mx, int my, int chxo, int chyo, int wxs, int wys, 
	float pixXScale, float pixYScale)
{
    int pixXSize2 = (CURSOR_3D_HALFSIZE * pixXScale) + 0.5f;
    int pixYSize2 = (CURSOR_3D_HALFSIZE * pixYScale) + 0.5f;
    int pixXSize = pixXSize2 * 2;
    int pixYSize = pixYSize2 * 2;
    float pixScale = PF_MAX2(pixXScale, pixYScale);
    pfMatrix	 proj;
    static int lp[4][2] = { {-1, 0}, {1, 0}, 
			    {0, -1}, {0, 1} };

    mx = chxo + ((mx - chxo) * pixXScale + 0.5f);
    my = chyo + ((my - chyo) * pixYScale + 0.5f);

    pfPushIdentMatrix();
    pfPushState();
    pfBasicState();

    glDepthFunc(GL_ALWAYS);
    glPushAttrib(GL_VIEWPORT_BIT | GL_SCISSOR_BIT);
    /* make tiny viewport around mouse pos */
    glMatrixMode(GL_PROJECTION);
    glGetFloatv(GL_PROJECTION_MATRIX, (float*) proj);
    glLoadIdentity();

    if (wxs && wys)
    {
	/* cursor position will be more stable under video resize if we always fix the
	 * viewport to the window boundaries instead of trying arbitrary pixel centers 
	 */
	glViewport(0, 0, wxs, wys);
	glScissor(mx - pixXSize2,  my - pixYSize2, pixXSize, pixYSize); 
	glEnable(GL_SCISSOR_TEST);
	glOrtho(0,wxs,0,wys,-1,1);
	pfTranslate(mx, my, 0);
	pfScale((float)CURSOR_3D_HALFSIZE,(float)CURSOR_3D_HALFSIZE,1.0f);
    } 
    else
    {
	glViewport(mx - pixXSize2,  my - pixYSize2, pixXSize, pixYSize);
	glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
    }
    glMatrixMode(GL_MODELVIEW);


    glColor3fv(CM->bgColor);
    glLineWidth(3.0f * pixScale);
    glBegin(GL_LINES);
    glVertex2iv(lp[0]);
    glVertex2iv(lp[1]);
    glVertex2iv(lp[2]);
    glVertex2iv(lp[3]);
    glEnd();
    glColor3fv(CM->fgColor);
    glLineWidth(1.0f * pixScale);
    glBegin(GL_LINES);
    glVertex2iv(lp[0]);
    glVertex2iv(lp[1]);
    glVertex2iv(lp[2]);
    glVertex2iv(lp[3]);
    glEnd();
    glDepthFunc(GL_LEQUAL);
    glPopAttrib();
    glMatrixMode(GL_PROJECTION);
    pfLoadMatrix(proj);
    glMatrixMode(GL_MODELVIEW);
    pfPopMatrix();
    pfPopState();
}