83a7a68ea3107168aec5d1916ddbf60256b616f3
[platform/upstream/libXi.git] / src / XIProperties.c
1 /*
2  * Copyright © 2009 Red Hat, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  */
24
25 /***********************************************************************
26  * XI2 property requests, list, change, delete and get properties.
27  */
28
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33
34 #include <stdint.h>
35 #include <X11/Xlibint.h>
36 #include <X11/extensions/XI2.h>
37 #include <X11/extensions/XI2proto.h>
38 #include <X11/extensions/XInput2.h>
39 #include <X11/extensions/extutil.h>
40 #include "XIint.h"
41
42 Atom*
43 XIListProperties(Display* dpy, int deviceid, int *num_props_return)
44 {
45     xXIListPropertiesReq        *req;
46     xXIListPropertiesReply      rep;
47     XExtDisplayInfo             *info = XInput_find_display(dpy);
48     Atom                        *props = NULL;
49
50     LockDisplay(dpy);
51     *num_props_return = 0;
52     if (_XiCheckExtInit(dpy, XInput_2_0, info) == -1)
53         goto cleanup;
54
55     GetReq(XIListProperties, req);
56     req->reqType = info->codes->major_opcode;
57     req->ReqType = X_XIListProperties;
58     req->deviceid = deviceid;
59
60     if (!_XReply(dpy, (xReply*)&rep, 0, xFalse))
61         goto cleanup;
62
63     if (rep.num_properties) {
64         props = (Atom*)Xmalloc(rep.num_properties * sizeof(Atom));
65         if (!props)
66         {
67             _XEatData(dpy, rep.num_properties << 2);
68             goto cleanup;
69         }
70
71         _XRead32(dpy, (long*)props, rep.num_properties << 2);
72     }
73
74     *num_props_return = rep.num_properties;
75
76 cleanup:
77     UnlockDisplay(dpy);
78     SyncHandle();
79     return props;
80 }
81
82
83 void
84 XIDeleteProperty(Display* dpy, int deviceid, Atom property)
85 {
86     xXIDeletePropertyReq   *req;
87
88     XExtDisplayInfo *info = XInput_find_display(dpy);
89
90     LockDisplay(dpy);
91     if (_XiCheckExtInit(dpy, XInput_2_0, info) == -1)
92         return;
93
94     GetReq(XIDeleteProperty, req);
95     req->reqType    = info->codes->major_opcode;
96     req->ReqType    = X_XIDeleteProperty;
97     req->deviceid   = deviceid;
98     req->property   = property;
99
100     UnlockDisplay(dpy);
101     SyncHandle();
102 }
103
104 void
105 XIChangeProperty(Display* dpy, int deviceid, Atom property, Atom type,
106                  int format, int mode, unsigned char *data, int num_items)
107 {
108     xXIChangePropertyReq *req;
109     int len;
110
111     XExtDisplayInfo *info = XInput_find_display(dpy);
112
113     LockDisplay(dpy);
114     if (_XiCheckExtInit(dpy, XInput_2_0, info) == -1)
115         return;
116
117     GetReq(XIChangeProperty, req);
118     req->reqType    = info->codes->major_opcode;
119     req->ReqType    = X_XIChangeProperty;
120     req->deviceid   = deviceid;
121     req->property   = property;
122     req->type       = type;
123     req->mode       = mode;
124     if (num_items < 0) {
125         req->num_items = 0;
126         req->format = 0; /* ask for garbage, get garbage */
127     } else {
128         req->num_items = num_items;
129         req->format = format;
130     }
131
132     switch (req->format) {
133     case 8:
134         len = (num_items + 3)/4;
135         SetReqLen(req, len, len);
136         len = num_items;
137         break;
138
139     case 16:
140         len = (num_items + 1)/2;
141         SetReqLen(req, len, len);
142         len = num_items * 2;
143         break;
144
145     case 32:
146         len = num_items;
147         SetReqLen(req, len, len);
148         len = num_items * 4;
149         break;
150
151     default:
152         /* BadValue will be generated */ ;
153         len = 0;
154     }
155
156     /* we use data instead of Data32 and friends to avoid Xlib's braindead
157      * 64 bit handling.*/
158
159     Data(dpy, (const char*)data, len);
160     UnlockDisplay(dpy);
161     SyncHandle();
162 }
163
164 Status
165 XIGetProperty(Display* dpy, int deviceid, Atom property, long offset,
166               long length, Bool delete_property, Atom type,
167               Atom *type_return, int *format_return,
168               unsigned long *num_items_return,unsigned long *bytes_after_return,
169               unsigned char **data)
170 {
171     xXIGetPropertyReq   *req;
172     xXIGetPropertyReply rep;
173     long                    nbytes, rbytes;
174
175     XExtDisplayInfo *info = XInput_find_display(dpy);
176
177     LockDisplay(dpy);
178     if (_XiCheckExtInit(dpy, XInput_2_0, info) == -1)
179         return 1;
180
181     GetReq(XIGetProperty, req);
182     req->reqType    = info->codes->major_opcode;
183     req->ReqType    = X_XIGetProperty;
184     req->deviceid   = deviceid;
185     req->property   = property;
186     req->type       = type;
187     req->offset     = offset;
188     req->len        = length;
189     req->delete     = delete_property;
190
191     if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
192     {
193         UnlockDisplay (dpy);
194         SyncHandle ();
195         return 1;
196     }
197
198     *data = NULL;
199
200     if (rep.type != None) {
201         if (rep.format != 8 && rep.format != 16 && rep.format != 32) {
202             /*
203              * This part of the code should never be reached.  If it is,
204              * the server sent back a property with an invalid format.
205              */
206             nbytes = rep.length << 2;
207             _XEatData(dpy, nbytes);
208             UnlockDisplay(dpy);
209             SyncHandle();
210             return(BadImplementation);
211         }
212
213         /*
214          * One extra byte is malloced than is needed to contain the property
215          * data, but this last byte is null terminated and convenient for
216          * returning string properties, so the client doesn't then have to
217          * recopy the string to make it null terminated.
218          */
219
220         nbytes = rep.num_items * rep.format/8;
221         rbytes = nbytes + 1;
222         *data = Xmalloc(rbytes);
223
224         if (!(*data)) {
225             _XEatData(dpy, nbytes);
226             UnlockDisplay(dpy);
227             SyncHandle();
228             return(BadAlloc);
229         }
230
231         _XReadPad (dpy, (char *)*data, nbytes);
232         (*data)[rbytes - 1] = '\0';
233     }
234
235     *type_return        = rep.type;
236     *format_return      = rep.format;
237     *num_items_return   = rep.num_items;
238     *bytes_after_return = rep.bytes_after;
239     UnlockDisplay (dpy);
240     SyncHandle();
241     return Success;
242 }