xref: /OK3568_Linux_fs/external/xserver/randr/rrproviderproperty.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright © 2006 Keith Packard
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Permission to use, copy, modify, distribute, and sell this software and its
5*4882a593Smuzhiyun  * documentation for any purpose is hereby granted without fee, provided that
6*4882a593Smuzhiyun  * the above copyright notice appear in all copies and that both that copyright
7*4882a593Smuzhiyun  * notice and this permission notice appear in supporting documentation, and
8*4882a593Smuzhiyun  * that the name of the copyright holders not be used in advertising or
9*4882a593Smuzhiyun  * publicity pertaining to distribution of the software without specific,
10*4882a593Smuzhiyun  * written prior permission.  The copyright holders make no representations
11*4882a593Smuzhiyun  * about the suitability of this software for any purpose.  It is provided "as
12*4882a593Smuzhiyun  * is" without express or implied warranty.
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15*4882a593Smuzhiyun  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16*4882a593Smuzhiyun  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17*4882a593Smuzhiyun  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18*4882a593Smuzhiyun  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19*4882a593Smuzhiyun  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20*4882a593Smuzhiyun  * OF THIS SOFTWARE.
21*4882a593Smuzhiyun  */
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #include "randrstr.h"
24*4882a593Smuzhiyun #include "propertyst.h"
25*4882a593Smuzhiyun #include "swaprep.h"
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun static int
DeliverPropertyEvent(WindowPtr pWin,void * value)28*4882a593Smuzhiyun DeliverPropertyEvent(WindowPtr pWin, void *value)
29*4882a593Smuzhiyun {
30*4882a593Smuzhiyun     xRRProviderPropertyNotifyEvent *event = value;
31*4882a593Smuzhiyun     RREventPtr *pHead, pRREvent;
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun     dixLookupResourceByType((void **) &pHead, pWin->drawable.id,
34*4882a593Smuzhiyun                             RREventType, serverClient, DixReadAccess);
35*4882a593Smuzhiyun     if (!pHead)
36*4882a593Smuzhiyun         return WT_WALKCHILDREN;
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun     for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
39*4882a593Smuzhiyun         if (!(pRREvent->mask & RRProviderPropertyNotifyMask))
40*4882a593Smuzhiyun             continue;
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun         event->window = pRREvent->window->drawable.id;
43*4882a593Smuzhiyun         WriteEventsToClient(pRREvent->client, 1, (xEvent *) event);
44*4882a593Smuzhiyun     }
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun     return WT_WALKCHILDREN;
47*4882a593Smuzhiyun }
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun static void
RRDeliverPropertyEvent(ScreenPtr pScreen,xEvent * event)50*4882a593Smuzhiyun RRDeliverPropertyEvent(ScreenPtr pScreen, xEvent *event)
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun     if (!(dispatchException & (DE_RESET | DE_TERMINATE)))
53*4882a593Smuzhiyun         WalkTree(pScreen, DeliverPropertyEvent, event);
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun static void
RRDestroyProviderProperty(RRPropertyPtr prop)57*4882a593Smuzhiyun RRDestroyProviderProperty(RRPropertyPtr prop)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun     free(prop->valid_values);
60*4882a593Smuzhiyun     free(prop->current.data);
61*4882a593Smuzhiyun     free(prop->pending.data);
62*4882a593Smuzhiyun     free(prop);
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun static void
RRDeleteProperty(RRProviderRec * provider,RRPropertyRec * prop)66*4882a593Smuzhiyun RRDeleteProperty(RRProviderRec * provider, RRPropertyRec * prop)
67*4882a593Smuzhiyun {
68*4882a593Smuzhiyun     xRRProviderPropertyNotifyEvent event = {
69*4882a593Smuzhiyun         .type = RREventBase + RRNotify,
70*4882a593Smuzhiyun         .subCode = RRNotify_ProviderProperty,
71*4882a593Smuzhiyun         .provider = provider->id,
72*4882a593Smuzhiyun         .state = PropertyDelete,
73*4882a593Smuzhiyun         .atom = prop->propertyName,
74*4882a593Smuzhiyun         .timestamp = currentTime.milliseconds
75*4882a593Smuzhiyun     };
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun     RRDeliverPropertyEvent(provider->pScreen, (xEvent *) &event);
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun     RRDestroyProviderProperty(prop);
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun void
RRDeleteAllProviderProperties(RRProviderPtr provider)83*4882a593Smuzhiyun RRDeleteAllProviderProperties(RRProviderPtr provider)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun     RRPropertyPtr prop, next;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun     for (prop = provider->properties; prop; prop = next) {
88*4882a593Smuzhiyun         next = prop->next;
89*4882a593Smuzhiyun         RRDeleteProperty(provider, prop);
90*4882a593Smuzhiyun     }
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun static void
RRInitProviderPropertyValue(RRPropertyValuePtr property_value)94*4882a593Smuzhiyun RRInitProviderPropertyValue(RRPropertyValuePtr property_value)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun     property_value->type = None;
97*4882a593Smuzhiyun     property_value->format = 0;
98*4882a593Smuzhiyun     property_value->size = 0;
99*4882a593Smuzhiyun     property_value->data = NULL;
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun static RRPropertyPtr
RRCreateProviderProperty(Atom property)103*4882a593Smuzhiyun RRCreateProviderProperty(Atom property)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun     RRPropertyPtr prop;
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun     prop = (RRPropertyPtr) malloc(sizeof(RRPropertyRec));
108*4882a593Smuzhiyun     if (!prop)
109*4882a593Smuzhiyun         return NULL;
110*4882a593Smuzhiyun     prop->next = NULL;
111*4882a593Smuzhiyun     prop->propertyName = property;
112*4882a593Smuzhiyun     prop->is_pending = FALSE;
113*4882a593Smuzhiyun     prop->range = FALSE;
114*4882a593Smuzhiyun     prop->immutable = FALSE;
115*4882a593Smuzhiyun     prop->num_valid = 0;
116*4882a593Smuzhiyun     prop->valid_values = NULL;
117*4882a593Smuzhiyun     RRInitProviderPropertyValue(&prop->current);
118*4882a593Smuzhiyun     RRInitProviderPropertyValue(&prop->pending);
119*4882a593Smuzhiyun     return prop;
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun void
RRDeleteProviderProperty(RRProviderPtr provider,Atom property)123*4882a593Smuzhiyun RRDeleteProviderProperty(RRProviderPtr provider, Atom property)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun     RRPropertyRec *prop, **prev;
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun     for (prev = &provider->properties; (prop = *prev); prev = &(prop->next))
128*4882a593Smuzhiyun         if (prop->propertyName == property) {
129*4882a593Smuzhiyun             *prev = prop->next;
130*4882a593Smuzhiyun             RRDeleteProperty(provider, prop);
131*4882a593Smuzhiyun             return;
132*4882a593Smuzhiyun         }
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun int
RRChangeProviderProperty(RRProviderPtr provider,Atom property,Atom type,int format,int mode,unsigned long len,void * value,Bool sendevent,Bool pending)136*4882a593Smuzhiyun RRChangeProviderProperty(RRProviderPtr provider, Atom property, Atom type,
137*4882a593Smuzhiyun                        int format, int mode, unsigned long len,
138*4882a593Smuzhiyun                        void *value, Bool sendevent, Bool pending)
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun     RRPropertyPtr prop;
141*4882a593Smuzhiyun     rrScrPrivPtr pScrPriv = rrGetScrPriv(provider->pScreen);
142*4882a593Smuzhiyun     int size_in_bytes;
143*4882a593Smuzhiyun     int total_size;
144*4882a593Smuzhiyun     unsigned long total_len;
145*4882a593Smuzhiyun     RRPropertyValuePtr prop_value;
146*4882a593Smuzhiyun     RRPropertyValueRec new_value;
147*4882a593Smuzhiyun     Bool add = FALSE;
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun     size_in_bytes = format >> 3;
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun     /* first see if property already exists */
152*4882a593Smuzhiyun     prop = RRQueryProviderProperty(provider, property);
153*4882a593Smuzhiyun     if (!prop) {                /* just add to list */
154*4882a593Smuzhiyun         prop = RRCreateProviderProperty(property);
155*4882a593Smuzhiyun         if (!prop)
156*4882a593Smuzhiyun             return BadAlloc;
157*4882a593Smuzhiyun         add = TRUE;
158*4882a593Smuzhiyun         mode = PropModeReplace;
159*4882a593Smuzhiyun     }
160*4882a593Smuzhiyun     if (pending && prop->is_pending)
161*4882a593Smuzhiyun         prop_value = &prop->pending;
162*4882a593Smuzhiyun     else
163*4882a593Smuzhiyun         prop_value = &prop->current;
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun     /* To append or prepend to a property the request format and type
166*4882a593Smuzhiyun        must match those of the already defined property.  The
167*4882a593Smuzhiyun        existing format and type are irrelevant when using the mode
168*4882a593Smuzhiyun        "PropModeReplace" since they will be written over. */
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun     if ((format != prop_value->format) && (mode != PropModeReplace))
171*4882a593Smuzhiyun         return BadMatch;
172*4882a593Smuzhiyun     if ((prop_value->type != type) && (mode != PropModeReplace))
173*4882a593Smuzhiyun         return BadMatch;
174*4882a593Smuzhiyun     new_value = *prop_value;
175*4882a593Smuzhiyun     if (mode == PropModeReplace)
176*4882a593Smuzhiyun         total_len = len;
177*4882a593Smuzhiyun     else
178*4882a593Smuzhiyun         total_len = prop_value->size + len;
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun     if (mode == PropModeReplace || len > 0) {
181*4882a593Smuzhiyun         void *new_data = NULL, *old_data = NULL;
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun         total_size = total_len * size_in_bytes;
184*4882a593Smuzhiyun         new_value.data = (void *) malloc(total_size);
185*4882a593Smuzhiyun         if (!new_value.data && total_size) {
186*4882a593Smuzhiyun             if (add)
187*4882a593Smuzhiyun                 RRDestroyProviderProperty(prop);
188*4882a593Smuzhiyun             return BadAlloc;
189*4882a593Smuzhiyun         }
190*4882a593Smuzhiyun         new_value.size = len;
191*4882a593Smuzhiyun         new_value.type = type;
192*4882a593Smuzhiyun         new_value.format = format;
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun         switch (mode) {
195*4882a593Smuzhiyun         case PropModeReplace:
196*4882a593Smuzhiyun             new_data = new_value.data;
197*4882a593Smuzhiyun             old_data = NULL;
198*4882a593Smuzhiyun             break;
199*4882a593Smuzhiyun         case PropModeAppend:
200*4882a593Smuzhiyun             new_data = (void *) (((char *) new_value.data) +
201*4882a593Smuzhiyun                                   (prop_value->size * size_in_bytes));
202*4882a593Smuzhiyun             old_data = new_value.data;
203*4882a593Smuzhiyun             break;
204*4882a593Smuzhiyun         case PropModePrepend:
205*4882a593Smuzhiyun             new_data = new_value.data;
206*4882a593Smuzhiyun             old_data = (void *) (((char *) new_value.data) +
207*4882a593Smuzhiyun                                   (prop_value->size * size_in_bytes));
208*4882a593Smuzhiyun             break;
209*4882a593Smuzhiyun         }
210*4882a593Smuzhiyun         if (new_data)
211*4882a593Smuzhiyun             memcpy((char *) new_data, (char *) value, len * size_in_bytes);
212*4882a593Smuzhiyun         if (old_data)
213*4882a593Smuzhiyun             memcpy((char *) old_data, (char *) prop_value->data,
214*4882a593Smuzhiyun                    prop_value->size * size_in_bytes);
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun         if (pending && pScrPriv->rrProviderSetProperty &&
217*4882a593Smuzhiyun             !pScrPriv->rrProviderSetProperty(provider->pScreen, provider,
218*4882a593Smuzhiyun                                            prop->propertyName, &new_value)) {
219*4882a593Smuzhiyun             if (add)
220*4882a593Smuzhiyun                 RRDestroyProviderProperty(prop);
221*4882a593Smuzhiyun             free(new_value.data);
222*4882a593Smuzhiyun             return BadValue;
223*4882a593Smuzhiyun         }
224*4882a593Smuzhiyun         free(prop_value->data);
225*4882a593Smuzhiyun         *prop_value = new_value;
226*4882a593Smuzhiyun     }
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun     else if (len == 0) {
229*4882a593Smuzhiyun         /* do nothing */
230*4882a593Smuzhiyun     }
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun     if (add) {
233*4882a593Smuzhiyun         prop->next = provider->properties;
234*4882a593Smuzhiyun         provider->properties = prop;
235*4882a593Smuzhiyun     }
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun     if (pending && prop->is_pending)
238*4882a593Smuzhiyun         provider->pendingProperties = TRUE;
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun     if (sendevent) {
241*4882a593Smuzhiyun         xRRProviderPropertyNotifyEvent event = {
242*4882a593Smuzhiyun             .type = RREventBase + RRNotify,
243*4882a593Smuzhiyun             .subCode = RRNotify_ProviderProperty,
244*4882a593Smuzhiyun             .provider = provider->id,
245*4882a593Smuzhiyun             .state = PropertyNewValue,
246*4882a593Smuzhiyun             .atom = prop->propertyName,
247*4882a593Smuzhiyun             .timestamp = currentTime.milliseconds
248*4882a593Smuzhiyun         };
249*4882a593Smuzhiyun         RRDeliverPropertyEvent(provider->pScreen, (xEvent *) &event);
250*4882a593Smuzhiyun     }
251*4882a593Smuzhiyun     return Success;
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun Bool
RRPostProviderPendingProperties(RRProviderPtr provider)255*4882a593Smuzhiyun RRPostProviderPendingProperties(RRProviderPtr provider)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun     RRPropertyValuePtr pending_value;
258*4882a593Smuzhiyun     RRPropertyValuePtr current_value;
259*4882a593Smuzhiyun     RRPropertyPtr property;
260*4882a593Smuzhiyun     Bool ret = TRUE;
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun     if (!provider->pendingProperties)
263*4882a593Smuzhiyun         return TRUE;
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun     provider->pendingProperties = FALSE;
266*4882a593Smuzhiyun     for (property = provider->properties; property; property = property->next) {
267*4882a593Smuzhiyun         /* Skip non-pending properties */
268*4882a593Smuzhiyun         if (!property->is_pending)
269*4882a593Smuzhiyun             continue;
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun         pending_value = &property->pending;
272*4882a593Smuzhiyun         current_value = &property->current;
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun         /*
275*4882a593Smuzhiyun          * If the pending and current values are equal, don't mark it
276*4882a593Smuzhiyun          * as changed (which would deliver an event)
277*4882a593Smuzhiyun          */
278*4882a593Smuzhiyun         if (pending_value->type == current_value->type &&
279*4882a593Smuzhiyun             pending_value->format == current_value->format &&
280*4882a593Smuzhiyun             pending_value->size == current_value->size &&
281*4882a593Smuzhiyun             !memcmp(pending_value->data, current_value->data,
282*4882a593Smuzhiyun                     pending_value->size * (pending_value->format / 8)))
283*4882a593Smuzhiyun             continue;
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun         if (RRChangeProviderProperty(provider, property->propertyName,
286*4882a593Smuzhiyun                                    pending_value->type, pending_value->format,
287*4882a593Smuzhiyun                                    PropModeReplace, pending_value->size,
288*4882a593Smuzhiyun                                    pending_value->data, TRUE, FALSE) != Success)
289*4882a593Smuzhiyun             ret = FALSE;
290*4882a593Smuzhiyun     }
291*4882a593Smuzhiyun     return ret;
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun RRPropertyPtr
RRQueryProviderProperty(RRProviderPtr provider,Atom property)295*4882a593Smuzhiyun RRQueryProviderProperty(RRProviderPtr provider, Atom property)
296*4882a593Smuzhiyun {
297*4882a593Smuzhiyun     RRPropertyPtr prop;
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun     for (prop = provider->properties; prop; prop = prop->next)
300*4882a593Smuzhiyun         if (prop->propertyName == property)
301*4882a593Smuzhiyun             return prop;
302*4882a593Smuzhiyun     return NULL;
303*4882a593Smuzhiyun }
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun RRPropertyValuePtr
RRGetProviderProperty(RRProviderPtr provider,Atom property,Bool pending)306*4882a593Smuzhiyun RRGetProviderProperty(RRProviderPtr provider, Atom property, Bool pending)
307*4882a593Smuzhiyun {
308*4882a593Smuzhiyun     RRPropertyPtr prop = RRQueryProviderProperty(provider, property);
309*4882a593Smuzhiyun     rrScrPrivPtr pScrPriv = rrGetScrPriv(provider->pScreen);
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun     if (!prop)
312*4882a593Smuzhiyun         return NULL;
313*4882a593Smuzhiyun     if (pending && prop->is_pending)
314*4882a593Smuzhiyun         return &prop->pending;
315*4882a593Smuzhiyun     else {
316*4882a593Smuzhiyun #if RANDR_13_INTERFACE
317*4882a593Smuzhiyun         /* If we can, try to update the property value first */
318*4882a593Smuzhiyun         if (pScrPriv->rrProviderGetProperty)
319*4882a593Smuzhiyun             pScrPriv->rrProviderGetProperty(provider->pScreen, provider,
320*4882a593Smuzhiyun                                           prop->propertyName);
321*4882a593Smuzhiyun #endif
322*4882a593Smuzhiyun         return &prop->current;
323*4882a593Smuzhiyun     }
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun int
RRConfigureProviderProperty(RRProviderPtr provider,Atom property,Bool pending,Bool range,Bool immutable,int num_values,INT32 * values)327*4882a593Smuzhiyun RRConfigureProviderProperty(RRProviderPtr provider, Atom property,
328*4882a593Smuzhiyun                           Bool pending, Bool range, Bool immutable,
329*4882a593Smuzhiyun                           int num_values, INT32 *values)
330*4882a593Smuzhiyun {
331*4882a593Smuzhiyun     RRPropertyPtr prop = RRQueryProviderProperty(provider, property);
332*4882a593Smuzhiyun     Bool add = FALSE;
333*4882a593Smuzhiyun     INT32 *new_values;
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun     if (!prop) {
336*4882a593Smuzhiyun         prop = RRCreateProviderProperty(property);
337*4882a593Smuzhiyun         if (!prop)
338*4882a593Smuzhiyun             return BadAlloc;
339*4882a593Smuzhiyun         add = TRUE;
340*4882a593Smuzhiyun     }
341*4882a593Smuzhiyun     else if (prop->immutable && !immutable)
342*4882a593Smuzhiyun         return BadAccess;
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun     /*
345*4882a593Smuzhiyun      * ranges must have even number of values
346*4882a593Smuzhiyun      */
347*4882a593Smuzhiyun     if (range && (num_values & 1)) {
348*4882a593Smuzhiyun         if (add)
349*4882a593Smuzhiyun             RRDestroyProviderProperty(prop);
350*4882a593Smuzhiyun         return BadMatch;
351*4882a593Smuzhiyun     }
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun     new_values = xallocarray(num_values, sizeof(INT32));
354*4882a593Smuzhiyun     if (!new_values && num_values) {
355*4882a593Smuzhiyun         if (add)
356*4882a593Smuzhiyun             RRDestroyProviderProperty(prop);
357*4882a593Smuzhiyun         return BadAlloc;
358*4882a593Smuzhiyun     }
359*4882a593Smuzhiyun     if (num_values)
360*4882a593Smuzhiyun         memcpy(new_values, values, num_values * sizeof(INT32));
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun     /*
363*4882a593Smuzhiyun      * Property moving from pending to non-pending
364*4882a593Smuzhiyun      * loses any pending values
365*4882a593Smuzhiyun      */
366*4882a593Smuzhiyun     if (prop->is_pending && !pending) {
367*4882a593Smuzhiyun         free(prop->pending.data);
368*4882a593Smuzhiyun         RRInitProviderPropertyValue(&prop->pending);
369*4882a593Smuzhiyun     }
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun     prop->is_pending = pending;
372*4882a593Smuzhiyun     prop->range = range;
373*4882a593Smuzhiyun     prop->immutable = immutable;
374*4882a593Smuzhiyun     prop->num_valid = num_values;
375*4882a593Smuzhiyun     free(prop->valid_values);
376*4882a593Smuzhiyun     prop->valid_values = new_values;
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun     if (add) {
379*4882a593Smuzhiyun         prop->next = provider->properties;
380*4882a593Smuzhiyun         provider->properties = prop;
381*4882a593Smuzhiyun     }
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun     return Success;
384*4882a593Smuzhiyun }
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun int
ProcRRListProviderProperties(ClientPtr client)387*4882a593Smuzhiyun ProcRRListProviderProperties(ClientPtr client)
388*4882a593Smuzhiyun {
389*4882a593Smuzhiyun     REQUEST(xRRListProviderPropertiesReq);
390*4882a593Smuzhiyun     Atom *pAtoms = NULL, *temppAtoms;
391*4882a593Smuzhiyun     xRRListProviderPropertiesReply rep;
392*4882a593Smuzhiyun     int numProps = 0;
393*4882a593Smuzhiyun     RRProviderPtr provider;
394*4882a593Smuzhiyun     RRPropertyPtr prop;
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xRRListProviderPropertiesReq);
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun     VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun     for (prop = provider->properties; prop; prop = prop->next)
401*4882a593Smuzhiyun         numProps++;
402*4882a593Smuzhiyun     if (numProps)
403*4882a593Smuzhiyun         if (!(pAtoms = xallocarray(numProps, sizeof(Atom))))
404*4882a593Smuzhiyun             return BadAlloc;
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun     rep = (xRRListProviderPropertiesReply) {
407*4882a593Smuzhiyun         .type = X_Reply,
408*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
409*4882a593Smuzhiyun         .length = bytes_to_int32(numProps * sizeof(Atom)),
410*4882a593Smuzhiyun         .nAtoms = numProps
411*4882a593Smuzhiyun     };
412*4882a593Smuzhiyun     if (client->swapped) {
413*4882a593Smuzhiyun         swaps(&rep.sequenceNumber);
414*4882a593Smuzhiyun         swapl(&rep.length);
415*4882a593Smuzhiyun         swaps(&rep.nAtoms);
416*4882a593Smuzhiyun     }
417*4882a593Smuzhiyun     temppAtoms = pAtoms;
418*4882a593Smuzhiyun     for (prop = provider->properties; prop; prop = prop->next)
419*4882a593Smuzhiyun         *temppAtoms++ = prop->propertyName;
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun     WriteToClient(client, sizeof(xRRListProviderPropertiesReply), (char *) &rep);
422*4882a593Smuzhiyun     if (numProps) {
423*4882a593Smuzhiyun         client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
424*4882a593Smuzhiyun         WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms);
425*4882a593Smuzhiyun         free(pAtoms);
426*4882a593Smuzhiyun     }
427*4882a593Smuzhiyun     return Success;
428*4882a593Smuzhiyun }
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun int
ProcRRQueryProviderProperty(ClientPtr client)431*4882a593Smuzhiyun ProcRRQueryProviderProperty(ClientPtr client)
432*4882a593Smuzhiyun {
433*4882a593Smuzhiyun     REQUEST(xRRQueryProviderPropertyReq);
434*4882a593Smuzhiyun     xRRQueryProviderPropertyReply rep;
435*4882a593Smuzhiyun     RRProviderPtr provider;
436*4882a593Smuzhiyun     RRPropertyPtr prop;
437*4882a593Smuzhiyun     char *extra = NULL;
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xRRQueryProviderPropertyReq);
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun     VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun     prop = RRQueryProviderProperty(provider, stuff->property);
444*4882a593Smuzhiyun     if (!prop)
445*4882a593Smuzhiyun         return BadName;
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun     if (prop->num_valid) {
448*4882a593Smuzhiyun         extra = xallocarray(prop->num_valid, sizeof(INT32));
449*4882a593Smuzhiyun         if (!extra)
450*4882a593Smuzhiyun             return BadAlloc;
451*4882a593Smuzhiyun     }
452*4882a593Smuzhiyun     rep = (xRRQueryProviderPropertyReply) {
453*4882a593Smuzhiyun         .type = X_Reply,
454*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
455*4882a593Smuzhiyun         .length = prop->num_valid,
456*4882a593Smuzhiyun         .pending = prop->is_pending,
457*4882a593Smuzhiyun         .range = prop->range,
458*4882a593Smuzhiyun         .immutable = prop->immutable
459*4882a593Smuzhiyun     };
460*4882a593Smuzhiyun     if (client->swapped) {
461*4882a593Smuzhiyun         swaps(&rep.sequenceNumber);
462*4882a593Smuzhiyun         swapl(&rep.length);
463*4882a593Smuzhiyun     }
464*4882a593Smuzhiyun     WriteToClient(client, sizeof(xRRQueryProviderPropertyReply), (char *) &rep);
465*4882a593Smuzhiyun     if (prop->num_valid) {
466*4882a593Smuzhiyun         memcpy(extra, prop->valid_values, prop->num_valid * sizeof(INT32));
467*4882a593Smuzhiyun         client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
468*4882a593Smuzhiyun         WriteSwappedDataToClient(client, prop->num_valid * sizeof(INT32),
469*4882a593Smuzhiyun                                  extra);
470*4882a593Smuzhiyun         free(extra);
471*4882a593Smuzhiyun     }
472*4882a593Smuzhiyun     return Success;
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun int
ProcRRConfigureProviderProperty(ClientPtr client)476*4882a593Smuzhiyun ProcRRConfigureProviderProperty(ClientPtr client)
477*4882a593Smuzhiyun {
478*4882a593Smuzhiyun     REQUEST(xRRConfigureProviderPropertyReq);
479*4882a593Smuzhiyun     RRProviderPtr provider;
480*4882a593Smuzhiyun     int num_valid;
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun     REQUEST_AT_LEAST_SIZE(xRRConfigureProviderPropertyReq);
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun     VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun     num_valid =
487*4882a593Smuzhiyun         stuff->length - bytes_to_int32(sizeof(xRRConfigureProviderPropertyReq));
488*4882a593Smuzhiyun     return RRConfigureProviderProperty(provider, stuff->property, stuff->pending,
489*4882a593Smuzhiyun                                      stuff->range, FALSE, num_valid,
490*4882a593Smuzhiyun                                      (INT32 *) (stuff + 1));
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun int
ProcRRChangeProviderProperty(ClientPtr client)494*4882a593Smuzhiyun ProcRRChangeProviderProperty(ClientPtr client)
495*4882a593Smuzhiyun {
496*4882a593Smuzhiyun     REQUEST(xRRChangeProviderPropertyReq);
497*4882a593Smuzhiyun     RRProviderPtr provider;
498*4882a593Smuzhiyun     char format, mode;
499*4882a593Smuzhiyun     unsigned long len;
500*4882a593Smuzhiyun     int sizeInBytes;
501*4882a593Smuzhiyun     int totalSize;
502*4882a593Smuzhiyun     int err;
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun     REQUEST_AT_LEAST_SIZE(xRRChangeProviderPropertyReq);
505*4882a593Smuzhiyun     UpdateCurrentTime();
506*4882a593Smuzhiyun     format = stuff->format;
507*4882a593Smuzhiyun     mode = stuff->mode;
508*4882a593Smuzhiyun     if ((mode != PropModeReplace) && (mode != PropModeAppend) &&
509*4882a593Smuzhiyun         (mode != PropModePrepend)) {
510*4882a593Smuzhiyun         client->errorValue = mode;
511*4882a593Smuzhiyun         return BadValue;
512*4882a593Smuzhiyun     }
513*4882a593Smuzhiyun     if ((format != 8) && (format != 16) && (format != 32)) {
514*4882a593Smuzhiyun         client->errorValue = format;
515*4882a593Smuzhiyun         return BadValue;
516*4882a593Smuzhiyun     }
517*4882a593Smuzhiyun     len = stuff->nUnits;
518*4882a593Smuzhiyun     if (len > bytes_to_int32((0xffffffff - sizeof(xChangePropertyReq))))
519*4882a593Smuzhiyun         return BadLength;
520*4882a593Smuzhiyun     sizeInBytes = format >> 3;
521*4882a593Smuzhiyun     totalSize = len * sizeInBytes;
522*4882a593Smuzhiyun     REQUEST_FIXED_SIZE(xRRChangeProviderPropertyReq, totalSize);
523*4882a593Smuzhiyun 
524*4882a593Smuzhiyun     VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun     if (!ValidAtom(stuff->property)) {
527*4882a593Smuzhiyun         client->errorValue = stuff->property;
528*4882a593Smuzhiyun         return BadAtom;
529*4882a593Smuzhiyun     }
530*4882a593Smuzhiyun     if (!ValidAtom(stuff->type)) {
531*4882a593Smuzhiyun         client->errorValue = stuff->type;
532*4882a593Smuzhiyun         return BadAtom;
533*4882a593Smuzhiyun     }
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun     err = RRChangeProviderProperty(provider, stuff->property,
536*4882a593Smuzhiyun                                  stuff->type, (int) format,
537*4882a593Smuzhiyun                                  (int) mode, len, (void *) &stuff[1], TRUE,
538*4882a593Smuzhiyun                                  TRUE);
539*4882a593Smuzhiyun     if (err != Success)
540*4882a593Smuzhiyun         return err;
541*4882a593Smuzhiyun     else
542*4882a593Smuzhiyun         return Success;
543*4882a593Smuzhiyun }
544*4882a593Smuzhiyun 
545*4882a593Smuzhiyun int
ProcRRDeleteProviderProperty(ClientPtr client)546*4882a593Smuzhiyun ProcRRDeleteProviderProperty(ClientPtr client)
547*4882a593Smuzhiyun {
548*4882a593Smuzhiyun     REQUEST(xRRDeleteProviderPropertyReq);
549*4882a593Smuzhiyun     RRProviderPtr provider;
550*4882a593Smuzhiyun     RRPropertyPtr prop;
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xRRDeleteProviderPropertyReq);
553*4882a593Smuzhiyun     UpdateCurrentTime();
554*4882a593Smuzhiyun     VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun     if (!ValidAtom(stuff->property)) {
557*4882a593Smuzhiyun         client->errorValue = stuff->property;
558*4882a593Smuzhiyun         return BadAtom;
559*4882a593Smuzhiyun     }
560*4882a593Smuzhiyun 
561*4882a593Smuzhiyun     prop = RRQueryProviderProperty(provider, stuff->property);
562*4882a593Smuzhiyun     if (!prop) {
563*4882a593Smuzhiyun         client->errorValue = stuff->property;
564*4882a593Smuzhiyun         return BadName;
565*4882a593Smuzhiyun     }
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun     if (prop->immutable) {
568*4882a593Smuzhiyun         client->errorValue = stuff->property;
569*4882a593Smuzhiyun         return BadAccess;
570*4882a593Smuzhiyun     }
571*4882a593Smuzhiyun 
572*4882a593Smuzhiyun     RRDeleteProviderProperty(provider, stuff->property);
573*4882a593Smuzhiyun     return Success;
574*4882a593Smuzhiyun }
575*4882a593Smuzhiyun 
576*4882a593Smuzhiyun int
ProcRRGetProviderProperty(ClientPtr client)577*4882a593Smuzhiyun ProcRRGetProviderProperty(ClientPtr client)
578*4882a593Smuzhiyun {
579*4882a593Smuzhiyun     REQUEST(xRRGetProviderPropertyReq);
580*4882a593Smuzhiyun     RRPropertyPtr prop, *prev;
581*4882a593Smuzhiyun     RRPropertyValuePtr prop_value;
582*4882a593Smuzhiyun     unsigned long n, len, ind;
583*4882a593Smuzhiyun     RRProviderPtr provider;
584*4882a593Smuzhiyun     xRRGetProviderPropertyReply reply = {
585*4882a593Smuzhiyun         .type = X_Reply,
586*4882a593Smuzhiyun         .sequenceNumber = client->sequence
587*4882a593Smuzhiyun     };
588*4882a593Smuzhiyun     char *extra = NULL;
589*4882a593Smuzhiyun 
590*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xRRGetProviderPropertyReq);
591*4882a593Smuzhiyun     if (stuff->delete)
592*4882a593Smuzhiyun         UpdateCurrentTime();
593*4882a593Smuzhiyun     VERIFY_RR_PROVIDER(stuff->provider, provider,
594*4882a593Smuzhiyun                      stuff->delete ? DixWriteAccess : DixReadAccess);
595*4882a593Smuzhiyun 
596*4882a593Smuzhiyun     if (!ValidAtom(stuff->property)) {
597*4882a593Smuzhiyun         client->errorValue = stuff->property;
598*4882a593Smuzhiyun         return BadAtom;
599*4882a593Smuzhiyun     }
600*4882a593Smuzhiyun     if ((stuff->delete != xTrue) && (stuff->delete != xFalse)) {
601*4882a593Smuzhiyun         client->errorValue = stuff->delete;
602*4882a593Smuzhiyun         return BadValue;
603*4882a593Smuzhiyun     }
604*4882a593Smuzhiyun     if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type)) {
605*4882a593Smuzhiyun         client->errorValue = stuff->type;
606*4882a593Smuzhiyun         return BadAtom;
607*4882a593Smuzhiyun     }
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun     for (prev = &provider->properties; (prop = *prev); prev = &prop->next)
610*4882a593Smuzhiyun         if (prop->propertyName == stuff->property)
611*4882a593Smuzhiyun             break;
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun     if (!prop) {
614*4882a593Smuzhiyun         reply.nItems = 0;
615*4882a593Smuzhiyun         reply.length = 0;
616*4882a593Smuzhiyun         reply.bytesAfter = 0;
617*4882a593Smuzhiyun         reply.propertyType = None;
618*4882a593Smuzhiyun         reply.format = 0;
619*4882a593Smuzhiyun         if (client->swapped) {
620*4882a593Smuzhiyun             swaps(&reply.sequenceNumber);
621*4882a593Smuzhiyun             swapl(&reply.length);
622*4882a593Smuzhiyun             swapl(&reply.propertyType);
623*4882a593Smuzhiyun             swapl(&reply.bytesAfter);
624*4882a593Smuzhiyun             swapl(&reply.nItems);
625*4882a593Smuzhiyun         }
626*4882a593Smuzhiyun         WriteToClient(client, sizeof(xRRGetProviderPropertyReply), &reply);
627*4882a593Smuzhiyun         return Success;
628*4882a593Smuzhiyun     }
629*4882a593Smuzhiyun 
630*4882a593Smuzhiyun     if (prop->immutable && stuff->delete)
631*4882a593Smuzhiyun         return BadAccess;
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun     prop_value = RRGetProviderProperty(provider, stuff->property, stuff->pending);
634*4882a593Smuzhiyun     if (!prop_value)
635*4882a593Smuzhiyun         return BadAtom;
636*4882a593Smuzhiyun 
637*4882a593Smuzhiyun     /* If the request type and actual type don't match. Return the
638*4882a593Smuzhiyun        property information, but not the data. */
639*4882a593Smuzhiyun 
640*4882a593Smuzhiyun     if (((stuff->type != prop_value->type) && (stuff->type != AnyPropertyType))
641*4882a593Smuzhiyun         ) {
642*4882a593Smuzhiyun         reply.bytesAfter = prop_value->size;
643*4882a593Smuzhiyun         reply.format = prop_value->format;
644*4882a593Smuzhiyun         reply.length = 0;
645*4882a593Smuzhiyun         reply.nItems = 0;
646*4882a593Smuzhiyun         reply.propertyType = prop_value->type;
647*4882a593Smuzhiyun         if (client->swapped) {
648*4882a593Smuzhiyun             swaps(&reply.sequenceNumber);
649*4882a593Smuzhiyun             swapl(&reply.length);
650*4882a593Smuzhiyun             swapl(&reply.propertyType);
651*4882a593Smuzhiyun             swapl(&reply.bytesAfter);
652*4882a593Smuzhiyun             swapl(&reply.nItems);
653*4882a593Smuzhiyun         }
654*4882a593Smuzhiyun         WriteToClient(client, sizeof(xRRGetProviderPropertyReply), &reply);
655*4882a593Smuzhiyun         return Success;
656*4882a593Smuzhiyun     }
657*4882a593Smuzhiyun 
658*4882a593Smuzhiyun /*
659*4882a593Smuzhiyun  *  Return type, format, value to client
660*4882a593Smuzhiyun  */
661*4882a593Smuzhiyun     n = (prop_value->format / 8) * prop_value->size;    /* size (bytes) of prop */
662*4882a593Smuzhiyun     ind = stuff->longOffset << 2;
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun     /* If longOffset is invalid such that it causes "len" to
665*4882a593Smuzhiyun        be negative, it's a value error. */
666*4882a593Smuzhiyun 
667*4882a593Smuzhiyun     if (n < ind) {
668*4882a593Smuzhiyun         client->errorValue = stuff->longOffset;
669*4882a593Smuzhiyun         return BadValue;
670*4882a593Smuzhiyun     }
671*4882a593Smuzhiyun 
672*4882a593Smuzhiyun     len = min(n - ind, 4 * stuff->longLength);
673*4882a593Smuzhiyun 
674*4882a593Smuzhiyun     if (len) {
675*4882a593Smuzhiyun         extra = malloc(len);
676*4882a593Smuzhiyun         if (!extra)
677*4882a593Smuzhiyun             return BadAlloc;
678*4882a593Smuzhiyun     }
679*4882a593Smuzhiyun     reply.bytesAfter = n - (ind + len);
680*4882a593Smuzhiyun     reply.format = prop_value->format;
681*4882a593Smuzhiyun     reply.length = bytes_to_int32(len);
682*4882a593Smuzhiyun     if (prop_value->format)
683*4882a593Smuzhiyun         reply.nItems = len / (prop_value->format / 8);
684*4882a593Smuzhiyun     else
685*4882a593Smuzhiyun         reply.nItems = 0;
686*4882a593Smuzhiyun     reply.propertyType = prop_value->type;
687*4882a593Smuzhiyun 
688*4882a593Smuzhiyun     if (stuff->delete && (reply.bytesAfter == 0)) {
689*4882a593Smuzhiyun         xRRProviderPropertyNotifyEvent event = {
690*4882a593Smuzhiyun             .type = RREventBase + RRNotify,
691*4882a593Smuzhiyun             .subCode = RRNotify_ProviderProperty,
692*4882a593Smuzhiyun             .provider = provider->id,
693*4882a593Smuzhiyun             .state = PropertyDelete,
694*4882a593Smuzhiyun             .atom = prop->propertyName,
695*4882a593Smuzhiyun             .timestamp = currentTime.milliseconds
696*4882a593Smuzhiyun         };
697*4882a593Smuzhiyun         RRDeliverPropertyEvent(provider->pScreen, (xEvent *) &event);
698*4882a593Smuzhiyun     }
699*4882a593Smuzhiyun 
700*4882a593Smuzhiyun     if (client->swapped) {
701*4882a593Smuzhiyun         swaps(&reply.sequenceNumber);
702*4882a593Smuzhiyun         swapl(&reply.length);
703*4882a593Smuzhiyun         swapl(&reply.propertyType);
704*4882a593Smuzhiyun         swapl(&reply.bytesAfter);
705*4882a593Smuzhiyun         swapl(&reply.nItems);
706*4882a593Smuzhiyun     }
707*4882a593Smuzhiyun     WriteToClient(client, sizeof(xGenericReply), &reply);
708*4882a593Smuzhiyun     if (len) {
709*4882a593Smuzhiyun         memcpy(extra, (char *) prop_value->data + ind, len);
710*4882a593Smuzhiyun         switch (reply.format) {
711*4882a593Smuzhiyun         case 32:
712*4882a593Smuzhiyun             client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write;
713*4882a593Smuzhiyun             break;
714*4882a593Smuzhiyun         case 16:
715*4882a593Smuzhiyun             client->pSwapReplyFunc = (ReplySwapPtr) CopySwap16Write;
716*4882a593Smuzhiyun             break;
717*4882a593Smuzhiyun         default:
718*4882a593Smuzhiyun             client->pSwapReplyFunc = (ReplySwapPtr) WriteToClient;
719*4882a593Smuzhiyun             break;
720*4882a593Smuzhiyun         }
721*4882a593Smuzhiyun         WriteSwappedDataToClient(client, len, extra);
722*4882a593Smuzhiyun         free(extra);
723*4882a593Smuzhiyun     }
724*4882a593Smuzhiyun 
725*4882a593Smuzhiyun     if (stuff->delete && (reply.bytesAfter == 0)) {     /* delete the Property */
726*4882a593Smuzhiyun         *prev = prop->next;
727*4882a593Smuzhiyun         RRDestroyProviderProperty(prop);
728*4882a593Smuzhiyun     }
729*4882a593Smuzhiyun     return Success;
730*4882a593Smuzhiyun }
731