xkb: make XkbSetControls work on all core-sending devices
This commit is contained in:
		
							parent
							
								
									7b4dc171b0
								
							
						
					
					
						commit
						3686cd0fbf
					
				
							
								
								
									
										340
									
								
								xkb/xkb.c
								
								
								
								
							
							
						
						
									
										340
									
								
								xkb/xkb.c
								
								
								
								
							|  | @ -677,7 +677,7 @@ ProcXkbGetControls(ClientPtr client) | ||||||
| int | int | ||||||
| ProcXkbSetControls(ClientPtr client) | ProcXkbSetControls(ClientPtr client) | ||||||
| { | { | ||||||
|     DeviceIntPtr 	dev; |     DeviceIntPtr 	dev, tmpd; | ||||||
|     XkbSrvInfoPtr	xkbi; |     XkbSrvInfoPtr	xkbi; | ||||||
|     XkbControlsPtr	ctrl; |     XkbControlsPtr	ctrl; | ||||||
|     XkbControlsRec	new,old; |     XkbControlsRec	new,old; | ||||||
|  | @ -688,159 +688,207 @@ ProcXkbSetControls(ClientPtr client) | ||||||
|     REQUEST(xkbSetControlsReq); |     REQUEST(xkbSetControlsReq); | ||||||
|     REQUEST_SIZE_MATCH(xkbSetControlsReq); |     REQUEST_SIZE_MATCH(xkbSetControlsReq); | ||||||
| 
 | 
 | ||||||
|     if (!(client->xkbClientFlags&_XkbClientInitialized)) |     if (!(client->xkbClientFlags & _XkbClientInitialized)) | ||||||
| 	return BadAccess; | 	return BadAccess; | ||||||
| 
 | 
 | ||||||
|     CHK_KBD_DEVICE(dev,stuff->deviceSpec); |     CHK_KBD_DEVICE(dev, stuff->deviceSpec); | ||||||
|     CHK_MASK_LEGAL(0x01,stuff->changeCtrls,XkbAllControlsMask); |     CHK_MASK_LEGAL(0x01, stuff->changeCtrls, XkbAllControlsMask); | ||||||
| 
 | 
 | ||||||
|     xkbi = dev->key->xkbInfo; |     for (tmpd = inputInfo.keyboard; tmpd; tmpd = tmpd->next) { | ||||||
|     ctrl = xkbi->desc->ctrls; |         if ((dev == inputInfo.keyboard && tmpd->key && tmpd->coreEvents) || | ||||||
|     new = *ctrl; |             tmpd == inputInfo.keyboard) { | ||||||
|     XkbSetCauseXkbReq(&cause,X_kbSetControls,client); |  | ||||||
|     if (stuff->changeCtrls&XkbInternalModsMask) { |  | ||||||
| 	CHK_MASK_MATCH(0x02,stuff->affectInternalMods,stuff->internalMods); |  | ||||||
| 	CHK_MASK_MATCH(0x03,stuff->affectInternalVMods,stuff->internalVMods); |  | ||||||
| 	new.internal.real_mods&=~stuff->affectInternalMods; |  | ||||||
| 	new.internal.real_mods|=(stuff->affectInternalMods&stuff->internalMods); |  | ||||||
| 	new.internal.vmods&=~stuff->affectInternalVMods; |  | ||||||
| 	new.internal.vmods|= (stuff->affectInternalVMods&stuff->internalVMods); |  | ||||||
| 	new.internal.mask= new.internal.real_mods| |  | ||||||
| 	      XkbMaskForVMask(xkbi->desc,new.internal.vmods); |  | ||||||
|     } |  | ||||||
|     if (stuff->changeCtrls&XkbIgnoreLockModsMask) { |  | ||||||
| 	CHK_MASK_MATCH(0x4,stuff->affectIgnoreLockMods,stuff->ignoreLockMods); |  | ||||||
| 	CHK_MASK_MATCH(0x5,stuff->affectIgnoreLockVMods,stuff->ignoreLockVMods); |  | ||||||
| 	new.ignore_lock.real_mods&=~stuff->affectIgnoreLockMods; |  | ||||||
| 	new.ignore_lock.real_mods|= |  | ||||||
| 	      (stuff->affectIgnoreLockMods&stuff->ignoreLockMods); |  | ||||||
| 	new.ignore_lock.vmods&= ~stuff->affectIgnoreLockVMods; |  | ||||||
| 	new.ignore_lock.vmods|= |  | ||||||
| 	      (stuff->affectIgnoreLockVMods&stuff->ignoreLockVMods); |  | ||||||
| 	new.ignore_lock.mask= new.ignore_lock.real_mods| |  | ||||||
| 	      XkbMaskForVMask(xkbi->desc,new.ignore_lock.vmods); |  | ||||||
|     } |  | ||||||
|     CHK_MASK_MATCH(0x06,stuff->affectEnabledCtrls,stuff->enabledCtrls); |  | ||||||
|     if (stuff->affectEnabledCtrls) { |  | ||||||
| 	CHK_MASK_LEGAL(0x07,stuff->affectEnabledCtrls,XkbAllBooleanCtrlsMask); |  | ||||||
| 	new.enabled_ctrls&= ~stuff->affectEnabledCtrls; |  | ||||||
| 	new.enabled_ctrls|= (stuff->affectEnabledCtrls&stuff->enabledCtrls); |  | ||||||
|     } |  | ||||||
|     if (stuff->changeCtrls&XkbRepeatKeysMask) { |  | ||||||
| 	if ((stuff->repeatDelay<1)||(stuff->repeatInterval<1)) { |  | ||||||
| 	   client->errorValue = _XkbErrCode3(0x08,stuff->repeatDelay, |  | ||||||
| 							stuff->repeatInterval); |  | ||||||
| 	   return BadValue; |  | ||||||
| 	} |  | ||||||
| 	new.repeat_delay = stuff->repeatDelay; |  | ||||||
| 	new.repeat_interval = stuff->repeatInterval; |  | ||||||
|     } |  | ||||||
|     if (stuff->changeCtrls&XkbSlowKeysMask) { |  | ||||||
| 	if (stuff->slowKeysDelay<1) { |  | ||||||
| 	    client->errorValue = _XkbErrCode2(0x09,stuff->slowKeysDelay); |  | ||||||
| 	    return BadValue; |  | ||||||
| 	} |  | ||||||
| 	new.slow_keys_delay = stuff->slowKeysDelay; |  | ||||||
|     } |  | ||||||
|     if (stuff->changeCtrls&XkbBounceKeysMask) { |  | ||||||
| 	if (stuff->debounceDelay<1) { |  | ||||||
| 	    client->errorValue = _XkbErrCode2(0x0A,stuff->debounceDelay); |  | ||||||
| 	    return BadValue; |  | ||||||
| 	} |  | ||||||
| 	new.debounce_delay = stuff->debounceDelay; |  | ||||||
|     } |  | ||||||
|     if (stuff->changeCtrls&XkbMouseKeysMask) { |  | ||||||
| 	if (stuff->mkDfltBtn>XkbMaxMouseKeysBtn) { |  | ||||||
| 	    client->errorValue = _XkbErrCode2(0x0B,stuff->mkDfltBtn); |  | ||||||
| 	    return BadValue; |  | ||||||
| 	} |  | ||||||
| 	new.mk_dflt_btn = stuff->mkDfltBtn; |  | ||||||
|     } |  | ||||||
|     if (stuff->changeCtrls&XkbMouseKeysAccelMask) { |  | ||||||
| 	if ((stuff->mkDelay<1) || (stuff->mkInterval<1) || |  | ||||||
| 	    (stuff->mkTimeToMax<1) || (stuff->mkMaxSpeed<1)|| |  | ||||||
| 	    (stuff->mkCurve<-1000)) { |  | ||||||
| 	    client->errorValue = _XkbErrCode2(0x0C,0); |  | ||||||
| 	    return BadValue; |  | ||||||
| 	} |  | ||||||
| 	new.mk_delay = stuff->mkDelay; |  | ||||||
| 	new.mk_interval = stuff->mkInterval; |  | ||||||
| 	new.mk_time_to_max = stuff->mkTimeToMax; |  | ||||||
| 	new.mk_max_speed = stuff->mkMaxSpeed; |  | ||||||
| 	new.mk_curve = stuff->mkCurve; |  | ||||||
| 	AccessXComputeCurveFactor(xkbi,&new); |  | ||||||
|     } |  | ||||||
|     if (stuff->changeCtrls&XkbGroupsWrapMask) { |  | ||||||
| 	unsigned act,num; |  | ||||||
| 	act= XkbOutOfRangeGroupAction(stuff->groupsWrap); |  | ||||||
| 	switch (act) { |  | ||||||
| 	    case XkbRedirectIntoRange: |  | ||||||
| 		num= XkbOutOfRangeGroupNumber(stuff->groupsWrap); |  | ||||||
| 		if (num>=new.num_groups) { |  | ||||||
| 		    client->errorValue= _XkbErrCode3(0x0D,new.num_groups,num); |  | ||||||
| 		    return BadValue; |  | ||||||
| 		} |  | ||||||
| 	    case XkbWrapIntoRange: |  | ||||||
| 	    case XkbClampIntoRange: |  | ||||||
| 		break; |  | ||||||
| 	    default: |  | ||||||
| 		client->errorValue= _XkbErrCode2(0x0E,act); |  | ||||||
| 		return BadValue; |  | ||||||
| 	} |  | ||||||
| 	new.groups_wrap= stuff->groupsWrap; |  | ||||||
|     } |  | ||||||
|     CHK_MASK_LEGAL(0x0F,stuff->axOptions,XkbAX_AllOptionsMask); |  | ||||||
|     if (stuff->changeCtrls&XkbAccessXKeysMask) |  | ||||||
| 	new.ax_options = stuff->axOptions&XkbAX_AllOptionsMask; |  | ||||||
|     else { |  | ||||||
| 	if (stuff->changeCtrls&XkbStickyKeysMask) { |  | ||||||
| 	   new.ax_options&= ~XkbAX_SKOptionsMask; |  | ||||||
| 	   new.ax_options|= stuff->axOptions&XkbAX_SKOptionsMask; |  | ||||||
| 	} |  | ||||||
| 	if (stuff->changeCtrls&XkbAccessXFeedbackMask) { |  | ||||||
| 	   new.ax_options&= ~XkbAX_FBOptionsMask; |  | ||||||
| 	   new.ax_options|= stuff->axOptions&XkbAX_FBOptionsMask; |  | ||||||
| 	} |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     if (stuff->changeCtrls&XkbAccessXTimeoutMask) { |             xkbi = tmpd->key->xkbInfo; | ||||||
| 	if (stuff->axTimeout<1) { |             ctrl = xkbi->desc->ctrls; | ||||||
| 	    client->errorValue = _XkbErrCode2(0x10,stuff->axTimeout); |             new = *ctrl; | ||||||
| 	    return BadValue; |             XkbSetCauseXkbReq(&cause, X_kbSetControls, client); | ||||||
| 	} |  | ||||||
| 	CHK_MASK_MATCH(0x11,stuff->axtCtrlsMask,stuff->axtCtrlsValues); |  | ||||||
| 	CHK_MASK_LEGAL(0x12,stuff->axtCtrlsMask,XkbAllBooleanCtrlsMask); |  | ||||||
| 	CHK_MASK_MATCH(0x13,stuff->axtOptsMask,stuff->axtOptsValues); |  | ||||||
| 	CHK_MASK_LEGAL(0x14,stuff->axtOptsMask,XkbAX_AllOptionsMask); |  | ||||||
| 	new.ax_timeout = stuff->axTimeout; |  | ||||||
| 	new.axt_ctrls_mask = stuff->axtCtrlsMask; |  | ||||||
| 	new.axt_ctrls_values = (stuff->axtCtrlsValues&stuff->axtCtrlsMask); |  | ||||||
| 	new.axt_opts_mask = stuff->axtOptsMask; |  | ||||||
| 	new.axt_opts_values= (stuff->axtOptsValues&stuff->axtOptsMask); |  | ||||||
|     } |  | ||||||
|     if (stuff->changeCtrls&XkbPerKeyRepeatMask) { |  | ||||||
| 	memcpy(new.per_key_repeat,stuff->perKeyRepeat,XkbPerKeyBitArraySize); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     old= *ctrl; |             if (stuff->changeCtrls & XkbInternalModsMask) { | ||||||
|     *ctrl= new; |                 CHK_MASK_MATCH(0x02, stuff->affectInternalMods, | ||||||
|     XkbDDXChangeControls(dev,&old,ctrl); |                                stuff->internalMods); | ||||||
|  |                 CHK_MASK_MATCH(0x03, stuff->affectInternalVMods, | ||||||
|  |                                stuff->internalVMods); | ||||||
| 
 | 
 | ||||||
|     if (XkbComputeControlsNotify(dev,&old,ctrl,&cn,False)) { |                 new.internal.real_mods &= ~(stuff->affectInternalMods); | ||||||
| 	cn.keycode= 0; |                 new.internal.real_mods |= (stuff->affectInternalMods & | ||||||
| 	cn.eventType = 0; |                                            stuff->internalMods); | ||||||
| 	cn.requestMajor = XkbReqCode; |                 new.internal.vmods &= ~(stuff->affectInternalVMods); | ||||||
| 	cn.requestMinor = X_kbSetControls; |                 new.internal.vmods |= (stuff->affectInternalVMods & | ||||||
| 	XkbSendControlsNotify(dev,&cn); |                                        stuff->internalVMods); | ||||||
|     } |                 new.internal.mask = new.internal.real_mods | | ||||||
|  |                                     XkbMaskForVMask(xkbi->desc, | ||||||
|  |                                                     new.internal.vmods); | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|     if ((sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0))!=NULL) |             if (stuff->changeCtrls & XkbIgnoreLockModsMask) { | ||||||
| 	XkbUpdateIndicators(dev,sli->usesControls,True,NULL,&cause); |                 CHK_MASK_MATCH(0x4, stuff->affectIgnoreLockMods, | ||||||
|  |                                stuff->ignoreLockMods); | ||||||
|  |                 CHK_MASK_MATCH(0x5, stuff->affectIgnoreLockVMods, | ||||||
|  |                                stuff->ignoreLockVMods); | ||||||
| 
 | 
 | ||||||
|     /* If sticky keys were disabled, clear all locks and latches */ |                 new.ignore_lock.real_mods &= ~(stuff->affectIgnoreLockMods); | ||||||
|     if ((old.enabled_ctrls&XkbStickyKeysMask)&& |                 new.ignore_lock.real_mods |= (stuff->affectIgnoreLockMods & | ||||||
| 	(!(ctrl->enabled_ctrls&XkbStickyKeysMask))) { |                                               stuff->ignoreLockMods); | ||||||
| 	XkbClearAllLatchesAndLocks(dev,xkbi,True,&cause); |                 new.ignore_lock.vmods &= ~(stuff->affectIgnoreLockVMods); | ||||||
|  |                 new.ignore_lock.vmods |= (stuff->affectIgnoreLockVMods & | ||||||
|  |                                           stuff->ignoreLockVMods); | ||||||
|  |                 new.ignore_lock.mask = new.ignore_lock.real_mods | | ||||||
|  |                                        XkbMaskForVMask(xkbi->desc, | ||||||
|  |                                                        new.ignore_lock.vmods); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             CHK_MASK_MATCH(0x06, stuff->affectEnabledCtrls, | ||||||
|  |                            stuff->enabledCtrls); | ||||||
|  |             if (stuff->affectEnabledCtrls) { | ||||||
|  |                 CHK_MASK_LEGAL(0x07, stuff->affectEnabledCtrls, | ||||||
|  |                                XkbAllBooleanCtrlsMask); | ||||||
|  | 
 | ||||||
|  |                 new.enabled_ctrls &= ~(stuff->affectEnabledCtrls); | ||||||
|  |                 new.enabled_ctrls |= (stuff->affectEnabledCtrls & | ||||||
|  |                                       stuff->enabledCtrls); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (stuff->changeCtrls & XkbRepeatKeysMask) { | ||||||
|  |                 if (stuff->repeatDelay < 1 || stuff->repeatInterval < 1) { | ||||||
|  |                     client->errorValue = _XkbErrCode3(0x08, stuff->repeatDelay, | ||||||
|  |                                                       stuff->repeatInterval); | ||||||
|  |                     return BadValue; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 new.repeat_delay = stuff->repeatDelay; | ||||||
|  |                 new.repeat_interval = stuff->repeatInterval; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (stuff->changeCtrls & XkbSlowKeysMask) { | ||||||
|  |                 if (stuff->slowKeysDelay < 1) { | ||||||
|  |                     client->errorValue = _XkbErrCode2(0x09, | ||||||
|  |                                                       stuff->slowKeysDelay); | ||||||
|  |                     return BadValue; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 new.slow_keys_delay = stuff->slowKeysDelay; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (stuff->changeCtrls & XkbBounceKeysMask) { | ||||||
|  |                 if (stuff->debounceDelay < 1) { | ||||||
|  |                     client->errorValue = _XkbErrCode2(0x0A, | ||||||
|  |                                                       stuff->debounceDelay); | ||||||
|  |                     return BadValue; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 new.debounce_delay = stuff->debounceDelay; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (stuff->changeCtrls & XkbMouseKeysMask) { | ||||||
|  |                 if (stuff->mkDfltBtn > XkbMaxMouseKeysBtn) { | ||||||
|  |                     client->errorValue = _XkbErrCode2(0x0B, stuff->mkDfltBtn); | ||||||
|  |                     return BadValue; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 new.mk_dflt_btn = stuff->mkDfltBtn; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (stuff->changeCtrls & XkbMouseKeysAccelMask) { | ||||||
|  |                 if (stuff->mkDelay < 1 || stuff->mkInterval < 1 || | ||||||
|  |                     stuff->mkTimeToMax < 1 || stuff->mkMaxSpeed < 1 || | ||||||
|  |                     stuff->mkCurve < -1000) { | ||||||
|  |                     client->errorValue = _XkbErrCode2(0x0C,0); | ||||||
|  |                     return BadValue; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 new.mk_delay = stuff->mkDelay; | ||||||
|  |                 new.mk_interval = stuff->mkInterval; | ||||||
|  |                 new.mk_time_to_max = stuff->mkTimeToMax; | ||||||
|  |                 new.mk_max_speed = stuff->mkMaxSpeed; | ||||||
|  |                 new.mk_curve = stuff->mkCurve; | ||||||
|  |                 AccessXComputeCurveFactor(xkbi, &new); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (stuff->changeCtrls & XkbGroupsWrapMask) { | ||||||
|  |                 unsigned act, num; | ||||||
|  | 
 | ||||||
|  |                 act = XkbOutOfRangeGroupAction(stuff->groupsWrap); | ||||||
|  |                 switch (act) { | ||||||
|  |                 case XkbRedirectIntoRange: | ||||||
|  |                     num = XkbOutOfRangeGroupNumber(stuff->groupsWrap); | ||||||
|  |                     if (num >= new.num_groups) { | ||||||
|  |                         client->errorValue = _XkbErrCode3(0x0D, new.num_groups, | ||||||
|  |                                                           num); | ||||||
|  |                         return BadValue; | ||||||
|  |                     } | ||||||
|  |                 case XkbWrapIntoRange: | ||||||
|  |                 case XkbClampIntoRange: | ||||||
|  |                     break; | ||||||
|  |                 default: | ||||||
|  |                     client->errorValue = _XkbErrCode2(0x0E, act); | ||||||
|  |                     return BadValue; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 new.groups_wrap= stuff->groupsWrap; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             CHK_MASK_LEGAL(0x0F, stuff->axOptions, XkbAX_AllOptionsMask); | ||||||
|  |             if (stuff->changeCtrls & XkbAccessXKeysMask) { | ||||||
|  |                 new.ax_options = stuff->axOptions & XkbAX_AllOptionsMask; | ||||||
|  |             } | ||||||
|  |             else { | ||||||
|  |                 if (stuff->changeCtrls & XkbStickyKeysMask) { | ||||||
|  |                     new.ax_options &= ~(XkbAX_SKOptionsMask); | ||||||
|  |                     new.ax_options |= (stuff->axOptions & XkbAX_SKOptionsMask); | ||||||
|  |                 } | ||||||
|  |              | ||||||
|  |                 if (stuff->changeCtrls & XkbAccessXFeedbackMask) { | ||||||
|  |                     new.ax_options &= ~(XkbAX_FBOptionsMask); | ||||||
|  |                     new.ax_options |= (stuff->axOptions & XkbAX_FBOptionsMask); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (stuff->changeCtrls & XkbAccessXTimeoutMask) { | ||||||
|  |                 if (stuff->axTimeout < 1) { | ||||||
|  |                     client->errorValue = _XkbErrCode2(0x10, stuff->axTimeout); | ||||||
|  |                     return BadValue; | ||||||
|  |                 } | ||||||
|  |                 CHK_MASK_MATCH(0x11, stuff->axtCtrlsMask, | ||||||
|  |                                stuff->axtCtrlsValues); | ||||||
|  |                 CHK_MASK_LEGAL(0x12, stuff->axtCtrlsMask, | ||||||
|  |                                XkbAllBooleanCtrlsMask); | ||||||
|  |                 CHK_MASK_MATCH(0x13, stuff->axtOptsMask, stuff->axtOptsValues); | ||||||
|  |                 CHK_MASK_LEGAL(0x14, stuff->axtOptsMask, XkbAX_AllOptionsMask); | ||||||
|  |                 new.ax_timeout = stuff->axTimeout; | ||||||
|  |                 new.axt_ctrls_mask = stuff->axtCtrlsMask; | ||||||
|  |                 new.axt_ctrls_values = (stuff->axtCtrlsValues & | ||||||
|  |                                         stuff->axtCtrlsMask); | ||||||
|  |                 new.axt_opts_mask = stuff->axtOptsMask; | ||||||
|  |                 new.axt_opts_values = (stuff->axtOptsValues & | ||||||
|  |                                        stuff->axtOptsMask); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (stuff->changeCtrls & XkbPerKeyRepeatMask) | ||||||
|  |                 memcpy(new.per_key_repeat, stuff->perKeyRepeat, | ||||||
|  |                        XkbPerKeyBitArraySize); | ||||||
|  | 
 | ||||||
|  |             old= *ctrl; | ||||||
|  |             *ctrl= new; | ||||||
|  |             XkbDDXChangeControls(tmpd, &old, ctrl); | ||||||
|  | 
 | ||||||
|  |             if (XkbComputeControlsNotify(tmpd, &old, ctrl, &cn, False)) { | ||||||
|  |                 cn.keycode = 0; | ||||||
|  |                 cn.eventType = 0; | ||||||
|  |                 cn.requestMajor = XkbReqCode; | ||||||
|  |                 cn.requestMinor = X_kbSetControls; | ||||||
|  |                 XkbSendControlsNotify(tmpd, &cn); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             sli = XkbFindSrvLedInfo(tmpd, XkbDfltXIClass, XkbDfltXIId, 0); | ||||||
|  |             if (sli) | ||||||
|  |                 XkbUpdateIndicators(tmpd, sli->usesControls, True, NULL, | ||||||
|  |                                     &cause); | ||||||
|  | 
 | ||||||
|  |             /* If sticky keys were disabled, clear all locks and latches */ | ||||||
|  |             if ((old.enabled_ctrls & XkbStickyKeysMask) && | ||||||
|  |                 !(ctrl->enabled_ctrls & XkbStickyKeysMask)) | ||||||
|  |                 XkbClearAllLatchesAndLocks(tmpd, xkbi, True, &cause); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return client->noClientException; |     return client->noClientException; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue