1 /*
2 * sprite.c
3 *
4 * software sprite routines - based on misprite
5 */
6
7 /*
8 * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
9 *
10 * This is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This software is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this software; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
23 * USA.
24 */
25
26 /* $XConsortium: misprite.c,v 5.47 94/04/17 20:27:53 dpw Exp $ */
27
28 /*
29
30 Copyright (c) 1989 X Consortium
31
32 Permission is hereby granted, free of charge, to any person obtaining a copy
33 of this software and associated documentation files (the "Software"), to deal
34 in the Software without restriction, including without limitation the rights
35 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
36 copies of the Software, and to permit persons to whom the Software is
37 furnished to do so, subject to the following conditions:
38
39 The above copyright notice and this permission notice shall be included in
40 all copies or substantial portions of the Software.
41
42 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
43 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
44 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
45 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
46 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
47 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
48
49 Except as contained in this notice, the name of the X Consortium shall not be
50 used in advertising or otherwise to promote the sale, use or other dealings
51 in this Software without prior written authorization from the X Consortium.
52 */
53
54 # include "X.h"
55 # include "Xproto.h"
56 # include "misc.h"
57 # include "pixmapstr.h"
58 # include "input.h"
59 # include "mi.h"
60 # include "cursorstr.h"
61 # include "font.h"
62 # include "scrnintstr.h"
63 # include "colormapst.h"
64 # include "windowstr.h"
65 # include "gcstruct.h"
66 # include "mipointer.h"
67 # include "spritest.h"
68 # include "dixfontstr.h"
69 # include "fontstruct.h"
70 #include "rfb.h"
71
72 /*
73 * screen wrappers
74 */
75
76 static int rfbSpriteScreenIndex;
77 static unsigned long rfbSpriteGeneration = 0;
78
79 static Bool rfbSpriteCloseScreen();
80 static void rfbSpriteGetImage();
81 static void rfbSpriteGetSpans();
82 static void rfbSpriteSourceValidate();
83 static Bool rfbSpriteCreateGC();
84 static void rfbSpriteInstallColormap();
85 static void rfbSpriteStoreColors();
86
87 static void rfbSpritePaintWindowBackground();
88 static void rfbSpritePaintWindowBorder();
89 static void rfbSpriteCopyWindow();
90 static void rfbSpriteClearToBackground();
91
92 static void rfbSpriteSaveDoomedAreas();
93 static RegionPtr rfbSpriteRestoreAreas();
94 static void rfbSpriteComputeSaved();
95
96 #define SCREEN_PROLOGUE(pScreen, field)\
97 ((pScreen)->field = \
98 ((rfbSpriteScreenPtr) (pScreen)->devPrivates[rfbSpriteScreenIndex].ptr)->field)
99
100 #define SCREEN_EPILOGUE(pScreen, field, wrapper)\
101 ((pScreen)->field = wrapper)
102
103 /*
104 * GC func wrappers
105 */
106
107 static int rfbSpriteGCIndex;
108
109 static void rfbSpriteValidateGC (), rfbSpriteCopyGC ();
110 static void rfbSpriteDestroyGC(), rfbSpriteChangeGC();
111 static void rfbSpriteChangeClip(), rfbSpriteDestroyClip();
112 static void rfbSpriteCopyClip();
113
114 static GCFuncs rfbSpriteGCFuncs = {
115 rfbSpriteValidateGC,
116 rfbSpriteChangeGC,
117 rfbSpriteCopyGC,
118 rfbSpriteDestroyGC,
119 rfbSpriteChangeClip,
120 rfbSpriteDestroyClip,
121 rfbSpriteCopyClip,
122 };
123
124 #define GC_FUNC_PROLOGUE(pGC) \
125 rfbSpriteGCPtr pGCPriv = \
126 (rfbSpriteGCPtr) (pGC)->devPrivates[rfbSpriteGCIndex].ptr;\
127 (pGC)->funcs = pGCPriv->wrapFuncs; \
128 if (pGCPriv->wrapOps) \
129 (pGC)->ops = pGCPriv->wrapOps;
130
131 #define GC_FUNC_EPILOGUE(pGC) \
132 pGCPriv->wrapFuncs = (pGC)->funcs; \
133 (pGC)->funcs = &rfbSpriteGCFuncs; \
134 if (pGCPriv->wrapOps) \
135 { \
136 pGCPriv->wrapOps = (pGC)->ops; \
137 (pGC)->ops = &rfbSpriteGCOps; \
138 }
139
140 /*
141 * GC op wrappers
142 */
143
144 static void rfbSpriteFillSpans(), rfbSpriteSetSpans();
145 static void rfbSpritePutImage();
146 static RegionPtr rfbSpriteCopyArea(), rfbSpriteCopyPlane();
147 static void rfbSpritePolyPoint(), rfbSpritePolylines();
148 static void rfbSpritePolySegment(), rfbSpritePolyRectangle();
149 static void rfbSpritePolyArc(), rfbSpriteFillPolygon();
150 static void rfbSpritePolyFillRect(), rfbSpritePolyFillArc();
151 static int rfbSpritePolyText8(), rfbSpritePolyText16();
152 static void rfbSpriteImageText8(), rfbSpriteImageText16();
153 static void rfbSpriteImageGlyphBlt(), rfbSpritePolyGlyphBlt();
154 static void rfbSpritePushPixels();
155 #ifdef NEED_LINEHELPER
156 static void rfbSpriteLineHelper();
157 #endif
158
159 static GCOps rfbSpriteGCOps = {
160 rfbSpriteFillSpans, rfbSpriteSetSpans, rfbSpritePutImage,
161 rfbSpriteCopyArea, rfbSpriteCopyPlane, rfbSpritePolyPoint,
162 rfbSpritePolylines, rfbSpritePolySegment, rfbSpritePolyRectangle,
163 rfbSpritePolyArc, rfbSpriteFillPolygon, rfbSpritePolyFillRect,
164 rfbSpritePolyFillArc, rfbSpritePolyText8, rfbSpritePolyText16,
165 rfbSpriteImageText8, rfbSpriteImageText16, rfbSpriteImageGlyphBlt,
166 rfbSpritePolyGlyphBlt, rfbSpritePushPixels
167 #ifdef NEED_LINEHELPER
168 , rfbSpriteLineHelper
169 #endif
170 };
171
172 /*
173 * testing only -- remove cursor for every draw. Eventually,
174 * each draw operation will perform a bounding box check against
175 * the saved cursor area
176 */
177
178 #define GC_SETUP_CHEAP(pDrawable) \
179 rfbSpriteScreenPtr pScreenPriv = (rfbSpriteScreenPtr) \
180 (pDrawable)->pScreen->devPrivates[rfbSpriteScreenIndex].ptr; \
181
182 #define GC_SETUP(pDrawable, pGC) \
183 GC_SETUP_CHEAP(pDrawable) \
184 rfbSpriteGCPtr pGCPrivate = (rfbSpriteGCPtr) \
185 (pGC)->devPrivates[rfbSpriteGCIndex].ptr; \
186 GCFuncs *oldFuncs = pGC->funcs;
187
188 #define GC_SETUP_AND_CHECK(pDrawable, pGC) \
189 GC_SETUP(pDrawable, pGC); \
190 if (GC_CHECK((WindowPtr)pDrawable)) \
191 rfbSpriteRemoveCursor (pDrawable->pScreen);
192
193 #define GC_CHECK(pWin) \
194 (rfbScreen.cursorIsDrawn && \
195 (pScreenPriv->pCacheWin == pWin ? \
196 pScreenPriv->isInCacheWin : ( \
197 ((int) (pScreenPriv->pCacheWin = (pWin))) , \
198 (pScreenPriv->isInCacheWin = \
199 (pWin)->drawable.x < pScreenPriv->saved.x2 && \
200 pScreenPriv->saved.x1 < (pWin)->drawable.x + \
201 (int) (pWin)->drawable.width && \
202 (pWin)->drawable.y < pScreenPriv->saved.y2 && \
203 pScreenPriv->saved.y1 < (pWin)->drawable.y + \
204 (int) (pWin)->drawable.height &&\
205 RECT_IN_REGION((pWin)->drawable.pScreen, &(pWin)->borderClip, \
206 &pScreenPriv->saved) != rgnOUT))))
207
208 #define GC_OP_PROLOGUE(pGC) { \
209 (pGC)->funcs = pGCPrivate->wrapFuncs; \
210 (pGC)->ops = pGCPrivate->wrapOps; \
211 }
212
213 #define GC_OP_EPILOGUE(pGC) { \
214 pGCPrivate->wrapOps = (pGC)->ops; \
215 (pGC)->funcs = oldFuncs; \
216 (pGC)->ops = &rfbSpriteGCOps; \
217 }
218
219 /*
220 * pointer-sprite method table
221 */
222
223 static Bool rfbSpriteRealizeCursor (), rfbSpriteUnrealizeCursor ();
224 static void rfbSpriteSetCursor (), rfbSpriteMoveCursor ();
225
226 miPointerSpriteFuncRec rfbSpritePointerFuncs = {
227 rfbSpriteRealizeCursor,
228 rfbSpriteUnrealizeCursor,
229 rfbSpriteSetCursor,
230 rfbSpriteMoveCursor,
231 };
232
233 /*
234 * other misc functions
235 */
236
237 static Bool rfbDisplayCursor (ScreenPtr pScreen, CursorPtr pCursor);
238
239
240 /*
241 * rfbSpriteInitialize -- called from device-dependent screen
242 * initialization proc after all of the function pointers have
243 * been stored in the screen structure.
244 */
245
246 Bool
rfbSpriteInitialize(pScreen,cursorFuncs,screenFuncs)247 rfbSpriteInitialize (pScreen, cursorFuncs, screenFuncs)
248 ScreenPtr pScreen;
249 rfbSpriteCursorFuncPtr cursorFuncs;
250 miPointerScreenFuncPtr screenFuncs;
251 {
252 rfbSpriteScreenPtr pPriv;
253 VisualPtr pVisual;
254
255 if (rfbSpriteGeneration != serverGeneration)
256 {
257 rfbSpriteScreenIndex = AllocateScreenPrivateIndex ();
258 if (rfbSpriteScreenIndex < 0)
259 return FALSE;
260 rfbSpriteGeneration = serverGeneration;
261 rfbSpriteGCIndex = AllocateGCPrivateIndex ();
262 }
263 if (!AllocateGCPrivate(pScreen, rfbSpriteGCIndex, sizeof(rfbSpriteGCRec)))
264 return FALSE;
265 pPriv = (rfbSpriteScreenPtr) xalloc (sizeof (rfbSpriteScreenRec));
266 if (!pPriv)
267 return FALSE;
268 if (!miPointerInitialize (pScreen, &rfbSpritePointerFuncs, screenFuncs,TRUE))
269 {
270 xfree ((pointer) pPriv);
271 return FALSE;
272 }
273 for (pVisual = pScreen->visuals;
274 pVisual->vid != pScreen->rootVisual;
275 pVisual++)
276 ;
277 pPriv->pVisual = pVisual;
278 pPriv->CloseScreen = pScreen->CloseScreen;
279 pPriv->GetImage = pScreen->GetImage;
280 pPriv->GetSpans = pScreen->GetSpans;
281 pPriv->SourceValidate = pScreen->SourceValidate;
282 pPriv->CreateGC = pScreen->CreateGC;
283 pPriv->InstallColormap = pScreen->InstallColormap;
284 pPriv->StoreColors = pScreen->StoreColors;
285 pPriv->DisplayCursor = pScreen->DisplayCursor;
286
287 pPriv->PaintWindowBackground = pScreen->PaintWindowBackground;
288 pPriv->PaintWindowBorder = pScreen->PaintWindowBorder;
289 pPriv->CopyWindow = pScreen->CopyWindow;
290 pPriv->ClearToBackground = pScreen->ClearToBackground;
291
292 pPriv->SaveDoomedAreas = pScreen->SaveDoomedAreas;
293 pPriv->RestoreAreas = pScreen->RestoreAreas;
294
295 pPriv->pCursor = NULL;
296 pPriv->x = 0;
297 pPriv->y = 0;
298 pPriv->pCacheWin = NullWindow;
299 pPriv->isInCacheWin = FALSE;
300 pPriv->checkPixels = TRUE;
301 pPriv->pInstalledMap = NULL;
302 pPriv->pColormap = NULL;
303 pPriv->funcs = cursorFuncs;
304 pPriv->colors[SOURCE_COLOR].red = 0;
305 pPriv->colors[SOURCE_COLOR].green = 0;
306 pPriv->colors[SOURCE_COLOR].blue = 0;
307 pPriv->colors[MASK_COLOR].red = 0;
308 pPriv->colors[MASK_COLOR].green = 0;
309 pPriv->colors[MASK_COLOR].blue = 0;
310 pScreen->devPrivates[rfbSpriteScreenIndex].ptr = (pointer) pPriv;
311 pScreen->CloseScreen = rfbSpriteCloseScreen;
312 pScreen->GetImage = rfbSpriteGetImage;
313 pScreen->GetSpans = rfbSpriteGetSpans;
314 pScreen->SourceValidate = rfbSpriteSourceValidate;
315 pScreen->CreateGC = rfbSpriteCreateGC;
316 pScreen->InstallColormap = rfbSpriteInstallColormap;
317 pScreen->StoreColors = rfbSpriteStoreColors;
318
319 pScreen->PaintWindowBackground = rfbSpritePaintWindowBackground;
320 pScreen->PaintWindowBorder = rfbSpritePaintWindowBorder;
321 pScreen->CopyWindow = rfbSpriteCopyWindow;
322 pScreen->ClearToBackground = rfbSpriteClearToBackground;
323
324 pScreen->SaveDoomedAreas = rfbSpriteSaveDoomedAreas;
325 pScreen->RestoreAreas = rfbSpriteRestoreAreas;
326
327 pScreen->DisplayCursor = rfbDisplayCursor;
328
329 return TRUE;
330 }
331
332 /*
333 * Screen wrappers
334 */
335
336 /*
337 * CloseScreen wrapper -- unwrap everything, free the private data
338 * and call the wrapped function
339 */
340
341 static Bool
rfbSpriteCloseScreen(i,pScreen)342 rfbSpriteCloseScreen (i, pScreen)
343 ScreenPtr pScreen;
344 {
345 rfbSpriteScreenPtr pScreenPriv;
346
347 pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr;
348
349 pScreen->CloseScreen = pScreenPriv->CloseScreen;
350 pScreen->GetImage = pScreenPriv->GetImage;
351 pScreen->GetSpans = pScreenPriv->GetSpans;
352 pScreen->SourceValidate = pScreenPriv->SourceValidate;
353 pScreen->CreateGC = pScreenPriv->CreateGC;
354 pScreen->InstallColormap = pScreenPriv->InstallColormap;
355 pScreen->StoreColors = pScreenPriv->StoreColors;
356
357 pScreen->PaintWindowBackground = pScreenPriv->PaintWindowBackground;
358 pScreen->PaintWindowBorder = pScreenPriv->PaintWindowBorder;
359 pScreen->CopyWindow = pScreenPriv->CopyWindow;
360 pScreen->ClearToBackground = pScreenPriv->ClearToBackground;
361
362 pScreen->SaveDoomedAreas = pScreenPriv->SaveDoomedAreas;
363 pScreen->RestoreAreas = pScreenPriv->RestoreAreas;
364
365 xfree ((pointer) pScreenPriv);
366
367 return (*pScreen->CloseScreen) (i, pScreen);
368 }
369
370 static void
rfbSpriteGetImage(pDrawable,sx,sy,w,h,format,planemask,pdstLine)371 rfbSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine)
372 DrawablePtr pDrawable;
373 int sx, sy, w, h;
374 unsigned int format;
375 unsigned long planemask;
376 char *pdstLine;
377 {
378 ScreenPtr pScreen = pDrawable->pScreen;
379 rfbSpriteScreenPtr pScreenPriv;
380
381 SCREEN_PROLOGUE (pScreen, GetImage);
382
383 pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr;
384
385 if (pDrawable->type == DRAWABLE_WINDOW &&
386 rfbScreen.cursorIsDrawn &&
387 ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y, sx, sy, w, h))
388 {
389 rfbSpriteRemoveCursor (pScreen);
390 }
391
392 (*pScreen->GetImage) (pDrawable, sx, sy, w, h,
393 format, planemask, pdstLine);
394
395 SCREEN_EPILOGUE (pScreen, GetImage, rfbSpriteGetImage);
396 }
397
398 static void
rfbSpriteGetSpans(pDrawable,wMax,ppt,pwidth,nspans,pdstStart)399 rfbSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart)
400 DrawablePtr pDrawable;
401 int wMax;
402 DDXPointPtr ppt;
403 int *pwidth;
404 int nspans;
405 char *pdstStart;
406 {
407 ScreenPtr pScreen = pDrawable->pScreen;
408 rfbSpriteScreenPtr pScreenPriv;
409
410 SCREEN_PROLOGUE (pScreen, GetSpans);
411
412 pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr;
413
414 if (pDrawable->type == DRAWABLE_WINDOW && rfbScreen.cursorIsDrawn)
415 {
416 register DDXPointPtr pts;
417 register int *widths;
418 register int nPts;
419 register int xorg,
420 yorg;
421
422 xorg = pDrawable->x;
423 yorg = pDrawable->y;
424
425 for (pts = ppt, widths = pwidth, nPts = nspans;
426 nPts--;
427 pts++, widths++)
428 {
429 if (SPN_OVERLAP(&pScreenPriv->saved,pts->y+yorg,
430 pts->x+xorg,*widths))
431 {
432 rfbSpriteRemoveCursor (pScreen);
433 break;
434 }
435 }
436 }
437
438 (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
439
440 SCREEN_EPILOGUE (pScreen, GetSpans, rfbSpriteGetSpans);
441 }
442
443 static void
rfbSpriteSourceValidate(pDrawable,x,y,width,height)444 rfbSpriteSourceValidate (pDrawable, x, y, width, height)
445 DrawablePtr pDrawable;
446 int x, y, width, height;
447 {
448 ScreenPtr pScreen = pDrawable->pScreen;
449 rfbSpriteScreenPtr pScreenPriv;
450
451 SCREEN_PROLOGUE (pScreen, SourceValidate);
452
453 pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr;
454
455 if (pDrawable->type == DRAWABLE_WINDOW && rfbScreen.cursorIsDrawn &&
456 ORG_OVERLAP(&pScreenPriv->saved, pDrawable->x, pDrawable->y,
457 x, y, width, height))
458 {
459 rfbSpriteRemoveCursor (pScreen);
460 }
461
462 if (pScreen->SourceValidate)
463 (*pScreen->SourceValidate) (pDrawable, x, y, width, height);
464
465 SCREEN_EPILOGUE (pScreen, SourceValidate, rfbSpriteSourceValidate);
466 }
467
468 static Bool
rfbSpriteCreateGC(pGC)469 rfbSpriteCreateGC (pGC)
470 GCPtr pGC;
471 {
472 ScreenPtr pScreen = pGC->pScreen;
473 Bool ret;
474 rfbSpriteGCPtr pPriv;
475
476 SCREEN_PROLOGUE (pScreen, CreateGC);
477
478 pPriv = (rfbSpriteGCPtr)pGC->devPrivates[rfbSpriteGCIndex].ptr;
479
480 ret = (*pScreen->CreateGC) (pGC);
481
482 pPriv->wrapOps = NULL;
483 pPriv->wrapFuncs = pGC->funcs;
484 pGC->funcs = &rfbSpriteGCFuncs;
485
486 SCREEN_EPILOGUE (pScreen, CreateGC, rfbSpriteCreateGC);
487
488 return ret;
489 }
490
491 static void
rfbSpriteInstallColormap(pMap)492 rfbSpriteInstallColormap (pMap)
493 ColormapPtr pMap;
494 {
495 ScreenPtr pScreen = pMap->pScreen;
496 rfbSpriteScreenPtr pPriv;
497
498 pPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr;
499
500 SCREEN_PROLOGUE(pScreen, InstallColormap);
501
502 (*pScreen->InstallColormap) (pMap);
503
504 SCREEN_EPILOGUE(pScreen, InstallColormap, rfbSpriteInstallColormap);
505
506 pPriv->pInstalledMap = pMap;
507 if (pPriv->pColormap != pMap)
508 {
509 pPriv->checkPixels = TRUE;
510 if (rfbScreen.cursorIsDrawn)
511 rfbSpriteRemoveCursor (pScreen);
512 }
513 }
514
515 static void
rfbSpriteStoreColors(pMap,ndef,pdef)516 rfbSpriteStoreColors (pMap, ndef, pdef)
517 ColormapPtr pMap;
518 int ndef;
519 xColorItem *pdef;
520 {
521 ScreenPtr pScreen = pMap->pScreen;
522 rfbSpriteScreenPtr pPriv;
523 int i;
524 int updated;
525 VisualPtr pVisual;
526
527 pPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr;
528
529 SCREEN_PROLOGUE(pScreen, StoreColors);
530
531 (*pScreen->StoreColors) (pMap, ndef, pdef);
532
533 SCREEN_EPILOGUE(pScreen, StoreColors, rfbSpriteStoreColors);
534
535 if (pPriv->pColormap == pMap)
536 {
537 updated = 0;
538 pVisual = pMap->pVisual;
539 if (pVisual->class == DirectColor)
540 {
541 /* Direct color - match on any of the subfields */
542
543 #define MaskMatch(a,b,mask) ((a) & (pVisual->mask) == (b) & (pVisual->mask))
544
545 #define UpdateDAC(plane,dac,mask) {\
546 if (MaskMatch (pPriv->colors[plane].pixel,pdef[i].pixel,mask)) {\
547 pPriv->colors[plane].dac = pdef[i].dac; \
548 updated = 1; \
549 } \
550 }
551
552 #define CheckDirect(plane) \
553 UpdateDAC(plane,red,redMask) \
554 UpdateDAC(plane,green,greenMask) \
555 UpdateDAC(plane,blue,blueMask)
556
557 for (i = 0; i < ndef; i++)
558 {
559 CheckDirect (SOURCE_COLOR)
560 CheckDirect (MASK_COLOR)
561 }
562 }
563 else
564 {
565 /* PseudoColor/GrayScale - match on exact pixel */
566 for (i = 0; i < ndef; i++)
567 {
568 if (pdef[i].pixel == pPriv->colors[SOURCE_COLOR].pixel)
569 {
570 pPriv->colors[SOURCE_COLOR] = pdef[i];
571 if (++updated == 2)
572 break;
573 }
574 if (pdef[i].pixel == pPriv->colors[MASK_COLOR].pixel)
575 {
576 pPriv->colors[MASK_COLOR] = pdef[i];
577 if (++updated == 2)
578 break;
579 }
580 }
581 }
582 if (updated)
583 {
584 pPriv->checkPixels = TRUE;
585 if (rfbScreen.cursorIsDrawn)
586 rfbSpriteRemoveCursor (pScreen);
587 }
588 }
589 }
590
591 static void
rfbSpriteFindColors(pScreen)592 rfbSpriteFindColors (pScreen)
593 ScreenPtr pScreen;
594 {
595 rfbSpriteScreenPtr pScreenPriv = (rfbSpriteScreenPtr)
596 pScreen->devPrivates[rfbSpriteScreenIndex].ptr;
597 CursorPtr pCursor;
598 xColorItem *sourceColor, *maskColor;
599
600 pCursor = pScreenPriv->pCursor;
601 sourceColor = &pScreenPriv->colors[SOURCE_COLOR];
602 maskColor = &pScreenPriv->colors[MASK_COLOR];
603 if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap ||
604 !(pCursor->foreRed == sourceColor->red &&
605 pCursor->foreGreen == sourceColor->green &&
606 pCursor->foreBlue == sourceColor->blue &&
607 pCursor->backRed == maskColor->red &&
608 pCursor->backGreen == maskColor->green &&
609 pCursor->backBlue == maskColor->blue))
610 {
611 pScreenPriv->pColormap = pScreenPriv->pInstalledMap;
612 sourceColor->red = pCursor->foreRed;
613 sourceColor->green = pCursor->foreGreen;
614 sourceColor->blue = pCursor->foreBlue;
615 FakeAllocColor (pScreenPriv->pColormap, sourceColor);
616 maskColor->red = pCursor->backRed;
617 maskColor->green = pCursor->backGreen;
618 maskColor->blue = pCursor->backBlue;
619 FakeAllocColor (pScreenPriv->pColormap, maskColor);
620 /* "free" the pixels right away, don't let this confuse you */
621 FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel);
622 FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel);
623 }
624 pScreenPriv->checkPixels = FALSE;
625 }
626
627 /*
628 * BackingStore wrappers
629 */
630
631 static void
rfbSpriteSaveDoomedAreas(pWin,pObscured,dx,dy)632 rfbSpriteSaveDoomedAreas (pWin, pObscured, dx, dy)
633 WindowPtr pWin;
634 RegionPtr pObscured;
635 int dx, dy;
636 {
637 ScreenPtr pScreen;
638 rfbSpriteScreenPtr pScreenPriv;
639 BoxRec cursorBox;
640
641 pScreen = pWin->drawable.pScreen;
642
643 SCREEN_PROLOGUE (pScreen, SaveDoomedAreas);
644
645 pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr;
646 if (rfbScreen.cursorIsDrawn)
647 {
648 cursorBox = pScreenPriv->saved;
649
650 if (dx || dy)
651 {
652 cursorBox.x1 += dx;
653 cursorBox.y1 += dy;
654 cursorBox.x2 += dx;
655 cursorBox.y2 += dy;
656 }
657 if (RECT_IN_REGION( pScreen, pObscured, &cursorBox) != rgnOUT)
658 rfbSpriteRemoveCursor (pScreen);
659 }
660
661 (*pScreen->SaveDoomedAreas) (pWin, pObscured, dx, dy);
662
663 SCREEN_EPILOGUE (pScreen, SaveDoomedAreas, rfbSpriteSaveDoomedAreas);
664 }
665
666 static RegionPtr
rfbSpriteRestoreAreas(pWin,prgnExposed)667 rfbSpriteRestoreAreas (pWin, prgnExposed)
668 WindowPtr pWin;
669 RegionPtr prgnExposed;
670 {
671 ScreenPtr pScreen;
672 rfbSpriteScreenPtr pScreenPriv;
673 RegionPtr result;
674
675 pScreen = pWin->drawable.pScreen;
676
677 SCREEN_PROLOGUE (pScreen, RestoreAreas);
678
679 pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr;
680 if (rfbScreen.cursorIsDrawn)
681 {
682 if (RECT_IN_REGION( pScreen, prgnExposed, &pScreenPriv->saved) != rgnOUT)
683 rfbSpriteRemoveCursor (pScreen);
684 }
685
686 result = (*pScreen->RestoreAreas) (pWin, prgnExposed);
687
688 SCREEN_EPILOGUE (pScreen, RestoreAreas, rfbSpriteRestoreAreas);
689
690 return result;
691 }
692
693 /*
694 * Window wrappers
695 */
696
697 static void
rfbSpritePaintWindowBackground(pWin,pRegion,what)698 rfbSpritePaintWindowBackground (pWin, pRegion, what)
699 WindowPtr pWin;
700 RegionPtr pRegion;
701 int what;
702 {
703 ScreenPtr pScreen;
704 rfbSpriteScreenPtr pScreenPriv;
705
706 pScreen = pWin->drawable.pScreen;
707
708 SCREEN_PROLOGUE (pScreen, PaintWindowBackground);
709
710 pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr;
711 if (rfbScreen.cursorIsDrawn)
712 {
713 /*
714 * If the cursor is on the same screen as the window, check the
715 * region to paint for the cursor and remove it as necessary
716 */
717 if (RECT_IN_REGION( pScreen, pRegion, &pScreenPriv->saved) != rgnOUT)
718 rfbSpriteRemoveCursor (pScreen);
719 }
720
721 (*pScreen->PaintWindowBackground) (pWin, pRegion, what);
722
723 SCREEN_EPILOGUE (pScreen, PaintWindowBackground, rfbSpritePaintWindowBackground);
724 }
725
726 static void
rfbSpritePaintWindowBorder(pWin,pRegion,what)727 rfbSpritePaintWindowBorder (pWin, pRegion, what)
728 WindowPtr pWin;
729 RegionPtr pRegion;
730 int what;
731 {
732 ScreenPtr pScreen;
733 rfbSpriteScreenPtr pScreenPriv;
734
735 pScreen = pWin->drawable.pScreen;
736
737 SCREEN_PROLOGUE (pScreen, PaintWindowBorder);
738
739 pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr;
740 if (rfbScreen.cursorIsDrawn)
741 {
742 /*
743 * If the cursor is on the same screen as the window, check the
744 * region to paint for the cursor and remove it as necessary
745 */
746 if (RECT_IN_REGION( pScreen, pRegion, &pScreenPriv->saved) != rgnOUT)
747 rfbSpriteRemoveCursor (pScreen);
748 }
749
750 (*pScreen->PaintWindowBorder) (pWin, pRegion, what);
751
752 SCREEN_EPILOGUE (pScreen, PaintWindowBorder, rfbSpritePaintWindowBorder);
753 }
754
755 static void
rfbSpriteCopyWindow(pWin,ptOldOrg,pRegion)756 rfbSpriteCopyWindow (pWin, ptOldOrg, pRegion)
757 WindowPtr pWin;
758 DDXPointRec ptOldOrg;
759 RegionPtr pRegion;
760 {
761 ScreenPtr pScreen;
762 rfbSpriteScreenPtr pScreenPriv;
763 BoxRec cursorBox;
764 int dx, dy;
765
766 pScreen = pWin->drawable.pScreen;
767
768 SCREEN_PROLOGUE (pScreen, CopyWindow);
769
770 pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr;
771 if (rfbScreen.cursorIsDrawn)
772 {
773 /*
774 * check both the source and the destination areas. The given
775 * region is source relative, so offset the cursor box by
776 * the delta position
777 */
778 cursorBox = pScreenPriv->saved;
779 dx = pWin->drawable.x - ptOldOrg.x;
780 dy = pWin->drawable.y - ptOldOrg.y;
781 cursorBox.x1 -= dx;
782 cursorBox.x2 -= dx;
783 cursorBox.y1 -= dy;
784 cursorBox.y2 -= dy;
785 if (RECT_IN_REGION( pScreen, pRegion, &pScreenPriv->saved) != rgnOUT ||
786 RECT_IN_REGION( pScreen, pRegion, &cursorBox) != rgnOUT)
787 rfbSpriteRemoveCursor (pScreen);
788 }
789
790 (*pScreen->CopyWindow) (pWin, ptOldOrg, pRegion);
791
792 SCREEN_EPILOGUE (pScreen, CopyWindow, rfbSpriteCopyWindow);
793 }
794
795 static void
rfbSpriteClearToBackground(pWin,x,y,w,h,generateExposures)796 rfbSpriteClearToBackground (pWin, x, y, w, h, generateExposures)
797 WindowPtr pWin;
798 short x,y;
799 unsigned short w,h;
800 Bool generateExposures;
801 {
802 ScreenPtr pScreen;
803 rfbSpriteScreenPtr pScreenPriv;
804 int realw, realh;
805
806 pScreen = pWin->drawable.pScreen;
807
808 SCREEN_PROLOGUE (pScreen, ClearToBackground);
809
810 pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr;
811 if (GC_CHECK(pWin))
812 {
813 if (!(realw = w))
814 realw = (int) pWin->drawable.width - x;
815 if (!(realh = h))
816 realh = (int) pWin->drawable.height - y;
817 if (ORG_OVERLAP(&pScreenPriv->saved, pWin->drawable.x, pWin->drawable.y,
818 x, y, realw, realh))
819 {
820 rfbSpriteRemoveCursor (pScreen);
821 }
822 }
823
824 (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures);
825
826 SCREEN_EPILOGUE (pScreen, ClearToBackground, rfbSpriteClearToBackground);
827 }
828
829 /*
830 * GC Func wrappers
831 */
832
833 static void
rfbSpriteValidateGC(pGC,changes,pDrawable)834 rfbSpriteValidateGC (pGC, changes, pDrawable)
835 GCPtr pGC;
836 Mask changes;
837 DrawablePtr pDrawable;
838 {
839 GC_FUNC_PROLOGUE (pGC);
840
841 (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable);
842
843 pGCPriv->wrapOps = NULL;
844 if (pDrawable->type == DRAWABLE_WINDOW && ((WindowPtr) pDrawable)->viewable)
845 {
846 WindowPtr pWin;
847 RegionPtr pRegion;
848
849 pWin = (WindowPtr) pDrawable;
850 pRegion = &pWin->clipList;
851 if (pGC->subWindowMode == IncludeInferiors)
852 pRegion = &pWin->borderClip;
853 if (REGION_NOTEMPTY(pDrawable->pScreen, pRegion))
854 pGCPriv->wrapOps = pGC->ops;
855 }
856
857 GC_FUNC_EPILOGUE (pGC);
858 }
859
860 static void
rfbSpriteChangeGC(pGC,mask)861 rfbSpriteChangeGC (pGC, mask)
862 GCPtr pGC;
863 unsigned long mask;
864 {
865 GC_FUNC_PROLOGUE (pGC);
866
867 (*pGC->funcs->ChangeGC) (pGC, mask);
868
869 GC_FUNC_EPILOGUE (pGC);
870 }
871
872 static void
rfbSpriteCopyGC(pGCSrc,mask,pGCDst)873 rfbSpriteCopyGC (pGCSrc, mask, pGCDst)
874 GCPtr pGCSrc, pGCDst;
875 unsigned long mask;
876 {
877 GC_FUNC_PROLOGUE (pGCDst);
878
879 (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
880
881 GC_FUNC_EPILOGUE (pGCDst);
882 }
883
884 static void
rfbSpriteDestroyGC(pGC)885 rfbSpriteDestroyGC (pGC)
886 GCPtr pGC;
887 {
888 GC_FUNC_PROLOGUE (pGC);
889
890 (*pGC->funcs->DestroyGC) (pGC);
891
892 GC_FUNC_EPILOGUE (pGC);
893 }
894
895 static void
rfbSpriteChangeClip(pGC,type,pvalue,nrects)896 rfbSpriteChangeClip (pGC, type, pvalue, nrects)
897 GCPtr pGC;
898 int type;
899 pointer pvalue;
900 int nrects;
901 {
902 GC_FUNC_PROLOGUE (pGC);
903
904 (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
905
906 GC_FUNC_EPILOGUE (pGC);
907 }
908
909 static void
rfbSpriteCopyClip(pgcDst,pgcSrc)910 rfbSpriteCopyClip(pgcDst, pgcSrc)
911 GCPtr pgcDst, pgcSrc;
912 {
913 GC_FUNC_PROLOGUE (pgcDst);
914
915 (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
916
917 GC_FUNC_EPILOGUE (pgcDst);
918 }
919
920 static void
rfbSpriteDestroyClip(pGC)921 rfbSpriteDestroyClip(pGC)
922 GCPtr pGC;
923 {
924 GC_FUNC_PROLOGUE (pGC);
925
926 (* pGC->funcs->DestroyClip)(pGC);
927
928 GC_FUNC_EPILOGUE (pGC);
929 }
930
931 /*
932 * GC Op wrappers
933 */
934
935 static void
rfbSpriteFillSpans(pDrawable,pGC,nInit,pptInit,pwidthInit,fSorted)936 rfbSpriteFillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted)
937 DrawablePtr pDrawable;
938 GCPtr pGC;
939 int nInit; /* number of spans to fill */
940 DDXPointPtr pptInit; /* pointer to list of start points */
941 int *pwidthInit; /* pointer to list of n widths */
942 int fSorted;
943 {
944 GC_SETUP(pDrawable, pGC);
945
946 if (GC_CHECK((WindowPtr) pDrawable))
947 {
948 register DDXPointPtr pts;
949 register int *widths;
950 register int nPts;
951
952 for (pts = pptInit, widths = pwidthInit, nPts = nInit;
953 nPts--;
954 pts++, widths++)
955 {
956 if (SPN_OVERLAP(&pScreenPriv->saved,pts->y,pts->x,*widths))
957 {
958 rfbSpriteRemoveCursor (pDrawable->pScreen);
959 break;
960 }
961 }
962 }
963
964 GC_OP_PROLOGUE (pGC);
965
966 (*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
967
968 GC_OP_EPILOGUE (pGC);
969 }
970
971 static void
rfbSpriteSetSpans(pDrawable,pGC,psrc,ppt,pwidth,nspans,fSorted)972 rfbSpriteSetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted)
973 DrawablePtr pDrawable;
974 GCPtr pGC;
975 char *psrc;
976 register DDXPointPtr ppt;
977 int *pwidth;
978 int nspans;
979 int fSorted;
980 {
981 GC_SETUP(pDrawable, pGC);
982
983 if (GC_CHECK((WindowPtr) pDrawable))
984 {
985 register DDXPointPtr pts;
986 register int *widths;
987 register int nPts;
988
989 for (pts = ppt, widths = pwidth, nPts = nspans;
990 nPts--;
991 pts++, widths++)
992 {
993 if (SPN_OVERLAP(&pScreenPriv->saved,pts->y,pts->x,*widths))
994 {
995 rfbSpriteRemoveCursor(pDrawable->pScreen);
996 break;
997 }
998 }
999 }
1000
1001 GC_OP_PROLOGUE (pGC);
1002
1003 (*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
1004
1005 GC_OP_EPILOGUE (pGC);
1006 }
1007
1008 static void
rfbSpritePutImage(pDrawable,pGC,depth,x,y,w,h,leftPad,format,pBits)1009 rfbSpritePutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits)
1010 DrawablePtr pDrawable;
1011 GCPtr pGC;
1012 int depth;
1013 int x;
1014 int y;
1015 int w;
1016 int h;
1017 int format;
1018 char *pBits;
1019 {
1020 GC_SETUP(pDrawable, pGC);
1021
1022 if (GC_CHECK((WindowPtr) pDrawable))
1023 {
1024 if (ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y,
1025 x,y,w,h))
1026 {
1027 rfbSpriteRemoveCursor (pDrawable->pScreen);
1028 }
1029 }
1030
1031 GC_OP_PROLOGUE (pGC);
1032
1033 (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits);
1034
1035 GC_OP_EPILOGUE (pGC);
1036 }
1037
1038 static RegionPtr
rfbSpriteCopyArea(pSrc,pDst,pGC,srcx,srcy,w,h,dstx,dsty)1039 rfbSpriteCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty)
1040 DrawablePtr pSrc;
1041 DrawablePtr pDst;
1042 GCPtr pGC;
1043 int srcx;
1044 int srcy;
1045 int w;
1046 int h;
1047 int dstx;
1048 int dsty;
1049 {
1050 RegionPtr rgn;
1051
1052 GC_SETUP(pDst, pGC);
1053
1054 /* check destination/source overlap. */
1055 if (GC_CHECK((WindowPtr) pDst) &&
1056 (ORG_OVERLAP(&pScreenPriv->saved,pDst->x,pDst->y,dstx,dsty,w,h) ||
1057 ((pDst == pSrc) &&
1058 ORG_OVERLAP(&pScreenPriv->saved,pSrc->x,pSrc->y,srcx,srcy,w,h))))
1059 {
1060 rfbSpriteRemoveCursor (pDst->pScreen);
1061 }
1062
1063 GC_OP_PROLOGUE (pGC);
1064
1065 rgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h,
1066 dstx, dsty);
1067
1068 GC_OP_EPILOGUE (pGC);
1069
1070 return rgn;
1071 }
1072
1073 static RegionPtr
rfbSpriteCopyPlane(pSrc,pDst,pGC,srcx,srcy,w,h,dstx,dsty,plane)1074 rfbSpriteCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane)
1075 DrawablePtr pSrc;
1076 DrawablePtr pDst;
1077 register GCPtr pGC;
1078 int srcx,
1079 srcy;
1080 int w,
1081 h;
1082 int dstx,
1083 dsty;
1084 unsigned long plane;
1085 {
1086 RegionPtr rgn;
1087
1088 GC_SETUP(pDst, pGC);
1089
1090 /*
1091 * check destination/source for overlap.
1092 */
1093 if (GC_CHECK((WindowPtr) pDst) &&
1094 (ORG_OVERLAP(&pScreenPriv->saved,pDst->x,pDst->y,dstx,dsty,w,h) ||
1095 ((pDst == pSrc) &&
1096 ORG_OVERLAP(&pScreenPriv->saved,pSrc->x,pSrc->y,srcx,srcy,w,h))))
1097 {
1098 rfbSpriteRemoveCursor (pDst->pScreen);
1099 }
1100
1101 GC_OP_PROLOGUE (pGC);
1102
1103 rgn = (*pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h,
1104 dstx, dsty, plane);
1105
1106 GC_OP_EPILOGUE (pGC);
1107
1108 return rgn;
1109 }
1110
1111 static void
rfbSpritePolyPoint(pDrawable,pGC,mode,npt,pptInit)1112 rfbSpritePolyPoint (pDrawable, pGC, mode, npt, pptInit)
1113 DrawablePtr pDrawable;
1114 GCPtr pGC;
1115 int mode; /* Origin or Previous */
1116 int npt;
1117 xPoint *pptInit;
1118 {
1119 xPoint t;
1120 int n;
1121 BoxRec cursor;
1122 register xPoint *pts;
1123
1124 GC_SETUP (pDrawable, pGC);
1125
1126 if (npt && GC_CHECK((WindowPtr) pDrawable))
1127 {
1128 cursor.x1 = pScreenPriv->saved.x1 - pDrawable->x;
1129 cursor.y1 = pScreenPriv->saved.y1 - pDrawable->y;
1130 cursor.x2 = pScreenPriv->saved.x2 - pDrawable->x;
1131 cursor.y2 = pScreenPriv->saved.y2 - pDrawable->y;
1132
1133 if (mode == CoordModePrevious)
1134 {
1135 t.x = 0;
1136 t.y = 0;
1137 for (pts = pptInit, n = npt; n--; pts++)
1138 {
1139 t.x += pts->x;
1140 t.y += pts->y;
1141 if (cursor.x1 <= t.x && t.x <= cursor.x2 &&
1142 cursor.y1 <= t.y && t.y <= cursor.y2)
1143 {
1144 rfbSpriteRemoveCursor (pDrawable->pScreen);
1145 break;
1146 }
1147 }
1148 }
1149 else
1150 {
1151 for (pts = pptInit, n = npt; n--; pts++)
1152 {
1153 if (cursor.x1 <= pts->x && pts->x <= cursor.x2 &&
1154 cursor.y1 <= pts->y && pts->y <= cursor.y2)
1155 {
1156 rfbSpriteRemoveCursor (pDrawable->pScreen);
1157 break;
1158 }
1159 }
1160 }
1161 }
1162
1163 GC_OP_PROLOGUE (pGC);
1164
1165 (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pptInit);
1166
1167 GC_OP_EPILOGUE (pGC);
1168 }
1169
1170 static void
rfbSpritePolylines(pDrawable,pGC,mode,npt,pptInit)1171 rfbSpritePolylines (pDrawable, pGC, mode, npt, pptInit)
1172 DrawablePtr pDrawable;
1173 GCPtr pGC;
1174 int mode;
1175 int npt;
1176 DDXPointPtr pptInit;
1177 {
1178 BoxPtr cursor;
1179 register DDXPointPtr pts;
1180 int n;
1181 int x, y, x1, y1, x2, y2;
1182 int lw;
1183 int extra;
1184
1185 GC_SETUP (pDrawable, pGC);
1186
1187 if (npt && GC_CHECK((WindowPtr) pDrawable))
1188 {
1189 cursor = &pScreenPriv->saved;
1190 lw = pGC->lineWidth;
1191 x = pptInit->x + pDrawable->x;
1192 y = pptInit->y + pDrawable->y;
1193
1194 if (npt == 1)
1195 {
1196 extra = lw >> 1;
1197 if (LINE_OVERLAP(cursor, x, y, x, y, extra))
1198 rfbSpriteRemoveCursor (pDrawable->pScreen);
1199 }
1200 else
1201 {
1202 extra = lw >> 1;
1203 /*
1204 * mitered joins can project quite a way from
1205 * the line end; the 11 degree miter limit limits
1206 * this extension to 10.43 * lw / 2, rounded up
1207 * and converted to int yields 6 * lw
1208 */
1209 if (pGC->joinStyle == JoinMiter)
1210 extra = 6 * lw;
1211 else if (pGC->capStyle == CapProjecting)
1212 extra = lw;
1213 for (pts = pptInit + 1, n = npt - 1; n--; pts++)
1214 {
1215 x1 = x;
1216 y1 = y;
1217 if (mode == CoordModeOrigin)
1218 {
1219 x2 = pDrawable->x + pts->x;
1220 y2 = pDrawable->y + pts->y;
1221 }
1222 else
1223 {
1224 x2 = x + pts->x;
1225 y2 = y + pts->y;
1226 }
1227 x = x2;
1228 y = y2;
1229 LINE_SORT(x1, y1, x2, y2);
1230 if (LINE_OVERLAP(cursor, x1, y1, x2, y2, extra))
1231 {
1232 rfbSpriteRemoveCursor (pDrawable->pScreen);
1233 break;
1234 }
1235 }
1236 }
1237 }
1238 GC_OP_PROLOGUE (pGC);
1239
1240 (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, pptInit);
1241
1242 GC_OP_EPILOGUE (pGC);
1243 }
1244
1245 static void
rfbSpritePolySegment(pDrawable,pGC,nseg,pSegs)1246 rfbSpritePolySegment(pDrawable, pGC, nseg, pSegs)
1247 DrawablePtr pDrawable;
1248 GCPtr pGC;
1249 int nseg;
1250 xSegment *pSegs;
1251 {
1252 int n;
1253 register xSegment *segs;
1254 BoxPtr cursor;
1255 int x1, y1, x2, y2;
1256 int extra;
1257
1258 GC_SETUP(pDrawable, pGC);
1259
1260 if (nseg && GC_CHECK((WindowPtr) pDrawable))
1261 {
1262 cursor = &pScreenPriv->saved;
1263 extra = pGC->lineWidth >> 1;
1264 if (pGC->capStyle == CapProjecting)
1265 extra = pGC->lineWidth;
1266 for (segs = pSegs, n = nseg; n--; segs++)
1267 {
1268 x1 = segs->x1 + pDrawable->x;
1269 y1 = segs->y1 + pDrawable->y;
1270 x2 = segs->x2 + pDrawable->x;
1271 y2 = segs->y2 + pDrawable->y;
1272 LINE_SORT(x1, y1, x2, y2);
1273 if (LINE_OVERLAP(cursor, x1, y1, x2, y2, extra))
1274 {
1275 rfbSpriteRemoveCursor (pDrawable->pScreen);
1276 break;
1277 }
1278 }
1279 }
1280
1281 GC_OP_PROLOGUE (pGC);
1282
1283 (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, pSegs);
1284
1285 GC_OP_EPILOGUE (pGC);
1286 }
1287
1288 static void
rfbSpritePolyRectangle(pDrawable,pGC,nrects,pRects)1289 rfbSpritePolyRectangle(pDrawable, pGC, nrects, pRects)
1290 DrawablePtr pDrawable;
1291 GCPtr pGC;
1292 int nrects;
1293 xRectangle *pRects;
1294 {
1295 register xRectangle *rects;
1296 BoxPtr cursor;
1297 int lw;
1298 int n;
1299 int x1, y1, x2, y2;
1300
1301 GC_SETUP (pDrawable, pGC);
1302
1303 if (GC_CHECK((WindowPtr) pDrawable))
1304 {
1305 lw = pGC->lineWidth >> 1;
1306 cursor = &pScreenPriv->saved;
1307 for (rects = pRects, n = nrects; n--; rects++)
1308 {
1309 x1 = rects->x + pDrawable->x;
1310 y1 = rects->y + pDrawable->y;
1311 x2 = x1 + (int)rects->width;
1312 y2 = y1 + (int)rects->height;
1313 if (LINE_OVERLAP(cursor, x1, y1, x2, y1, lw) ||
1314 LINE_OVERLAP(cursor, x2, y1, x2, y2, lw) ||
1315 LINE_OVERLAP(cursor, x1, y2, x2, y2, lw) ||
1316 LINE_OVERLAP(cursor, x1, y1, x1, y2, lw))
1317 {
1318 rfbSpriteRemoveCursor (pDrawable->pScreen);
1319 break;
1320 }
1321 }
1322 }
1323
1324 GC_OP_PROLOGUE (pGC);
1325
1326 (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, pRects);
1327
1328 GC_OP_EPILOGUE (pGC);
1329 }
1330
1331 static void
rfbSpritePolyArc(pDrawable,pGC,narcs,parcs)1332 rfbSpritePolyArc(pDrawable, pGC, narcs, parcs)
1333 DrawablePtr pDrawable;
1334 register GCPtr pGC;
1335 int narcs;
1336 xArc *parcs;
1337 {
1338 BoxPtr cursor;
1339 int lw;
1340 int n;
1341 register xArc *arcs;
1342
1343 GC_SETUP (pDrawable, pGC);
1344
1345 if (GC_CHECK((WindowPtr) pDrawable))
1346 {
1347 lw = pGC->lineWidth >> 1;
1348 cursor = &pScreenPriv->saved;
1349 for (arcs = parcs, n = narcs; n--; arcs++)
1350 {
1351 if (ORG_OVERLAP (cursor, pDrawable->x, pDrawable->y,
1352 arcs->x - lw, arcs->y - lw,
1353 (int) arcs->width + pGC->lineWidth,
1354 (int) arcs->height + pGC->lineWidth))
1355 {
1356 rfbSpriteRemoveCursor (pDrawable->pScreen);
1357 break;
1358 }
1359 }
1360 }
1361
1362 GC_OP_PROLOGUE (pGC);
1363
1364 (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, parcs);
1365
1366 GC_OP_EPILOGUE (pGC);
1367 }
1368
1369 static void
rfbSpriteFillPolygon(pDrawable,pGC,shape,mode,count,pPts)1370 rfbSpriteFillPolygon(pDrawable, pGC, shape, mode, count, pPts)
1371 register DrawablePtr pDrawable;
1372 register GCPtr pGC;
1373 int shape, mode;
1374 int count;
1375 DDXPointPtr pPts;
1376 {
1377 int x, y, minx, miny, maxx, maxy;
1378 register DDXPointPtr pts;
1379 int n;
1380
1381 GC_SETUP (pDrawable, pGC);
1382
1383 if (count && GC_CHECK((WindowPtr) pDrawable))
1384 {
1385 x = pDrawable->x;
1386 y = pDrawable->y;
1387 pts = pPts;
1388 minx = maxx = pts->x;
1389 miny = maxy = pts->y;
1390 pts++;
1391 n = count - 1;
1392
1393 if (mode == CoordModeOrigin)
1394 {
1395 for (; n--; pts++)
1396 {
1397 if (pts->x < minx)
1398 minx = pts->x;
1399 else if (pts->x > maxx)
1400 maxx = pts->x;
1401 if (pts->y < miny)
1402 miny = pts->y;
1403 else if (pts->y > maxy)
1404 maxy = pts->y;
1405 }
1406 minx += x;
1407 miny += y;
1408 maxx += x;
1409 maxy += y;
1410 }
1411 else
1412 {
1413 x += minx;
1414 y += miny;
1415 minx = maxx = x;
1416 miny = maxy = y;
1417 for (; n--; pts++)
1418 {
1419 x += pts->x;
1420 y += pts->y;
1421 if (x < minx)
1422 minx = x;
1423 else if (x > maxx)
1424 maxx = x;
1425 if (y < miny)
1426 miny = y;
1427 else if (y > maxy)
1428 maxy = y;
1429 }
1430 }
1431 if (BOX_OVERLAP(&pScreenPriv->saved,minx,miny,maxx,maxy))
1432 rfbSpriteRemoveCursor (pDrawable->pScreen);
1433 }
1434
1435 GC_OP_PROLOGUE (pGC);
1436
1437 (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pPts);
1438
1439 GC_OP_EPILOGUE (pGC);
1440 }
1441
1442 static void
rfbSpritePolyFillRect(pDrawable,pGC,nrectFill,prectInit)1443 rfbSpritePolyFillRect(pDrawable, pGC, nrectFill, prectInit)
1444 DrawablePtr pDrawable;
1445 GCPtr pGC;
1446 int nrectFill; /* number of rectangles to fill */
1447 xRectangle *prectInit; /* Pointer to first rectangle to fill */
1448 {
1449 GC_SETUP(pDrawable, pGC);
1450
1451 if (GC_CHECK((WindowPtr) pDrawable))
1452 {
1453 register int nRect;
1454 register xRectangle *pRect;
1455 register int xorg, yorg;
1456
1457 xorg = pDrawable->x;
1458 yorg = pDrawable->y;
1459
1460 for (nRect = nrectFill, pRect = prectInit; nRect--; pRect++) {
1461 if (ORGRECT_OVERLAP(&pScreenPriv->saved,xorg,yorg,pRect)){
1462 rfbSpriteRemoveCursor(pDrawable->pScreen);
1463 break;
1464 }
1465 }
1466 }
1467
1468 GC_OP_PROLOGUE (pGC);
1469
1470 (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrectFill, prectInit);
1471
1472 GC_OP_EPILOGUE (pGC);
1473 }
1474
1475 static void
rfbSpritePolyFillArc(pDrawable,pGC,narcs,parcs)1476 rfbSpritePolyFillArc(pDrawable, pGC, narcs, parcs)
1477 DrawablePtr pDrawable;
1478 GCPtr pGC;
1479 int narcs;
1480 xArc *parcs;
1481 {
1482 GC_SETUP(pDrawable, pGC);
1483
1484 if (GC_CHECK((WindowPtr) pDrawable))
1485 {
1486 register int n;
1487 BoxPtr cursor;
1488 register xArc *arcs;
1489
1490 cursor = &pScreenPriv->saved;
1491
1492 for (arcs = parcs, n = narcs; n--; arcs++)
1493 {
1494 if (ORG_OVERLAP(cursor, pDrawable->x, pDrawable->y,
1495 arcs->x, arcs->y,
1496 (int) arcs->width, (int) arcs->height))
1497 {
1498 rfbSpriteRemoveCursor (pDrawable->pScreen);
1499 break;
1500 }
1501 }
1502 }
1503
1504 GC_OP_PROLOGUE (pGC);
1505
1506 (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, parcs);
1507
1508 GC_OP_EPILOGUE (pGC);
1509 }
1510
1511 /*
1512 * general Poly/Image text function. Extract glyph information,
1513 * compute bounding box and remove cursor if it is overlapped.
1514 */
1515
1516 static Bool
rfbSpriteTextOverlap(pDraw,font,x,y,n,charinfo,imageblt,w,cursorBox)1517 rfbSpriteTextOverlap (pDraw, font, x, y, n, charinfo, imageblt, w, cursorBox)
1518 DrawablePtr pDraw;
1519 FontPtr font;
1520 int x, y;
1521 unsigned int n;
1522 CharInfoPtr *charinfo;
1523 Bool imageblt;
1524 unsigned int w;
1525 BoxPtr cursorBox;
1526 {
1527 ExtentInfoRec extents;
1528
1529 x += pDraw->x;
1530 y += pDraw->y;
1531
1532 if (FONTMINBOUNDS(font,characterWidth) >= 0)
1533 {
1534 /* compute an approximate (but covering) bounding box */
1535 if (!imageblt || (charinfo[0]->metrics.leftSideBearing < 0))
1536 extents.overallLeft = charinfo[0]->metrics.leftSideBearing;
1537 else
1538 extents.overallLeft = 0;
1539 if (w)
1540 extents.overallRight = w - charinfo[n-1]->metrics.characterWidth;
1541 else
1542 extents.overallRight = FONTMAXBOUNDS(font,characterWidth)
1543 * (n - 1);
1544 if (imageblt && (charinfo[n-1]->metrics.characterWidth >
1545 charinfo[n-1]->metrics.rightSideBearing))
1546 extents.overallRight += charinfo[n-1]->metrics.characterWidth;
1547 else
1548 extents.overallRight += charinfo[n-1]->metrics.rightSideBearing;
1549 if (imageblt && FONTASCENT(font) > FONTMAXBOUNDS(font,ascent))
1550 extents.overallAscent = FONTASCENT(font);
1551 else
1552 extents.overallAscent = FONTMAXBOUNDS(font, ascent);
1553 if (imageblt && FONTDESCENT(font) > FONTMAXBOUNDS(font,descent))
1554 extents.overallDescent = FONTDESCENT(font);
1555 else
1556 extents.overallDescent = FONTMAXBOUNDS(font,descent);
1557 if (!BOX_OVERLAP(cursorBox,
1558 x + extents.overallLeft,
1559 y - extents.overallAscent,
1560 x + extents.overallRight,
1561 y + extents.overallDescent))
1562 return FALSE;
1563 else if (imageblt && w)
1564 return TRUE;
1565 /* if it does overlap, fall through and compute exactly, because
1566 * taking down the cursor is expensive enough to make this worth it
1567 */
1568 }
1569 QueryGlyphExtents(font, charinfo, n, &extents);
1570 if (imageblt)
1571 {
1572 if (extents.overallWidth > extents.overallRight)
1573 extents.overallRight = extents.overallWidth;
1574 if (extents.overallWidth < extents.overallLeft)
1575 extents.overallLeft = extents.overallWidth;
1576 if (extents.overallLeft > 0)
1577 extents.overallLeft = 0;
1578 if (extents.fontAscent > extents.overallAscent)
1579 extents.overallAscent = extents.fontAscent;
1580 if (extents.fontDescent > extents.overallDescent)
1581 extents.overallDescent = extents.fontDescent;
1582 }
1583 return (BOX_OVERLAP(cursorBox,
1584 x + extents.overallLeft,
1585 y - extents.overallAscent,
1586 x + extents.overallRight,
1587 y + extents.overallDescent));
1588 }
1589
1590 /*
1591 * values for textType:
1592 */
1593 #define TT_POLY8 0
1594 #define TT_IMAGE8 1
1595 #define TT_POLY16 2
1596 #define TT_IMAGE16 3
1597
1598 static int
rfbSpriteText(pDraw,pGC,x,y,count,chars,fontEncoding,textType,cursorBox)1599 rfbSpriteText (pDraw, pGC, x, y, count, chars, fontEncoding, textType, cursorBox)
1600 DrawablePtr pDraw;
1601 GCPtr pGC;
1602 int x,
1603 y;
1604 unsigned long count;
1605 char *chars;
1606 FontEncoding fontEncoding;
1607 Bool textType;
1608 BoxPtr cursorBox;
1609 {
1610 CharInfoPtr *charinfo;
1611 register CharInfoPtr *info;
1612 unsigned long i;
1613 unsigned int n;
1614 int w;
1615 void (*drawFunc)();
1616
1617 Bool imageblt;
1618
1619 imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16);
1620
1621 charinfo = (CharInfoPtr *) ALLOCATE_LOCAL(count * sizeof(CharInfoPtr));
1622 if (!charinfo)
1623 return x;
1624
1625 GetGlyphs(pGC->font, count, (unsigned char *)chars,
1626 fontEncoding, &i, charinfo);
1627 n = (unsigned int)i;
1628 w = 0;
1629 if (!imageblt)
1630 for (info = charinfo; i--; info++)
1631 w += (*info)->metrics.characterWidth;
1632
1633 if (n != 0) {
1634 if (rfbSpriteTextOverlap(pDraw, pGC->font, x, y, n, charinfo, imageblt, w, cursorBox))
1635 rfbSpriteRemoveCursor(pDraw->pScreen);
1636
1637 #ifdef AVOID_GLYPHBLT
1638 /*
1639 * On displays like Apollos, which do not optimize the GlyphBlt functions because they
1640 * convert fonts to their internal form in RealizeFont and optimize text directly, we
1641 * want to invoke the text functions here, not the GlyphBlt functions.
1642 */
1643 switch (textType)
1644 {
1645 case TT_POLY8:
1646 drawFunc = (void (*)())pGC->ops->PolyText8;
1647 break;
1648 case TT_IMAGE8:
1649 drawFunc = pGC->ops->ImageText8;
1650 break;
1651 case TT_POLY16:
1652 drawFunc = (void (*)())pGC->ops->PolyText16;
1653 break;
1654 case TT_IMAGE16:
1655 drawFunc = pGC->ops->ImageText16;
1656 break;
1657 }
1658 (*drawFunc) (pDraw, pGC, x, y, (int) count, chars);
1659 #else /* don't AVOID_GLYPHBLT */
1660 /*
1661 * On the other hand, if the device does use GlyphBlt ultimately to do text, we
1662 * don't want to slow it down by invoking the text functions and having them call
1663 * GetGlyphs all over again, so we go directly to the GlyphBlt functions here.
1664 */
1665 drawFunc = imageblt ? pGC->ops->ImageGlyphBlt : pGC->ops->PolyGlyphBlt;
1666 (*drawFunc) (pDraw, pGC, x, y, n, charinfo, FONTGLYPHS(pGC->font));
1667 #endif /* AVOID_GLYPHBLT */
1668 }
1669 DEALLOCATE_LOCAL(charinfo);
1670 return x + w;
1671 }
1672
1673 static int
rfbSpritePolyText8(pDrawable,pGC,x,y,count,chars)1674 rfbSpritePolyText8(pDrawable, pGC, x, y, count, chars)
1675 DrawablePtr pDrawable;
1676 GCPtr pGC;
1677 int x, y;
1678 int count;
1679 char *chars;
1680 {
1681 int ret;
1682
1683 GC_SETUP (pDrawable, pGC);
1684
1685 GC_OP_PROLOGUE (pGC);
1686
1687 if (GC_CHECK((WindowPtr) pDrawable))
1688 ret = rfbSpriteText (pDrawable, pGC, x, y, (unsigned long)count, chars,
1689 Linear8Bit, TT_POLY8, &pScreenPriv->saved);
1690 else
1691 ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);
1692
1693 GC_OP_EPILOGUE (pGC);
1694 return ret;
1695 }
1696
1697 static int
rfbSpritePolyText16(pDrawable,pGC,x,y,count,chars)1698 rfbSpritePolyText16(pDrawable, pGC, x, y, count, chars)
1699 DrawablePtr pDrawable;
1700 GCPtr pGC;
1701 int x, y;
1702 int count;
1703 unsigned short *chars;
1704 {
1705 int ret;
1706
1707 GC_SETUP(pDrawable, pGC);
1708
1709 GC_OP_PROLOGUE (pGC);
1710
1711 if (GC_CHECK((WindowPtr) pDrawable))
1712 ret = rfbSpriteText (pDrawable, pGC, x, y, (unsigned long)count,
1713 (char *)chars,
1714 FONTLASTROW(pGC->font) == 0 ?
1715 Linear16Bit : TwoD16Bit, TT_POLY16, &pScreenPriv->saved);
1716 else
1717 ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);
1718
1719 GC_OP_EPILOGUE (pGC);
1720 return ret;
1721 }
1722
1723 static void
rfbSpriteImageText8(pDrawable,pGC,x,y,count,chars)1724 rfbSpriteImageText8(pDrawable, pGC, x, y, count, chars)
1725 DrawablePtr pDrawable;
1726 GCPtr pGC;
1727 int x, y;
1728 int count;
1729 char *chars;
1730 {
1731 GC_SETUP(pDrawable, pGC);
1732
1733 GC_OP_PROLOGUE (pGC);
1734
1735 if (GC_CHECK((WindowPtr) pDrawable))
1736 (void) rfbSpriteText (pDrawable, pGC, x, y, (unsigned long)count,
1737 chars, Linear8Bit, TT_IMAGE8, &pScreenPriv->saved);
1738 else
1739 (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);
1740
1741 GC_OP_EPILOGUE (pGC);
1742 }
1743
1744 static void
rfbSpriteImageText16(pDrawable,pGC,x,y,count,chars)1745 rfbSpriteImageText16(pDrawable, pGC, x, y, count, chars)
1746 DrawablePtr pDrawable;
1747 GCPtr pGC;
1748 int x, y;
1749 int count;
1750 unsigned short *chars;
1751 {
1752 GC_SETUP(pDrawable, pGC);
1753
1754 GC_OP_PROLOGUE (pGC);
1755
1756 if (GC_CHECK((WindowPtr) pDrawable))
1757 (void) rfbSpriteText (pDrawable, pGC, x, y, (unsigned long)count,
1758 (char *)chars,
1759 FONTLASTROW(pGC->font) == 0 ?
1760 Linear16Bit : TwoD16Bit, TT_IMAGE16, &pScreenPriv->saved);
1761 else
1762 (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);
1763
1764 GC_OP_EPILOGUE (pGC);
1765 }
1766
1767 static void
rfbSpriteImageGlyphBlt(pDrawable,pGC,x,y,nglyph,ppci,pglyphBase)1768 rfbSpriteImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
1769 DrawablePtr pDrawable;
1770 GCPtr pGC;
1771 int x, y;
1772 unsigned int nglyph;
1773 CharInfoPtr *ppci; /* array of character info */
1774 pointer pglyphBase; /* start of array of glyphs */
1775 {
1776 GC_SETUP(pDrawable, pGC);
1777
1778 GC_OP_PROLOGUE (pGC);
1779
1780 if (GC_CHECK((WindowPtr) pDrawable) &&
1781 rfbSpriteTextOverlap (pDrawable, pGC->font, x, y, nglyph, ppci, TRUE, 0, &pScreenPriv->saved))
1782 {
1783 rfbSpriteRemoveCursor(pDrawable->pScreen);
1784 }
1785 (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
1786
1787 GC_OP_EPILOGUE (pGC);
1788 }
1789
1790 static void
rfbSpritePolyGlyphBlt(pDrawable,pGC,x,y,nglyph,ppci,pglyphBase)1791 rfbSpritePolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
1792 DrawablePtr pDrawable;
1793 GCPtr pGC;
1794 int x, y;
1795 unsigned int nglyph;
1796 CharInfoPtr *ppci; /* array of character info */
1797 pointer pglyphBase; /* start of array of glyphs */
1798 {
1799 GC_SETUP (pDrawable, pGC);
1800
1801 GC_OP_PROLOGUE (pGC);
1802
1803 if (GC_CHECK((WindowPtr) pDrawable) &&
1804 rfbSpriteTextOverlap (pDrawable, pGC->font, x, y, nglyph, ppci, FALSE, 0, &pScreenPriv->saved))
1805 {
1806 rfbSpriteRemoveCursor(pDrawable->pScreen);
1807 }
1808 (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
1809
1810 GC_OP_EPILOGUE (pGC);
1811 }
1812
1813 static void
rfbSpritePushPixels(pGC,pBitMap,pDrawable,w,h,x,y)1814 rfbSpritePushPixels(pGC, pBitMap, pDrawable, w, h, x, y)
1815 GCPtr pGC;
1816 PixmapPtr pBitMap;
1817 DrawablePtr pDrawable;
1818 int w, h, x, y;
1819 {
1820 GC_SETUP(pDrawable, pGC);
1821
1822 if (GC_CHECK((WindowPtr) pDrawable) &&
1823 ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y,x,y,w,h))
1824 {
1825 rfbSpriteRemoveCursor (pDrawable->pScreen);
1826 }
1827
1828 GC_OP_PROLOGUE (pGC);
1829
1830 (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, w, h, x, y);
1831
1832 GC_OP_EPILOGUE (pGC);
1833 }
1834
1835 #ifdef NEED_LINEHELPER
1836 /*
1837 * I don't expect this routine will ever be called, as the GC
1838 * will have been unwrapped for the line drawing
1839 */
1840
1841 static void
rfbSpriteLineHelper()1842 rfbSpriteLineHelper()
1843 {
1844 FatalError("rfbSpriteLineHelper called\n");
1845 }
1846 #endif
1847
1848 /*
1849 * miPointer interface routines
1850 */
1851
1852 static Bool
rfbSpriteRealizeCursor(pScreen,pCursor)1853 rfbSpriteRealizeCursor (pScreen, pCursor)
1854 ScreenPtr pScreen;
1855 CursorPtr pCursor;
1856 {
1857 rfbSpriteScreenPtr pScreenPriv;
1858
1859 pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr;
1860 if (pCursor == pScreenPriv->pCursor)
1861 pScreenPriv->checkPixels = TRUE;
1862 return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor);
1863 }
1864
1865 static Bool
rfbSpriteUnrealizeCursor(pScreen,pCursor)1866 rfbSpriteUnrealizeCursor (pScreen, pCursor)
1867 ScreenPtr pScreen;
1868 CursorPtr pCursor;
1869 {
1870 rfbSpriteScreenPtr pScreenPriv;
1871
1872 pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr;
1873 return (*pScreenPriv->funcs->UnrealizeCursor) (pScreen, pCursor);
1874 }
1875
1876 static void
rfbSpriteSetCursor(pScreen,pCursor,x,y)1877 rfbSpriteSetCursor (pScreen, pCursor, x, y)
1878 ScreenPtr pScreen;
1879 CursorPtr pCursor;
1880 {
1881 rfbSpriteScreenPtr pScreenPriv;
1882 rfbClientPtr cl, nextCl;
1883
1884 pScreenPriv
1885 = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr;
1886
1887 if (pScreenPriv->x == x &&
1888 pScreenPriv->y == y &&
1889 pScreenPriv->pCursor == pCursor &&
1890 !pScreenPriv->checkPixels)
1891 {
1892 return;
1893 }
1894
1895 if (rfbScreen.cursorIsDrawn)
1896 rfbSpriteRemoveCursor (pScreen);
1897
1898 pScreenPriv->x = x;
1899 pScreenPriv->y = y;
1900 pScreenPriv->pCursor = pCursor;
1901
1902 for (cl = rfbClientHead; cl; cl = nextCl) {
1903 nextCl = cl->next;
1904 if (cl->enableCursorPosUpdates) {
1905 if (x == cl->cursorX && y == cl->cursorY) {
1906 cl->cursorWasMoved = FALSE;
1907 continue;
1908 }
1909 cl->cursorWasMoved = TRUE;
1910 }
1911 if ( !cl->deferredUpdateScheduled &&
1912 REGION_NOTEMPTY(pScreen,&cl->requestedRegion) ) {
1913 /* cursorIsDrawn is guaranteed to be FALSE here, so we definitely
1914 want to send a screen update to the client, even if that's only
1915 putting up the cursor */
1916 rfbSendFramebufferUpdate(cl);
1917 }
1918 }
1919 }
1920
1921 static void
rfbSpriteMoveCursor(pScreen,x,y)1922 rfbSpriteMoveCursor (pScreen, x, y)
1923 ScreenPtr pScreen;
1924 int x, y;
1925 {
1926 rfbSpriteScreenPtr pScreenPriv;
1927
1928 pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr;
1929 rfbSpriteSetCursor (pScreen, pScreenPriv->pCursor, x, y);
1930 }
1931
1932 /*
1933 * undraw/draw cursor
1934 */
1935
1936 void
rfbSpriteRemoveCursor(pScreen)1937 rfbSpriteRemoveCursor (pScreen)
1938 ScreenPtr pScreen;
1939 {
1940 rfbSpriteScreenPtr pScreenPriv;
1941
1942 if (!rfbScreen.cursorIsDrawn)
1943 return;
1944
1945 pScreenPriv
1946 = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr;
1947
1948 rfbScreen.dontSendFramebufferUpdate = TRUE;
1949 rfbScreen.cursorIsDrawn = FALSE;
1950 pScreenPriv->pCacheWin = NullWindow;
1951 if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pScreen,
1952 pScreenPriv->saved.x1,
1953 pScreenPriv->saved.y1,
1954 pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
1955 pScreenPriv->saved.y2 - pScreenPriv->saved.y1))
1956 {
1957 rfbScreen.cursorIsDrawn = TRUE;
1958 }
1959 rfbScreen.dontSendFramebufferUpdate = FALSE;
1960 }
1961
1962
1963 void
rfbSpriteRestoreCursor(pScreen)1964 rfbSpriteRestoreCursor (pScreen)
1965 ScreenPtr pScreen;
1966 {
1967 rfbSpriteScreenPtr pScreenPriv;
1968 int x, y;
1969 CursorPtr pCursor;
1970
1971 pScreenPriv
1972 = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr;
1973 pCursor = pScreenPriv->pCursor;
1974
1975 if (rfbScreen.cursorIsDrawn || !pCursor)
1976 return;
1977
1978 rfbScreen.dontSendFramebufferUpdate = TRUE;
1979
1980 rfbSpriteComputeSaved (pScreen);
1981
1982 x = pScreenPriv->x - (int)pCursor->bits->xhot;
1983 y = pScreenPriv->y - (int)pCursor->bits->yhot;
1984 if ((*pScreenPriv->funcs->SaveUnderCursor) (pScreen,
1985 pScreenPriv->saved.x1,
1986 pScreenPriv->saved.y1,
1987 pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
1988 pScreenPriv->saved.y2 - pScreenPriv->saved.y1))
1989 {
1990 if (pScreenPriv->checkPixels)
1991 rfbSpriteFindColors (pScreen);
1992 if ((*pScreenPriv->funcs->PutUpCursor) (pScreen, pCursor, x, y,
1993 pScreenPriv->colors[SOURCE_COLOR].pixel,
1994 pScreenPriv->colors[MASK_COLOR].pixel))
1995 rfbScreen.cursorIsDrawn = TRUE;
1996 }
1997
1998 rfbScreen.dontSendFramebufferUpdate = FALSE;
1999 }
2000
2001 /*
2002 * compute the desired area of the screen to save
2003 */
2004
2005 static void
rfbSpriteComputeSaved(pScreen)2006 rfbSpriteComputeSaved (pScreen)
2007 ScreenPtr pScreen;
2008 {
2009 rfbSpriteScreenPtr pScreenPriv;
2010 int x, y, w, h;
2011 CursorPtr pCursor;
2012
2013 pScreenPriv = (rfbSpriteScreenPtr) pScreen->devPrivates[rfbSpriteScreenIndex].ptr;
2014 pCursor = pScreenPriv->pCursor;
2015 x = pScreenPriv->x - (int)pCursor->bits->xhot;
2016 y = pScreenPriv->y - (int)pCursor->bits->yhot;
2017 w = pCursor->bits->width;
2018 h = pCursor->bits->height;
2019 pScreenPriv->saved.x1 = x;
2020 pScreenPriv->saved.y1 = y;
2021 pScreenPriv->saved.x2 = pScreenPriv->saved.x1 + w;
2022 pScreenPriv->saved.y2 = pScreenPriv->saved.y1 + h;
2023 }
2024
2025
2026 /*
2027 * this function is called when the cursor shape is being changed
2028 */
2029
2030 static Bool
rfbDisplayCursor(pScreen,pCursor)2031 rfbDisplayCursor(pScreen, pCursor)
2032 ScreenPtr pScreen;
2033 CursorPtr pCursor;
2034 {
2035 rfbClientPtr cl;
2036 rfbSpriteScreenPtr pPriv;
2037 Bool result;
2038
2039 pPriv = (rfbSpriteScreenPtr)pScreen->devPrivates[rfbSpriteScreenIndex].ptr;
2040 result = (*pPriv->DisplayCursor)(pScreen, pCursor);
2041
2042 for (cl = rfbClientHead; cl; cl = cl->next) {
2043 if (cl->enableCursorShapeUpdates) {
2044 cl->cursorWasChanged = TRUE;
2045 if ( !cl->deferredUpdateScheduled &&
2046 REGION_NOTEMPTY(pScreen,&cl->requestedRegion) ) {
2047 rfbSendFramebufferUpdate(cl);
2048 }
2049 }
2050 }
2051
2052 return result;
2053 }
2054
2055
2056 /*
2057 * obtain current cursor pointer
2058 */
2059
2060 CursorPtr
rfbSpriteGetCursorPtr(pScreen)2061 rfbSpriteGetCursorPtr (pScreen)
2062 ScreenPtr pScreen;
2063 {
2064 rfbSpriteScreenPtr pScreenPriv;
2065
2066 pScreenPriv = (rfbSpriteScreenPtr)
2067 pScreen->devPrivates[rfbSpriteScreenIndex].ptr;
2068
2069 return pScreenPriv->pCursor;
2070 }
2071
2072 /*
2073 * obtain current cursor position
2074 */
2075
2076 void
rfbSpriteGetCursorPos(pScreen,px,py)2077 rfbSpriteGetCursorPos (pScreen, px, py)
2078 ScreenPtr pScreen;
2079 int *px, *py;
2080 {
2081 rfbSpriteScreenPtr pScreenPriv;
2082
2083 pScreenPriv = (rfbSpriteScreenPtr)
2084 pScreen->devPrivates[rfbSpriteScreenIndex].ptr;
2085
2086 *px = pScreenPriv->x;
2087 *py = pScreenPriv->y;
2088 }
2089
2090