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