XKB.c revision 1ab64890
1/* $Xorg: XKB.c,v 1.3 2000/08/17 19:44:59 cpqbld Exp $ */
2/************************************************************
3Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
4
5Permission to use, copy, modify, and distribute this
6software and its documentation for any purpose and without
7fee is hereby granted, provided that the above copyright
8notice appear in all copies and that both that copyright
9notice and this permission notice appear in supporting
10documentation, and that the name of Silicon Graphics not be
11used in advertising or publicity pertaining to distribution
12of the software without specific prior written permission.
13Silicon Graphics makes no representation about the suitability
14of this software for any purpose. It is provided "as is"
15without any express or implied warranty.
16
17SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
18SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
19AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
20GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
21DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
22DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
23OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
24THE USE OR PERFORMANCE OF THIS SOFTWARE.
25
26********************************************************/
27/* $XFree86: xc/lib/X11/XKB.c,v 1.9 2003/04/17 02:06:31 dawes Exp $ */
28
29#ifdef HAVE_CONFIG_H
30#include <config.h>
31#endif
32#include <stdio.h>
33#define NEED_REPLIES
34#define NEED_EVENTS
35#include "Xlibint.h"
36#include <X11/extensions/XKBproto.h>
37#include "XKBlibint.h"
38
39XkbInternAtomFunc	_XkbInternAtomFunc= XInternAtom;
40XkbGetAtomNameFunc	_XkbGetAtomNameFunc= XGetAtomName;
41
42Bool
43XkbQueryExtension(	Display *dpy,
44			int *	opcodeReturn,
45			int *	eventBaseReturn,
46			int *	errorBaseReturn,
47			int *	majorReturn,
48			int *	minorReturn)
49{
50    if (!XkbUseExtension(dpy,majorReturn,minorReturn))
51	return False;
52    if (opcodeReturn)
53	*opcodeReturn = dpy->xkb_info->codes->major_opcode;
54    if (eventBaseReturn)
55	*eventBaseReturn = dpy->xkb_info->codes->first_event;
56    if (errorBaseReturn)
57	*errorBaseReturn = dpy->xkb_info->codes->first_error;
58    if (majorReturn)
59	*majorReturn = dpy->xkb_info->srv_major;
60    if (minorReturn)
61	*minorReturn = dpy->xkb_info->srv_minor;
62    return True;
63}
64
65Bool
66XkbLibraryVersion(int *libMajorRtrn,int *libMinorRtrn)
67{
68int supported;
69
70    if (*libMajorRtrn != XkbMajorVersion) {
71	/* version 0.65 is (almost) compatible with 1.00 */
72	if ((XkbMajorVersion==1)&&(((*libMajorRtrn)==0)&&((*libMinorRtrn)==65)))
73	     supported= True;
74	else supported= False;
75    }
76    else {
77	supported = True;
78    }
79
80    *libMajorRtrn = XkbMajorVersion;
81    *libMinorRtrn = XkbMinorVersion;
82    return supported;
83}
84
85Bool
86XkbSelectEvents(	Display *	dpy,
87			unsigned int 	deviceSpec,
88			unsigned int 	affect,
89			unsigned int 	selectAll)
90{
91    register xkbSelectEventsReq *req;
92    XkbInfoPtr xkbi;
93
94    if ((dpy->flags & XlibDisplayNoXkb) ||
95	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
96	return False;
97    LockDisplay(dpy);
98    xkbi = dpy->xkb_info;
99    xkbi->selected_events&= ~affect;
100    xkbi->selected_events|= (affect&selectAll);
101    GetReq(kbSelectEvents, req);
102    req->reqType = xkbi->codes->major_opcode;
103    req->xkbReqType = X_kbSelectEvents;
104    req->deviceSpec = deviceSpec;
105    req->affectWhich = (CARD16)affect;
106    req->clear = affect&(~selectAll);
107    req->selectAll = affect&selectAll;
108    if (affect&XkbMapNotifyMask) {
109	req->affectMap= XkbAllMapComponentsMask;
110	/* the implicit support needs the client info */
111	/* even if the client itself doesn't want it */
112	if (selectAll&XkbMapNotifyMask)
113	     req->map= XkbAllMapEventsMask;
114	else req->map= XkbAllClientInfoMask;
115	if (selectAll&XkbMapNotifyMask)
116	     xkbi->selected_map_details= XkbAllMapEventsMask;
117	else xkbi->selected_map_details= 0;
118    }
119    if (affect&XkbNewKeyboardNotifyMask) {
120	if (selectAll&XkbNewKeyboardNotifyMask)
121	     xkbi->selected_nkn_details= XkbAllNewKeyboardEventsMask;
122	else xkbi->selected_nkn_details= 0;
123	if (!(xkbi->xlib_ctrls&XkbLC_IgnoreNewKeyboards)) {
124	    /* we want it, even if the client doesn't.  Don't mess */
125	    /* around with details -- ask for all of them and throw */
126	    /* away the ones we don't need */
127	    req->selectAll|= XkbNewKeyboardNotifyMask;
128	}
129    }
130    UnlockDisplay(dpy);
131    SyncHandle();
132    return True;
133}
134
135Bool
136XkbSelectEventDetails(	Display *		dpy,
137			unsigned 		deviceSpec,
138			unsigned 		eventType,
139			unsigned long int 	affect,
140			unsigned long int 	details)
141{
142    register xkbSelectEventsReq *req;
143    XkbInfoPtr xkbi;
144    int	     size = 0;
145    char     *out;
146    union {
147	CARD8	*c8;
148	CARD16	*c16;
149	CARD32	*c32;
150    } u;
151
152    if ((dpy->flags & XlibDisplayNoXkb) ||
153	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
154	return False;
155    LockDisplay(dpy);
156    xkbi = dpy->xkb_info;
157    if (affect&details)	xkbi->selected_events|= (1<<eventType);
158    else		xkbi->selected_events&= ~(1<<eventType);
159    GetReq(kbSelectEvents, req);
160    req->reqType = xkbi->codes->major_opcode;
161    req->xkbReqType = X_kbSelectEvents;
162    req->deviceSpec = deviceSpec;
163    req->clear= req->selectAll= 0;
164    if (eventType==XkbMapNotify) {
165	/* we need all of the client info, even if the application */
166	/* doesn't.   Make sure that we always request the stuff */
167	/* that the implicit support needs, and just filter out anything */
168	/* the client doesn't want later */
169	req->affectWhich = 0;
170	req->selectAll = 0;
171	req->clear = 0;
172	req->affectMap = (CARD16)affect;
173	req->map = (CARD16)details|(XkbAllClientInfoMask&affect);
174	req->affectWhich = XkbMapNotifyMask;
175	xkbi->selected_map_details&= ~affect;
176	xkbi->selected_map_details|=  (details&affect);
177    }
178    else {
179	req->affectMap = req->map = 0;
180	req->affectWhich= (1<<eventType);
181	switch (eventType) {
182	    case XkbNewKeyboardNotify:
183		xkbi->selected_nkn_details&= ~affect;
184		xkbi->selected_nkn_details|= (details&affect);
185		if (!(xkbi->xlib_ctrls&XkbLC_IgnoreNewKeyboards))
186		    details= (affect&XkbAllNewKeyboardEventsMask);
187	    case XkbStateNotify:
188	    case XkbNamesNotify:
189	    case XkbAccessXNotify:
190	    case XkbExtensionDeviceNotify:
191		size= 2;
192		req->length+= 1;
193		break;
194	    case XkbControlsNotify:
195	    case XkbIndicatorStateNotify:
196	    case XkbIndicatorMapNotify:
197		size= 4;
198		req->length+= 2;
199		break;
200	    case XkbBellNotify:
201	    case XkbActionMessage:
202	    case XkbCompatMapNotify:
203		size= 1;
204		req->length+= 1;
205		break;
206	}
207	BufAlloc(char *,out,(((size*2)+(unsigned)3)/4)*4);
208	u.c8= (CARD8 *)out;
209	if (size==2) {
210	    u.c16[0]= (CARD16)affect;
211	    u.c16[1]= (CARD16)details;
212	}
213	else if (size==4) {
214	    u.c32[0]= (CARD32)affect;
215	    u.c32[1]= (CARD32)details;
216	}
217	else {
218	    u.c8[0]= (CARD8)affect;
219	    u.c8[1]= (CARD8)details;
220	}
221    }
222    UnlockDisplay(dpy);
223    SyncHandle();
224    return True;
225}
226
227Bool
228XkbLockModifiers(	Display *	dpy,
229			unsigned int 	deviceSpec,
230			unsigned int 	affect,
231			unsigned int 	values)
232{
233    register xkbLatchLockStateReq *req;
234    XkbInfoPtr xkbi;
235
236    if ((dpy->flags & XlibDisplayNoXkb) ||
237	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
238	return False;
239    LockDisplay(dpy);
240    xkbi = dpy->xkb_info;
241    GetReq(kbLatchLockState, req);
242    req->reqType = xkbi->codes->major_opcode;
243    req->xkbReqType = X_kbLatchLockState;
244    req->deviceSpec = deviceSpec;
245    req->affectModLocks= affect;
246    req->modLocks = values;
247    req->lockGroup = False;
248    req->groupLock = 0;
249
250    req->affectModLatches = req->modLatches = 0;
251    req->latchGroup = False;
252    req->groupLatch = 0;
253    UnlockDisplay(dpy);
254    SyncHandle();
255    return True;
256}
257
258Bool
259XkbLatchModifiers(	Display *	dpy,
260			unsigned int	deviceSpec,
261			unsigned int	affect,
262			unsigned int	values)
263{
264    register xkbLatchLockStateReq *req;
265    XkbInfoPtr xkbi;
266
267    if ((dpy->flags & XlibDisplayNoXkb) ||
268	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
269	return False;
270    LockDisplay(dpy);
271    xkbi = dpy->xkb_info;
272    GetReq(kbLatchLockState, req);
273    req->reqType = xkbi->codes->major_opcode;
274    req->xkbReqType = X_kbLatchLockState;
275    req->deviceSpec = deviceSpec;
276
277    req->affectModLatches= affect;
278    req->modLatches = values;
279    req->latchGroup = False;
280    req->groupLatch = 0;
281
282    req->affectModLocks = req->modLocks = 0;
283    req->lockGroup = False;
284    req->groupLock = 0;
285
286    UnlockDisplay(dpy);
287    SyncHandle();
288    return True;
289}
290
291Bool
292XkbLockGroup(Display *dpy,unsigned int deviceSpec,unsigned int group)
293{
294    register xkbLatchLockStateReq *req;
295    XkbInfoPtr xkbi;
296
297    if ((dpy->flags & XlibDisplayNoXkb) ||
298	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
299	return False;
300    LockDisplay(dpy);
301    xkbi = dpy->xkb_info;
302    GetReq(kbLatchLockState, req);
303    req->reqType = xkbi->codes->major_opcode;
304    req->xkbReqType = X_kbLatchLockState;
305    req->deviceSpec = deviceSpec;
306    req->affectModLocks= 0;
307    req->modLocks = 0;
308    req->lockGroup = True;
309    req->groupLock = group;
310
311    req->affectModLatches = req->modLatches = 0;
312    req->latchGroup = False;
313    req->groupLatch = 0;
314    UnlockDisplay(dpy);
315    SyncHandle();
316    return True;
317}
318
319Bool
320XkbLatchGroup(Display *dpy,unsigned int deviceSpec,unsigned int group)
321{
322    register xkbLatchLockStateReq *req;
323    XkbInfoPtr xkbi;
324
325    if ((dpy->flags & XlibDisplayNoXkb) ||
326	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
327	return False;
328    LockDisplay(dpy);
329    xkbi = dpy->xkb_info;
330    GetReq(kbLatchLockState, req);
331    req->reqType = xkbi->codes->major_opcode;
332    req->xkbReqType = X_kbLatchLockState;
333    req->deviceSpec = deviceSpec;
334
335    req->affectModLatches= 0;
336    req->modLatches = 0;
337    req->latchGroup = True;
338    req->groupLatch = group;
339
340    req->affectModLocks = req->modLocks = 0;
341    req->lockGroup = False;
342    req->groupLock = 0;
343
344    UnlockDisplay(dpy);
345    SyncHandle();
346    return True;
347}
348
349unsigned
350XkbSetXlibControls(Display *dpy,unsigned affect,unsigned values)
351{
352    if (!dpy->xkb_info)
353	XkbUseExtension(dpy,NULL,NULL);
354    if (!dpy->xkb_info)
355	return 0;
356    affect&= XkbLC_AllControls;
357    dpy->xkb_info->xlib_ctrls&= ~affect;
358    dpy->xkb_info->xlib_ctrls|= (affect&values);
359    return dpy->xkb_info->xlib_ctrls;
360}
361
362unsigned
363XkbGetXlibControls(Display *dpy)
364{
365    if (!dpy->xkb_info)
366	XkbUseExtension(dpy,NULL,NULL);
367    if (!dpy->xkb_info)
368	return 0;
369    return dpy->xkb_info->xlib_ctrls;
370}
371
372unsigned int
373XkbXlibControlsImplemented(void)
374{
375#ifdef __sgi
376    return XkbLC_AllControls;
377#else
378    return XkbLC_AllControls&~XkbLC_AllComposeControls;
379#endif
380}
381
382Bool
383XkbSetDebuggingFlags(	Display *	dpy,
384			unsigned int 	mask,
385			unsigned int 	flags,
386			char *		msg,
387			unsigned int	ctrls_mask,
388			unsigned int	ctrls,
389			unsigned int *	rtrn_flags,
390			unsigned int *	rtrn_ctrls)
391{
392    register xkbSetDebuggingFlagsReq *req;
393    xkbSetDebuggingFlagsReply rep;
394    XkbInfoPtr xkbi;
395
396    if ((dpy->flags & XlibDisplayNoXkb) ||
397	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
398	return False;
399    LockDisplay(dpy);
400    xkbi = dpy->xkb_info;
401    GetReq(kbSetDebuggingFlags, req);
402    req->reqType= 	xkbi->codes->major_opcode;
403    req->xkbReqType=	X_kbSetDebuggingFlags;
404    req->affectFlags=	mask;
405    req->flags= 	flags;
406    req->affectCtrls=	ctrls_mask;
407    req->ctrls= 	ctrls;
408
409    if (msg) {
410	char *out;
411	req->msgLength= (unsigned short)strlen(msg)+1;
412	req->length+= (req->msgLength+(unsigned)3)>>2;
413	BufAlloc(char *,out,((req->msgLength+(unsigned)3)/4)*4);
414	memcpy(out,msg,req->msgLength);
415    }
416    else req->msgLength= 0;
417    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
418	UnlockDisplay(dpy);
419	SyncHandle();
420	return False;
421    }
422    if (rtrn_flags)
423	*rtrn_flags= rep.currentFlags;
424    if (rtrn_ctrls)
425	*rtrn_ctrls= rep.currentCtrls;
426    UnlockDisplay(dpy);
427    SyncHandle();
428    return True;
429}
430
431Bool
432XkbComputeEffectiveMap(	XkbDescPtr 	xkb,
433			XkbKeyTypePtr 	type,
434			unsigned char *	map_rtrn)
435{
436register int 		i;
437unsigned     		tmp;
438XkbKTMapEntryPtr	entry = NULL;
439
440    if ((!xkb)||(!type)||(!xkb->server))
441	return False;
442
443    if (type->mods.vmods!=0) {
444	if (!XkbVirtualModsToReal(xkb,type->mods.vmods,&tmp))
445	    return False;
446
447	type->mods.mask= tmp|type->mods.real_mods;
448	entry= type->map;
449	for (i=0;i<type->map_count;i++,entry++) {
450	    tmp= 0;
451	    if (entry->mods.vmods!=0) {
452		if (!XkbVirtualModsToReal(xkb,entry->mods.vmods,&tmp))
453		    return False;
454		if (tmp==0) {
455		    entry->active= False;
456		    continue;
457		}
458	    }
459	    entry->active= True;
460	    entry->mods.mask= (entry->mods.real_mods|tmp)&type->mods.mask;
461	}
462    }
463    else {
464	type->mods.mask= type->mods.real_mods;
465    }
466    if (map_rtrn!=NULL) {
467	bzero(map_rtrn,type->mods.mask+1);
468	for (i=0;i<type->map_count;i++) {
469	    if (entry->active) {
470		map_rtrn[type->map[i].mods.mask]= type->map[i].level;
471	    }
472	}
473    }
474    return True;
475}
476
477Status
478XkbGetState(Display *dpy,unsigned deviceSpec,XkbStatePtr rtrn)
479{
480    register xkbGetStateReq	*req;
481    xkbGetStateReply rep;
482    XkbInfoPtr xkbi;
483
484    if ((dpy->flags & XlibDisplayNoXkb) ||
485	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
486	return BadAccess;
487    LockDisplay(dpy);
488    xkbi = dpy->xkb_info;
489    GetReq(kbGetState, req);
490    req->reqType = xkbi->codes->major_opcode;
491    req->xkbReqType = X_kbGetState;
492    req->deviceSpec = deviceSpec;
493    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
494	UnlockDisplay(dpy);
495	SyncHandle();
496	return BadImplementation;
497    }
498    rtrn->mods= 		rep.mods;
499    rtrn->base_mods= 		rep.baseMods;
500    rtrn->latched_mods= 	rep.latchedMods;
501    rtrn->locked_mods= 		rep.lockedMods;
502    rtrn->group= 		rep.group;
503    rtrn->base_group= 		rep.baseGroup;
504    rtrn->latched_group= 	rep.latchedGroup;
505    rtrn->locked_group= 	rep.lockedGroup;
506    rtrn->compat_state= 	rep.compatState;
507    rtrn->grab_mods=		rep.grabMods;
508    rtrn->compat_grab_mods=	rep.compatGrabMods;
509    rtrn->lookup_mods=		rep.lookupMods;
510    rtrn->compat_lookup_mods=	rep.compatLookupMods;
511    rtrn->ptr_buttons=		rep.ptrBtnState;
512    UnlockDisplay(dpy);
513    SyncHandle();
514    return Success;
515}
516
517Bool
518XkbSetDetectableAutoRepeat(Display *dpy,Bool detectable,Bool *supported)
519{
520register xkbPerClientFlagsReq *	req;
521xkbPerClientFlagsReply 		rep;
522XkbInfoPtr 			xkbi;
523
524    if ((dpy->flags & XlibDisplayNoXkb) ||
525	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
526	return False;
527    LockDisplay(dpy);
528    xkbi = dpy->xkb_info;
529    GetReq(kbPerClientFlags, req);
530    req->reqType = xkbi->codes->major_opcode;
531    req->xkbReqType = X_kbPerClientFlags;
532    req->deviceSpec = XkbUseCoreKbd;
533    req->change = XkbPCF_DetectableAutoRepeatMask;
534    if (detectable)
535	 req->value = XkbPCF_DetectableAutoRepeatMask;
536    else req->value = 0;
537    req->ctrlsToChange = req->autoCtrls= req->autoCtrlValues= 0;
538    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
539	UnlockDisplay(dpy);
540	SyncHandle();
541	return False;
542    }
543    UnlockDisplay(dpy);
544    SyncHandle();
545    if (supported!=NULL)
546	*supported= ((rep.supported&XkbPCF_DetectableAutoRepeatMask)!=0);
547    return ((rep.value&XkbPCF_DetectableAutoRepeatMask)!=0);
548}
549
550Bool
551XkbGetDetectableAutoRepeat(Display *dpy,Bool *supported)
552{
553register xkbPerClientFlagsReq *	req;
554xkbPerClientFlagsReply 		rep;
555XkbInfoPtr 			xkbi;
556
557    if ((dpy->flags & XlibDisplayNoXkb) ||
558	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
559	return False;
560    LockDisplay(dpy);
561    xkbi = dpy->xkb_info;
562    GetReq(kbPerClientFlags, req);
563    req->reqType = xkbi->codes->major_opcode;
564    req->xkbReqType = X_kbPerClientFlags;
565    req->deviceSpec = XkbUseCoreKbd;
566    req->change = 0;
567    req->value = 0;
568    req->ctrlsToChange = req->autoCtrls= req->autoCtrlValues= 0;
569    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
570	UnlockDisplay(dpy);
571	SyncHandle();
572	return False;
573    }
574    UnlockDisplay(dpy);
575    SyncHandle();
576    if (supported!=NULL)
577	*supported= ((rep.supported&XkbPCF_DetectableAutoRepeatMask)!=0);
578    return ((rep.value&XkbPCF_DetectableAutoRepeatMask)!=0);
579}
580
581Bool
582XkbSetAutoResetControls(	Display *	dpy,
583				unsigned 	changes,
584				unsigned *	auto_ctrls,
585				unsigned *	auto_values)
586{
587register xkbPerClientFlagsReq *	req;
588xkbPerClientFlagsReply 		rep;
589XkbInfoPtr 			xkbi;
590
591    if ((dpy->flags & XlibDisplayNoXkb) ||
592	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
593	return False;
594    LockDisplay(dpy);
595    xkbi = dpy->xkb_info;
596    GetReq(kbPerClientFlags, req);
597    req->reqType = xkbi->codes->major_opcode;
598    req->xkbReqType = X_kbPerClientFlags;
599    req->change = XkbPCF_AutoResetControlsMask;
600    req->deviceSpec = XkbUseCoreKbd;
601    req->value = XkbPCF_AutoResetControlsMask;
602    req->ctrlsToChange= changes;
603    req->autoCtrls= *auto_ctrls;
604    req->autoCtrlValues= *auto_values;
605    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
606	UnlockDisplay(dpy);
607	SyncHandle();
608	return False;
609    }
610    UnlockDisplay(dpy);
611    SyncHandle();
612    *auto_ctrls= rep.autoCtrls;
613    *auto_values= rep.autoCtrlValues;
614    return ((rep.value&XkbPCF_AutoResetControlsMask)!=0);
615}
616
617Bool
618XkbGetAutoResetControls(	Display *	dpy,
619				unsigned *	auto_ctrls,
620				unsigned *	auto_ctrl_values)
621{
622register xkbPerClientFlagsReq *	req;
623xkbPerClientFlagsReply 		rep;
624XkbInfoPtr 			xkbi;
625
626    if ((dpy->flags & XlibDisplayNoXkb) ||
627	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
628	return False;
629    LockDisplay(dpy);
630    xkbi = dpy->xkb_info;
631    GetReq(kbPerClientFlags, req);
632    req->reqType = xkbi->codes->major_opcode;
633    req->xkbReqType = X_kbPerClientFlags;
634    req->deviceSpec = XkbUseCoreKbd;
635    req->change = 0;
636    req->value = 0;
637    req->ctrlsToChange = req->autoCtrls= req->autoCtrlValues= 0;
638    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
639	UnlockDisplay(dpy);
640	SyncHandle();
641	return False;
642    }
643    UnlockDisplay(dpy);
644    SyncHandle();
645    if (auto_ctrls)
646	*auto_ctrls= rep.autoCtrls;
647    if (auto_ctrl_values)
648	*auto_ctrl_values= rep.autoCtrlValues;
649    return ((rep.value&XkbPCF_AutoResetControlsMask)!=0);
650}
651
652Bool
653XkbSetPerClientControls(	Display *	dpy,
654				unsigned 	change,
655				unsigned *	values)
656{
657register xkbPerClientFlagsReq *	req;
658xkbPerClientFlagsReply 		rep;
659XkbInfoPtr 			xkbi;
660unsigned			value_hold = *values;
661
662    if ((dpy->flags & XlibDisplayNoXkb) ||
663	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)) ||
664	(change & ~(XkbPCF_GrabsUseXKBStateMask|XkbPCF_LookupStateWhenGrabbed|XkbPCF_SendEventUsesXKBState)))
665	return False;
666    LockDisplay(dpy);
667    xkbi = dpy->xkb_info;
668    GetReq(kbPerClientFlags, req);
669    req->reqType = xkbi->codes->major_opcode;
670    req->xkbReqType = X_kbPerClientFlags;
671    req->change = change;
672    req->deviceSpec = XkbUseCoreKbd;
673    req->value = *values;
674    req->ctrlsToChange = req->autoCtrls = req->autoCtrlValues= 0;
675    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
676	UnlockDisplay(dpy);
677	SyncHandle();
678	return False;
679    }
680    UnlockDisplay(dpy);
681    SyncHandle();
682    *values = rep.value;
683    return ((rep.value&value_hold)!=0);
684}
685
686Bool
687XkbGetPerClientControls(	Display *	dpy,
688				unsigned *	ctrls)
689{
690register xkbPerClientFlagsReq *	req;
691xkbPerClientFlagsReply 		rep;
692XkbInfoPtr 			xkbi;
693
694    if ((dpy->flags & XlibDisplayNoXkb) ||
695	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)) ||
696	(*ctrls & ~(XkbPCF_GrabsUseXKBStateMask|XkbPCF_LookupStateWhenGrabbed|XkbPCF_SendEventUsesXKBState)))
697	return False;
698    LockDisplay(dpy);
699    xkbi = dpy->xkb_info;
700    GetReq(kbPerClientFlags, req);
701    req->reqType = xkbi->codes->major_opcode;
702    req->xkbReqType = X_kbPerClientFlags;
703    req->deviceSpec = XkbUseCoreKbd;
704    req->change = 0;
705    req->value = 0;
706    req->ctrlsToChange = req->autoCtrls= req->autoCtrlValues= 0;
707    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
708	UnlockDisplay(dpy);
709	SyncHandle();
710	return False;
711    }
712    UnlockDisplay(dpy);
713    SyncHandle();
714    if (ctrls)
715	*ctrls= (rep.value & (XkbPCF_GrabsUseXKBStateMask |
716		 XkbPCF_LookupStateWhenGrabbed |
717		 XkbPCF_SendEventUsesXKBState));
718    return (True);
719}
720
721Display *
722XkbOpenDisplay(	char *	name,
723		int *	ev_rtrn,
724		int *	err_rtrn,
725		int *	major_rtrn,
726		int *	minor_rtrn,
727		int *	reason)
728{
729    Display* dpy;
730    int	 major_num,minor_num;
731
732    if ((major_rtrn!=NULL) && (minor_rtrn!=NULL)) {
733	if (!XkbLibraryVersion(major_rtrn,minor_rtrn)) {
734	    if (reason!=NULL)
735		*reason= XkbOD_BadLibraryVersion;
736	    return NULL;
737	}
738    }
739    else {
740	major_num= XkbMajorVersion;
741	minor_num= XkbMinorVersion;
742	major_rtrn= &major_num;
743	minor_rtrn= &minor_num;
744    }
745    dpy= XOpenDisplay(name);
746    if (dpy==NULL) {
747	if (reason!=NULL)
748	    *reason= XkbOD_ConnectionRefused;
749	return NULL;
750    }
751    if (!XkbQueryExtension(dpy,NULL,ev_rtrn,err_rtrn,major_rtrn,minor_rtrn)) {
752	if (reason!=NULL) {
753	    if ((*major_rtrn!=0)||(*minor_rtrn!=0))
754		 *reason= XkbOD_BadServerVersion;
755	    else *reason= XkbOD_NonXkbServer;
756	}
757	XCloseDisplay(dpy);
758	return NULL;
759    }
760    if (reason!=NULL)
761	*reason= XkbOD_Success;
762    return dpy;
763}
764
765void
766XkbSetAtomFuncs(XkbInternAtomFunc getAtom,XkbGetAtomNameFunc getName)
767{
768    _XkbInternAtomFunc= (getAtom?getAtom:XInternAtom);
769    _XkbGetAtomNameFunc= (getName?getName:XGetAtomName);
770    return;
771}
772