XKBExtDev.c revision 0f8248bf
11ab64890Smrg/************************************************************
21ab64890SmrgCopyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
31ab64890Smrg
41ab64890SmrgPermission to use, copy, modify, and distribute this
51ab64890Smrgsoftware and its documentation for any purpose and without
61ab64890Smrgfee is hereby granted, provided that the above copyright
71ab64890Smrgnotice appear in all copies and that both that copyright
81ab64890Smrgnotice and this permission notice appear in supporting
961b2299dSmrgdocumentation, and that the name of Silicon Graphics not be
1061b2299dSmrgused in advertising or publicity pertaining to distribution
111ab64890Smrgof the software without specific prior written permission.
1261b2299dSmrgSilicon Graphics makes no representation about the suitability
131ab64890Smrgof this software for any purpose. It is provided "as is"
141ab64890Smrgwithout any express or implied warranty.
151ab64890Smrg
1661b2299dSmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
1761b2299dSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
181ab64890SmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
1961b2299dSmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
2061b2299dSmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
2161b2299dSmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
221ab64890SmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
231ab64890SmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE.
241ab64890Smrg
251ab64890Smrg********************************************************/
261ab64890Smrg
271ab64890Smrg#ifdef HAVE_CONFIG_H
281ab64890Smrg#include <config.h>
291ab64890Smrg#endif
301ab64890Smrg#include <stdio.h>
311ab64890Smrg#define	NEED_MAP_READERS
321ab64890Smrg#include "Xlibint.h"
331ab64890Smrg#include <X11/extensions/XKBproto.h>
341ab64890Smrg#include "XKBlibint.h"
351ab64890Smrg#include <X11/extensions/XI.h>
361ab64890Smrg
371ab64890Smrg/***====================================================================***/
381ab64890Smrg
391ab64890Smrgextern void
40818534a1SmrgXkbNoteDeviceChanges(XkbDeviceChangesPtr old,
41818534a1Smrg                     XkbExtensionDeviceNotifyEvent *new,
42818534a1Smrg                     unsigned int wanted)
431ab64890Smrg{
44818534a1Smrg    if ((!old) || (!new) || (!wanted) || ((new->reason & wanted) == 0))
45818534a1Smrg        return;
46818534a1Smrg    if ((wanted & new->reason) & XkbXI_ButtonActionsMask) {
47818534a1Smrg        if (old->changed & XkbXI_ButtonActionsMask) {
48818534a1Smrg            int first, last, newLast;
49818534a1Smrg
50818534a1Smrg            if (new->first_btn < old->first_btn)
51818534a1Smrg                first = new->first_btn;
52818534a1Smrg            else
53818534a1Smrg                first = old->first_btn;
54818534a1Smrg            last = old->first_btn + old->num_btns - 1;
55818534a1Smrg            newLast = new->first_btn + new->num_btns - 1;
56818534a1Smrg            if (newLast > last)
57818534a1Smrg                last = newLast;
58818534a1Smrg            old->first_btn = first;
59818534a1Smrg            old->num_btns = (last - first) + 1;
60818534a1Smrg        }
61818534a1Smrg        else {
62818534a1Smrg            old->changed |= XkbXI_ButtonActionsMask;
63818534a1Smrg            old->first_btn = new->first_btn;
64818534a1Smrg            old->num_btns = new->num_btns;
65818534a1Smrg        }
661ab64890Smrg    }
67818534a1Smrg    if ((wanted & new->reason) & XkbXI_IndicatorsMask) {
68818534a1Smrg        XkbDeviceLedChangesPtr this;
69818534a1Smrg
70818534a1Smrg        if (old->changed & XkbXI_IndicatorsMask) {
71818534a1Smrg            XkbDeviceLedChangesPtr found = NULL;
72818534a1Smrg
73818534a1Smrg            for (this = &old->leds; this && (!found); this = this->next) {
74818534a1Smrg                if ((this->led_class == new->led_class) &&
75818534a1Smrg                    (this->led_id == new->led_id)) {
76818534a1Smrg                    found = this;
77818534a1Smrg                }
78818534a1Smrg            }
79818534a1Smrg            if (!found) {
80818534a1Smrg                found = _XkbTypedCalloc(1, XkbDeviceLedChangesRec);
81818534a1Smrg                if (!found)
82818534a1Smrg                    return;
83818534a1Smrg                found->next = old->leds.next;
84818534a1Smrg                found->led_class = new->led_class;
85818534a1Smrg                found->led_id = new->led_id;
86818534a1Smrg                old->leds.next = found;
87818534a1Smrg            }
88818534a1Smrg            if ((wanted & new->reason) & XkbXI_IndicatorNamesMask)
89818534a1Smrg                found->defined = new->leds_defined;
90818534a1Smrg        }
91818534a1Smrg        else {
92818534a1Smrg            old->changed |= ((wanted & new->reason) & XkbXI_IndicatorsMask);
93818534a1Smrg            old->leds.led_class = new->led_class;
94818534a1Smrg            old->leds.led_id = new->led_id;
95818534a1Smrg            old->leds.defined = new->leds_defined;
96818534a1Smrg            if (old->leds.next) {
97818534a1Smrg                XkbDeviceLedChangesPtr next;
98818534a1Smrg
99818534a1Smrg                for (this = old->leds.next; this; this = next) {
100818534a1Smrg                    next = this->next;
101818534a1Smrg                    _XkbFree(this);
102818534a1Smrg                }
103818534a1Smrg                old->leds.next = NULL;
104818534a1Smrg            }
105818534a1Smrg        }
1061ab64890Smrg    }
1071ab64890Smrg    return;
1081ab64890Smrg}
1091ab64890Smrg
1101ab64890Smrg/***====================================================================***/
1111ab64890Smrg
1121ab64890Smrgstatic Status
113818534a1Smrg_XkbReadDeviceLedInfo(XkbReadBufferPtr buf,
114818534a1Smrg                      unsigned present,
115818534a1Smrg                      XkbDeviceInfoPtr devi)
1161ab64890Smrg{
117818534a1Smrg    register unsigned i, bit;
118818534a1Smrg    XkbDeviceLedInfoPtr devli;
119818534a1Smrg    xkbDeviceLedsWireDesc *wireli;
1201ab64890Smrg
121818534a1Smrg    wireli = _XkbGetTypedRdBufPtr(buf, 1, xkbDeviceLedsWireDesc);
1221ab64890Smrg    if (!wireli)
123818534a1Smrg        return BadLength;
124818534a1Smrg    devli = XkbAddDeviceLedInfo(devi, wireli->ledClass, wireli->ledID);
1251ab64890Smrg    if (!devli)
126818534a1Smrg        return BadAlloc;
127818534a1Smrg    devli->phys_indicators = wireli->physIndicators;
128818534a1Smrg
129818534a1Smrg    if (present & XkbXI_IndicatorStateMask)
130818534a1Smrg        devli->state = wireli->state;
131818534a1Smrg
132818534a1Smrg    if (present & XkbXI_IndicatorNamesMask) {
133818534a1Smrg        devli->names_present = wireli->namesPresent;
134818534a1Smrg        if (devli->names_present) {
135818534a1Smrg            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
136818534a1Smrg                if (wireli->namesPresent & bit) {
137818534a1Smrg                    if (!_XkbCopyFromReadBuffer(buf,
138818534a1Smrg                                                (char *) &devli->names[i], 4))
139818534a1Smrg                        return BadLength;
140818534a1Smrg                }
141818534a1Smrg            }
142818534a1Smrg        }
1431ab64890Smrg    }
1441ab64890Smrg
145818534a1Smrg    if (present & XkbXI_IndicatorMapsMask) {
146818534a1Smrg        devli->maps_present = wireli->mapsPresent;
147818534a1Smrg        if (devli->maps_present) {
148818534a1Smrg            XkbIndicatorMapPtr im;
149818534a1Smrg            xkbIndicatorMapWireDesc *wireim;
150818534a1Smrg
151818534a1Smrg            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
152818534a1Smrg                if (wireli->mapsPresent & bit) {
153818534a1Smrg                    wireim =
154818534a1Smrg                        _XkbGetTypedRdBufPtr(buf, 1, xkbIndicatorMapWireDesc);
155818534a1Smrg                    if (!wireim)
156818534a1Smrg                        return BadAlloc;
157818534a1Smrg                    im = &devli->maps[i];
158818534a1Smrg                    im->flags = wireim->flags;
159818534a1Smrg                    im->which_groups = wireim->whichGroups;
160818534a1Smrg                    im->groups = wireim->groups;
161818534a1Smrg                    im->which_mods = wireim->whichMods;
162818534a1Smrg                    im->mods.mask = wireim->mods;
163818534a1Smrg                    im->mods.real_mods = wireim->realMods;
164818534a1Smrg                    im->mods.vmods = wireim->virtualMods;
165818534a1Smrg                    im->ctrls = wireim->ctrls;
166818534a1Smrg                }
167818534a1Smrg            }
168818534a1Smrg        }
1691ab64890Smrg    }
1701ab64890Smrg    return Success;
1711ab64890Smrg}
1721ab64890Smrg
1731ab64890Smrgstatic Status
174818534a1Smrg_XkbReadGetDeviceInfoReply(Display *dpy,
175818534a1Smrg                           xkbGetDeviceInfoReply *rep,
176818534a1Smrg                           XkbDeviceInfoPtr devi)
1771ab64890Smrg{
178818534a1Smrg    XkbReadBufferRec buf;
179818534a1Smrg    XkbAction *act;
180818534a1Smrg    int tmp;
1811ab64890Smrg
182818534a1Smrg    if (!_XkbInitReadBuffer(dpy, &buf, (int) rep->length * 4))
183818534a1Smrg        return BadAlloc;
1841ab64890Smrg
185818534a1Smrg    if ((rep->totalBtns > 0) && (rep->totalBtns != devi->num_btns)) {
186818534a1Smrg        tmp = XkbResizeDeviceButtonActions(devi, rep->totalBtns);
187818534a1Smrg        if (tmp != Success)
188818534a1Smrg            return tmp;
1891ab64890Smrg    }
190818534a1Smrg    if (rep->nBtnsWanted > 0) {
191818534a1Smrg        if (((unsigned short) rep->firstBtnWanted + rep->nBtnsWanted)
192818534a1Smrg            >= devi->num_btns)
193818534a1Smrg            goto BAILOUT;
194818534a1Smrg        act = &devi->btn_acts[rep->firstBtnWanted];
195818534a1Smrg        bzero((char *) act, (rep->nBtnsWanted * sizeof(XkbAction)));
1961ab64890Smrg    }
1970f8248bfSmrg
1980f8248bfSmrg    _XkbFree(devi->name);
199818534a1Smrg    if (!_XkbGetReadBufferCountedString(&buf, &devi->name))
200818534a1Smrg        goto BAILOUT;
201818534a1Smrg    if (rep->nBtnsRtrn > 0) {
202818534a1Smrg        int size;
203818534a1Smrg
204818534a1Smrg        if (((unsigned short) rep->firstBtnRtrn + rep->nBtnsRtrn)
205818534a1Smrg            >= devi->num_btns)
206818534a1Smrg            goto BAILOUT;
207818534a1Smrg        act = &devi->btn_acts[rep->firstBtnRtrn];
208818534a1Smrg        size = rep->nBtnsRtrn * SIZEOF(xkbActionWireDesc);
209818534a1Smrg        if (!_XkbCopyFromReadBuffer(&buf, (char *) act, size))
210818534a1Smrg            goto BAILOUT;
2111ab64890Smrg    }
212818534a1Smrg    if (rep->nDeviceLedFBs > 0) {
213818534a1Smrg        register int i;
214818534a1Smrg
215818534a1Smrg        for (i = 0; i < rep->nDeviceLedFBs; i++) {
216818534a1Smrg            if ((tmp = _XkbReadDeviceLedInfo(&buf, rep->present, devi))
217818534a1Smrg                != Success)
218818534a1Smrg                return tmp;
219818534a1Smrg        }
2201ab64890Smrg    }
221818534a1Smrg    tmp = _XkbFreeReadBuffer(&buf);
22261b2299dSmrg    if (tmp)
223818534a1Smrg        fprintf(stderr, "GetDeviceInfo! Bad length (%d extra bytes)\n", tmp);
2241ab64890Smrg    if (tmp || buf.error)
225818534a1Smrg        return BadLength;
2261ab64890Smrg    return Success;
227818534a1Smrg BAILOUT:
2281ab64890Smrg    _XkbFreeReadBuffer(&buf);
2291ab64890Smrg    return BadLength;
2301ab64890Smrg}
2311ab64890Smrg
2321ab64890SmrgXkbDeviceInfoPtr
233818534a1SmrgXkbGetDeviceInfo(Display *dpy,
234818534a1Smrg                 unsigned which,
235818534a1Smrg                 unsigned deviceSpec,
236818534a1Smrg                 unsigned class,
237818534a1Smrg                 unsigned id)
2381ab64890Smrg{
239818534a1Smrg    register xkbGetDeviceInfoReq *req;
240818534a1Smrg    xkbGetDeviceInfoReply rep;
241818534a1Smrg    Status status;
242818534a1Smrg    XkbDeviceInfoPtr devi;
2431ab64890Smrg
2441ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
245818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
246818534a1Smrg        return NULL;
2471ab64890Smrg    LockDisplay(dpy);
2481ab64890Smrg    GetReq(kbGetDeviceInfo, req);
2491ab64890Smrg    req->reqType = dpy->xkb_info->codes->major_opcode;
2501ab64890Smrg    req->xkbReqType = X_kbGetDeviceInfo;
2511ab64890Smrg    req->deviceSpec = deviceSpec;
252818534a1Smrg    req->wanted = which;
253818534a1Smrg    req->allBtns = ((which & XkbXI_ButtonActionsMask) != 0);
254818534a1Smrg    req->firstBtn = req->nBtns = 0;
255818534a1Smrg    req->ledClass = class;
256818534a1Smrg    req->ledID = id;
257818534a1Smrg    if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
258818534a1Smrg        UnlockDisplay(dpy);
259818534a1Smrg        SyncHandle();
260818534a1Smrg        return NULL;
2611ab64890Smrg    }
262818534a1Smrg    devi = XkbAllocDeviceInfo(rep.deviceID, rep.totalBtns, rep.nDeviceLedFBs);
2631ab64890Smrg    if (devi) {
264818534a1Smrg        devi->supported = rep.supported;
265818534a1Smrg        devi->unsupported = rep.unsupported;
266818534a1Smrg        devi->type = rep.devType;
267818534a1Smrg        devi->has_own_state = rep.hasOwnState;
268818534a1Smrg        devi->dflt_kbd_fb = rep.dfltKbdFB;
269818534a1Smrg        devi->dflt_led_fb = rep.dfltLedFB;
270818534a1Smrg        status = _XkbReadGetDeviceInfoReply(dpy, &rep, devi);
271818534a1Smrg        if (status != Success) {
272818534a1Smrg            XkbFreeDeviceInfo(devi, XkbXI_AllDeviceFeaturesMask, True);
273818534a1Smrg            devi = NULL;
274818534a1Smrg        }
2751ab64890Smrg    }
2761ab64890Smrg    UnlockDisplay(dpy);
2771ab64890Smrg    SyncHandle();
2781ab64890Smrg    return devi;
2791ab64890Smrg}
2801ab64890Smrg
2811ab64890SmrgStatus
282818534a1SmrgXkbGetDeviceInfoChanges(Display *dpy,
283818534a1Smrg                        XkbDeviceInfoPtr devi,
284818534a1Smrg                        XkbDeviceChangesPtr changes)
2851ab64890Smrg{
286818534a1Smrg    register xkbGetDeviceInfoReq *req;
287818534a1Smrg    xkbGetDeviceInfoReply rep;
288818534a1Smrg    Status status;
2891ab64890Smrg
2901ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
291818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
292818534a1Smrg        return BadMatch;
293818534a1Smrg    if ((changes->changed & XkbXI_AllDeviceFeaturesMask) == 0)
294818534a1Smrg        return Success;
295818534a1Smrg    changes->changed &= ~XkbXI_AllDeviceFeaturesMask;
296818534a1Smrg    status = Success;
2971ab64890Smrg    LockDisplay(dpy);
298818534a1Smrg    while ((changes->changed) && (status == Success)) {
299818534a1Smrg        GetReq(kbGetDeviceInfo, req);
300818534a1Smrg        req->reqType = dpy->xkb_info->codes->major_opcode;
301818534a1Smrg        req->xkbReqType = X_kbGetDeviceInfo;
302818534a1Smrg        req->deviceSpec = devi->device_spec;
303818534a1Smrg        req->wanted = changes->changed;
304818534a1Smrg        req->allBtns = False;
305818534a1Smrg        if (changes->changed & XkbXI_ButtonActionsMask) {
306818534a1Smrg            req->firstBtn = changes->first_btn;
307818534a1Smrg            req->nBtns = changes->num_btns;
308818534a1Smrg            changes->changed &= ~XkbXI_ButtonActionsMask;
309818534a1Smrg        }
310818534a1Smrg        else
311818534a1Smrg            req->firstBtn = req->nBtns = 0;
312818534a1Smrg        if (changes->changed & XkbXI_IndicatorsMask) {
313818534a1Smrg            req->ledClass = changes->leds.led_class;
314818534a1Smrg            req->ledID = changes->leds.led_id;
315818534a1Smrg            if (changes->leds.next == NULL)
316818534a1Smrg                changes->changed &= ~XkbXI_IndicatorsMask;
317818534a1Smrg            else {
318818534a1Smrg                XkbDeviceLedChangesPtr next;
319818534a1Smrg
320818534a1Smrg                next = changes->leds.next;
321818534a1Smrg                changes->leds = *next;
322818534a1Smrg                _XkbFree(next);
323818534a1Smrg            }
324818534a1Smrg        }
325818534a1Smrg        else {
326818534a1Smrg            req->ledClass = XkbDfltXIClass;
327818534a1Smrg            req->ledID = XkbDfltXIId;
328818534a1Smrg        }
329818534a1Smrg        if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
330818534a1Smrg            status = BadLength;
331818534a1Smrg            break;
332818534a1Smrg        }
333818534a1Smrg        devi->supported |= rep.supported;
334818534a1Smrg        devi->unsupported |= rep.unsupported;
335818534a1Smrg        devi->type = rep.devType;
336818534a1Smrg        status = _XkbReadGetDeviceInfoReply(dpy, &rep, devi);
3371ab64890Smrg    }
3381ab64890Smrg    UnlockDisplay(dpy);
3391ab64890Smrg    SyncHandle();
3401ab64890Smrg    return status;
3411ab64890Smrg}
3421ab64890Smrg
3431ab64890SmrgStatus
344818534a1SmrgXkbGetDeviceButtonActions(Display *dpy,
345818534a1Smrg                          XkbDeviceInfoPtr devi,
346818534a1Smrg                          Bool all,
347818534a1Smrg                          unsigned int first,
348818534a1Smrg                          unsigned int num)
3491ab64890Smrg{
350818534a1Smrg    register xkbGetDeviceInfoReq *req;
351818534a1Smrg    xkbGetDeviceInfoReply rep;
352818534a1Smrg    Status status;
3531ab64890Smrg
35461b2299dSmrg    if ((dpy->flags & XlibDisplayNoXkb) ||
355818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
356818534a1Smrg        return BadMatch;
3571ab64890Smrg    if (!devi)
358818534a1Smrg        return BadValue;
3591ab64890Smrg    LockDisplay(dpy);
3601ab64890Smrg    GetReq(kbGetDeviceInfo, req);
3611ab64890Smrg    req->reqType = dpy->xkb_info->codes->major_opcode;
3621ab64890Smrg    req->xkbReqType = X_kbGetDeviceInfo;
3631ab64890Smrg    req->deviceSpec = devi->device_spec;
364818534a1Smrg    req->wanted = XkbXI_ButtonActionsMask;
365818534a1Smrg    req->allBtns = all;
366818534a1Smrg    req->firstBtn = first;
367818534a1Smrg    req->nBtns = num;
368818534a1Smrg    req->ledClass = XkbDfltXIClass;
369818534a1Smrg    req->ledID = XkbDfltXIId;
370818534a1Smrg    if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
371818534a1Smrg        UnlockDisplay(dpy);
372818534a1Smrg        SyncHandle();
373818534a1Smrg        return BadLength;
3741ab64890Smrg    }
375818534a1Smrg    devi->type = rep.devType;
376818534a1Smrg    devi->supported = rep.supported;
377818534a1Smrg    devi->unsupported = rep.unsupported;
378818534a1Smrg    status = _XkbReadGetDeviceInfoReply(dpy, &rep, devi);
3791ab64890Smrg    UnlockDisplay(dpy);
3801ab64890Smrg    SyncHandle();
3811ab64890Smrg    return status;
3821ab64890Smrg}
3831ab64890Smrg
3841ab64890SmrgStatus
385818534a1SmrgXkbGetDeviceLedInfo(Display *dpy,
386818534a1Smrg                    XkbDeviceInfoPtr devi,
387818534a1Smrg                    unsigned int ledClass,
388818534a1Smrg                    unsigned int ledId,
389818534a1Smrg                    unsigned int which)
3901ab64890Smrg{
391818534a1Smrg    register xkbGetDeviceInfoReq *req;
392818534a1Smrg    xkbGetDeviceInfoReply rep;
393818534a1Smrg    Status status;
3941ab64890Smrg
39561b2299dSmrg    if ((dpy->flags & XlibDisplayNoXkb) ||
396818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
397818534a1Smrg        return BadMatch;
398818534a1Smrg    if (((which & XkbXI_IndicatorsMask) == 0) ||
399818534a1Smrg        (which & (~XkbXI_IndicatorsMask)))
400818534a1Smrg        return BadMatch;
4011ab64890Smrg    if (!devi)
402818534a1Smrg        return BadValue;
4031ab64890Smrg    LockDisplay(dpy);
4041ab64890Smrg    GetReq(kbGetDeviceInfo, req);
4051ab64890Smrg    req->reqType = dpy->xkb_info->codes->major_opcode;
4061ab64890Smrg    req->xkbReqType = X_kbGetDeviceInfo;
4071ab64890Smrg    req->deviceSpec = devi->device_spec;
408818534a1Smrg    req->wanted = which;
409818534a1Smrg    req->allBtns = False;
410818534a1Smrg    req->firstBtn = req->nBtns = 0;
411818534a1Smrg    req->ledClass = ledClass;
412818534a1Smrg    req->ledID = ledId;
413818534a1Smrg    if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
414818534a1Smrg        UnlockDisplay(dpy);
415818534a1Smrg        SyncHandle();
416818534a1Smrg        return BadLength;
41761b2299dSmrg    }
418818534a1Smrg    devi->type = rep.devType;
419818534a1Smrg    devi->supported = rep.supported;
420818534a1Smrg    devi->unsupported = rep.unsupported;
421818534a1Smrg    status = _XkbReadGetDeviceInfoReply(dpy, &rep, devi);
4221ab64890Smrg    UnlockDisplay(dpy);
4231ab64890Smrg    SyncHandle();
4241ab64890Smrg    return status;
4251ab64890Smrg}
4261ab64890Smrg
4271ab64890Smrg/***====================================================================***/
4281ab64890Smrg
4291ab64890Smrgtypedef struct _LedInfoStuff {
430818534a1Smrg    Bool used;
431818534a1Smrg    XkbDeviceLedInfoPtr devli;
4321ab64890Smrg} LedInfoStuff;
4331ab64890Smrg
4341ab64890Smrgtypedef struct _SetLedStuff {
435818534a1Smrg    unsigned wanted;
436818534a1Smrg    int num_info;
437818534a1Smrg    int dflt_class;
438818534a1Smrg    LedInfoStuff *dflt_kbd_fb;
439818534a1Smrg    LedInfoStuff *dflt_led_fb;
440818534a1Smrg    LedInfoStuff *info;
4411ab64890Smrg} SetLedStuff;
4421ab64890Smrg
4431ab64890Smrgstatic void
444818534a1Smrg_InitLedStuff(SetLedStuff *stuff, unsigned wanted, XkbDeviceInfoPtr devi)
4451ab64890Smrg{
446818534a1Smrg    int i;
447818534a1Smrg    register XkbDeviceLedInfoPtr devli;
448818534a1Smrg
449818534a1Smrg    bzero(stuff, sizeof(SetLedStuff));
450818534a1Smrg    stuff->wanted = wanted;
451818534a1Smrg    stuff->dflt_class = XkbXINone;
452818534a1Smrg    if ((devi->num_leds < 1) || ((wanted & XkbXI_IndicatorsMask) == 0))
453818534a1Smrg        return;
454818534a1Smrg    stuff->info = _XkbTypedCalloc(devi->num_leds, LedInfoStuff);
4551ab64890Smrg    if (!stuff->info)
456818534a1Smrg        return;
457818534a1Smrg    stuff->num_info = devi->num_leds;
458818534a1Smrg    for (devli = &devi->leds[0], i = 0; i < devi->num_leds; i++, devli++) {
459818534a1Smrg        stuff->info[i].devli = devli;
460818534a1Smrg        if (devli->led_class == KbdFeedbackClass) {
461818534a1Smrg            stuff->dflt_class = KbdFeedbackClass;
462818534a1Smrg            if (stuff->dflt_kbd_fb == NULL)
463818534a1Smrg                stuff->dflt_kbd_fb = &stuff->info[i];
464818534a1Smrg        }
465818534a1Smrg        else if (devli->led_class == LedFeedbackClass) {
466818534a1Smrg            if (stuff->dflt_class == XkbXINone)
467818534a1Smrg                stuff->dflt_class = LedFeedbackClass;
468818534a1Smrg            if (stuff->dflt_led_fb == NULL)
469818534a1Smrg                stuff->dflt_led_fb = &stuff->info[i];
470818534a1Smrg        }
4711ab64890Smrg    }
4721ab64890Smrg    return;
4731ab64890Smrg}
4741ab64890Smrg
4751ab64890Smrgstatic void
476818534a1Smrg_FreeLedStuff(SetLedStuff * stuff)
4771ab64890Smrg{
4780f8248bfSmrg    if (stuff->num_info > 0)
479818534a1Smrg        _XkbFree(stuff->info);
480818534a1Smrg    bzero(stuff, sizeof(SetLedStuff));
4811ab64890Smrg    return;
4821ab64890Smrg}
4831ab64890Smrg
4841ab64890Smrgstatic int
485818534a1Smrg_XkbSizeLedInfo(unsigned changed, XkbDeviceLedInfoPtr devli)
4861ab64890Smrg{
487818534a1Smrg    register int i, size;
488818534a1Smrg    register unsigned bit, namesNeeded, mapsNeeded;
489818534a1Smrg
490818534a1Smrg    size = SIZEOF(xkbDeviceLedsWireDesc);
491818534a1Smrg    namesNeeded = mapsNeeded = 0;
492818534a1Smrg    if (changed & XkbXI_IndicatorNamesMask)
493818534a1Smrg        namesNeeded = devli->names_present;
494818534a1Smrg    if (changed & XkbXI_IndicatorMapsMask)
495818534a1Smrg        mapsNeeded = devli->maps_present;
496818534a1Smrg    if ((namesNeeded) || (mapsNeeded)) {
497818534a1Smrg        for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
498818534a1Smrg            if (namesNeeded & bit)
499818534a1Smrg                size += 4;      /* atoms are 4 bytes on the wire */
500818534a1Smrg            if (mapsNeeded & bit)
501818534a1Smrg                size += SIZEOF(xkbIndicatorMapWireDesc);
502818534a1Smrg        }
5031ab64890Smrg    }
5041ab64890Smrg    return size;
5051ab64890Smrg}
5061ab64890Smrg
5071ab64890Smrgstatic Bool
508818534a1Smrg_SizeMatches(SetLedStuff *stuff,
509818534a1Smrg             XkbDeviceLedChangesPtr changes,
510818534a1Smrg             int *sz_rtrn,
511818534a1Smrg             int *nleds_rtrn)
5121ab64890Smrg{
513818534a1Smrg    int i, nMatch, class, id;
514818534a1Smrg    LedInfoStuff *linfo;
515818534a1Smrg    Bool match;
516818534a1Smrg
517818534a1Smrg    nMatch = 0;
518818534a1Smrg    class = changes->led_class;
519818534a1Smrg    id = changes->led_id;
520818534a1Smrg    if (class == XkbDfltXIClass)
521818534a1Smrg        class = stuff->dflt_class;
522818534a1Smrg    for (i = 0, linfo = &stuff->info[0]; i < stuff->num_info; i++, linfo++) {
523818534a1Smrg        XkbDeviceLedInfoPtr devli;
524818534a1Smrg        LedInfoStuff *dflt;
525818534a1Smrg
526818534a1Smrg        devli = linfo->devli;
527818534a1Smrg        match = ((class == devli->led_class) || (class == XkbAllXIClasses));
528818534a1Smrg        if (devli->led_class == KbdFeedbackClass)
529818534a1Smrg            dflt = stuff->dflt_kbd_fb;
530818534a1Smrg        else
531818534a1Smrg            dflt = stuff->dflt_led_fb;
532818534a1Smrg        match = (match && (id == devli->led_id)) ||
533818534a1Smrg            (id == XkbAllXIIds) ||
534818534a1Smrg            ((id == XkbDfltXIId) && (linfo == dflt));
535818534a1Smrg        if (match) {
536818534a1Smrg            if (!linfo->used) {
537818534a1Smrg                *sz_rtrn += _XkbSizeLedInfo(stuff->wanted, devli);
538818534a1Smrg                *nleds_rtrn += 1;
539818534a1Smrg                linfo->used = True;
540818534a1Smrg                if ((class != XkbAllXIClasses) && (id != XkbAllXIIds))
541818534a1Smrg                    return True;
542818534a1Smrg            }
543818534a1Smrg            nMatch++;
544818534a1Smrg            linfo->used = True;
545818534a1Smrg        }
5461ab64890Smrg    }
547818534a1Smrg    return (nMatch > 0);
5481ab64890Smrg}
5491ab64890Smrg
5501ab64890Smrg/***====================================================================***/
5511ab64890Smrg
5521ab64890Smrg
5531ab64890Smrgstatic Status
554818534a1Smrg_XkbSetDeviceInfoSize(XkbDeviceInfoPtr devi,
555818534a1Smrg                      XkbDeviceChangesPtr changes,
556818534a1Smrg                      SetLedStuff *stuff,
557818534a1Smrg                      int *sz_rtrn,
558818534a1Smrg                      int *num_leds_rtrn)
5591ab64890Smrg{
560818534a1Smrg    *sz_rtrn = 0;
561818534a1Smrg    if ((changes->changed & XkbXI_ButtonActionsMask) && (changes->num_btns > 0)) {
562818534a1Smrg        if (!XkbXI_LegalDevBtn
563818534a1Smrg            (devi, (changes->first_btn + changes->num_btns - 1)))
564818534a1Smrg            return BadMatch;
565818534a1Smrg        *sz_rtrn += changes->num_btns * SIZEOF(xkbActionWireDesc);
5661ab64890Smrg    }
5671ab64890Smrg    else {
568818534a1Smrg        changes->changed &= ~XkbXI_ButtonActionsMask;
569818534a1Smrg        changes->first_btn = changes->num_btns = 0;
5701ab64890Smrg    }
571818534a1Smrg    if ((changes->changed & XkbXI_IndicatorsMask) &&
572818534a1Smrg        XkbLegalXILedClass(changes->leds.led_class)) {
573818534a1Smrg        XkbDeviceLedChangesPtr leds;
574818534a1Smrg
575818534a1Smrg        for (leds = &changes->leds; leds != NULL; leds = leds->next) {
576818534a1Smrg            if (!_SizeMatches(stuff, leds, sz_rtrn, num_leds_rtrn))
577818534a1Smrg                return BadMatch;
578818534a1Smrg        }
5791ab64890Smrg    }
5801ab64890Smrg    else {
581818534a1Smrg        changes->changed &= ~XkbXI_IndicatorsMask;
582818534a1Smrg        *num_leds_rtrn = 0;
5831ab64890Smrg    }
5841ab64890Smrg    return Success;
5851ab64890Smrg}
5861ab64890Smrg
5871ab64890Smrgstatic char *
588818534a1Smrg_XkbWriteLedInfo(char *wire, unsigned changed, XkbDeviceLedInfoPtr devli)
5891ab64890Smrg{
590818534a1Smrg    register int i;
591818534a1Smrg    register unsigned bit, namesNeeded, mapsNeeded;
592818534a1Smrg    xkbDeviceLedsWireDesc *lwire;
593818534a1Smrg
594818534a1Smrg    namesNeeded = mapsNeeded = 0;
595818534a1Smrg    if (changed & XkbXI_IndicatorNamesMask)
596818534a1Smrg        namesNeeded = devli->names_present;
597818534a1Smrg    if (changed & XkbXI_IndicatorMapsMask)
598818534a1Smrg        mapsNeeded = devli->maps_present;
599818534a1Smrg
600818534a1Smrg    lwire = (xkbDeviceLedsWireDesc *) wire;
601818534a1Smrg    lwire->ledClass = devli->led_class;
602818534a1Smrg    lwire->ledID = devli->led_id;
603818534a1Smrg    lwire->namesPresent = namesNeeded;
604818534a1Smrg    lwire->mapsPresent = mapsNeeded;
605818534a1Smrg    lwire->physIndicators = devli->phys_indicators;
606818534a1Smrg    lwire->state = devli->state;
607818534a1Smrg    wire = (char *) &lwire[1];
6081ab64890Smrg    if (namesNeeded) {
609818534a1Smrg        CARD32 *awire = (CARD32 *) wire;
610818534a1Smrg
611818534a1Smrg        for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
612818534a1Smrg            if (namesNeeded & bit) {
613818534a1Smrg                *awire = (CARD32) devli->names[i];
614818534a1Smrg                awire++;
615818534a1Smrg            }
616818534a1Smrg        }
617818534a1Smrg        wire = (char *) awire;
6181ab64890Smrg    }
6191ab64890Smrg    if (mapsNeeded) {
620818534a1Smrg        xkbIndicatorMapWireDesc *mwire = (xkbIndicatorMapWireDesc *) wire;
621818534a1Smrg
622818534a1Smrg        for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
623818534a1Smrg            if (mapsNeeded & bit) {
624818534a1Smrg                XkbIndicatorMapPtr map = &devli->maps[i];
625818534a1Smrg
626818534a1Smrg                mwire->flags = map->flags;
627818534a1Smrg                mwire->whichGroups = map->which_groups;
628818534a1Smrg                mwire->groups = map->groups;
629818534a1Smrg                mwire->whichMods = map->which_mods;
630818534a1Smrg                mwire->mods = map->mods.mask;
631818534a1Smrg                mwire->realMods = map->mods.real_mods;
632818534a1Smrg                mwire->virtualMods = map->mods.vmods;
633818534a1Smrg                mwire->ctrls = map->ctrls;
634818534a1Smrg                mwire++;
635818534a1Smrg            }
636818534a1Smrg        }
637818534a1Smrg        wire = (char *) mwire;
6381ab64890Smrg    }
6391ab64890Smrg    return wire;
6401ab64890Smrg}
6411ab64890Smrg
6421ab64890Smrg
6431ab64890Smrgstatic int
644818534a1Smrg_XkbWriteSetDeviceInfo(char *wire,
645818534a1Smrg                       XkbDeviceChangesPtr changes,
646818534a1Smrg                       SetLedStuff *stuff,
647818534a1Smrg                       XkbDeviceInfoPtr devi)
6481ab64890Smrg{
649818534a1Smrg    char *start = wire;
650818534a1Smrg
651818534a1Smrg    if (changes->changed & XkbXI_ButtonActionsMask) {
652818534a1Smrg        int size = changes->num_btns * SIZEOF(xkbActionWireDesc);
653818534a1Smrg
654818534a1Smrg        memcpy(wire, (char *) &devi->btn_acts[changes->first_btn], size);
655818534a1Smrg        wire += size;
6561ab64890Smrg    }
657818534a1Smrg    if (changes->changed & XkbXI_IndicatorsMask) {
658818534a1Smrg        register int i;
659818534a1Smrg        register LedInfoStuff *linfo;
660818534a1Smrg
661818534a1Smrg        for (i = 0, linfo = &stuff->info[0]; i < stuff->num_info; i++, linfo++) {
662818534a1Smrg            if (linfo->used) {
663818534a1Smrg                register char *new_wire;
664818534a1Smrg
665818534a1Smrg                new_wire = _XkbWriteLedInfo(wire, stuff->wanted, linfo->devli);
666818534a1Smrg                if (!new_wire)
667818534a1Smrg                    return wire - start;
668818534a1Smrg                wire = new_wire;
669818534a1Smrg            }
670818534a1Smrg        }
6711ab64890Smrg    }
672818534a1Smrg    return wire - start;
6731ab64890Smrg}
6741ab64890Smrg
6751ab64890SmrgBool
676818534a1SmrgXkbSetDeviceInfo(Display *dpy, unsigned which, XkbDeviceInfoPtr devi)
6771ab64890Smrg{
6781ab64890Smrg    register xkbSetDeviceInfoReq *req;
679818534a1Smrg    Status ok = 0;
680818534a1Smrg    int size, nLeds;
681818534a1Smrg    XkbInfoPtr xkbi;
682818534a1Smrg    XkbDeviceChangesRec changes;
683818534a1Smrg    SetLedStuff lstuff;
6841ab64890Smrg
6851ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
686818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
687818534a1Smrg        return False;
688818534a1Smrg    if ((!devi) || (which & (~XkbXI_AllDeviceFeaturesMask)) ||
689818534a1Smrg        ((which & XkbXI_ButtonActionsMask) && (!XkbXI_DevHasBtnActs(devi))) ||
690818534a1Smrg        ((which & XkbXI_IndicatorsMask) && (!XkbXI_DevHasLeds(devi))))
691818534a1Smrg        return False;
692818534a1Smrg
693818534a1Smrg    bzero((char *) &changes, sizeof(XkbDeviceChangesRec));
694818534a1Smrg    changes.changed = which;
695818534a1Smrg    changes.first_btn = 0;
696818534a1Smrg    changes.num_btns = devi->num_btns;
697818534a1Smrg    changes.leds.led_class = XkbAllXIClasses;
698818534a1Smrg    changes.leds.led_id = XkbAllXIIds;
699818534a1Smrg    changes.leds.defined = 0;
700818534a1Smrg    size = nLeds = 0;
701818534a1Smrg    _InitLedStuff(&lstuff, changes.changed, devi);
702818534a1Smrg    if (_XkbSetDeviceInfoSize(devi, &changes, &lstuff, &size, &nLeds) !=
703818534a1Smrg        Success)
704818534a1Smrg        return False;
7051ab64890Smrg    LockDisplay(dpy);
7061ab64890Smrg    xkbi = dpy->xkb_info;
7071ab64890Smrg    GetReq(kbSetDeviceInfo, req);
708818534a1Smrg    req->length += size / 4;
709818534a1Smrg    req->reqType = xkbi->codes->major_opcode;
710818534a1Smrg    req->xkbReqType = X_kbSetDeviceInfo;
711818534a1Smrg    req->deviceSpec = devi->device_spec;
712818534a1Smrg    req->firstBtn = changes.first_btn;
713818534a1Smrg    req->nBtns = changes.num_btns;
714818534a1Smrg    req->change = changes.changed;
715818534a1Smrg    req->nDeviceLedFBs = nLeds;
716818534a1Smrg    if (size > 0) {
717818534a1Smrg        char *wire;
718818534a1Smrg
719818534a1Smrg        BufAlloc(char *, wire, size);
720818534a1Smrg        ok = (wire != NULL) &&
721818534a1Smrg            (_XkbWriteSetDeviceInfo(wire, &changes, &lstuff, devi) == size);
7221ab64890Smrg    }
7231ab64890Smrg    UnlockDisplay(dpy);
7241ab64890Smrg    SyncHandle();
7251ab64890Smrg    _FreeLedStuff(&lstuff);
7261ab64890Smrg    /* 12/11/95 (ef) -- XXX!! should clear changes here */
7271ab64890Smrg    return ok;
7281ab64890Smrg}
7291ab64890Smrg
7301ab64890SmrgBool
731818534a1SmrgXkbChangeDeviceInfo(Display *dpy,
732818534a1Smrg                    XkbDeviceInfoPtr devi,
733818534a1Smrg                    XkbDeviceChangesPtr changes)
7341ab64890Smrg{
7351ab64890Smrg    register xkbSetDeviceInfoReq *req;
736818534a1Smrg    Status ok = 0;
737818534a1Smrg    int size, nLeds;
738818534a1Smrg    XkbInfoPtr xkbi;
739818534a1Smrg    SetLedStuff lstuff;
7401ab64890Smrg
7411ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
742818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
743818534a1Smrg        return False;
744818534a1Smrg    if ((!devi) || (changes->changed & (~XkbXI_AllDeviceFeaturesMask)) ||
745818534a1Smrg        ((changes->changed & XkbXI_ButtonActionsMask) &&
746818534a1Smrg         (!XkbXI_DevHasBtnActs(devi))) ||
747818534a1Smrg        ((changes->changed & XkbXI_IndicatorsMask) &&
748818534a1Smrg         (!XkbXI_DevHasLeds(devi))))
749818534a1Smrg        return False;
750818534a1Smrg
751818534a1Smrg    size = nLeds = 0;
752818534a1Smrg    _InitLedStuff(&lstuff, changes->changed, devi);
753818534a1Smrg    if (_XkbSetDeviceInfoSize(devi, changes, &lstuff, &size, &nLeds) != Success)
754818534a1Smrg        return False;
7551ab64890Smrg    LockDisplay(dpy);
7561ab64890Smrg    xkbi = dpy->xkb_info;
7571ab64890Smrg    GetReq(kbSetDeviceInfo, req);
758818534a1Smrg    req->length += size / 4;
759818534a1Smrg    req->reqType = xkbi->codes->major_opcode;
760818534a1Smrg    req->xkbReqType = X_kbSetDeviceInfo;
761818534a1Smrg    req->deviceSpec = devi->device_spec;
762818534a1Smrg    req->firstBtn = changes->first_btn;
763818534a1Smrg    req->nBtns = changes->num_btns;
764818534a1Smrg    req->change = changes->changed;
765818534a1Smrg    req->nDeviceLedFBs = nLeds;
766818534a1Smrg    if (size > 0) {
767818534a1Smrg        char *wire;
768818534a1Smrg
769818534a1Smrg        BufAlloc(char *, wire, size);
770818534a1Smrg        ok = (wire != NULL) &&
771818534a1Smrg            (_XkbWriteSetDeviceInfo(wire, changes, &lstuff, devi) == size);
7721ab64890Smrg    }
7731ab64890Smrg    UnlockDisplay(dpy);
7741ab64890Smrg    SyncHandle();
7751ab64890Smrg    _FreeLedStuff(&lstuff);
7761ab64890Smrg    /* 12/11/95 (ef) -- XXX!! should clear changes here */
7771ab64890Smrg    return ok;
7781ab64890Smrg}
7791ab64890Smrg
78061b2299dSmrgBool
781818534a1SmrgXkbSetDeviceLedInfo(Display *dpy,
782818534a1Smrg                    XkbDeviceInfoPtr devi,
783818534a1Smrg                    unsigned ledClass,
784818534a1Smrg                    unsigned ledID,
785818534a1Smrg                    unsigned which)
7861ab64890Smrg{
7871ab64890Smrg    return False;
7881ab64890Smrg}
7891ab64890Smrg
79061b2299dSmrgBool
791818534a1SmrgXkbSetDeviceButtonActions(Display *dpy,
792818534a1Smrg                          XkbDeviceInfoPtr devi,
793818534a1Smrg                          unsigned int first,
794818534a1Smrg                          unsigned int nBtns)
7951ab64890Smrg{
7961ab64890Smrg    register xkbSetDeviceInfoReq *req;
797818534a1Smrg    Status ok = 0;
798818534a1Smrg    int size, nLeds;
799818534a1Smrg    XkbInfoPtr xkbi;
800818534a1Smrg    XkbDeviceChangesRec changes;
801818534a1Smrg    SetLedStuff lstuff;
8021ab64890Smrg
8031ab64890Smrg    if ((dpy->flags & XlibDisplayNoXkb) ||
804818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
805818534a1Smrg        return False;
806818534a1Smrg    if ((!devi) || (!XkbXI_DevHasBtnActs(devi)) ||
807818534a1Smrg        (first + nBtns > devi->num_btns))
808818534a1Smrg        return False;
809818534a1Smrg    if (nBtns == 0)
810818534a1Smrg        return True;
811818534a1Smrg
812818534a1Smrg    bzero((char *) &changes, sizeof(XkbDeviceChangesRec));
813818534a1Smrg    changes.changed = XkbXI_ButtonActionsMask;
814818534a1Smrg    changes.first_btn = first;
815818534a1Smrg    changes.num_btns = nBtns;
816818534a1Smrg    changes.leds.led_class = XkbXINone;
817818534a1Smrg    changes.leds.led_id = XkbXINone;
818818534a1Smrg    changes.leds.defined = 0;
819818534a1Smrg    size = nLeds = 0;
820818534a1Smrg    if (_XkbSetDeviceInfoSize(devi, &changes, NULL, &size, &nLeds) != Success)
821818534a1Smrg        return False;
8221ab64890Smrg    LockDisplay(dpy);
8231ab64890Smrg    xkbi = dpy->xkb_info;
8241ab64890Smrg    GetReq(kbSetDeviceInfo, req);
825818534a1Smrg    req->length += size / 4;
826818534a1Smrg    req->reqType = xkbi->codes->major_opcode;
827818534a1Smrg    req->xkbReqType = X_kbSetDeviceInfo;
828818534a1Smrg    req->deviceSpec = devi->device_spec;
829818534a1Smrg    req->firstBtn = changes.first_btn;
830818534a1Smrg    req->nBtns = changes.num_btns;
831818534a1Smrg    req->change = changes.changed;
832818534a1Smrg    req->nDeviceLedFBs = nLeds;
833818534a1Smrg    if (size > 0) {
834818534a1Smrg        char *wire;
835818534a1Smrg
836818534a1Smrg        BufAlloc(char *, wire, size);
837818534a1Smrg        ok = (wire != NULL) &&
838818534a1Smrg            (_XkbWriteSetDeviceInfo(wire, &changes, &lstuff, devi) == size);
8391ab64890Smrg    }
8401ab64890Smrg    UnlockDisplay(dpy);
8411ab64890Smrg    SyncHandle();
8421ab64890Smrg    return ok;
8431ab64890Smrg}
844