~ubuntu-branches/debian/lenny/italc/lenny

« back to all changes in this revision

Viewing changes to client/demoviewer/cursor.c

  • Committer: Bazaar Package Importer
  • Author(s): Patrick Winnertz
  • Date: 2008-06-17 13:46:54 UTC
  • mfrom: (1.2.1 upstream) (4.1.1 gutsy)
  • Revision ID: james.westby@ubuntu.com-20080617134654-cl0gi4u524cv1ici
Tags: 1:1.0.9~rc3-1
* Package new upstream version
  - upstream ported the code to qt4.4 (Closes: #481974)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  Copyright (C) 2001,2002 Constantin Kaplinsky.  All Rights Reserved.
3
 
 *
4
 
 *  This is free software; you can redistribute it and/or modify
5
 
 *  it under the terms of the GNU General Public License as published by
6
 
 *  the Free Software Foundation; either version 2 of the License, or
7
 
 *  (at your option) any later version.
8
 
 *
9
 
 *  This software is distributed in the hope that it will be useful,
10
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
 *  GNU General Public License for more details.
13
 
 *
14
 
 *  You should have received a copy of the GNU General Public License
15
 
 *  along with this software; if not, write to the Free Software
16
 
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
17
 
 *  USA.
18
 
 */
19
 
 
20
 
/*
21
 
 * cursor.c - code to support cursor shape updates (XCursor and
22
 
 * RichCursor preudo-encodings).
23
 
 */
24
 
 
25
 
#include <demoviewer.h>
26
 
 
27
 
 
28
 
#define OPER_SAVE     0
29
 
#define OPER_RESTORE  1
30
 
 
31
 
#define RGB24_TO_PIXEL(bpp,r,g,b)                                       \
32
 
   ((((CARD##bpp)(r) & 0xFF) * myFormat.redMax + 127) / 255             \
33
 
    << myFormat.redShift |                                              \
34
 
    (((CARD##bpp)(g) & 0xFF) * myFormat.greenMax + 127) / 255           \
35
 
    << myFormat.greenShift |                                            \
36
 
    (((CARD##bpp)(b) & 0xFF) * myFormat.blueMax + 127) / 255            \
37
 
    << myFormat.blueShift)
38
 
 
39
 
 
40
 
static Bool prevSoftCursorSet = False;
41
 
static Pixmap rcSavedArea;
42
 
static CARD8 *rcSource, *rcMask;
43
 
static int rcHotX, rcHotY, rcWidth, rcHeight;
44
 
static int rcCursorX = 0, rcCursorY = 0;
45
 
static int rcLockX, rcLockY, rcLockWidth, rcLockHeight;
46
 
static Bool rcCursorHidden, rcLockSet;
47
 
 
48
 
static Bool SoftCursorInLockedArea(void);
49
 
static void SoftCursorCopyArea(int oper);
50
 
static void SoftCursorDraw(void);
51
 
static void FreeSoftCursor(void);
52
 
static void FreeX11Cursor();
53
 
 
54
 
/* Copied from Xvnc/lib/font/util/utilbitmap.c */
55
 
static unsigned char _reverse_byte[0x100] = {
56
 
        0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
57
 
        0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
58
 
        0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
59
 
        0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
60
 
        0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
61
 
        0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
62
 
        0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
63
 
        0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
64
 
        0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
65
 
        0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
66
 
        0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
67
 
        0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
68
 
        0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
69
 
        0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
70
 
        0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
71
 
        0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
72
 
        0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
73
 
        0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
74
 
        0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
75
 
        0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
76
 
        0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
77
 
        0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
78
 
        0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
79
 
        0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
80
 
        0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
81
 
        0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
82
 
        0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
83
 
        0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
84
 
        0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
85
 
        0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
86
 
        0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
87
 
        0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
88
 
};
89
 
 
90
 
/* Data kept for HandleXCursor() function. */
91
 
static Bool prevXCursorSet = False;
92
 
static Cursor prevXCursor;
93
 
 
94
 
 
95
 
Bool HandleXCursor(int xhot, int yhot, int width, int height)
96
 
{
97
 
  rfbXCursorColors colors;
98
 
  size_t bytesPerRow, bytesData;
99
 
  char *buf = NULL;
100
 
  XColor bg, fg;
101
 
  Drawable dr;
102
 
  unsigned int wret = 0, hret = 0;
103
 
  Pixmap source, mask;
104
 
  Cursor cursor;
105
 
  int i;
106
 
 
107
 
  bytesPerRow = (width + 7) / 8;
108
 
  bytesData = bytesPerRow * height;
109
 
  dr = DefaultRootWindow(dpy);
110
 
 
111
 
  if (width * height) {
112
 
    if (!ReadFromRFBServer((char *)&colors, sz_rfbXCursorColors))
113
 
      return False;
114
 
 
115
 
    buf = malloc(bytesData * 2);
116
 
    if (buf == NULL)
117
 
      return False;
118
 
 
119
 
    if (!ReadFromRFBServer(buf, bytesData * 2)) {
120
 
      free(buf);
121
 
      return False;
122
 
    }
123
 
 
124
 
    XQueryBestCursor(dpy, dr, width, height, &wret, &hret);
125
 
  }
126
 
 
127
 
  if (width * height == 0 || wret < width || hret < height) {
128
 
    /* Free resources */
129
 
    if (buf != NULL)
130
 
      free(buf);
131
 
    FreeX11Cursor();
132
 
    return True;
133
 
  }
134
 
 
135
 
  bg.red   = (unsigned short)colors.backRed   << 8 | colors.backRed;
136
 
  bg.green = (unsigned short)colors.backGreen << 8 | colors.backGreen;
137
 
  bg.blue  = (unsigned short)colors.backBlue  << 8 | colors.backBlue;
138
 
  fg.red   = (unsigned short)colors.foreRed   << 8 | colors.foreRed;
139
 
  fg.green = (unsigned short)colors.foreGreen << 8 | colors.foreGreen;
140
 
  fg.blue  = (unsigned short)colors.foreBlue  << 8 | colors.foreBlue;
141
 
 
142
 
  for (i = 0; i < bytesData * 2; i++)
143
 
    buf[i] = (char)_reverse_byte[(int)buf[i] & 0xFF];
144
 
 
145
 
  source = XCreateBitmapFromData(dpy, dr, buf, width, height);
146
 
  mask = XCreateBitmapFromData(dpy, dr, &buf[bytesData], width, height);
147
 
  cursor = XCreatePixmapCursor(dpy, source, mask, &fg, &bg, xhot, yhot);
148
 
  XFreePixmap(dpy, source);
149
 
  XFreePixmap(dpy, mask);
150
 
  free(buf);
151
 
 
152
 
  XDefineCursor(dpy, desktopWin, cursor);
153
 
  FreeX11Cursor();
154
 
  prevXCursor = cursor;
155
 
  prevXCursorSet = True;
156
 
 
157
 
  return True;
158
 
}
159
 
 
160
 
 
161
 
 
162
 
/*********************************************************************
163
 
 * HandleCursorShape(). Support for XCursor and RichCursor shape
164
 
 * updates. We emulate cursor operating on the frame buffer (that is
165
 
 * why we call it "software cursor").
166
 
 ********************************************************************/
167
 
 
168
 
Bool HandleCursorShape(int xhot, int yhot, int width, int height, CARD32 enc)
169
 
{
170
 
  int bytesPerPixel;
171
 
  size_t bytesPerRow, bytesMaskData;
172
 
  Drawable dr;
173
 
  rfbXCursorColors rgb;
174
 
  CARD32 colors[2];
175
 
  char *buf;
176
 
  CARD8 *ptr;
177
 
  int x, y, b;
178
 
 
179
 
  bytesPerPixel = myFormat.bitsPerPixel / 8;
180
 
  bytesPerRow = (width + 7) / 8;
181
 
  bytesMaskData = bytesPerRow * height;
182
 
  dr = DefaultRootWindow(dpy);
183
 
 
184
 
  FreeSoftCursor();
185
 
 
186
 
  if (width * height == 0)
187
 
    return True;
188
 
 
189
 
  /* Allocate memory for pixel data and temporary mask data. */
190
 
 
191
 
  rcSource = malloc(width * height * bytesPerPixel);
192
 
  if (rcSource == NULL)
193
 
    return False;
194
 
 
195
 
  buf = malloc(bytesMaskData);
196
 
  if (buf == NULL) {
197
 
    free(rcSource);
198
 
    return False;
199
 
  }
200
 
 
201
 
  /* Read and decode cursor pixel data, depending on the encoding type. */
202
 
 
203
 
  if (enc == rfbEncodingXCursor) {
204
 
    if (appData.useX11Cursor) {
205
 
      HandleXCursor(xhot, yhot, width, height);
206
 
      return True;
207
 
    }
208
 
 
209
 
    /* Read and convert background and foreground colors. */
210
 
    if (!ReadFromRFBServer((char *)&rgb, sz_rfbXCursorColors)) {
211
 
      free(rcSource);
212
 
      free(buf);
213
 
      return False;
214
 
    }
215
 
    colors[0] = RGB24_TO_PIXEL(32, rgb.backRed, rgb.backGreen, rgb.backBlue);
216
 
    colors[1] = RGB24_TO_PIXEL(32, rgb.foreRed, rgb.foreGreen, rgb.foreBlue);
217
 
 
218
 
    /* Read 1bpp pixel data into a temporary buffer. */
219
 
    if (!ReadFromRFBServer(buf, bytesMaskData)) {
220
 
      free(rcSource);
221
 
      free(buf);
222
 
      return False;
223
 
    }
224
 
 
225
 
    /* Convert 1bpp data to byte-wide color indices. */
226
 
    ptr = rcSource;
227
 
    for (y = 0; y < height; y++) {
228
 
      for (x = 0; x < width / 8; x++) {
229
 
        for (b = 7; b >= 0; b--) {
230
 
          *ptr = buf[y * bytesPerRow + x] >> b & 1;
231
 
          ptr += bytesPerPixel;
232
 
        }
233
 
      }
234
 
      for (b = 7; b > 7 - width % 8; b--) {
235
 
        *ptr = buf[y * bytesPerRow + x] >> b & 1;
236
 
        ptr += bytesPerPixel;
237
 
      }
238
 
    }
239
 
 
240
 
    /* Convert indices into the actual pixel values. */
241
 
    switch (bytesPerPixel) {
242
 
    case 1:
243
 
      for (x = 0; x < width * height; x++)
244
 
        rcSource[x] = (CARD8)colors[rcSource[x]];
245
 
      break;
246
 
    case 2:
247
 
      for (x = 0; x < width * height; x++)
248
 
        ((CARD16 *)rcSource)[x] = (CARD16)colors[rcSource[x * 2]];
249
 
      break;
250
 
    case 4:
251
 
      for (x = 0; x < width * height; x++)
252
 
        ((CARD32 *)rcSource)[x] = colors[rcSource[x * 4]];
253
 
      break;
254
 
    }
255
 
 
256
 
  } else {                      /* enc == rfbEncodingRichCursor */
257
 
 
258
 
    if (!ReadFromRFBServer((char *)rcSource, width * height * bytesPerPixel)) {
259
 
      free(rcSource);
260
 
      free(buf);
261
 
      return False;
262
 
    }
263
 
 
264
 
  }
265
 
 
266
 
  /* Read and decode mask data. */
267
 
 
268
 
  if (!ReadFromRFBServer(buf, bytesMaskData)) {
269
 
    free(rcSource);
270
 
    free(buf);
271
 
    return False;
272
 
  }
273
 
 
274
 
  rcMask = malloc(width * height);
275
 
  if (rcMask == NULL) {
276
 
    free(rcSource);
277
 
    free(buf);
278
 
    return False;
279
 
  }
280
 
 
281
 
  ptr = rcMask;
282
 
  for (y = 0; y < height; y++) {
283
 
    for (x = 0; x < width / 8; x++) {
284
 
      for (b = 7; b >= 0; b--) {
285
 
        *ptr++ = buf[y * bytesPerRow + x] >> b & 1;
286
 
      }
287
 
    }
288
 
    for (b = 7; b > 7 - width % 8; b--) {
289
 
      *ptr++ = buf[y * bytesPerRow + x] >> b & 1;
290
 
    }
291
 
  }
292
 
 
293
 
  free(buf);
294
 
 
295
 
  /* Set remaining data associated with cursor. */
296
 
 
297
 
  dr = DefaultRootWindow(dpy);
298
 
  rcSavedArea = XCreatePixmap(dpy, dr, width, height, visdepth);
299
 
  rcHotX = xhot;
300
 
  rcHotY = yhot;
301
 
  rcWidth = width;
302
 
  rcHeight = height;
303
 
 
304
 
  SoftCursorCopyArea(OPER_SAVE);
305
 
  SoftCursorDraw();
306
 
 
307
 
  rcCursorHidden = False;
308
 
  rcLockSet = False;
309
 
 
310
 
  prevSoftCursorSet = True;
311
 
  return True;
312
 
}
313
 
 
314
 
/*********************************************************************
315
 
 * HandleCursorPos(). Support for the PointerPos pseudo-encoding used
316
 
 * to transmit changes in pointer position from server to clients.
317
 
 * PointerPos encoding is used together with cursor shape updates.
318
 
 ********************************************************************/
319
 
 
320
 
Bool HandleCursorPos(int x, int y)
321
 
{
322
 
  if (appData.useX11Cursor) {
323
 
    if (appData.fullScreen)
324
 
      XWarpPointer(dpy, None, desktopWin, 0, 0, 0, 0, x, y);
325
 
    
326
 
    return True; 
327
 
  }
328
 
 
329
 
  if (x >= si.framebufferWidth)
330
 
    x = si.framebufferWidth - 1;
331
 
  if (y >= si.framebufferHeight)
332
 
    y = si.framebufferHeight - 1;
333
 
 
334
 
  SoftCursorMove(x, y);
335
 
  return True;
336
 
}
337
 
 
338
 
/*********************************************************************
339
 
 * SoftCursorLockArea(). This function should be used to prevent
340
 
 * collisions between simultaneous framebuffer update operations and
341
 
 * cursor drawing operations caused by movements of pointing device.
342
 
 * The parameters denote a rectangle where mouse cursor should not be
343
 
 * drawn. Every next call to this function expands locked area so
344
 
 * previous locks remain active.
345
 
 ********************************************************************/
346
 
 
347
 
void SoftCursorLockArea(int x, int y, int w, int h)
348
 
{
349
 
  int newX, newY;
350
 
 
351
 
  if (!prevSoftCursorSet)
352
 
    return;
353
 
 
354
 
  if (!rcLockSet) {
355
 
    rcLockX = x;
356
 
    rcLockY = y;
357
 
    rcLockWidth = w;
358
 
    rcLockHeight = h;
359
 
    rcLockSet = True;
360
 
  } else {
361
 
    newX = (x < rcLockX) ? x : rcLockX;
362
 
    newY = (y < rcLockY) ? y : rcLockY;
363
 
    rcLockWidth = (x + w > rcLockX + rcLockWidth) ?
364
 
      (x + w - newX) : (rcLockX + rcLockWidth - newX);
365
 
    rcLockHeight = (y + h > rcLockY + rcLockHeight) ?
366
 
      (y + h - newY) : (rcLockY + rcLockHeight - newY);
367
 
    rcLockX = newX;
368
 
    rcLockY = newY;
369
 
  }
370
 
 
371
 
  if (!rcCursorHidden && SoftCursorInLockedArea()) {
372
 
    SoftCursorCopyArea(OPER_RESTORE);
373
 
    rcCursorHidden = True;
374
 
  }
375
 
}
376
 
 
377
 
/*********************************************************************
378
 
 * SoftCursorUnlockScreen(). This function discards all locks
379
 
 * performed since previous SoftCursorUnlockScreen() call.
380
 
 ********************************************************************/
381
 
 
382
 
void SoftCursorUnlockScreen(void)
383
 
{
384
 
  if (!prevSoftCursorSet)
385
 
    return;
386
 
 
387
 
  if (rcCursorHidden) {
388
 
    SoftCursorCopyArea(OPER_SAVE);
389
 
    SoftCursorDraw();
390
 
    rcCursorHidden = False;
391
 
  }
392
 
  rcLockSet = False;
393
 
}
394
 
 
395
 
/*********************************************************************
396
 
 * SoftCursorMove(). Moves soft cursor into a particular location. 
397
 
 * This function respects locking of screen areas so when the cursor
398
 
 * is moved into the locked area, it becomes invisible until
399
 
 * SoftCursorUnlock() functions is called.
400
 
 ********************************************************************/
401
 
 
402
 
void SoftCursorMove(int x, int y)
403
 
{
404
 
  if (prevSoftCursorSet && !rcCursorHidden) {
405
 
    SoftCursorCopyArea(OPER_RESTORE);
406
 
    rcCursorHidden = True;
407
 
  }
408
 
 
409
 
  rcCursorX = x;
410
 
  rcCursorY = y;
411
 
 
412
 
  if (prevSoftCursorSet && !(rcLockSet && SoftCursorInLockedArea())) {
413
 
    SoftCursorCopyArea(OPER_SAVE);
414
 
    SoftCursorDraw();
415
 
    rcCursorHidden = False;
416
 
  }
417
 
}
418
 
 
419
 
 
420
 
/*********************************************************************
421
 
 * Internal (static) low-level functions.
422
 
 ********************************************************************/
423
 
 
424
 
static Bool SoftCursorInLockedArea(void)
425
 
{
426
 
  return (rcLockX < rcCursorX - rcHotX + rcWidth &&
427
 
          rcLockY < rcCursorY - rcHotY + rcHeight &&
428
 
          rcLockX + rcLockWidth > rcCursorX - rcHotX &&
429
 
          rcLockY + rcLockHeight > rcCursorY - rcHotY);
430
 
}
431
 
 
432
 
static void SoftCursorCopyArea(int oper)
433
 
{
434
 
  int x, y, w, h;
435
 
 
436
 
  x = rcCursorX - rcHotX;
437
 
  y = rcCursorY - rcHotY;
438
 
  if (x >= si.framebufferWidth || y >= si.framebufferHeight)
439
 
    return;
440
 
 
441
 
  w = rcWidth;
442
 
  h = rcHeight;
443
 
  if (x < 0) {
444
 
    w += x;
445
 
    x = 0;
446
 
  } else if (x + w > si.framebufferWidth) {
447
 
    w = si.framebufferWidth - x;
448
 
  }
449
 
  if (y < 0) {
450
 
    h += y;
451
 
    y = 0;
452
 
  } else if (y + h > si.framebufferHeight) {
453
 
    h = si.framebufferHeight - y;
454
 
  }
455
 
 
456
 
  if (oper == OPER_SAVE) {
457
 
    /* Save screen area in memory. */
458
 
#ifdef MITSHM
459
 
    if (appData.useShm)
460
 
      XSync(dpy, False);
461
 
#endif
462
 
    XCopyArea(dpy, desktopWin, rcSavedArea, gc, x, y, w, h, 0, 0);
463
 
  } else {
464
 
    /* Restore screen area. */
465
 
    XCopyArea(dpy, rcSavedArea, desktopWin, gc, 0, 0, w, h, x, y);
466
 
  }
467
 
}
468
 
 
469
 
static void SoftCursorDraw(void)
470
 
{
471
 
 
472
 
  int x, y, x0, y0;
473
 
  int offset, bytesPerPixel;
474
 
  char *pos;
475
 
 
476
 
  bytesPerPixel = myFormat.bitsPerPixel / 8;
477
 
 
478
 
  /* FIXME: Speed optimization is possible. */
479
 
  for (y = 0; y < rcHeight; y++) {
480
 
    y0 = rcCursorY - rcHotY + y;
481
 
    if (y0 >= 0 && y0 < si.framebufferHeight) {
482
 
      for (x = 0; x < rcWidth; x++) {
483
 
        x0 = rcCursorX - rcHotX + x;
484
 
        if (x0 >= 0 && x0 < si.framebufferWidth) {
485
 
          offset = y * rcWidth + x;
486
 
          if (rcMask[offset]) {
487
 
            pos = (char *)&rcSource[offset * bytesPerPixel];
488
 
            CopyDataToScreen(pos, x0, y0, 1, 1);
489
 
          }
490
 
        }
491
 
      }
492
 
    }
493
 
  }
494
 
}
495
 
 
496
 
static void FreeSoftCursor(void)
497
 
{
498
 
  if (prevSoftCursorSet) {
499
 
    SoftCursorCopyArea(OPER_RESTORE);
500
 
    XFreePixmap(dpy, rcSavedArea);
501
 
    free(rcSource);
502
 
    free(rcMask);
503
 
    prevSoftCursorSet = False;
504
 
  }
505
 
}
506
 
 
507
 
 
508
 
static void FreeX11Cursor()
509
 
{
510
 
  if (prevXCursorSet) {
511
 
    XFreeCursor(dpy, prevXCursor);
512
 
    prevXCursorSet = False;
513
 
  }
514
 
}
515