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