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