Git init
[framework/uifw/xorg/server/xorg-server.git] / hw / xquartz / xpr / xprCursor.c
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 "darwin.h"
41 #include "darwinEvents.h"
42 #include <Xplugin.h>
43
44 #include "mi.h"
45 #include "scrnintstr.h"
46 #include "cursorstr.h"
47 #include "mipointrst.h"
48 #include "windowstr.h"
49 #include "globals.h"
50 #include "servermd.h"
51 #include "dixevents.h"
52 #include "x-hash.h"
53
54 typedef struct {
55     int                     cursorVisible;
56     QueryBestSizeProcPtr    QueryBestSize;
57     miPointerSpriteFuncPtr  spriteFuncs;
58 } QuartzCursorScreenRec, *QuartzCursorScreenPtr;
59
60 static DevPrivateKeyRec darwinCursorScreenKeyRec;
61 #define darwinCursorScreenKey (&darwinCursorScreenKeyRec)
62
63 #define CURSOR_PRIV(pScreen) ((QuartzCursorScreenPtr) \
64     dixLookupPrivate(&pScreen->devPrivates, darwinCursorScreenKey))
65
66 static Bool
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 #ifdef ARGB_CURSOR
89     if (src->bits->argb != NULL)
90     {
91 #if BITMAP_BIT_ORDER == MSBFirst
92         rowbytes = src->bits->width * sizeof (CARD32);
93         data = (uint32_t *) src->bits->argb;
94 #else
95         const uint32_t *be_data=(uint32_t *) src->bits->argb;
96         unsigned i;
97         rowbytes = src->bits->width * sizeof (CARD32);
98         data = malloc(rowbytes * src->bits->height);
99         free_data = TRUE;
100         if(!data) {
101             FatalError("Failed to allocate memory in %s\n", __func__);
102         }
103         for(i=0;i<(src->bits->width*src->bits->height);i++)
104             data[i]=ntohl(be_data[i]);
105 #endif
106     }
107     else
108 #endif
109     {
110         fg_color = 0xFF00 | (src->foreRed >> 8);
111         fg_color <<= 16;
112         fg_color |= src->foreGreen & 0xFF00;
113         fg_color |= src->foreBlue >> 8;
114
115         bg_color = 0xFF00 | (src->backRed >> 8);
116         bg_color <<= 16;
117         bg_color |= src->backGreen & 0xFF00;
118         bg_color |= src->backBlue >> 8;
119
120         fg_color = htonl(fg_color);
121         bg_color = htonl(bg_color);
122
123         /* round up to 8 pixel boundary so we can convert whole bytes */
124         rowbytes = ((src->bits->width * 4) + 31) & ~31;
125         data = malloc(rowbytes * src->bits->height);
126         free_data = TRUE;
127         if(!data) {
128             FatalError("Failed to allocate memory in %s\n", __func__);
129         }
130         
131         if (!src->bits->emptyMask)
132         {
133             ycount = src->bits->height;
134             srow = src->bits->source; mrow = src->bits->mask;
135             drow = data;
136
137             while (ycount-- > 0)
138             {
139                 xcount = bits_to_bytes(src->bits->width);
140                 sptr = srow; mptr = mrow;
141                 dptr = drow;
142
143                 while (xcount-- > 0)
144                 {
145                     uint8_t s, m;
146                     int i;
147
148                     s = *sptr++; m = *mptr++;
149                     for (i = 0; i < 8; i++)
150                     {
151 #if BITMAP_BIT_ORDER == MSBFirst
152                         if (m & 128)
153                             *dptr++ = (s & 128) ? fg_color : bg_color;
154                         else
155                             *dptr++ = 0;
156                         s <<= 1; m <<= 1;
157 #else
158                         if (m & 1)
159                             *dptr++ = (s & 1) ? fg_color : bg_color;
160                         else
161                             *dptr++ = 0;
162                         s >>= 1; 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         {
174             memset(data, 0, src->bits->height * rowbytes);
175         }
176     }
177
178     err = xp_set_cursor(width, height, hot_x, hot_y, data, rowbytes);
179     if(free_data)
180         free(data);
181     return err == Success;
182 }
183
184
185 /*
186 ===========================================================================
187
188  Pointer sprite functions
189
190 ===========================================================================
191 */
192
193 /*
194  * QuartzRealizeCursor
195  *  Convert the X cursor representation to native format if possible.
196  */
197 static Bool
198 QuartzRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
199 {
200     if(pCursor == NULL || pCursor->bits == NULL)
201         return FALSE;
202
203     /* FIXME: cache ARGB8888 representation? */
204
205     return TRUE;
206 }
207
208
209 /*
210  * QuartzUnrealizeCursor
211  *  Free the storage space associated with a realized cursor.
212  */
213 static Bool
214 QuartzUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
215 {
216     return TRUE;
217 }
218
219
220 /*
221  * QuartzSetCursor
222  *  Set the cursor sprite and position.
223  */
224 static void
225 QuartzSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
226 {
227     QuartzCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen);
228
229     if (!XQuartzServerVisible)
230         return;
231
232     if (pCursor == NULL)
233     {
234         if (ScreenPriv->cursorVisible)
235         {
236             xp_hide_cursor();
237             ScreenPriv->cursorVisible = FALSE;
238         }
239     }
240     else
241     {
242         load_cursor(pCursor, pScreen->myNum);
243
244         if (!ScreenPriv->cursorVisible)
245         {
246             xp_show_cursor();
247             ScreenPriv->cursorVisible = TRUE;
248         }
249     }
250 }
251
252 /*
253  * QuartzMoveCursor
254  *  Move the cursor. This is a noop for us.
255  */
256 static void
257 QuartzMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
258 {
259 }
260
261 /*
262 ===========================================================================
263
264  Pointer screen functions
265
266 ===========================================================================
267 */
268
269 /*
270  * QuartzCursorOffScreen
271  */
272 static Bool
273 QuartzCursorOffScreen(ScreenPtr *pScreen, int *x, int *y)
274 {
275     return FALSE;
276 }
277
278
279 /*
280  * QuartzCrossScreen
281  */
282 static void
283 QuartzCrossScreen(ScreenPtr pScreen, Bool entering)
284 {
285     return;
286 }
287
288
289 /*
290  * QuartzWarpCursor
291  *  Change the cursor position without generating an event or motion history.
292  *  The input coordinates (x,y) are in pScreen-local X11 coordinates.
293  *
294  */
295 static void
296 QuartzWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
297 {
298     if (XQuartzServerVisible)
299     {
300         int sx, sy;
301
302         sx = pScreen->x + darwinMainScreenX;
303         sy = pScreen->y + darwinMainScreenY;
304
305         CGWarpMouseCursorPosition(CGPointMake(sx + x, sy + y));
306     }
307
308     miPointerWarpCursor(pDev, pScreen, x, y);
309     miPointerUpdateSprite(pDev);
310 }
311
312
313 static miPointerScreenFuncRec quartzScreenFuncsRec = {
314     QuartzCursorOffScreen,
315     QuartzCrossScreen,
316     QuartzWarpCursor,
317     NULL,
318     NULL
319 };
320
321
322 /*
323 ===========================================================================
324
325  Other screen functions
326
327 ===========================================================================
328 */
329
330 /*
331  * QuartzCursorQueryBestSize
332  *  Handle queries for best cursor size
333  */
334 static void
335 QuartzCursorQueryBestSize(int class, unsigned short *width,
336                           unsigned short *height, ScreenPtr pScreen)
337 {
338     QuartzCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen);
339
340     if (class == CursorShape)
341     {
342         /* FIXME: query window server? */
343         *width = 32;
344         *height = 32;
345     }
346     else
347     {
348         (*ScreenPriv->QueryBestSize)(class, width, height, pScreen);
349     }
350 }
351
352 /*
353  * QuartzInitCursor
354  *  Initialize cursor support
355  */
356 Bool
357 QuartzInitCursor(ScreenPtr pScreen)
358 {
359     QuartzCursorScreenPtr ScreenPriv;
360     miPointerScreenPtr PointPriv;
361
362     /* initialize software cursor handling (always needed as backup) */
363     if (!miDCInitialize(pScreen, &quartzScreenFuncsRec))
364         return FALSE;
365
366     if (!dixRegisterPrivateKey(&darwinCursorScreenKeyRec, PRIVATE_SCREEN, 0))
367         return FALSE;
368
369     ScreenPriv = calloc(1, sizeof(QuartzCursorScreenRec));
370     if (ScreenPriv == NULL)
371         return FALSE;
372
373     /* CURSOR_PRIV(pScreen) = ScreenPriv; */
374     dixSetPrivate(&pScreen->devPrivates, darwinCursorScreenKey, ScreenPriv);
375
376     /* override some screen procedures */
377     ScreenPriv->QueryBestSize = pScreen->QueryBestSize;
378     pScreen->QueryBestSize = QuartzCursorQueryBestSize;
379
380     PointPriv = dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey);
381
382     ScreenPriv->spriteFuncs = PointPriv->spriteFuncs;
383
384     PointPriv->spriteFuncs->RealizeCursor = QuartzRealizeCursor;
385     PointPriv->spriteFuncs->UnrealizeCursor = QuartzUnrealizeCursor;
386     PointPriv->spriteFuncs->SetCursor = QuartzSetCursor;
387     PointPriv->spriteFuncs->MoveCursor = QuartzMoveCursor;
388     
389     ScreenPriv->cursorVisible = TRUE;
390     return TRUE;
391 }
392
393 /*
394  * QuartzSuspendXCursor
395  *  X server is hiding. Restore the Aqua cursor.
396  */
397 void
398 QuartzSuspendXCursor(ScreenPtr pScreen)
399 {
400 }
401
402
403 /*
404  * QuartzResumeXCursor
405  *  X server is showing. Restore the X cursor.
406  */
407 void
408 QuartzResumeXCursor(ScreenPtr pScreen)
409 {
410     WindowPtr pWin;
411     CursorPtr pCursor;
412
413     /* TODO: Tablet? */
414     
415     pWin = GetSpriteWindow(darwinPointer);
416     if (pWin->drawable.pScreen != pScreen)
417         return;
418
419     pCursor = GetSpriteCursor(darwinPointer);
420     if (pCursor == NULL)
421         return;
422
423     QuartzSetCursor(darwinPointer, pScreen, pCursor, /* x */ 0, /* y */ 0);
424 }