14456fccdSmrg/*
2a7e741d5Smrg * Copyright (c) 2006, Oracle and/or its affiliates.
3ff63a143Smrg * Copyright 2011 Red Hat, Inc.
44456fccdSmrg *
5521070a0Smrg * Permission is hereby granted, free of charge, to any person obtaining a
6521070a0Smrg * copy of this software and associated documentation files (the "Software"),
7521070a0Smrg * to deal in the Software without restriction, including without limitation
8521070a0Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9521070a0Smrg * and/or sell copies of the Software, and to permit persons to whom the
10521070a0Smrg * Software is furnished to do so, subject to the following conditions:
114456fccdSmrg *
12521070a0Smrg * The above copyright notice and this permission notice (including the next
13521070a0Smrg * paragraph) shall be included in all copies or substantial portions of the
14521070a0Smrg * Software.
154456fccdSmrg *
16521070a0Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17521070a0Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18521070a0Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19521070a0Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20521070a0Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21521070a0Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22521070a0Smrg * DEALINGS IN THE SOFTWARE.
23521070a0Smrg */
24521070a0Smrg/*
254456fccdSmrg * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
264456fccdSmrg *
274456fccdSmrg * Permission to use, copy, modify, distribute, and sell this software and its
284456fccdSmrg * documentation for any purpose is hereby granted without fee, provided that
294456fccdSmrg * the above copyright notice appear in all copies and that both that
304456fccdSmrg * copyright notice and this permission notice appear in supporting
314456fccdSmrg * documentation, and that the name of Keith Packard not be used in
324456fccdSmrg * advertising or publicity pertaining to distribution of the software without
334456fccdSmrg * specific, written prior permission.  Keith Packard makes no
344456fccdSmrg * representations about the suitability of this software for any purpose.  It
354456fccdSmrg * is provided "as is" without express or implied warranty.
364456fccdSmrg *
374456fccdSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
384456fccdSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
394456fccdSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
404456fccdSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
414456fccdSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
424456fccdSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
434456fccdSmrg * PERFORMANCE OF THIS SOFTWARE.
444456fccdSmrg */
454456fccdSmrg
464456fccdSmrg#ifdef HAVE_CONFIG_H
474456fccdSmrg#include <config.h>
484456fccdSmrg#endif
494456fccdSmrg#include "Xfixesint.h"
503e6c936aSmrg#include <limits.h>
514456fccdSmrg
524456fccdSmrgvoid
534456fccdSmrgXFixesSelectCursorInput (Display	*dpy,
544456fccdSmrg			 Window		win,
554456fccdSmrg			 unsigned long	eventMask)
564456fccdSmrg{
574456fccdSmrg    XFixesExtDisplayInfo	    *info = XFixesFindDisplay (dpy);
584456fccdSmrg    xXFixesSelectCursorInputReq	    *req;
594456fccdSmrg
604456fccdSmrg    XFixesSimpleCheckExtension (dpy, info);
614456fccdSmrg
624456fccdSmrg    LockDisplay (dpy);
634456fccdSmrg    GetReq (XFixesSelectCursorInput, req);
64a7e741d5Smrg    req->reqType = (CARD8) info->codes->major_opcode;
654456fccdSmrg    req->xfixesReqType = X_XFixesSelectCursorInput;
66a7e741d5Smrg    req->window = (CARD32) win;
67a7e741d5Smrg    req->eventMask = (CARD32) eventMask;
684456fccdSmrg    UnlockDisplay (dpy);
694456fccdSmrg    SyncHandle ();
704456fccdSmrg}
714456fccdSmrg
724456fccdSmrgXFixesCursorImage *
734456fccdSmrgXFixesGetCursorImage (Display *dpy)
744456fccdSmrg{
754456fccdSmrg    XFixesExtDisplayInfo		*info = XFixesFindDisplay (dpy);
764456fccdSmrg    xXFixesGetCursorImageAndNameReq	*req;
774456fccdSmrg    xXFixesGetCursorImageAndNameReply	rep;
783e6c936aSmrg    size_t				npixels;
793e6c936aSmrg    size_t				nbytes_name;
80a7e741d5Smrg    size_t				nbytes = 0, nread = 0;
814456fccdSmrg    XFixesCursorImage			*image;
824456fccdSmrg    char				*name;
834456fccdSmrg
8442d69509Smrg    XFixesCheckExtension (dpy, info, NULL);
854456fccdSmrg    LockDisplay (dpy);
864456fccdSmrg    GetReq (XFixesGetCursorImageAndName, req);
87a7e741d5Smrg    req->reqType = (CARD8) info->codes->major_opcode;
884456fccdSmrg    if (info->major_version >= 2)
894456fccdSmrg	req->xfixesReqType = X_XFixesGetCursorImageAndName;
904456fccdSmrg    else
914456fccdSmrg	req->xfixesReqType = X_XFixesGetCursorImage;
924456fccdSmrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
934456fccdSmrg    {
944456fccdSmrg	UnlockDisplay (dpy);
954456fccdSmrg	SyncHandle ();
9642d69509Smrg	return NULL;
974456fccdSmrg    }
984456fccdSmrg    if (info->major_version < 2)
994456fccdSmrg    {
1004456fccdSmrg	rep.cursorName = None;
1014456fccdSmrg	rep.nbytes = 0;
1024456fccdSmrg    }
1034456fccdSmrg    npixels = rep.width * rep.height;
1044456fccdSmrg    nbytes_name = rep.nbytes;
1053e6c936aSmrg    if ((rep.length < (INT_MAX >> 2)) &&
1063e6c936aSmrg	npixels < (((INT_MAX >> 3) - sizeof (XFixesCursorImage) - 1)
1073e6c936aSmrg		   - nbytes_name)) {
108a7e741d5Smrg	size_t	rlength;
109a7e741d5Smrg
1103e6c936aSmrg	/* reply data length */
1113e6c936aSmrg	nbytes = (size_t) rep.length << 2;
1123e6c936aSmrg	/* bytes of actual data in the reply */
1133e6c936aSmrg	nread = (npixels << 2) + nbytes_name;
1143e6c936aSmrg	/* size of data returned to application */
1153e6c936aSmrg	rlength = (sizeof (XFixesCursorImage) +
1163e6c936aSmrg		   npixels * sizeof (unsigned long) +
1173e6c936aSmrg		   nbytes_name + 1);
1184456fccdSmrg
1193e6c936aSmrg	image = Xmalloc (rlength);
1203e6c936aSmrg    } else
1213e6c936aSmrg	image = NULL;
1224456fccdSmrg    if (!image)
1234456fccdSmrg    {
1243e6c936aSmrg	_XEatDataWords(dpy, rep.length);
1254456fccdSmrg	UnlockDisplay (dpy);
1264456fccdSmrg	SyncHandle ();
12742d69509Smrg	return NULL;
1284456fccdSmrg    }
1294456fccdSmrg    image->x = rep.x;
1304456fccdSmrg    image->y = rep.y;
1314456fccdSmrg    image->width = rep.width;
1324456fccdSmrg    image->height = rep.height;
1334456fccdSmrg    image->xhot = rep.xhot;
1344456fccdSmrg    image->yhot = rep.yhot;
1354456fccdSmrg    image->cursor_serial = rep.cursorSerial;
1364456fccdSmrg    image->pixels = (unsigned long *) (image + 1);
1374456fccdSmrg    image->atom = rep.cursorName;
1384456fccdSmrg    name = (char *) (image->pixels + npixels);
1394456fccdSmrg    image->name = name;
1404456fccdSmrg    _XRead32 (dpy, (long *) image->pixels, npixels << 2);
1414456fccdSmrg    _XRead (dpy, name, nbytes_name);
1424456fccdSmrg    name[nbytes_name] = '\0';	/* null-terminate */
1434456fccdSmrg    /* skip any padding */
1444456fccdSmrg    if(nbytes > nread)
1454456fccdSmrg    {
1464456fccdSmrg	_XEatData (dpy, (unsigned long) (nbytes - nread));
1474456fccdSmrg    }
1484456fccdSmrg    UnlockDisplay (dpy);
1494456fccdSmrg    SyncHandle ();
1504456fccdSmrg    return image;
1514456fccdSmrg}
1524456fccdSmrg
1534456fccdSmrgvoid
1544456fccdSmrgXFixesSetCursorName (Display *dpy, Cursor cursor, const char *name)
1554456fccdSmrg{
1564456fccdSmrg    XFixesExtDisplayInfo	*info = XFixesFindDisplay (dpy);
1574456fccdSmrg    xXFixesSetCursorNameReq	*req;
158a7e741d5Smrg    CARD16			nbytes = (CARD16) strlen (name);
1594456fccdSmrg
1604456fccdSmrg    XFixesSimpleCheckExtension (dpy, info);
1614456fccdSmrg    if (info->major_version < 2)
1624456fccdSmrg	return;
1634456fccdSmrg    LockDisplay (dpy);
1644456fccdSmrg    GetReq (XFixesSetCursorName, req);
165a7e741d5Smrg    req->reqType = (CARD8) info->codes->major_opcode;
1664456fccdSmrg    req->xfixesReqType = X_XFixesSetCursorName;
167a7e741d5Smrg    req->cursor = (CARD32) cursor;
1684456fccdSmrg    req->nbytes = nbytes;
1694456fccdSmrg    req->length += (nbytes + 3) >> 2;
1704456fccdSmrg    Data (dpy, name, nbytes);
1714456fccdSmrg    UnlockDisplay (dpy);
1724456fccdSmrg    SyncHandle ();
1734456fccdSmrg}
1744456fccdSmrg
1754456fccdSmrgconst char *
1764456fccdSmrgXFixesGetCursorName (Display *dpy, Cursor cursor, Atom *atom)
1774456fccdSmrg{
1784456fccdSmrg    XFixesExtDisplayInfo	*info = XFixesFindDisplay (dpy);
1794456fccdSmrg    xXFixesGetCursorNameReq	*req;
1804456fccdSmrg    xXFixesGetCursorNameReply	rep;
1814456fccdSmrg    char			*name;
1824456fccdSmrg
18342d69509Smrg    XFixesCheckExtension (dpy, info, NULL);
1844456fccdSmrg    if (info->major_version < 2)
18542d69509Smrg	return NULL;
1864456fccdSmrg    LockDisplay (dpy);
1874456fccdSmrg    GetReq (XFixesGetCursorName, req);
188a7e741d5Smrg    req->reqType = (CARD8) info->codes->major_opcode;
1894456fccdSmrg    req->xfixesReqType = X_XFixesGetCursorName;
190a7e741d5Smrg    req->cursor = (CARD32) cursor;
1914456fccdSmrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
1924456fccdSmrg    {
1934456fccdSmrg	UnlockDisplay (dpy);
1944456fccdSmrg	SyncHandle ();
19542d69509Smrg	return NULL;
1964456fccdSmrg    }
1974456fccdSmrg    *atom = rep.atom;
198a7e741d5Smrg    if ((name = Xmalloc(rep.nbytes+1)) != NULL) {
1994456fccdSmrg	_XReadPad(dpy, name, (long)rep.nbytes);
2004456fccdSmrg	name[rep.nbytes] = '\0';
2014456fccdSmrg    } else {
2023e6c936aSmrg	_XEatDataWords(dpy, rep.length);
2034456fccdSmrg	name = (char *) NULL;
2044456fccdSmrg    }
2054456fccdSmrg    UnlockDisplay(dpy);
2064456fccdSmrg    SyncHandle();
2074456fccdSmrg    return(name);
2084456fccdSmrg}
2094456fccdSmrg
2104456fccdSmrgvoid
2114456fccdSmrgXFixesChangeCursor (Display *dpy, Cursor source, Cursor destination)
2124456fccdSmrg{
2134456fccdSmrg    XFixesExtDisplayInfo	*info = XFixesFindDisplay (dpy);
2144456fccdSmrg    xXFixesChangeCursorReq	*req;
2154456fccdSmrg
2164456fccdSmrg    XFixesSimpleCheckExtension (dpy, info);
2174456fccdSmrg    if (info->major_version < 2)
2184456fccdSmrg	return;
2194456fccdSmrg    LockDisplay (dpy);
2204456fccdSmrg    GetReq (XFixesChangeCursor, req);
221a7e741d5Smrg    req->reqType = (CARD8) info->codes->major_opcode;
2224456fccdSmrg    req->xfixesReqType = X_XFixesChangeCursor;
223a7e741d5Smrg    req->source = (CARD32) source;
224a7e741d5Smrg    req->destination = (CARD32) destination;
2254456fccdSmrg    UnlockDisplay(dpy);
2264456fccdSmrg    SyncHandle();
2274456fccdSmrg}
2284456fccdSmrg
2294456fccdSmrgvoid
2304456fccdSmrgXFixesChangeCursorByName (Display *dpy, Cursor source, const char *name)
2314456fccdSmrg{
2324456fccdSmrg    XFixesExtDisplayInfo	    *info = XFixesFindDisplay (dpy);
2334456fccdSmrg    xXFixesChangeCursorByNameReq    *req;
234a7e741d5Smrg    CARD16			    nbytes = (CARD16) strlen (name);
2354456fccdSmrg
2364456fccdSmrg    XFixesSimpleCheckExtension (dpy, info);
2374456fccdSmrg    if (info->major_version < 2)
2384456fccdSmrg	return;
2394456fccdSmrg    LockDisplay (dpy);
2404456fccdSmrg    GetReq (XFixesChangeCursorByName, req);
241a7e741d5Smrg    req->reqType = (CARD8) info->codes->major_opcode;
2424456fccdSmrg    req->xfixesReqType = X_XFixesChangeCursorByName;
243a7e741d5Smrg    req->source = (CARD32) source;
2444456fccdSmrg    req->nbytes = nbytes;
2454456fccdSmrg    req->length += (nbytes + 3) >> 2;
2464456fccdSmrg    Data (dpy, name, nbytes);
2474456fccdSmrg    UnlockDisplay(dpy);
2484456fccdSmrg    SyncHandle();
2494456fccdSmrg}
2504456fccdSmrg
2514456fccdSmrgvoid
2524456fccdSmrgXFixesHideCursor (Display *dpy, Window win)
2534456fccdSmrg{
2544456fccdSmrg    XFixesExtDisplayInfo	*info = XFixesFindDisplay (dpy);
2554456fccdSmrg    xXFixesHideCursorReq	*req;
2564456fccdSmrg
2574456fccdSmrg    XFixesSimpleCheckExtension (dpy, info);
2584456fccdSmrg    if (info->major_version < 4)
2594456fccdSmrg	return;
2604456fccdSmrg    LockDisplay (dpy);
2614456fccdSmrg    GetReq (XFixesHideCursor, req);
262a7e741d5Smrg    req->reqType = (CARD8) info->codes->major_opcode;
2634456fccdSmrg    req->xfixesReqType = X_XFixesHideCursor;
264a7e741d5Smrg    req->window = (CARD32) win;
2654456fccdSmrg    UnlockDisplay (dpy);
2664456fccdSmrg    SyncHandle ();
2674456fccdSmrg}
2684456fccdSmrg
2694456fccdSmrgvoid
2704456fccdSmrgXFixesShowCursor (Display *dpy, Window win)
2714456fccdSmrg{
2724456fccdSmrg    XFixesExtDisplayInfo	*info = XFixesFindDisplay (dpy);
2734456fccdSmrg    xXFixesShowCursorReq	*req;
2744456fccdSmrg
2754456fccdSmrg    XFixesSimpleCheckExtension (dpy, info);
2764456fccdSmrg    if (info->major_version < 4)
2774456fccdSmrg	return;
2784456fccdSmrg    LockDisplay (dpy);
2794456fccdSmrg    GetReq (XFixesShowCursor, req);
280a7e741d5Smrg    req->reqType = (CARD8) info->codes->major_opcode;
2814456fccdSmrg    req->xfixesReqType = X_XFixesShowCursor;
282a7e741d5Smrg    req->window = (CARD32) win;
2834456fccdSmrg    UnlockDisplay (dpy);
2844456fccdSmrg    SyncHandle ();
2854456fccdSmrg}
286ff63a143Smrg
287ff63a143SmrgPointerBarrier
288ff63a143SmrgXFixesCreatePointerBarrier(Display *dpy, Window w, int x1, int y1,
289ff63a143Smrg			   int x2, int y2, int directions,
290ff63a143Smrg			   int num_devices, int *devices)
291ff63a143Smrg{
292ff63a143Smrg    XFixesExtDisplayInfo *info = XFixesFindDisplay (dpy);
293ff63a143Smrg    xXFixesCreatePointerBarrierReq *req;
294ff63a143Smrg    PointerBarrier barrier;
295ff63a143Smrg    int extra = 0;
296ff63a143Smrg
297ff63a143Smrg    XFixesCheckExtension (dpy, info, 0);
298ff63a143Smrg    if (info->major_version < 5)
299ff63a143Smrg	return 0;
300ff63a143Smrg
301ff63a143Smrg    if (num_devices)
302ff63a143Smrg	extra = (((2 * num_devices) + 3) / 4) * 4;
303ff63a143Smrg
304ff63a143Smrg    LockDisplay (dpy);
305ff63a143Smrg    GetReqExtra (XFixesCreatePointerBarrier, extra, req);
306a7e741d5Smrg    req->reqType = (CARD8) info->codes->major_opcode;
307ff63a143Smrg    req->xfixesReqType = X_XFixesCreatePointerBarrier;
308a7e741d5Smrg    barrier = XAllocID (dpy);
309a7e741d5Smrg    req->barrier = (CARD32) barrier;
310a7e741d5Smrg    req->window = (CARD32) w;
311a7e741d5Smrg    req->x1 = (INT16) x1;
312a7e741d5Smrg    req->y1 = (INT16) y1;
313a7e741d5Smrg    req->x2 = (INT16) x2;
314a7e741d5Smrg    req->y2 = (INT16) y2;
315a7e741d5Smrg    req->directions = (CARD32) directions;
316a7e741d5Smrg    if ((req->num_devices = (CARD16) num_devices)) {
317ff63a143Smrg	int i;
318ff63a143Smrg	CARD16 *devs = (CARD16 *)(req + 1);
319ff63a143Smrg	for (i = 0; i < num_devices; i++)
320ff63a143Smrg	    devs[i] = (CARD16)(devices[i]);
321ff63a143Smrg    }
322ff63a143Smrg
323ff63a143Smrg    UnlockDisplay (dpy);
324ff63a143Smrg    SyncHandle();
325ff63a143Smrg    return barrier;
326ff63a143Smrg}
327ff63a143Smrg
328ff63a143Smrgvoid
329ff63a143SmrgXFixesDestroyPointerBarrier(Display *dpy, PointerBarrier b)
330ff63a143Smrg{
331ff63a143Smrg    XFixesExtDisplayInfo *info = XFixesFindDisplay (dpy);
332ff63a143Smrg    xXFixesDestroyPointerBarrierReq *req;
333ff63a143Smrg
334ff63a143Smrg    XFixesSimpleCheckExtension (dpy, info);
335ff63a143Smrg    if (info->major_version < 5)
336ff63a143Smrg	return;
337ff63a143Smrg
338ff63a143Smrg    LockDisplay (dpy);
339ff63a143Smrg    GetReq (XFixesDestroyPointerBarrier, req);
340a7e741d5Smrg    req->reqType = (CARD8) info->codes->major_opcode;
341ff63a143Smrg    req->xfixesReqType = X_XFixesDestroyPointerBarrier;
342a7e741d5Smrg    req->barrier = (CARD32) b;
343ff63a143Smrg    UnlockDisplay (dpy);
344ff63a143Smrg    SyncHandle();
345ff63a143Smrg}
346