Cursor.c revision ff63a143
1/*
2 * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
3 * Copyright 2011 Red Hat, Inc.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24/*
25 * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
26 *
27 * Permission to use, copy, modify, distribute, and sell this software and its
28 * documentation for any purpose is hereby granted without fee, provided that
29 * the above copyright notice appear in all copies and that both that
30 * copyright notice and this permission notice appear in supporting
31 * documentation, and that the name of Keith Packard not be used in
32 * advertising or publicity pertaining to distribution of the software without
33 * specific, written prior permission.  Keith Packard makes no
34 * representations about the suitability of this software for any purpose.  It
35 * is provided "as is" without express or implied warranty.
36 *
37 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
38 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
39 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
40 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
41 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
42 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
43 * PERFORMANCE OF THIS SOFTWARE.
44 */
45
46#ifdef HAVE_CONFIG_H
47#include <config.h>
48#endif
49#include "Xfixesint.h"
50
51void
52XFixesSelectCursorInput (Display	*dpy,
53			 Window		win,
54			 unsigned long	eventMask)
55{
56    XFixesExtDisplayInfo	    *info = XFixesFindDisplay (dpy);
57    xXFixesSelectCursorInputReq	    *req;
58
59    XFixesSimpleCheckExtension (dpy, info);
60
61    LockDisplay (dpy);
62    GetReq (XFixesSelectCursorInput, req);
63    req->reqType = info->codes->major_opcode;
64    req->xfixesReqType = X_XFixesSelectCursorInput;
65    req->window = win;
66    req->eventMask = eventMask;
67    UnlockDisplay (dpy);
68    SyncHandle ();
69}
70
71XFixesCursorImage *
72XFixesGetCursorImage (Display *dpy)
73{
74    XFixesExtDisplayInfo		*info = XFixesFindDisplay (dpy);
75    xXFixesGetCursorImageAndNameReq	*req;
76    xXFixesGetCursorImageAndNameReply	rep;
77    int					npixels;
78    int					nbytes_name;
79    int					nbytes, nread, rlength;
80    XFixesCursorImage			*image;
81    char				*name;
82
83    XFixesCheckExtension (dpy, info, NULL);
84    LockDisplay (dpy);
85    GetReq (XFixesGetCursorImageAndName, req);
86    req->reqType = info->codes->major_opcode;
87    if (info->major_version >= 2)
88	req->xfixesReqType = X_XFixesGetCursorImageAndName;
89    else
90	req->xfixesReqType = X_XFixesGetCursorImage;
91    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
92    {
93	UnlockDisplay (dpy);
94	SyncHandle ();
95	return NULL;
96    }
97    if (info->major_version < 2)
98    {
99	rep.cursorName = None;
100	rep.nbytes = 0;
101    }
102    npixels = rep.width * rep.height;
103    nbytes_name = rep.nbytes;
104    /* reply data length */
105    nbytes = (long) rep.length << 2;
106    /* bytes of actual data in the reply */
107    nread = (npixels << 2) + nbytes_name;
108    /* size of data returned to application */
109    rlength = (sizeof (XFixesCursorImage) +
110	       npixels * sizeof (unsigned long) +
111	       nbytes_name + 1);
112
113    image = (XFixesCursorImage *) Xmalloc (rlength);
114    if (!image)
115    {
116	_XEatData (dpy, nbytes);
117	UnlockDisplay (dpy);
118	SyncHandle ();
119	return NULL;
120    }
121    image->x = rep.x;
122    image->y = rep.y;
123    image->width = rep.width;
124    image->height = rep.height;
125    image->xhot = rep.xhot;
126    image->yhot = rep.yhot;
127    image->cursor_serial = rep.cursorSerial;
128    image->pixels = (unsigned long *) (image + 1);
129    image->atom = rep.cursorName;
130    name = (char *) (image->pixels + npixels);
131    image->name = name;
132    _XRead32 (dpy, (long *) image->pixels, npixels << 2);
133    _XRead (dpy, name, nbytes_name);
134    name[nbytes_name] = '\0';	/* null-terminate */
135    /* skip any padding */
136    if(nbytes > nread)
137    {
138	_XEatData (dpy, (unsigned long) (nbytes - nread));
139    }
140    UnlockDisplay (dpy);
141    SyncHandle ();
142    return image;
143}
144
145void
146XFixesSetCursorName (Display *dpy, Cursor cursor, const char *name)
147{
148    XFixesExtDisplayInfo	*info = XFixesFindDisplay (dpy);
149    xXFixesSetCursorNameReq	*req;
150    int				nbytes = strlen (name);
151
152    XFixesSimpleCheckExtension (dpy, info);
153    if (info->major_version < 2)
154	return;
155    LockDisplay (dpy);
156    GetReq (XFixesSetCursorName, req);
157    req->reqType = info->codes->major_opcode;
158    req->xfixesReqType = X_XFixesSetCursorName;
159    req->cursor = cursor;
160    req->nbytes = nbytes;
161    req->length += (nbytes + 3) >> 2;
162    Data (dpy, name, nbytes);
163    UnlockDisplay (dpy);
164    SyncHandle ();
165}
166
167const char *
168XFixesGetCursorName (Display *dpy, Cursor cursor, Atom *atom)
169{
170    XFixesExtDisplayInfo	*info = XFixesFindDisplay (dpy);
171    xXFixesGetCursorNameReq	*req;
172    xXFixesGetCursorNameReply	rep;
173    char			*name;
174
175    XFixesCheckExtension (dpy, info, NULL);
176    if (info->major_version < 2)
177	return NULL;
178    LockDisplay (dpy);
179    GetReq (XFixesGetCursorName, req);
180    req->reqType = info->codes->major_opcode;
181    req->xfixesReqType = X_XFixesGetCursorName;
182    req->cursor = cursor;
183    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
184    {
185	UnlockDisplay (dpy);
186	SyncHandle ();
187	return NULL;
188    }
189    *atom = rep.atom;
190    if ((name = (char *) Xmalloc(rep.nbytes+1))) {
191	_XReadPad(dpy, name, (long)rep.nbytes);
192	name[rep.nbytes] = '\0';
193    } else {
194	_XEatData(dpy, (unsigned long) (rep.nbytes + 3) & ~3);
195	name = (char *) NULL;
196    }
197    UnlockDisplay(dpy);
198    SyncHandle();
199    return(name);
200}
201
202void
203XFixesChangeCursor (Display *dpy, Cursor source, Cursor destination)
204{
205    XFixesExtDisplayInfo	*info = XFixesFindDisplay (dpy);
206    xXFixesChangeCursorReq	*req;
207
208    XFixesSimpleCheckExtension (dpy, info);
209    if (info->major_version < 2)
210	return;
211    LockDisplay (dpy);
212    GetReq (XFixesChangeCursor, req);
213    req->reqType = info->codes->major_opcode;
214    req->xfixesReqType = X_XFixesChangeCursor;
215    req->source = source;
216    req->destination = destination;
217    UnlockDisplay(dpy);
218    SyncHandle();
219}
220
221void
222XFixesChangeCursorByName (Display *dpy, Cursor source, const char *name)
223{
224    XFixesExtDisplayInfo	    *info = XFixesFindDisplay (dpy);
225    xXFixesChangeCursorByNameReq    *req;
226    int				    nbytes = strlen (name);
227
228    XFixesSimpleCheckExtension (dpy, info);
229    if (info->major_version < 2)
230	return;
231    LockDisplay (dpy);
232    GetReq (XFixesChangeCursorByName, req);
233    req->reqType = info->codes->major_opcode;
234    req->xfixesReqType = X_XFixesChangeCursorByName;
235    req->source = source;
236    req->nbytes = nbytes;
237    req->length += (nbytes + 3) >> 2;
238    Data (dpy, name, nbytes);
239    UnlockDisplay(dpy);
240    SyncHandle();
241}
242
243void
244XFixesHideCursor (Display *dpy, Window win)
245{
246    XFixesExtDisplayInfo	*info = XFixesFindDisplay (dpy);
247    xXFixesHideCursorReq	*req;
248
249    XFixesSimpleCheckExtension (dpy, info);
250    if (info->major_version < 4)
251	return;
252    LockDisplay (dpy);
253    GetReq (XFixesHideCursor, req);
254    req->reqType = info->codes->major_opcode;
255    req->xfixesReqType = X_XFixesHideCursor;
256    req->window = win;
257    UnlockDisplay (dpy);
258    SyncHandle ();
259}
260
261void
262XFixesShowCursor (Display *dpy, Window win)
263{
264    XFixesExtDisplayInfo	*info = XFixesFindDisplay (dpy);
265    xXFixesShowCursorReq	*req;
266
267    XFixesSimpleCheckExtension (dpy, info);
268    if (info->major_version < 4)
269	return;
270    LockDisplay (dpy);
271    GetReq (XFixesShowCursor, req);
272    req->reqType = info->codes->major_opcode;
273    req->xfixesReqType = X_XFixesShowCursor;
274    req->window = win;
275    UnlockDisplay (dpy);
276    SyncHandle ();
277}
278
279PointerBarrier
280XFixesCreatePointerBarrier(Display *dpy, Window w, int x1, int y1,
281			   int x2, int y2, int directions,
282			   int num_devices, int *devices)
283{
284    XFixesExtDisplayInfo *info = XFixesFindDisplay (dpy);
285    xXFixesCreatePointerBarrierReq *req;
286    PointerBarrier barrier;
287    int extra = 0;
288
289    XFixesCheckExtension (dpy, info, 0);
290    if (info->major_version < 5)
291	return 0;
292
293    if (num_devices)
294	extra = (((2 * num_devices) + 3) / 4) * 4;
295
296    LockDisplay (dpy);
297    GetReqExtra (XFixesCreatePointerBarrier, extra, req);
298    req->reqType = info->codes->major_opcode;
299    req->xfixesReqType = X_XFixesCreatePointerBarrier;
300    barrier = req->barrier = XAllocID (dpy);
301    req->window = w;
302    req->x1 = x1;
303    req->y1 = y1;
304    req->x2 = x2;
305    req->y2 = y2;
306    req->directions = directions;
307    if ((req->num_devices = num_devices)) {
308	int i;
309	CARD16 *devs = (CARD16 *)(req + 1);
310	for (i = 0; i < num_devices; i++)
311	    devs[i] = (CARD16)(devices[i]);
312    }
313
314    UnlockDisplay (dpy);
315    SyncHandle();
316    return barrier;
317}
318
319void
320XFixesDestroyPointerBarrier(Display *dpy, PointerBarrier b)
321{
322    XFixesExtDisplayInfo *info = XFixesFindDisplay (dpy);
323    xXFixesDestroyPointerBarrierReq *req;
324
325    XFixesSimpleCheckExtension (dpy, info);
326    if (info->major_version < 5)
327	return;
328
329    LockDisplay (dpy);
330    GetReq (XFixesDestroyPointerBarrier, req);
331    req->reqType = info->codes->major_opcode;
332    req->xfixesReqType = X_XFixesDestroyPointerBarrier;
333    req->barrier = b;
334    UnlockDisplay (dpy);
335    SyncHandle();
336}
337