~ubuntu-branches/ubuntu/intrepid/xserver-xgl/intrepid

« back to all changes in this revision

Viewing changes to dix/cursor.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-13 14:21:43 UTC
  • Revision ID: james.westby@ubuntu.com-20060213142143-mad6z9xzem7hzxz9
Tags: upstream-7.0.0
ImportĀ upstreamĀ versionĀ 7.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $XFree86: xc/programs/Xserver/dix/cursor.c,v 3.8 2003/01/12 02:44:26 dawes Exp $ */
 
2
/***********************************************************
 
3
 
 
4
Copyright 1987, 1998  The Open Group
 
5
 
 
6
Permission to use, copy, modify, distribute, and sell this software and its
 
7
documentation for any purpose is hereby granted without fee, provided that
 
8
the above copyright notice appear in all copies and that both that
 
9
copyright notice and this permission notice appear in supporting
 
10
documentation.
 
11
 
 
12
The above copyright notice and this permission notice shall be included in
 
13
all copies or substantial portions of the Software.
 
14
 
 
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
16
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
17
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 
18
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 
19
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
20
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
21
 
 
22
Except as contained in this notice, the name of The Open Group shall not be
 
23
used in advertising or otherwise to promote the sale, use or other dealings
 
24
in this Software without prior written authorization from The Open Group.
 
25
 
 
26
 
 
27
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
 
28
 
 
29
                        All Rights Reserved
 
30
 
 
31
Permission to use, copy, modify, and distribute this software and its 
 
32
documentation for any purpose and without fee is hereby granted, 
 
33
provided that the above copyright notice appear in all copies and that
 
34
both that copyright notice and this permission notice appear in 
 
35
supporting documentation, and that the name of Digital not be
 
36
used in advertising or publicity pertaining to distribution of the
 
37
software without specific, written prior permission.  
 
38
 
 
39
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 
40
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 
41
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 
42
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 
43
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 
44
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 
45
SOFTWARE.
 
46
 
 
47
******************************************************************/
 
48
 
 
49
 
 
50
/* $Xorg: cursor.c,v 1.4 2001/02/09 02:04:39 xorgcvs Exp $ */
 
51
 
 
52
#ifdef HAVE_DIX_CONFIG_H
 
53
#include <dix-config.h>
 
54
#endif
 
55
 
 
56
#include <X11/X.h>
 
57
#include <X11/Xmd.h>
 
58
#include "servermd.h"
 
59
#include "scrnintstr.h"
 
60
#include "dixstruct.h"
 
61
#include "cursorstr.h"
 
62
#include "dixfontstr.h"
 
63
#include "opaque.h"
 
64
 
 
65
typedef struct _GlyphShare {
 
66
    FontPtr font;
 
67
    unsigned short sourceChar;
 
68
    unsigned short maskChar;
 
69
    CursorBitsPtr bits;
 
70
    struct _GlyphShare *next;
 
71
} GlyphShare, *GlyphSharePtr;
 
72
 
 
73
static GlyphSharePtr sharedGlyphs = (GlyphSharePtr)NULL;
 
74
 
 
75
#ifdef XFIXES
 
76
static CARD32   cursorSerial;
 
77
#endif
 
78
 
 
79
static void
 
80
FreeCursorBits(CursorBitsPtr bits)
 
81
{
 
82
    if (--bits->refcnt > 0)
 
83
        return;
 
84
    xfree(bits->source);
 
85
    xfree(bits->mask);
 
86
#ifdef ARGB_CURSOR
 
87
    xfree(bits->argb);
 
88
#endif
 
89
    if (bits->refcnt == 0)
 
90
    {
 
91
        register GlyphSharePtr *prev, this;
 
92
 
 
93
        for (prev = &sharedGlyphs;
 
94
             (this = *prev) && (this->bits != bits);
 
95
             prev = &this->next)
 
96
            ;
 
97
        if (this)
 
98
        {
 
99
            *prev = this->next;
 
100
            CloseFont(this->font, (Font)0);
 
101
            xfree(this);
 
102
        }
 
103
        xfree(bits);
 
104
    }
 
105
}
 
106
 
 
107
/**
 
108
 * To be called indirectly by DeleteResource; must use exactly two args.
 
109
 *
 
110
 *  \param value must conform to DeleteType
 
111
 */
 
112
int
 
113
FreeCursor(pointer value, XID cid)
 
114
{
 
115
    int         nscr;
 
116
    CursorPtr   pCurs = (CursorPtr)value;
 
117
 
 
118
    ScreenPtr   pscr;
 
119
 
 
120
    if ( --pCurs->refcnt > 0)
 
121
        return(Success);
 
122
 
 
123
    for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
 
124
    {
 
125
        pscr = screenInfo.screens[nscr];
 
126
        (void)( *pscr->UnrealizeCursor)( pscr, pCurs);
 
127
    }
 
128
    FreeCursorBits(pCurs->bits);
 
129
    xfree( pCurs);
 
130
    return(Success);
 
131
}
 
132
 
 
133
 
 
134
/*
 
135
 * We check for empty cursors so that we won't have to display them
 
136
 */
 
137
static void
 
138
CheckForEmptyMask(CursorBitsPtr bits)
 
139
{
 
140
    register unsigned char *msk = bits->mask;
 
141
    int n = BitmapBytePad(bits->width) * bits->height;
 
142
 
 
143
    bits->emptyMask = FALSE;
 
144
    while(n--) 
 
145
        if(*(msk++) != 0) return;
 
146
#ifdef ARGB_CURSOR
 
147
    if (bits->argb)
 
148
    {
 
149
        CARD32 *argb = bits->argb;
 
150
        int n = bits->width * bits->height;
 
151
        while (n--)
 
152
            if (*argb++ & 0xff000000) return;
 
153
    }
 
154
#endif
 
155
    bits->emptyMask = TRUE;
 
156
}
 
157
 
 
158
/**
 
159
 * does nothing about the resource table, just creates the data structure.
 
160
 * does not copy the src and mask bits
 
161
 *
 
162
 *  \param psrcbits  server-defined padding
 
163
 *  \param pmaskbits server-defined padding
 
164
 *  \param argb      no padding
 
165
 */
 
166
CursorPtr 
 
167
AllocCursorARGB(unsigned char *psrcbits, unsigned char *pmaskbits, CARD32 *argb, 
 
168
                CursorMetricPtr cm,
 
169
                unsigned foreRed, unsigned foreGreen, unsigned foreBlue, 
 
170
                unsigned backRed, unsigned backGreen, unsigned backBlue)
 
171
{
 
172
    CursorBitsPtr  bits;
 
173
    CursorPtr   pCurs;
 
174
    int         nscr;
 
175
    ScreenPtr   pscr;
 
176
 
 
177
    pCurs = (CursorPtr)xalloc(sizeof(CursorRec) + sizeof(CursorBits));
 
178
    if (!pCurs)
 
179
    {
 
180
        xfree(psrcbits);
 
181
        xfree(pmaskbits);
 
182
        return (CursorPtr)NULL;
 
183
    }
 
184
    bits = (CursorBitsPtr)((char *)pCurs + sizeof(CursorRec));
 
185
    bits->source = psrcbits;
 
186
    bits->mask = pmaskbits;
 
187
#ifdef ARGB_CURSOR
 
188
    bits->argb = argb;
 
189
#endif
 
190
    bits->width = cm->width;
 
191
    bits->height = cm->height;
 
192
    bits->xhot = cm->xhot;
 
193
    bits->yhot = cm->yhot;
 
194
    bits->refcnt = -1;
 
195
    CheckForEmptyMask(bits);
 
196
 
 
197
    pCurs->bits = bits;
 
198
    pCurs->refcnt = 1;          
 
199
#ifdef XFIXES
 
200
    pCurs->serialNumber = ++cursorSerial;
 
201
    pCurs->name = None;
 
202
#endif
 
203
 
 
204
    pCurs->foreRed = foreRed;
 
205
    pCurs->foreGreen = foreGreen;
 
206
    pCurs->foreBlue = foreBlue;
 
207
 
 
208
    pCurs->backRed = backRed;
 
209
    pCurs->backGreen = backGreen;
 
210
    pCurs->backBlue = backBlue;
 
211
 
 
212
    /*
 
213
     * realize the cursor for every screen
 
214
     */
 
215
    for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
 
216
    {
 
217
        pscr = screenInfo.screens[nscr];
 
218
        if (!( *pscr->RealizeCursor)( pscr, pCurs))
 
219
        {
 
220
            while (--nscr >= 0)
 
221
            {
 
222
                pscr = screenInfo.screens[nscr];
 
223
                ( *pscr->UnrealizeCursor)( pscr, pCurs);
 
224
            }
 
225
            FreeCursorBits(bits);
 
226
            xfree(pCurs);
 
227
            return (CursorPtr)NULL;
 
228
        }
 
229
    }
 
230
    return pCurs;
 
231
}
 
232
 
 
233
/**
 
234
 *
 
235
 * \param psrcbits   server-defined padding
 
236
 * \param pmaskbits  server-defined padding
 
237
 */
 
238
CursorPtr 
 
239
AllocCursor(unsigned char *psrcbits, unsigned char *pmaskbits, 
 
240
            CursorMetricPtr cm,
 
241
            unsigned foreRed, unsigned foreGreen, unsigned foreBlue,
 
242
            unsigned backRed, unsigned backGreen, unsigned backBlue)
 
243
{
 
244
    return AllocCursorARGB (psrcbits, pmaskbits, (CARD32 *) 0, cm,
 
245
                            foreRed, foreGreen, foreBlue,
 
246
                            backRed, backGreen, backBlue);
 
247
}
 
248
 
 
249
int
 
250
AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
 
251
                unsigned foreRed, unsigned foreGreen, unsigned foreBlue, 
 
252
                unsigned backRed, unsigned backGreen, unsigned backBlue,
 
253
                CursorPtr *ppCurs, ClientPtr client)
 
254
{
 
255
    FontPtr  sourcefont, maskfont;
 
256
    unsigned char   *srcbits;
 
257
    unsigned char   *mskbits;
 
258
    CursorMetricRec cm;
 
259
    int res;
 
260
    CursorBitsPtr  bits;
 
261
    CursorPtr   pCurs;
 
262
    int         nscr;
 
263
    ScreenPtr   pscr;
 
264
    GlyphSharePtr pShare;
 
265
 
 
266
    sourcefont = (FontPtr) SecurityLookupIDByType(client, source, RT_FONT,
 
267
                                                  SecurityReadAccess);
 
268
    maskfont = (FontPtr) SecurityLookupIDByType(client, mask, RT_FONT,
 
269
                                                SecurityReadAccess);
 
270
 
 
271
    if (!sourcefont)
 
272
    {
 
273
        client->errorValue = source;
 
274
        return(BadFont);
 
275
    }
 
276
    if (!maskfont && (mask != None))
 
277
    {
 
278
        client->errorValue = mask;
 
279
        return(BadFont);
 
280
    }
 
281
    if (sourcefont != maskfont)
 
282
        pShare = (GlyphSharePtr)NULL;
 
283
    else
 
284
    {
 
285
        for (pShare = sharedGlyphs;
 
286
             pShare &&
 
287
             ((pShare->font != sourcefont) ||
 
288
              (pShare->sourceChar != sourceChar) ||
 
289
              (pShare->maskChar != maskChar));
 
290
             pShare = pShare->next)
 
291
            ;
 
292
    }
 
293
    if (pShare)
 
294
    {
 
295
        pCurs = (CursorPtr)xalloc(sizeof(CursorRec));
 
296
        if (!pCurs)
 
297
            return BadAlloc;
 
298
        bits = pShare->bits;
 
299
        bits->refcnt++;
 
300
    }
 
301
    else
 
302
    {
 
303
        if (!CursorMetricsFromGlyph(sourcefont, sourceChar, &cm))
 
304
        {
 
305
            client->errorValue = sourceChar;
 
306
            return BadValue;
 
307
        }
 
308
        if (!maskfont)
 
309
        {
 
310
            register long n;
 
311
            register unsigned char *mskptr;
 
312
 
 
313
            n = BitmapBytePad(cm.width)*(long)cm.height;
 
314
            mskptr = mskbits = (unsigned char *)xalloc(n);
 
315
            if (!mskptr)
 
316
                return BadAlloc;
 
317
            while (--n >= 0)
 
318
                *mskptr++ = ~0;
 
319
        }
 
320
        else
 
321
        {
 
322
            if (!CursorMetricsFromGlyph(maskfont, maskChar, &cm))
 
323
            {
 
324
                client->errorValue = maskChar;
 
325
                return BadValue;
 
326
            }
 
327
            if ((res = ServerBitsFromGlyph(maskfont, maskChar, &cm, &mskbits)) != 0)
 
328
                return res;
 
329
        }
 
330
        if ((res = ServerBitsFromGlyph(sourcefont, sourceChar, &cm, &srcbits)) != 0)
 
331
        {
 
332
            xfree(mskbits);
 
333
            return res;
 
334
        }
 
335
        if (sourcefont != maskfont)
 
336
        {
 
337
            pCurs = (CursorPtr)xalloc(sizeof(CursorRec) + sizeof(CursorBits));
 
338
            if (pCurs)
 
339
                bits = (CursorBitsPtr)((char *)pCurs + sizeof(CursorRec));
 
340
            else
 
341
                bits = (CursorBitsPtr)NULL;
 
342
        }
 
343
        else
 
344
        {
 
345
            pCurs = (CursorPtr)xalloc(sizeof(CursorRec));
 
346
            if (pCurs)
 
347
                bits = (CursorBitsPtr)xalloc(sizeof(CursorBits));
 
348
            else
 
349
                bits = (CursorBitsPtr)NULL;
 
350
        }
 
351
        if (!bits)
 
352
        {
 
353
            xfree(pCurs);
 
354
            xfree(mskbits);
 
355
            xfree(srcbits);
 
356
            return BadAlloc;
 
357
        }
 
358
        bits->source = srcbits;
 
359
        bits->mask = mskbits;
 
360
#ifdef ARGB_CURSOR
 
361
        bits->argb = 0;
 
362
#endif
 
363
        bits->width = cm.width;
 
364
        bits->height = cm.height;
 
365
        bits->xhot = cm.xhot;
 
366
        bits->yhot = cm.yhot;
 
367
        if (sourcefont != maskfont)
 
368
            bits->refcnt = -1;
 
369
        else
 
370
        {
 
371
            bits->refcnt = 1;
 
372
            pShare = (GlyphSharePtr)xalloc(sizeof(GlyphShare));
 
373
            if (!pShare)
 
374
            {
 
375
                FreeCursorBits(bits);
 
376
                return BadAlloc;
 
377
            }
 
378
            pShare->font = sourcefont;
 
379
            sourcefont->refcnt++;
 
380
            pShare->sourceChar = sourceChar;
 
381
            pShare->maskChar = maskChar;
 
382
            pShare->bits = bits;
 
383
            pShare->next = sharedGlyphs;
 
384
            sharedGlyphs = pShare;
 
385
        }
 
386
    }
 
387
    CheckForEmptyMask(bits);
 
388
    pCurs->bits = bits;
 
389
    pCurs->refcnt = 1;
 
390
#ifdef XFIXES
 
391
    pCurs->serialNumber = ++cursorSerial;
 
392
    pCurs->name = None;
 
393
#endif
 
394
 
 
395
    pCurs->foreRed = foreRed;
 
396
    pCurs->foreGreen = foreGreen;
 
397
    pCurs->foreBlue = foreBlue;
 
398
 
 
399
    pCurs->backRed = backRed;
 
400
    pCurs->backGreen = backGreen;
 
401
    pCurs->backBlue = backBlue;
 
402
 
 
403
    /*
 
404
     * realize the cursor for every screen
 
405
     */
 
406
    for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
 
407
    {
 
408
        pscr = screenInfo.screens[nscr];
 
409
        if (!( *pscr->RealizeCursor)( pscr, pCurs))
 
410
        {
 
411
            while (--nscr >= 0)
 
412
            {
 
413
                pscr = screenInfo.screens[nscr];
 
414
                ( *pscr->UnrealizeCursor)( pscr, pCurs);
 
415
            }
 
416
            FreeCursorBits(pCurs->bits);
 
417
            xfree(pCurs);
 
418
            return BadAlloc;
 
419
        }
 
420
    }
 
421
    *ppCurs = pCurs;
 
422
    return Success;
 
423
}
 
424
 
 
425
/** CreateRootCursor
 
426
 *
 
427
 * look up the name of a font
 
428
 * open the font
 
429
 * add the font to the resource table
 
430
 * make a cursor from the glyphs
 
431
 * add the cursor to the resource table
 
432
 *************************************************************/
 
433
 
 
434
CursorPtr 
 
435
CreateRootCursor(char *pfilename, unsigned glyph)
 
436
{
 
437
    CursorPtr   curs;
 
438
    FontPtr     cursorfont;
 
439
    int err;
 
440
    XID         fontID;
 
441
 
 
442
    fontID = FakeClientID(0);
 
443
    err = OpenFont(serverClient, fontID, FontLoadAll | FontOpenSync,
 
444
        (unsigned)strlen( pfilename), pfilename);
 
445
    if (err != Success)
 
446
        return NullCursor;
 
447
 
 
448
    cursorfont = (FontPtr)LookupIDByType(fontID, RT_FONT);
 
449
    if (!cursorfont)
 
450
        return NullCursor;
 
451
    if (AllocGlyphCursor(fontID, glyph, fontID, glyph + 1,
 
452
                         0, 0, 0, ~0, ~0, ~0, &curs, serverClient) != Success)
 
453
        return NullCursor;
 
454
 
 
455
    if (!AddResource(FakeClientID(0), RT_CURSOR, (pointer)curs))
 
456
        return NullCursor;
 
457
 
 
458
    return curs;
 
459
}