~ubuntu-branches/ubuntu/dapper/vino/dapper

« back to all changes in this revision

Viewing changes to server/libvncserver/cursor.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2004-10-12 19:36:40 UTC
  • Revision ID: james.westby@ubuntu.com-20041012193640-ybetkwuqt7e04dke
Tags: upstream-2.8.1
ImportĀ upstreamĀ versionĀ 2.8.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * cursor.c - support for cursor shape updates.
 
3
 */
 
4
 
 
5
/*
 
6
 *  Copyright (C) 2000, 2001 Const Kaplinsky.  All Rights Reserved.
 
7
 *  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
 
8
 *
 
9
 *  This is free software; you can redistribute it and/or modify
 
10
 *  it under the terms of the GNU General Public License as published by
 
11
 *  the Free Software Foundation; either version 2 of the License, or
 
12
 *  (at your option) any later version.
 
13
 *
 
14
 *  This software is distributed in the hope that it will be useful,
 
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
 *  GNU General Public License for more details.
 
18
 *
 
19
 *  You should have received a copy of the GNU General Public License
 
20
 *  along with this software; if not, write to the Free Software
 
21
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
 
22
 *  USA.
 
23
 */
 
24
 
 
25
#include <rfb/rfb.h>
 
26
#include <rfb/rfbregion.h>
 
27
 
 
28
/*
 
29
 * Send cursor shape either in X-style format or in client pixel format.
 
30
 */
 
31
 
 
32
rfbBool
 
33
rfbSendCursorShape(cl)
 
34
    rfbClientPtr cl;
 
35
{
 
36
    rfbCursorPtr pCursor;
 
37
    rfbFramebufferUpdateRectHeader rect;
 
38
    rfbXCursorColors colors;
 
39
    int saved_ublen;
 
40
    int bitmapRowBytes, maskBytes, dataBytes;
 
41
    int i, j;
 
42
    uint8_t *bitmapData;
 
43
    uint8_t bitmapByte;
 
44
 
 
45
    pCursor = cl->screen->cursor;
 
46
    /*if(!pCursor) return TRUE;*/
 
47
 
 
48
    if (cl->useRichCursorEncoding) {
 
49
      if(pCursor && !pCursor->richSource)
 
50
        MakeRichCursorFromXCursor(cl->screen,pCursor);
 
51
      rect.encoding = Swap32IfLE(rfbEncodingRichCursor);
 
52
    } else {
 
53
       if(pCursor && !pCursor->source)
 
54
         MakeXCursorFromRichCursor(cl->screen,pCursor);
 
55
       rect.encoding = Swap32IfLE(rfbEncodingXCursor);
 
56
    }
 
57
 
 
58
    /* If there is no cursor, send update with empty cursor data. */
 
59
 
 
60
    if ( pCursor && pCursor->width == 1 &&
 
61
         pCursor->height == 1 &&
 
62
         pCursor->mask[0] == 0 ) {
 
63
        pCursor = NULL;
 
64
    }
 
65
 
 
66
    if (pCursor == NULL) {
 
67
        if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE ) {
 
68
            if (!rfbSendUpdateBuf(cl))
 
69
                return FALSE;
 
70
        }
 
71
        rect.r.x = rect.r.y = 0;
 
72
        rect.r.w = rect.r.h = 0;
 
73
        memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
 
74
               sz_rfbFramebufferUpdateRectHeader);
 
75
        cl->ublen += sz_rfbFramebufferUpdateRectHeader;
 
76
 
 
77
        cl->rfbCursorShapeBytesSent += sz_rfbFramebufferUpdateRectHeader;
 
78
        cl->rfbCursorShapeUpdatesSent++;
 
79
 
 
80
        if (!rfbSendUpdateBuf(cl))
 
81
            return FALSE;
 
82
 
 
83
        return TRUE;
 
84
    }
 
85
 
 
86
    /* Calculate data sizes. */
 
87
 
 
88
    bitmapRowBytes = (pCursor->width + 7) / 8;
 
89
    maskBytes = bitmapRowBytes * pCursor->height;
 
90
    dataBytes = (cl->useRichCursorEncoding) ?
 
91
        (pCursor->width * pCursor->height *
 
92
         (cl->format.bitsPerPixel / 8)) : maskBytes;
 
93
 
 
94
    /* Send buffer contents if needed. */
 
95
 
 
96
    if ( cl->ublen + sz_rfbFramebufferUpdateRectHeader +
 
97
         sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) {
 
98
        if (!rfbSendUpdateBuf(cl))
 
99
            return FALSE;
 
100
    }
 
101
 
 
102
    if ( cl->ublen + sz_rfbFramebufferUpdateRectHeader +
 
103
         sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) {
 
104
        return FALSE;           /* FIXME. */
 
105
    }
 
106
 
 
107
    saved_ublen = cl->ublen;
 
108
 
 
109
    /* Prepare rectangle header. */
 
110
 
 
111
    rect.r.x = Swap16IfLE(pCursor->xhot);
 
112
    rect.r.y = Swap16IfLE(pCursor->yhot);
 
113
    rect.r.w = Swap16IfLE(pCursor->width);
 
114
    rect.r.h = Swap16IfLE(pCursor->height);
 
115
 
 
116
    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
 
117
    cl->ublen += sz_rfbFramebufferUpdateRectHeader;
 
118
 
 
119
    /* Prepare actual cursor data (depends on encoding used). */
 
120
 
 
121
    if (!cl->useRichCursorEncoding) {
 
122
        /* XCursor encoding. */
 
123
        colors.foreRed   = (char)(pCursor->foreRed   >> 8);
 
124
        colors.foreGreen = (char)(pCursor->foreGreen >> 8);
 
125
        colors.foreBlue  = (char)(pCursor->foreBlue  >> 8);
 
126
        colors.backRed   = (char)(pCursor->backRed   >> 8);
 
127
        colors.backGreen = (char)(pCursor->backGreen >> 8);
 
128
        colors.backBlue  = (char)(pCursor->backBlue  >> 8);
 
129
 
 
130
        memcpy(&cl->updateBuf[cl->ublen], (char *)&colors, sz_rfbXCursorColors);
 
131
        cl->ublen += sz_rfbXCursorColors;
 
132
 
 
133
        bitmapData = (uint8_t *)pCursor->source;
 
134
 
 
135
        for (i = 0; i < pCursor->height; i++) {
 
136
            for (j = 0; j < bitmapRowBytes; j++) {
 
137
                bitmapByte = bitmapData[i * bitmapRowBytes + j];
 
138
                cl->updateBuf[cl->ublen++] = (char)bitmapByte;
 
139
            }
 
140
        }
 
141
    } else {
 
142
        /* RichCursor encoding. */
 
143
       int bpp1=cl->screen->rfbServerFormat.bitsPerPixel/8,
 
144
         bpp2=cl->format.bitsPerPixel/8;
 
145
       (*cl->translateFn)(cl->translateLookupTable,
 
146
                       &(cl->screen->rfbServerFormat),
 
147
                       &cl->format, (char*)pCursor->richSource,
 
148
                       &cl->updateBuf[cl->ublen],
 
149
                       pCursor->width*bpp1, pCursor->width, pCursor->height);
 
150
 
 
151
       cl->ublen += pCursor->width*bpp2*pCursor->height;
 
152
    }
 
153
 
 
154
    /* Prepare transparency mask. */
 
155
 
 
156
    bitmapData = (uint8_t *)pCursor->mask;
 
157
 
 
158
    for (i = 0; i < pCursor->height; i++) {
 
159
        for (j = 0; j < bitmapRowBytes; j++) {
 
160
            bitmapByte = bitmapData[i * bitmapRowBytes + j];
 
161
            cl->updateBuf[cl->ublen++] = (char)bitmapByte;
 
162
        }
 
163
    }
 
164
 
 
165
    /* Send everything we have prepared in the cl->updateBuf[]. */
 
166
 
 
167
    cl->rfbCursorShapeBytesSent += (cl->ublen - saved_ublen);
 
168
    cl->rfbCursorShapeUpdatesSent++;
 
169
 
 
170
    if (!rfbSendUpdateBuf(cl))
 
171
        return FALSE;
 
172
 
 
173
    return TRUE;
 
174
}
 
175
 
 
176
/*
 
177
 * Send cursor position (PointerPos pseudo-encoding).
 
178
 */
 
179
 
 
180
rfbBool
 
181
rfbSendCursorPos(rfbClientPtr cl)
 
182
{
 
183
  rfbFramebufferUpdateRectHeader rect;
 
184
 
 
185
  if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
 
186
    if (!rfbSendUpdateBuf(cl))
 
187
      return FALSE;
 
188
  }
 
189
 
 
190
  rect.encoding = Swap32IfLE(rfbEncodingPointerPos);
 
191
  rect.r.x = Swap16IfLE(cl->screen->cursorX);
 
192
  rect.r.y = Swap16IfLE(cl->screen->cursorY);
 
193
  rect.r.w = 0;
 
194
  rect.r.h = 0;
 
195
 
 
196
  memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
 
197
         sz_rfbFramebufferUpdateRectHeader);
 
198
  cl->ublen += sz_rfbFramebufferUpdateRectHeader;
 
199
 
 
200
  cl->rfbCursorPosBytesSent += sz_rfbFramebufferUpdateRectHeader;
 
201
  cl->rfbCursorPosUpdatesSent++;
 
202
 
 
203
  if (!rfbSendUpdateBuf(cl))
 
204
    return FALSE;
 
205
 
 
206
  return TRUE;
 
207
}
 
208
 
 
209
/* conversion routine for predefined cursors in LSB order */
 
210
unsigned char rfbReverseByte[0x100] = {
 
211
  /* copied from Xvnc/lib/font/util/utilbitmap.c */
 
212
        0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
 
213
        0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
 
214
        0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
 
215
        0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
 
216
        0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
 
217
        0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
 
218
        0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
 
219
        0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
 
220
        0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
 
221
        0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
 
222
        0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
 
223
        0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
 
224
        0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
 
225
        0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
 
226
        0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
 
227
        0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
 
228
        0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
 
229
        0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
 
230
        0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
 
231
        0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
 
232
        0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
 
233
        0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
 
234
        0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
 
235
        0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
 
236
        0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
 
237
        0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
 
238
        0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
 
239
        0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
 
240
        0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
 
241
        0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
 
242
        0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
 
243
        0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
 
244
};
 
245
 
 
246
void rfbConvertLSBCursorBitmapOrMask(int width,int height,unsigned char* bitmap)
 
247
{
 
248
   int i,t=(width+7)/8*height;
 
249
   for(i=0;i<t;i++)
 
250
     bitmap[i]=rfbReverseByte[(int)bitmap[i]];
 
251
}
 
252
 
 
253
/* Cursor creation. You "paint" a cursor and let these routines do the work */
 
254
 
 
255
rfbCursorPtr rfbMakeXCursor(int width,int height,const char* cursorString,const char* maskString)
 
256
{
 
257
   int i,j,w=(width+7)/8;
 
258
   rfbCursorPtr cursor = (rfbCursorPtr)calloc(1,sizeof(rfbCursor));
 
259
   const char* cp;
 
260
   unsigned char bit;
 
261
 
 
262
   cursor->cleanup=TRUE;
 
263
   cursor->width=width;
 
264
   cursor->height=height;
 
265
   /*cursor->backRed=cursor->backGreen=cursor->backBlue=0xffff;*/
 
266
   cursor->foreRed=cursor->foreGreen=cursor->foreBlue=0xffff;
 
267
   
 
268
   cursor->source = (unsigned char*)calloc(w,height);
 
269
   cursor->cleanupSource = TRUE;
 
270
   for(j=0,cp=cursorString;j<height;j++)
 
271
      for(i=0,bit=0x80;i<width;i++,bit=(bit&1)?0x80:bit>>1,cp++)
 
272
        if(*cp!=' ') cursor->source[j*w+i/8]|=bit;
 
273
 
 
274
   if(maskString) {
 
275
      cursor->mask = (unsigned char*)calloc(w,height);
 
276
      for(j=0,cp=maskString;j<height;j++)
 
277
        for(i=0,bit=0x80;i<width;i++,bit=(bit&1)?0x80:bit>>1,cp++)
 
278
          if(*cp!=' ') cursor->mask[j*w+i/8]|=bit;
 
279
   } else
 
280
     cursor->mask = (unsigned char*)rfbMakeMaskForXCursor(width,height,(char*)cursor->source);
 
281
   cursor->cleanupMask = TRUE;
 
282
 
 
283
   return(cursor);
 
284
}
 
285
 
 
286
char* rfbMakeMaskForXCursor(int width,int height,char* source)
 
287
{
 
288
   int i,j,w=(width+7)/8;
 
289
   char* mask=(char*)calloc(w,height);
 
290
   unsigned char c;
 
291
   
 
292
   for(j=0;j<height;j++)
 
293
     for(i=w-1;i>=0;i--) {
 
294
        c=source[j*w+i];
 
295
        if(j>0) c|=source[(j-1)*w+i];
 
296
        if(j<height-1) c|=source[(j+1)*w+i];
 
297
        
 
298
        if(i>0 && (c&0x80))
 
299
          mask[j*w+i-1]|=0x01;
 
300
        if(i<w-1 && (c&0x01))
 
301
          mask[j*w+i+1]|=0x80;
 
302
        
 
303
        mask[j*w+i]|=(c<<1)|c|(c>>1);
 
304
     }
 
305
   
 
306
   return(mask);
 
307
}
 
308
 
 
309
void rfbFreeCursor(rfbCursorPtr cursor)
 
310
{
 
311
   if(cursor) {
 
312
       if(cursor->cleanupRichSource && cursor->richSource)
 
313
           free(cursor->richSource);
 
314
       if(cursor->cleanupSource && cursor->source)
 
315
           free(cursor->source);
 
316
       if(cursor->cleanupMask && cursor->mask)
 
317
           free(cursor->mask);
 
318
       if(cursor->cleanup)
 
319
           free(cursor);
 
320
       else {
 
321
           cursor->cleanup=cursor->cleanupSource=cursor->cleanupMask
 
322
               =cursor->cleanupRichSource=FALSE;
 
323
           cursor->source=cursor->mask=cursor->richSource=0;
 
324
       }
 
325
   }
 
326
   
 
327
}
 
328
 
 
329
/* background and foregroud colour have to be set beforehand */
 
330
void MakeXCursorFromRichCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor)
 
331
{
 
332
   rfbPixelFormat* format=&rfbScreen->rfbServerFormat;
 
333
   int i,j,w=(cursor->width+7)/8,bpp=format->bitsPerPixel/8,
 
334
     width=cursor->width*bpp;
 
335
   uint32_t background;
 
336
   char *back=(char*)&background;
 
337
   unsigned char bit;
 
338
 
 
339
   if(cursor->source && cursor->cleanupSource)
 
340
       free(cursor->source);
 
341
   cursor->source=(unsigned char*)calloc(w,cursor->height);
 
342
   cursor->cleanupSource=TRUE;
 
343
   
 
344
   if(format->bigEndian)
 
345
      back+=4-bpp;
 
346
 
 
347
   background=cursor->backRed<<format->redShift|
 
348
     cursor->backGreen<<format->greenShift|cursor->backBlue<<format->blueShift;
 
349
 
 
350
   for(j=0;j<cursor->height;j++)
 
351
     for(i=0,bit=0x80;i<cursor->width;i++,bit=(bit&1)?0x80:bit>>1)
 
352
       if(memcmp(cursor->richSource+j*width+i*bpp,back,bpp))
 
353
         cursor->source[j*w+i/8]|=bit;
 
354
}
 
355
 
 
356
void MakeRichCursorFromXCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor)
 
357
{
 
358
   rfbPixelFormat* format=&rfbScreen->rfbServerFormat;
 
359
   int i,j,w=(cursor->width+7)/8,bpp=format->bitsPerPixel/8;
 
360
   uint32_t background,foreground;
 
361
   char *back=(char*)&background,*fore=(char*)&foreground;
 
362
   unsigned char *cp;
 
363
   unsigned char bit;
 
364
 
 
365
   if(cursor->richSource && cursor->cleanupRichSource)
 
366
       free(cursor->richSource);
 
367
   cp=cursor->richSource=(unsigned char*)calloc(cursor->width*bpp,cursor->height);
 
368
   cursor->cleanupRichSource=TRUE;
 
369
   
 
370
   if(format->bigEndian) {
 
371
      back+=4-bpp;
 
372
      fore+=4-bpp;
 
373
   }
 
374
 
 
375
   background=cursor->backRed<<format->redShift|
 
376
     cursor->backGreen<<format->greenShift|cursor->backBlue<<format->blueShift;
 
377
   foreground=cursor->foreRed<<format->redShift|
 
378
     cursor->foreGreen<<format->greenShift|cursor->foreBlue<<format->blueShift;
 
379
   
 
380
   for(j=0;j<cursor->height;j++)
 
381
     for(i=0,bit=0x80;i<cursor->height;i++,bit=(bit&1)?0x80:bit>>1,cp+=bpp)
 
382
       if(cursor->source[j*w+i/8]&bit) memcpy(cp,fore,bpp);
 
383
       else memcpy(cp,back,bpp);
 
384
}
 
385
 
 
386
rfbBool rfbGetCursorBounds(rfbScreenInfoPtr screen,
 
387
                           sraRectPtr       bounds)
 
388
{
 
389
    rfbCursorPtr cursor = screen->cursor;
 
390
    int          x1, y1, x2, y2;
 
391
 
 
392
    if (!bounds || !cursor)
 
393
        return FALSE;
 
394
 
 
395
   x1 = screen->cursorX - cursor->xhot;
 
396
   if (x1 < 0)
 
397
       x1 = 0;
 
398
   
 
399
   x2 = x1 + cursor->width;
 
400
   if (x2 >= screen->width)
 
401
       x2 = screen->width - 1;
 
402
   
 
403
   y1 = screen->cursorY - cursor->yhot;
 
404
   if (y1 < 0)
 
405
       y1 = 0;
 
406
 
 
407
   y2 = y1 + cursor->height;
 
408
   if (y2 >= screen->height)
 
409
       y2 = screen->height - 1;
 
410
 
 
411
   if (x2 <= x1 || y2 <= y1)
 
412
       return FALSE;
 
413
 
 
414
   bounds->x1 = x1;
 
415
   bounds->y1 = y1;
 
416
   bounds->x2 = x2;
 
417
   bounds->y2 = y2;
 
418
 
 
419
   return TRUE;
 
420
}
 
421
 
 
422
/* functions to draw/hide cursor directly in the frame buffer */
 
423
 
 
424
void rfbUndrawCursor(rfbScreenInfoPtr screen,
 
425
                     sraRectPtr       bounds)
 
426
{
 
427
   rfbCursorPtr cursor = screen->cursor;
 
428
   sraRect      rect;
 
429
   int          j, bpp, rowstride;
 
430
 
 
431
   if (!cursor)
 
432
       return;
 
433
   
 
434
   if (!bounds) {
 
435
       bounds = &rect;
 
436
 
 
437
       if (!rfbGetCursorBounds (screen, bounds))
 
438
           return;
 
439
   }
 
440
   
 
441
   bpp = screen->rfbServerFormat.bitsPerPixel / 8;
 
442
   rowstride = screen->paddedWidthInBytes;
 
443
 
 
444
   /* restore saved data */
 
445
   for (j = 0; j < (bounds->y2 - bounds->y1); j++)
 
446
       memcpy(screen->frameBuffer + (bounds->y1 + j) * rowstride + bounds->x1 * bpp,
 
447
              screen->underCursorBuffer + j * (bounds->x2 - bounds->x1) * bpp,
 
448
              (bounds->x2 - bounds->x1) * bpp);
 
449
}
 
450
 
 
451
void rfbDrawCursor(rfbScreenInfoPtr screen,
 
452
                   sraRectPtr       bounds)
 
453
{
 
454
   rfbCursorPtr cursor = screen->cursor;
 
455
   sraRect      rect;
 
456
   int          i, i1, j, j1;
 
457
   int          bpp, rowstride;
 
458
   int          bufSize, w;
 
459
 
 
460
   if (!cursor)
 
461
       return;
 
462
   
 
463
   if (!bounds) {
 
464
       bounds = &rect;
 
465
 
 
466
       if (!rfbGetCursorBounds (screen, bounds))
 
467
           return;
 
468
   }
 
469
 
 
470
   bpp = screen->rfbServerFormat.bitsPerPixel / 8;
 
471
   rowstride = screen->paddedWidthInBytes;
 
472
 
 
473
   bufSize = cursor->width * cursor->height * bpp;
 
474
   if (screen->underCursorBufferLen < bufSize) {
 
475
      if (screen->underCursorBuffer)
 
476
        free(screen->underCursorBuffer);
 
477
 
 
478
      screen->underCursorBuffer = malloc(bufSize);
 
479
      screen->underCursorBufferLen = bufSize;
 
480
   }
 
481
 
 
482
   i1 = j1 = 0; /* offset in cursor */
 
483
   if (screen->cursorX < cursor->xhot)
 
484
       i1 = cursor->xhot - screen->cursorX;
 
485
   if (screen->cursorY < cursor->yhot)
 
486
       j1 = cursor->xhot - screen->cursorY;
 
487
 
 
488
   /* save what is under the cursor */
 
489
   for (j = 0; j < (bounds->y2 - bounds->y1); j++)
 
490
       memcpy(screen->underCursorBuffer + j * (bounds->x2 - bounds->x1) * bpp,
 
491
              screen->frameBuffer + (bounds->y1 + j) * rowstride + bounds->x1 * bpp,
 
492
              (bounds->x2 - bounds->x1) * bpp);
 
493
   
 
494
   if (!cursor->richSource)
 
495
       MakeRichCursorFromXCursor(screen, cursor);
 
496
 
 
497
   w = (cursor->width + 7) / 8;
 
498
   
 
499
   /* now the cursor has to be drawn */
 
500
   for (j = 0; j < (bounds->y2 - bounds->y1); j++)
 
501
       for (i = 0; i < (bounds->x2 - bounds->x1); i++)
 
502
           if ((cursor->mask[(j + j1) * w + (i + i1) / 8] << ((i + i1) & 7)) & 0x80)
 
503
               memcpy(screen->frameBuffer + (bounds->y1 + j) * rowstride + (bounds->x1 + i) * bpp,
 
504
                      cursor->richSource + (j + j1) * cursor->width * bpp + (i + i1) * bpp,
 
505
                      bpp);
 
506
}
 
507
 
 
508
void rfbSetCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr c,rfbBool freeOld)
 
509
{
 
510
    LOCK(rfbScreen->cursorMutex);
 
511
 
 
512
    if(rfbScreen->cursor && (freeOld || rfbScreen->cursor->cleanup))
 
513
        rfbFreeCursor(rfbScreen->cursor);
 
514
 
 
515
    rfbScreen->cursor = c;
 
516
 
 
517
    UNLOCK(rfbScreen->cursorMutex);
 
518
}
 
519
 
 
520
void rfbSetCursorPosition(rfbScreenInfoPtr screen, rfbClientPtr client, int x, int y)
 
521
{
 
522
    rfbClientIteratorPtr iterator;
 
523
    rfbClientPtr cl;
 
524
 
 
525
    if (x == screen->cursorX || y == screen->cursorY)
 
526
        return;
 
527
 
 
528
    LOCK(screen->cursorMutex);
 
529
    screen->cursorX = x;
 
530
    screen->cursorY = y;
 
531
    UNLOCK(screen->cursorMutex);
 
532
 
 
533
    /* Inform all clients about this cursor movement. */
 
534
    iterator = rfbGetClientIterator(screen);
 
535
    while ((cl = rfbClientIteratorNext(iterator)) != NULL) {
 
536
        cl->cursorWasMoved = TRUE;
 
537
    }
 
538
    rfbReleaseClientIterator(iterator);
 
539
 
 
540
    /* The cursor was moved by this client, so don't send CursorPos. */
 
541
    if (client) {
 
542
        client->cursorWasMoved = FALSE;
 
543
    }
 
544
}