tizen 2.4 release
[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 "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
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 #if BITMAP_BIT_ORDER == MSBFirst
91         rowbytes = src->bits->width * sizeof(CARD32);
92         data = (uint32_t *)src->bits->argb;
93 #else
94         const uint32_t *be_data = (uint32_t *)src->bits->argb;
95         unsigned i;
96         rowbytes = src->bits->width * sizeof(CARD32);
97         data = malloc(rowbytes * src->bits->height);
98         free_data = TRUE;
99         if (!data) {
100             FatalError("Failed to allocate memory in %s\n", __func__);
101         }
102         for (i = 0; i < (src->bits->width * src->bits->height); i++)
103             data[i] = ntohl(be_data[i]);
104 #endif
105     }
106     else
107 #endif
108     {
109         fg_color = 0xFF00 | (src->foreRed >> 8);
110         fg_color <<= 16;
111         fg_color |= src->foreGreen & 0xFF00;
112         fg_color |= src->foreBlue >> 8;
113
114         bg_color = 0xFF00 | (src->backRed >> 8);
115         bg_color <<= 16;
116         bg_color |= src->backGreen & 0xFF00;
117         bg_color |= src->backBlue >> 8;
118
119         fg_color = htonl(fg_color);
120         bg_color = htonl(bg_color);
121
122         /* round up to 8 pixel boundary so we can convert whole bytes */
123         rowbytes = ((src->bits->width * 4) + 31) & ~31;
124         data = malloc(rowbytes * src->bits->height);
125         free_data = TRUE;
126         if (!data) {
127             FatalError("Failed to allocate memory in %s\n", __func__);
128         }
129
130         if (!src->bits->emptyMask) {
131             ycount = src->bits->height;
132             srow = src->bits->source;
133             mrow = src->bits->mask;
134             drow = data;
135
136             while (ycount-- > 0)
137             {
138                 xcount = bits_to_bytes(src->bits->width);
139                 sptr = srow;
140                 mptr = mrow;
141                 dptr = drow;
142
143                 while (xcount-- > 0)
144                 {
145                     uint8_t s, m;
146                     int i;
147
148                     s = *sptr++;
149                     m = *mptr++;
150                     for (i = 0; i < 8; i++) {
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;
157                         m <<= 1;
158 #else
159                         if (m & 1)
160                             *dptr++ = (s & 1) ? fg_color : bg_color;
161                         else
162                             *dptr++ = 0;
163                         s >>= 1;
164                         m >>= 1;
165 #endif
166                     }
167                 }
168
169                 srow += BitmapBytePad(src->bits->width);
170                 mrow += BitmapBytePad(src->bits->width);
171                 drow = (uint32_t *)((char *)drow + rowbytes);
172             }
173         }
174         else {
175             memset(data, 0, src->bits->height * rowbytes);
176         }
177     }
178
179     err = xp_set_cursor(width, height, hot_x, hot_y, data, rowbytes);
180     if (free_data)
181         free(data);
182     return err == Success;
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  * QuartzUnrealizeCursor
210  *  Free the storage space associated with a realized cursor.
211  */
212 static Bool
213 QuartzUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
214 {
215     return TRUE;
216 }
217
218 /*
219  * QuartzSetCursor
220  *  Set the cursor sprite and position.
221  */
222 static void
223 QuartzSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
224                 int x,
225                 int y)
226 {
227     QuartzCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen);
228
229     if (!XQuartzServerVisible)
230         return;
231
232     if (pCursor == NULL) {
233         if (ScreenPriv->cursorVisible) {
234             xp_hide_cursor();
235             ScreenPriv->cursorVisible = FALSE;
236         }
237     }
238     else {
239         load_cursor(pCursor, pScreen->myNum);
240
241         if (!ScreenPriv->cursorVisible) {
242             xp_show_cursor();
243             ScreenPriv->cursorVisible = TRUE;
244         }
245     }
246 }
247
248 /*
249  * QuartzMoveCursor
250  *  Move the cursor. This is a noop for us.
251  */
252 static void
253 QuartzMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
254 {}
255
256 /*
257    ===========================================================================
258
259    Pointer screen functions
260
261    ===========================================================================
262  */
263
264 /*
265  * QuartzCursorOffScreen
266  */
267 static Bool
268 QuartzCursorOffScreen(ScreenPtr *pScreen, int *x, int *y)
269 {
270     return FALSE;
271 }
272
273 /*
274  * QuartzCrossScreen
275  */
276 static void
277 QuartzCrossScreen(ScreenPtr pScreen, Bool entering)
278 {
279     return;
280 }
281
282 /*
283  * QuartzWarpCursor
284  *  Change the cursor position without generating an event or motion history.
285  *  The input coordinates (x,y) are in pScreen-local X11 coordinates.
286  *
287  */
288 static void
289 QuartzWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
290 {
291     if (XQuartzServerVisible) {
292         int sx, sy;
293
294         sx = pScreen->x + darwinMainScreenX;
295         sy = pScreen->y + darwinMainScreenY;
296
297         CGWarpMouseCursorPosition(CGPointMake(sx + x, sy + y));
298     }
299
300     miPointerWarpCursor(pDev, pScreen, x, y);
301     miPointerUpdateSprite(pDev);
302 }
303
304 static miPointerScreenFuncRec quartzScreenFuncsRec = {
305     QuartzCursorOffScreen,
306     QuartzCrossScreen,
307     QuartzWarpCursor,
308 };
309
310 /*
311    ===========================================================================
312
313    Other screen functions
314
315    ===========================================================================
316  */
317
318 /*
319  * QuartzCursorQueryBestSize
320  *  Handle queries for best cursor size
321  */
322 static void
323 QuartzCursorQueryBestSize(int class, unsigned short *width,
324                           unsigned short *height, ScreenPtr pScreen)
325 {
326     QuartzCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen);
327
328     if (class == CursorShape) {
329         /* FIXME: query window server? */
330         *width = 32;
331         *height = 32;
332     }
333     else {
334         (*ScreenPriv->QueryBestSize)(class, width, height, pScreen);
335     }
336 }
337
338 /*
339  * QuartzInitCursor
340  *  Initialize cursor support
341  */
342 Bool
343 QuartzInitCursor(ScreenPtr pScreen)
344 {
345     QuartzCursorScreenPtr ScreenPriv;
346     miPointerScreenPtr PointPriv;
347
348     /* initialize software cursor handling (always needed as backup) */
349     if (!miDCInitialize(pScreen, &quartzScreenFuncsRec))
350         return FALSE;
351
352     if (!dixRegisterPrivateKey(&darwinCursorScreenKeyRec, PRIVATE_SCREEN, 0))
353         return FALSE;
354
355     ScreenPriv = calloc(1, sizeof(QuartzCursorScreenRec));
356     if (ScreenPriv == NULL)
357         return FALSE;
358
359     /* CURSOR_PRIV(pScreen) = ScreenPriv; */
360     dixSetPrivate(&pScreen->devPrivates, darwinCursorScreenKey, ScreenPriv);
361
362     /* override some screen procedures */
363     ScreenPriv->QueryBestSize = pScreen->QueryBestSize;
364     pScreen->QueryBestSize = QuartzCursorQueryBestSize;
365
366     PointPriv = dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey);
367
368     ScreenPriv->spriteFuncs = PointPriv->spriteFuncs;
369
370     PointPriv->spriteFuncs->RealizeCursor = QuartzRealizeCursor;
371     PointPriv->spriteFuncs->UnrealizeCursor = QuartzUnrealizeCursor;
372     PointPriv->spriteFuncs->SetCursor = QuartzSetCursor;
373     PointPriv->spriteFuncs->MoveCursor = QuartzMoveCursor;
374
375     ScreenPriv->cursorVisible = TRUE;
376     return TRUE;
377 }
378
379 /*
380  * QuartzSuspendXCursor
381  *  X server is hiding. Restore the Aqua cursor.
382  */
383 void
384 QuartzSuspendXCursor(ScreenPtr pScreen)
385 {}
386
387 /*
388  * QuartzResumeXCursor
389  *  X server is showing. Restore the X cursor.
390  */
391 void
392 QuartzResumeXCursor(ScreenPtr pScreen)
393 {
394     WindowPtr pWin;
395     CursorPtr pCursor;
396
397     /* TODO: Tablet? */
398
399     pWin = GetSpriteWindow(darwinPointer);
400     if (pWin->drawable.pScreen != pScreen)
401         return;
402
403     pCursor = GetSpriteCursor(darwinPointer);
404     if (pCursor == NULL)
405         return;
406
407     QuartzSetCursor(darwinPointer, pScreen, pCursor, /* x */ 0, /* y */ 0);
408 }