xref: /OK3568_Linux_fs/external/xserver/mi/midispcur.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * midispcur.c
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * machine independent cursor display routines
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun /*
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun Copyright 1989, 1998  The Open Group
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun Permission to use, copy, modify, distribute, and sell this software and its
12*4882a593Smuzhiyun documentation for any purpose is hereby granted without fee, provided that
13*4882a593Smuzhiyun the above copyright notice appear in all copies and that both that
14*4882a593Smuzhiyun copyright notice and this permission notice appear in supporting
15*4882a593Smuzhiyun documentation.
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun The above copyright notice and this permission notice shall be included in
18*4882a593Smuzhiyun all copies or substantial portions of the Software.
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21*4882a593Smuzhiyun IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22*4882a593Smuzhiyun FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
23*4882a593Smuzhiyun OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
24*4882a593Smuzhiyun AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25*4882a593Smuzhiyun CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun Except as contained in this notice, the name of The Open Group shall not be
28*4882a593Smuzhiyun used in advertising or otherwise to promote the sale, use or other dealings
29*4882a593Smuzhiyun in this Software without prior written authorization from The Open Group.
30*4882a593Smuzhiyun */
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
33*4882a593Smuzhiyun #include <dix-config.h>
34*4882a593Smuzhiyun #endif
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun #include   <X11/X.h>
37*4882a593Smuzhiyun #include   "misc.h"
38*4882a593Smuzhiyun #include   "input.h"
39*4882a593Smuzhiyun #include   "cursorstr.h"
40*4882a593Smuzhiyun #include   "windowstr.h"
41*4882a593Smuzhiyun #include   "regionstr.h"
42*4882a593Smuzhiyun #include   "dixstruct.h"
43*4882a593Smuzhiyun #include   "scrnintstr.h"
44*4882a593Smuzhiyun #include   "servermd.h"
45*4882a593Smuzhiyun #include   "mipointer.h"
46*4882a593Smuzhiyun #include   "misprite.h"
47*4882a593Smuzhiyun #include   "gcstruct.h"
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun #include   "picturestr.h"
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun #include "inputstr.h"
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun /* per-screen private data */
54*4882a593Smuzhiyun static DevPrivateKeyRec miDCScreenKeyRec;
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun #define miDCScreenKey (&miDCScreenKeyRec)
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun static DevScreenPrivateKeyRec miDCDeviceKeyRec;
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun #define miDCDeviceKey (&miDCDeviceKeyRec)
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun static Bool miDCCloseScreen(ScreenPtr pScreen);
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun /* per device private data */
65*4882a593Smuzhiyun typedef struct {
66*4882a593Smuzhiyun     GCPtr pSourceGC, pMaskGC;
67*4882a593Smuzhiyun     GCPtr pSaveGC, pRestoreGC;
68*4882a593Smuzhiyun     PixmapPtr pSave;
69*4882a593Smuzhiyun     PicturePtr pRootPicture;
70*4882a593Smuzhiyun } miDCBufferRec, *miDCBufferPtr;
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun #define miGetDCDevice(dev, screen) \
73*4882a593Smuzhiyun  ((DevHasCursor(dev)) ? \
74*4882a593Smuzhiyun   (miDCBufferPtr)dixLookupScreenPrivate(&dev->devPrivates, miDCDeviceKey, screen) : \
75*4882a593Smuzhiyun   (miDCBufferPtr)dixLookupScreenPrivate(&GetMaster(dev, MASTER_POINTER)->devPrivates, miDCDeviceKey, screen))
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun /*
78*4882a593Smuzhiyun  * The core pointer buffer will point to the index of the virtual pointer
79*4882a593Smuzhiyun  * in the pCursorBuffers array.
80*4882a593Smuzhiyun  */
81*4882a593Smuzhiyun typedef struct {
82*4882a593Smuzhiyun     CloseScreenProcPtr CloseScreen;
83*4882a593Smuzhiyun     PixmapPtr sourceBits;       /* source bits */
84*4882a593Smuzhiyun     PixmapPtr maskBits;         /* mask bits */
85*4882a593Smuzhiyun     PicturePtr pPicture;
86*4882a593Smuzhiyun     CursorPtr pCursor;
87*4882a593Smuzhiyun } miDCScreenRec, *miDCScreenPtr;
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun #define miGetDCScreen(s)	((miDCScreenPtr)(dixLookupPrivate(&(s)->devPrivates, miDCScreenKey)))
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun Bool
miDCInitialize(ScreenPtr pScreen,miPointerScreenFuncPtr screenFuncs)92*4882a593Smuzhiyun miDCInitialize(ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun     miDCScreenPtr pScreenPriv;
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun     if (!dixRegisterPrivateKey(&miDCScreenKeyRec, PRIVATE_SCREEN, 0) ||
97*4882a593Smuzhiyun         !dixRegisterScreenPrivateKey(&miDCDeviceKeyRec, pScreen, PRIVATE_DEVICE,
98*4882a593Smuzhiyun                                      0))
99*4882a593Smuzhiyun         return FALSE;
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun     pScreenPriv = calloc(1, sizeof(miDCScreenRec));
102*4882a593Smuzhiyun     if (!pScreenPriv)
103*4882a593Smuzhiyun         return FALSE;
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun     pScreenPriv->CloseScreen = pScreen->CloseScreen;
106*4882a593Smuzhiyun     pScreen->CloseScreen = miDCCloseScreen;
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun     dixSetPrivate(&pScreen->devPrivates, miDCScreenKey, pScreenPriv);
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun     if (!miSpriteInitialize(pScreen, screenFuncs)) {
111*4882a593Smuzhiyun         free((void *) pScreenPriv);
112*4882a593Smuzhiyun         return FALSE;
113*4882a593Smuzhiyun     }
114*4882a593Smuzhiyun     return TRUE;
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun static void
miDCSwitchScreenCursor(ScreenPtr pScreen,CursorPtr pCursor,PixmapPtr sourceBits,PixmapPtr maskBits,PicturePtr pPicture)118*4882a593Smuzhiyun miDCSwitchScreenCursor(ScreenPtr pScreen, CursorPtr pCursor, PixmapPtr sourceBits, PixmapPtr maskBits, PicturePtr pPicture)
119*4882a593Smuzhiyun {
120*4882a593Smuzhiyun     miDCScreenPtr pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey);
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun     if (pScreenPriv->sourceBits)
123*4882a593Smuzhiyun         (*pScreen->DestroyPixmap)(pScreenPriv->sourceBits);
124*4882a593Smuzhiyun     pScreenPriv->sourceBits = sourceBits;
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun     if (pScreenPriv->maskBits)
127*4882a593Smuzhiyun         (*pScreen->DestroyPixmap)(pScreenPriv->maskBits);
128*4882a593Smuzhiyun     pScreenPriv->maskBits = maskBits;
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun     if (pScreenPriv->pPicture)
131*4882a593Smuzhiyun         FreePicture(pScreenPriv->pPicture, 0);
132*4882a593Smuzhiyun     pScreenPriv->pPicture = pPicture;
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun     pScreenPriv->pCursor = pCursor;
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun static Bool
miDCCloseScreen(ScreenPtr pScreen)138*4882a593Smuzhiyun miDCCloseScreen(ScreenPtr pScreen)
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun     miDCScreenPtr pScreenPriv;
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun     pScreenPriv = (miDCScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
143*4882a593Smuzhiyun                                                    miDCScreenKey);
144*4882a593Smuzhiyun     pScreen->CloseScreen = pScreenPriv->CloseScreen;
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun     miDCSwitchScreenCursor(pScreen, NULL, NULL, NULL, NULL);
147*4882a593Smuzhiyun     free((void *) pScreenPriv);
148*4882a593Smuzhiyun     return (*pScreen->CloseScreen) (pScreen);
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun Bool
miDCRealizeCursor(ScreenPtr pScreen,CursorPtr pCursor)152*4882a593Smuzhiyun miDCRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun     return TRUE;
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun #define EnsurePicture(picture,draw,win) (picture || miDCMakePicture(&picture,draw,win))
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun static PicturePtr
miDCMakePicture(PicturePtr * ppPicture,DrawablePtr pDraw,WindowPtr pWin)160*4882a593Smuzhiyun miDCMakePicture(PicturePtr * ppPicture, DrawablePtr pDraw, WindowPtr pWin)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun     PictFormatPtr pFormat;
163*4882a593Smuzhiyun     XID subwindow_mode = IncludeInferiors;
164*4882a593Smuzhiyun     PicturePtr pPicture;
165*4882a593Smuzhiyun     int error;
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun     pFormat = PictureWindowFormat(pWin);
168*4882a593Smuzhiyun     if (!pFormat)
169*4882a593Smuzhiyun         return 0;
170*4882a593Smuzhiyun     pPicture = CreatePicture(0, pDraw, pFormat,
171*4882a593Smuzhiyun                              CPSubwindowMode, &subwindow_mode,
172*4882a593Smuzhiyun                              serverClient, &error);
173*4882a593Smuzhiyun     *ppPicture = pPicture;
174*4882a593Smuzhiyun     return pPicture;
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun static Bool
miDCRealize(ScreenPtr pScreen,CursorPtr pCursor)178*4882a593Smuzhiyun miDCRealize(ScreenPtr pScreen, CursorPtr pCursor)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun     miDCScreenPtr pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey);
181*4882a593Smuzhiyun     GCPtr pGC;
182*4882a593Smuzhiyun     ChangeGCVal gcvals;
183*4882a593Smuzhiyun     PixmapPtr   sourceBits, maskBits;
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun     if (pScreenPriv->pCursor == pCursor)
186*4882a593Smuzhiyun         return TRUE;
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun     if (pCursor->bits->argb) {
189*4882a593Smuzhiyun         PixmapPtr pPixmap;
190*4882a593Smuzhiyun         PictFormatPtr pFormat;
191*4882a593Smuzhiyun         int error;
192*4882a593Smuzhiyun         PicturePtr  pPicture;
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun         pFormat = PictureMatchFormat(pScreen, 32, PICT_a8r8g8b8);
195*4882a593Smuzhiyun         if (!pFormat)
196*4882a593Smuzhiyun             return FALSE;
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun         pPixmap = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width,
199*4882a593Smuzhiyun                                             pCursor->bits->height, 32,
200*4882a593Smuzhiyun                                             CREATE_PIXMAP_USAGE_SCRATCH);
201*4882a593Smuzhiyun         if (!pPixmap)
202*4882a593Smuzhiyun             return FALSE;
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun         pGC = GetScratchGC(32, pScreen);
205*4882a593Smuzhiyun         if (!pGC) {
206*4882a593Smuzhiyun             (*pScreen->DestroyPixmap) (pPixmap);
207*4882a593Smuzhiyun             return FALSE;
208*4882a593Smuzhiyun         }
209*4882a593Smuzhiyun         ValidateGC(&pPixmap->drawable, pGC);
210*4882a593Smuzhiyun         (*pGC->ops->PutImage) (&pPixmap->drawable, pGC, 32,
211*4882a593Smuzhiyun                                0, 0, pCursor->bits->width,
212*4882a593Smuzhiyun                                pCursor->bits->height,
213*4882a593Smuzhiyun                                0, ZPixmap, (char *) pCursor->bits->argb);
214*4882a593Smuzhiyun         FreeScratchGC(pGC);
215*4882a593Smuzhiyun         pPicture = CreatePicture(0, &pPixmap->drawable,
216*4882a593Smuzhiyun                                  pFormat, 0, 0, serverClient, &error);
217*4882a593Smuzhiyun         (*pScreen->DestroyPixmap) (pPixmap);
218*4882a593Smuzhiyun         if (!pPicture)
219*4882a593Smuzhiyun             return FALSE;
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun         miDCSwitchScreenCursor(pScreen, pCursor, NULL, NULL, pPicture);
222*4882a593Smuzhiyun         return TRUE;
223*4882a593Smuzhiyun     }
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun     sourceBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width,
226*4882a593Smuzhiyun                                            pCursor->bits->height, 1, 0);
227*4882a593Smuzhiyun     if (!sourceBits)
228*4882a593Smuzhiyun         return FALSE;
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun     maskBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width,
231*4882a593Smuzhiyun                                          pCursor->bits->height, 1, 0);
232*4882a593Smuzhiyun     if (!maskBits) {
233*4882a593Smuzhiyun         (*pScreen->DestroyPixmap) (sourceBits);
234*4882a593Smuzhiyun         return FALSE;
235*4882a593Smuzhiyun     }
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun     /* create the two sets of bits, clipping as appropriate */
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun     pGC = GetScratchGC(1, pScreen);
240*4882a593Smuzhiyun     if (!pGC) {
241*4882a593Smuzhiyun         (*pScreen->DestroyPixmap) (sourceBits);
242*4882a593Smuzhiyun         (*pScreen->DestroyPixmap) (maskBits);
243*4882a593Smuzhiyun         return FALSE;
244*4882a593Smuzhiyun     }
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun     ValidateGC((DrawablePtr) sourceBits, pGC);
247*4882a593Smuzhiyun     (*pGC->ops->PutImage) ((DrawablePtr) sourceBits, pGC, 1,
248*4882a593Smuzhiyun                            0, 0, pCursor->bits->width, pCursor->bits->height,
249*4882a593Smuzhiyun                            0, XYPixmap, (char *) pCursor->bits->source);
250*4882a593Smuzhiyun     gcvals.val = GXand;
251*4882a593Smuzhiyun     ChangeGC(NullClient, pGC, GCFunction, &gcvals);
252*4882a593Smuzhiyun     ValidateGC((DrawablePtr) sourceBits, pGC);
253*4882a593Smuzhiyun     (*pGC->ops->PutImage) ((DrawablePtr) sourceBits, pGC, 1,
254*4882a593Smuzhiyun                            0, 0, pCursor->bits->width, pCursor->bits->height,
255*4882a593Smuzhiyun                            0, XYPixmap, (char *) pCursor->bits->mask);
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun     /* mask bits -- pCursor->mask & ~pCursor->source */
258*4882a593Smuzhiyun     gcvals.val = GXcopy;
259*4882a593Smuzhiyun     ChangeGC(NullClient, pGC, GCFunction, &gcvals);
260*4882a593Smuzhiyun     ValidateGC((DrawablePtr) maskBits, pGC);
261*4882a593Smuzhiyun     (*pGC->ops->PutImage) ((DrawablePtr) maskBits, pGC, 1,
262*4882a593Smuzhiyun                            0, 0, pCursor->bits->width, pCursor->bits->height,
263*4882a593Smuzhiyun                            0, XYPixmap, (char *) pCursor->bits->mask);
264*4882a593Smuzhiyun     gcvals.val = GXandInverted;
265*4882a593Smuzhiyun     ChangeGC(NullClient, pGC, GCFunction, &gcvals);
266*4882a593Smuzhiyun     ValidateGC((DrawablePtr) maskBits, pGC);
267*4882a593Smuzhiyun     (*pGC->ops->PutImage) ((DrawablePtr) maskBits, pGC, 1,
268*4882a593Smuzhiyun                            0, 0, pCursor->bits->width, pCursor->bits->height,
269*4882a593Smuzhiyun                            0, XYPixmap, (char *) pCursor->bits->source);
270*4882a593Smuzhiyun     FreeScratchGC(pGC);
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun     miDCSwitchScreenCursor(pScreen, pCursor, sourceBits, maskBits, NULL);
273*4882a593Smuzhiyun     return TRUE;
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun Bool
miDCUnrealizeCursor(ScreenPtr pScreen,CursorPtr pCursor)277*4882a593Smuzhiyun miDCUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
278*4882a593Smuzhiyun {
279*4882a593Smuzhiyun     miDCScreenPtr pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey);
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun     if (pCursor == pScreenPriv->pCursor)
282*4882a593Smuzhiyun         miDCSwitchScreenCursor(pScreen, NULL, NULL, NULL, NULL);
283*4882a593Smuzhiyun     return TRUE;
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun static void
miDCPutBits(DrawablePtr pDrawable,GCPtr sourceGC,GCPtr maskGC,int x_org,int y_org,unsigned w,unsigned h,unsigned long source,unsigned long mask)287*4882a593Smuzhiyun miDCPutBits(DrawablePtr pDrawable,
288*4882a593Smuzhiyun             GCPtr sourceGC,
289*4882a593Smuzhiyun             GCPtr maskGC,
290*4882a593Smuzhiyun             int x_org,
291*4882a593Smuzhiyun             int y_org,
292*4882a593Smuzhiyun             unsigned w, unsigned h, unsigned long source, unsigned long mask)
293*4882a593Smuzhiyun {
294*4882a593Smuzhiyun     miDCScreenPtr pScreenPriv = dixLookupPrivate(&pDrawable->pScreen->devPrivates, miDCScreenKey);
295*4882a593Smuzhiyun     ChangeGCVal gcval;
296*4882a593Smuzhiyun     int x, y;
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun     if (sourceGC->fgPixel != source) {
299*4882a593Smuzhiyun         gcval.val = source;
300*4882a593Smuzhiyun         ChangeGC(NullClient, sourceGC, GCForeground, &gcval);
301*4882a593Smuzhiyun     }
302*4882a593Smuzhiyun     if (sourceGC->serialNumber != pDrawable->serialNumber)
303*4882a593Smuzhiyun         ValidateGC(pDrawable, sourceGC);
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun     if (sourceGC->miTranslate) {
306*4882a593Smuzhiyun         x = pDrawable->x + x_org;
307*4882a593Smuzhiyun         y = pDrawable->y + y_org;
308*4882a593Smuzhiyun     }
309*4882a593Smuzhiyun     else {
310*4882a593Smuzhiyun         x = x_org;
311*4882a593Smuzhiyun         y = y_org;
312*4882a593Smuzhiyun     }
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun     (*sourceGC->ops->PushPixels) (sourceGC, pScreenPriv->sourceBits, pDrawable, w, h,
315*4882a593Smuzhiyun                                   x, y);
316*4882a593Smuzhiyun     if (maskGC->fgPixel != mask) {
317*4882a593Smuzhiyun         gcval.val = mask;
318*4882a593Smuzhiyun         ChangeGC(NullClient, maskGC, GCForeground, &gcval);
319*4882a593Smuzhiyun     }
320*4882a593Smuzhiyun     if (maskGC->serialNumber != pDrawable->serialNumber)
321*4882a593Smuzhiyun         ValidateGC(pDrawable, maskGC);
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun     if (maskGC->miTranslate) {
324*4882a593Smuzhiyun         x = pDrawable->x + x_org;
325*4882a593Smuzhiyun         y = pDrawable->y + y_org;
326*4882a593Smuzhiyun     }
327*4882a593Smuzhiyun     else {
328*4882a593Smuzhiyun         x = x_org;
329*4882a593Smuzhiyun         y = y_org;
330*4882a593Smuzhiyun     }
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun     (*maskGC->ops->PushPixels) (maskGC, pScreenPriv->maskBits, pDrawable, w, h, x, y);
333*4882a593Smuzhiyun }
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun static GCPtr
miDCMakeGC(WindowPtr pWin)336*4882a593Smuzhiyun miDCMakeGC(WindowPtr pWin)
337*4882a593Smuzhiyun {
338*4882a593Smuzhiyun     GCPtr pGC;
339*4882a593Smuzhiyun     int status;
340*4882a593Smuzhiyun     XID gcvals[2];
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun     gcvals[0] = IncludeInferiors;
343*4882a593Smuzhiyun     gcvals[1] = FALSE;
344*4882a593Smuzhiyun     pGC = CreateGC((DrawablePtr) pWin,
345*4882a593Smuzhiyun                    GCSubwindowMode | GCGraphicsExposures, gcvals, &status,
346*4882a593Smuzhiyun                    (XID) 0, serverClient);
347*4882a593Smuzhiyun     return pGC;
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun Bool
miDCPutUpCursor(DeviceIntPtr pDev,ScreenPtr pScreen,CursorPtr pCursor,int x,int y,unsigned long source,unsigned long mask)351*4882a593Smuzhiyun miDCPutUpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
352*4882a593Smuzhiyun                 int x, int y, unsigned long source, unsigned long mask)
353*4882a593Smuzhiyun {
354*4882a593Smuzhiyun     miDCScreenPtr pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey);
355*4882a593Smuzhiyun     miDCBufferPtr pBuffer;
356*4882a593Smuzhiyun     WindowPtr pWin;
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun     if (!miDCRealize(pScreen, pCursor))
359*4882a593Smuzhiyun         return FALSE;
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun     pWin = pScreen->root;
362*4882a593Smuzhiyun     pBuffer = miGetDCDevice(pDev, pScreen);
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun     if (pScreenPriv->pPicture) {
365*4882a593Smuzhiyun         if (!EnsurePicture(pBuffer->pRootPicture, &pWin->drawable, pWin))
366*4882a593Smuzhiyun             return FALSE;
367*4882a593Smuzhiyun         CompositePicture(PictOpOver,
368*4882a593Smuzhiyun                          pScreenPriv->pPicture,
369*4882a593Smuzhiyun                          NULL,
370*4882a593Smuzhiyun                          pBuffer->pRootPicture,
371*4882a593Smuzhiyun                          0, 0, 0, 0,
372*4882a593Smuzhiyun                          x, y, pCursor->bits->width, pCursor->bits->height);
373*4882a593Smuzhiyun     }
374*4882a593Smuzhiyun     else
375*4882a593Smuzhiyun     {
376*4882a593Smuzhiyun         miDCPutBits((DrawablePtr) pWin,
377*4882a593Smuzhiyun                     pBuffer->pSourceGC, pBuffer->pMaskGC,
378*4882a593Smuzhiyun                     x, y, pCursor->bits->width, pCursor->bits->height,
379*4882a593Smuzhiyun                     source, mask);
380*4882a593Smuzhiyun     }
381*4882a593Smuzhiyun     return TRUE;
382*4882a593Smuzhiyun }
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun Bool
miDCSaveUnderCursor(DeviceIntPtr pDev,ScreenPtr pScreen,int x,int y,int w,int h)385*4882a593Smuzhiyun miDCSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
386*4882a593Smuzhiyun                     int x, int y, int w, int h)
387*4882a593Smuzhiyun {
388*4882a593Smuzhiyun     miDCBufferPtr pBuffer;
389*4882a593Smuzhiyun     PixmapPtr pSave;
390*4882a593Smuzhiyun     WindowPtr pWin;
391*4882a593Smuzhiyun     GCPtr pGC;
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun     pBuffer = miGetDCDevice(pDev, pScreen);
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun     pSave = pBuffer->pSave;
396*4882a593Smuzhiyun     pWin = pScreen->root;
397*4882a593Smuzhiyun     if (!pSave || pSave->drawable.width < w || pSave->drawable.height < h) {
398*4882a593Smuzhiyun         if (pSave)
399*4882a593Smuzhiyun             (*pScreen->DestroyPixmap) (pSave);
400*4882a593Smuzhiyun         pBuffer->pSave = pSave =
401*4882a593Smuzhiyun             (*pScreen->CreatePixmap) (pScreen, w, h, pScreen->rootDepth, 0);
402*4882a593Smuzhiyun         if (!pSave)
403*4882a593Smuzhiyun             return FALSE;
404*4882a593Smuzhiyun     }
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun     pGC = pBuffer->pSaveGC;
407*4882a593Smuzhiyun     if (pSave->drawable.serialNumber != pGC->serialNumber)
408*4882a593Smuzhiyun         ValidateGC((DrawablePtr) pSave, pGC);
409*4882a593Smuzhiyun     (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
410*4882a593Smuzhiyun                            x, y, w, h, 0, 0);
411*4882a593Smuzhiyun     return TRUE;
412*4882a593Smuzhiyun }
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun Bool
miDCRestoreUnderCursor(DeviceIntPtr pDev,ScreenPtr pScreen,int x,int y,int w,int h)415*4882a593Smuzhiyun miDCRestoreUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
416*4882a593Smuzhiyun                        int x, int y, int w, int h)
417*4882a593Smuzhiyun {
418*4882a593Smuzhiyun     miDCBufferPtr pBuffer;
419*4882a593Smuzhiyun     PixmapPtr pSave;
420*4882a593Smuzhiyun     WindowPtr pWin;
421*4882a593Smuzhiyun     GCPtr pGC;
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun     pBuffer = miGetDCDevice(pDev, pScreen);
424*4882a593Smuzhiyun     pSave = pBuffer->pSave;
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun     pWin = pScreen->root;
427*4882a593Smuzhiyun     if (!pSave)
428*4882a593Smuzhiyun         return FALSE;
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun     pGC = pBuffer->pRestoreGC;
431*4882a593Smuzhiyun     if (pWin->drawable.serialNumber != pGC->serialNumber)
432*4882a593Smuzhiyun         ValidateGC((DrawablePtr) pWin, pGC);
433*4882a593Smuzhiyun     (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
434*4882a593Smuzhiyun                            0, 0, w, h, x, y);
435*4882a593Smuzhiyun     return TRUE;
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun Bool
miDCDeviceInitialize(DeviceIntPtr pDev,ScreenPtr pScreen)439*4882a593Smuzhiyun miDCDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
440*4882a593Smuzhiyun {
441*4882a593Smuzhiyun     miDCBufferPtr pBuffer;
442*4882a593Smuzhiyun     WindowPtr pWin;
443*4882a593Smuzhiyun     int i;
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun     if (!DevHasCursor(pDev))
446*4882a593Smuzhiyun         return TRUE;
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun     for (i = 0; i < screenInfo.numScreens; i++) {
449*4882a593Smuzhiyun         pScreen = screenInfo.screens[i];
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun         pBuffer = calloc(1, sizeof(miDCBufferRec));
452*4882a593Smuzhiyun         if (!pBuffer)
453*4882a593Smuzhiyun             goto failure;
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun         dixSetScreenPrivate(&pDev->devPrivates, miDCDeviceKey, pScreen,
456*4882a593Smuzhiyun                             pBuffer);
457*4882a593Smuzhiyun         pWin = pScreen->root;
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun         pBuffer->pSourceGC = miDCMakeGC(pWin);
460*4882a593Smuzhiyun         if (!pBuffer->pSourceGC)
461*4882a593Smuzhiyun             goto failure;
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun         pBuffer->pMaskGC = miDCMakeGC(pWin);
464*4882a593Smuzhiyun         if (!pBuffer->pMaskGC)
465*4882a593Smuzhiyun             goto failure;
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun         pBuffer->pSaveGC = miDCMakeGC(pWin);
468*4882a593Smuzhiyun         if (!pBuffer->pSaveGC)
469*4882a593Smuzhiyun             goto failure;
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun         pBuffer->pRestoreGC = miDCMakeGC(pWin);
472*4882a593Smuzhiyun         if (!pBuffer->pRestoreGC)
473*4882a593Smuzhiyun             goto failure;
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun         pBuffer->pRootPicture = NULL;
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun         /* (re)allocated lazily depending on the cursor size */
478*4882a593Smuzhiyun         pBuffer->pSave = NULL;
479*4882a593Smuzhiyun     }
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun     return TRUE;
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun  failure:
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun     miDCDeviceCleanup(pDev, pScreen);
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun     return FALSE;
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun void
miDCDeviceCleanup(DeviceIntPtr pDev,ScreenPtr pScreen)491*4882a593Smuzhiyun miDCDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
492*4882a593Smuzhiyun {
493*4882a593Smuzhiyun     miDCBufferPtr pBuffer;
494*4882a593Smuzhiyun     int i;
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun     if (DevHasCursor(pDev)) {
497*4882a593Smuzhiyun         for (i = 0; i < screenInfo.numScreens; i++) {
498*4882a593Smuzhiyun             pScreen = screenInfo.screens[i];
499*4882a593Smuzhiyun 
500*4882a593Smuzhiyun             pBuffer = miGetDCDevice(pDev, pScreen);
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun             if (pBuffer) {
503*4882a593Smuzhiyun                 if (pBuffer->pSourceGC)
504*4882a593Smuzhiyun                     FreeGC(pBuffer->pSourceGC, (GContext) 0);
505*4882a593Smuzhiyun                 if (pBuffer->pMaskGC)
506*4882a593Smuzhiyun                     FreeGC(pBuffer->pMaskGC, (GContext) 0);
507*4882a593Smuzhiyun                 if (pBuffer->pSaveGC)
508*4882a593Smuzhiyun                     FreeGC(pBuffer->pSaveGC, (GContext) 0);
509*4882a593Smuzhiyun                 if (pBuffer->pRestoreGC)
510*4882a593Smuzhiyun                     FreeGC(pBuffer->pRestoreGC, (GContext) 0);
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun                 /* If a pRootPicture was allocated for a root window, it
513*4882a593Smuzhiyun                  * is freed when that root window is destroyed, so don't
514*4882a593Smuzhiyun                  * free it again here. */
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun                 if (pBuffer->pSave)
517*4882a593Smuzhiyun                     (*pScreen->DestroyPixmap) (pBuffer->pSave);
518*4882a593Smuzhiyun 
519*4882a593Smuzhiyun                 free(pBuffer);
520*4882a593Smuzhiyun                 dixSetScreenPrivate(&pDev->devPrivates, miDCDeviceKey, pScreen,
521*4882a593Smuzhiyun                                     NULL);
522*4882a593Smuzhiyun             }
523*4882a593Smuzhiyun         }
524*4882a593Smuzhiyun     }
525*4882a593Smuzhiyun }
526