xref: /OK3568_Linux_fs/external/xserver/hw/xquartz/xpr/xprCursor.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /**************************************************************
2  *
3  * Xplugin cursor support
4  *
5  * Copyright (c) 2001 Torrey T. Lyons and Greg Parker.
6  * Copyright (c) 2002 Apple Computer, Inc.
7  *                 All Rights Reserved.
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a
10  * copy of this software and associated documentation files (the "Software"),
11  * to deal in the Software without restriction, including without limitation
12  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13  * and/or sell copies of the Software, and to permit persons to whom the
14  * Software is furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included in
17  * all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22  * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
23  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25  * DEALINGS IN THE SOFTWARE.
26  *
27  * Except as contained in this notice, the name(s) of the above copyright
28  * holders shall not be used in advertising or otherwise to promote the sale,
29  * use or other dealings in this Software without prior written authorization.
30  */
31 
32 #include "sanitizedCarbon.h"
33 
34 #ifdef HAVE_DIX_CONFIG_H
35 #include <dix-config.h>
36 #endif
37 
38 #include "quartz.h"
39 #include "xpr.h"
40 #include "darwinEvents.h"
41 #include <Xplugin.h>
42 
43 #include "mi.h"
44 #include "scrnintstr.h"
45 #include "cursorstr.h"
46 #include "mipointrst.h"
47 #include "windowstr.h"
48 #include "globals.h"
49 #include "servermd.h"
50 #include "dixevents.h"
51 #include "x-hash.h"
52 
53 typedef struct {
54     int cursorVisible;
55     QueryBestSizeProcPtr QueryBestSize;
56     miPointerSpriteFuncPtr spriteFuncs;
57 } QuartzCursorScreenRec, *QuartzCursorScreenPtr;
58 
59 static DevPrivateKeyRec darwinCursorScreenKeyRec;
60 #define darwinCursorScreenKey (&darwinCursorScreenKeyRec)
61 
62 #define CURSOR_PRIV(pScreen) ((QuartzCursorScreenPtr) \
63                               dixLookupPrivate(&pScreen->devPrivates, \
64                                                darwinCursorScreenKey))
65 
66 static Bool
load_cursor(CursorPtr src,int screen)67 load_cursor(CursorPtr src, int screen)
68 {
69     uint32_t *data;
70     Bool free_data = FALSE;
71     uint32_t rowbytes;
72     int width, height;
73     int hot_x, hot_y;
74 
75     uint32_t fg_color, bg_color;
76     uint8_t *srow, *sptr;
77     uint8_t *mrow, *mptr;
78     uint32_t *drow, *dptr;
79     unsigned xcount, ycount;
80 
81     xp_error err;
82 
83     width = src->bits->width;
84     height = src->bits->height;
85     hot_x = src->bits->xhot;
86     hot_y = src->bits->yhot;
87 
88     if (src->bits->argb != NULL) {
89 #if BITMAP_BIT_ORDER == MSBFirst
90         rowbytes = src->bits->width * sizeof(CARD32);
91         data = (uint32_t *)src->bits->argb;
92 #else
93         const uint32_t *be_data = (uint32_t *)src->bits->argb;
94         unsigned i;
95         rowbytes = src->bits->width * sizeof(CARD32);
96         data = malloc(rowbytes * src->bits->height);
97         free_data = TRUE;
98         if (!data) {
99             FatalError("Failed to allocate memory in %s\n", __func__);
100         }
101         for (i = 0; i < (src->bits->width * src->bits->height); i++)
102             data[i] = ntohl(be_data[i]);
103 #endif
104     }
105     else
106     {
107         fg_color = 0xFF00 | (src->foreRed >> 8);
108         fg_color <<= 16;
109         fg_color |= src->foreGreen & 0xFF00;
110         fg_color |= src->foreBlue >> 8;
111 
112         bg_color = 0xFF00 | (src->backRed >> 8);
113         bg_color <<= 16;
114         bg_color |= src->backGreen & 0xFF00;
115         bg_color |= src->backBlue >> 8;
116 
117         fg_color = htonl(fg_color);
118         bg_color = htonl(bg_color);
119 
120         /* round up to 8 pixel boundary so we can convert whole bytes */
121         rowbytes = ((src->bits->width * 4) + 31) & ~31;
122         data = malloc(rowbytes * src->bits->height);
123         free_data = TRUE;
124         if (!data) {
125             FatalError("Failed to allocate memory in %s\n", __func__);
126         }
127 
128         if (!src->bits->emptyMask) {
129             ycount = src->bits->height;
130             srow = src->bits->source;
131             mrow = src->bits->mask;
132             drow = data;
133 
134             while (ycount-- > 0)
135             {
136                 xcount = bits_to_bytes(src->bits->width);
137                 sptr = srow;
138                 mptr = mrow;
139                 dptr = drow;
140 
141                 while (xcount-- > 0)
142                 {
143                     uint8_t s, m;
144                     int i;
145 
146                     s = *sptr++;
147                     m = *mptr++;
148                     for (i = 0; i < 8; i++) {
149 #if BITMAP_BIT_ORDER == MSBFirst
150                         if (m & 128)
151                             *dptr++ = (s & 128) ? fg_color : bg_color;
152                         else
153                             *dptr++ = 0;
154                         s <<= 1;
155                         m <<= 1;
156 #else
157                         if (m & 1)
158                             *dptr++ = (s & 1) ? fg_color : bg_color;
159                         else
160                             *dptr++ = 0;
161                         s >>= 1;
162                         m >>= 1;
163 #endif
164                     }
165                 }
166 
167                 srow += BitmapBytePad(src->bits->width);
168                 mrow += BitmapBytePad(src->bits->width);
169                 drow = (uint32_t *)((char *)drow + rowbytes);
170             }
171         }
172         else {
173             memset(data, 0, src->bits->height * rowbytes);
174         }
175     }
176 
177     err = xp_set_cursor(width, height, hot_x, hot_y, data, rowbytes);
178     if (free_data)
179         free(data);
180     return err == Success;
181 }
182 
183 /*
184    ===========================================================================
185 
186    Pointer sprite functions
187 
188    ===========================================================================
189  */
190 
191 /*
192  * QuartzRealizeCursor
193  *  Convert the X cursor representation to native format if possible.
194  */
195 static Bool
QuartzRealizeCursor(DeviceIntPtr pDev,ScreenPtr pScreen,CursorPtr pCursor)196 QuartzRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
197 {
198     if (pCursor == NULL || pCursor->bits == NULL)
199         return FALSE;
200 
201     /* FIXME: cache ARGB8888 representation? */
202 
203     return TRUE;
204 }
205 
206 /*
207  * QuartzUnrealizeCursor
208  *  Free the storage space associated with a realized cursor.
209  */
210 static Bool
QuartzUnrealizeCursor(DeviceIntPtr pDev,ScreenPtr pScreen,CursorPtr pCursor)211 QuartzUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
212 {
213     return TRUE;
214 }
215 
216 /*
217  * QuartzSetCursor
218  *  Set the cursor sprite and position.
219  */
220 static void
QuartzSetCursor(DeviceIntPtr pDev,ScreenPtr pScreen,CursorPtr pCursor,int x,int y)221 QuartzSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
222                 int x,
223                 int y)
224 {
225     QuartzCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen);
226 
227     if (!XQuartzServerVisible)
228         return;
229 
230     if (pCursor == NULL) {
231         if (ScreenPriv->cursorVisible) {
232             xp_hide_cursor();
233             ScreenPriv->cursorVisible = FALSE;
234         }
235     }
236     else {
237         load_cursor(pCursor, pScreen->myNum);
238 
239         if (!ScreenPriv->cursorVisible) {
240             xp_show_cursor();
241             ScreenPriv->cursorVisible = TRUE;
242         }
243     }
244 }
245 
246 /*
247  * QuartzMoveCursor
248  *  Move the cursor. This is a noop for us.
249  */
250 static void
QuartzMoveCursor(DeviceIntPtr pDev,ScreenPtr pScreen,int x,int y)251 QuartzMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
252 {}
253 
254 /*
255    ===========================================================================
256 
257    Pointer screen functions
258 
259    ===========================================================================
260  */
261 
262 /*
263  * QuartzCursorOffScreen
264  */
265 static Bool
QuartzCursorOffScreen(ScreenPtr * pScreen,int * x,int * y)266 QuartzCursorOffScreen(ScreenPtr *pScreen, int *x, int *y)
267 {
268     return FALSE;
269 }
270 
271 /*
272  * QuartzCrossScreen
273  */
274 static void
QuartzCrossScreen(ScreenPtr pScreen,Bool entering)275 QuartzCrossScreen(ScreenPtr pScreen, Bool entering)
276 {
277     return;
278 }
279 
280 /*
281  * QuartzWarpCursor
282  *  Change the cursor position without generating an event or motion history.
283  *  The input coordinates (x,y) are in pScreen-local X11 coordinates.
284  *
285  */
286 static void
QuartzWarpCursor(DeviceIntPtr pDev,ScreenPtr pScreen,int x,int y)287 QuartzWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
288 {
289     if (XQuartzServerVisible) {
290         int sx, sy;
291 
292         sx = pScreen->x + darwinMainScreenX;
293         sy = pScreen->y + darwinMainScreenY;
294 
295         CGWarpMouseCursorPosition(CGPointMake(sx + x, sy + y));
296     }
297 
298     miPointerWarpCursor(pDev, pScreen, x, y);
299     miPointerUpdateSprite(pDev);
300 }
301 
302 static miPointerScreenFuncRec quartzScreenFuncsRec = {
303     QuartzCursorOffScreen,
304     QuartzCrossScreen,
305     QuartzWarpCursor,
306 };
307 
308 /*
309    ===========================================================================
310 
311    Other screen functions
312 
313    ===========================================================================
314  */
315 
316 /*
317  * QuartzCursorQueryBestSize
318  *  Handle queries for best cursor size
319  */
320 static void
QuartzCursorQueryBestSize(int class,unsigned short * width,unsigned short * height,ScreenPtr pScreen)321 QuartzCursorQueryBestSize(int class, unsigned short *width,
322                           unsigned short *height, ScreenPtr pScreen)
323 {
324     QuartzCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen);
325 
326     if (class == CursorShape) {
327         /* FIXME: query window server? */
328         *width = 32;
329         *height = 32;
330     }
331     else {
332         (*ScreenPriv->QueryBestSize)(class, width, height, pScreen);
333     }
334 }
335 
336 /*
337  * QuartzInitCursor
338  *  Initialize cursor support
339  */
340 Bool
QuartzInitCursor(ScreenPtr pScreen)341 QuartzInitCursor(ScreenPtr pScreen)
342 {
343     QuartzCursorScreenPtr ScreenPriv;
344     miPointerScreenPtr PointPriv;
345 
346     /* initialize software cursor handling (always needed as backup) */
347     if (!miDCInitialize(pScreen, &quartzScreenFuncsRec))
348         return FALSE;
349 
350     if (!dixRegisterPrivateKey(&darwinCursorScreenKeyRec, PRIVATE_SCREEN, 0))
351         return FALSE;
352 
353     ScreenPriv = calloc(1, sizeof(QuartzCursorScreenRec));
354     if (ScreenPriv == NULL)
355         return FALSE;
356 
357     /* CURSOR_PRIV(pScreen) = ScreenPriv; */
358     dixSetPrivate(&pScreen->devPrivates, darwinCursorScreenKey, ScreenPriv);
359 
360     /* override some screen procedures */
361     ScreenPriv->QueryBestSize = pScreen->QueryBestSize;
362     pScreen->QueryBestSize = QuartzCursorQueryBestSize;
363 
364     PointPriv = dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey);
365 
366     ScreenPriv->spriteFuncs = PointPriv->spriteFuncs;
367 
368     PointPriv->spriteFuncs->RealizeCursor = QuartzRealizeCursor;
369     PointPriv->spriteFuncs->UnrealizeCursor = QuartzUnrealizeCursor;
370     PointPriv->spriteFuncs->SetCursor = QuartzSetCursor;
371     PointPriv->spriteFuncs->MoveCursor = QuartzMoveCursor;
372 
373     ScreenPriv->cursorVisible = TRUE;
374     return TRUE;
375 }
376 
377 /*
378  * QuartzSuspendXCursor
379  *  X server is hiding. Restore the Aqua cursor.
380  */
381 void
QuartzSuspendXCursor(ScreenPtr pScreen)382 QuartzSuspendXCursor(ScreenPtr pScreen)
383 {}
384 
385 /*
386  * QuartzResumeXCursor
387  *  X server is showing. Restore the X cursor.
388  */
389 void
QuartzResumeXCursor(ScreenPtr pScreen)390 QuartzResumeXCursor(ScreenPtr pScreen)
391 {
392     WindowPtr pWin;
393     CursorPtr pCursor;
394 
395     /* TODO: Tablet? */
396 
397     pWin = GetSpriteWindow(darwinPointer);
398     if (pWin->drawable.pScreen != pScreen)
399         return;
400 
401     pCursor = GetSpriteCursor(darwinPointer);
402     if (pCursor == NULL)
403         return;
404 
405     QuartzSetCursor(darwinPointer, pScreen, pCursor, /* x */ 0, /* y */ 0);
406 }
407