本章节介绍在存在 XKB 扩展的 server 中处理键事件所涉及的步骤。键盘活动能够生成键事件,并经过 DDX 层传递给 XKB,或者能够经过其余扩展(例如 XTEST)合成。app
应用全局 controls
当 XKB 收到键事件时,它首先检查全局 controls 以决定是否当即处理或者不处理事件。按照优先级由高到低可能影响事件的全局 controls 有:测试
-
若是在启用 BounceKeys control 时按下某个键,则仅当该键处于活动状态时,XKB 才会生成该事件。当释放按键时,server 将取消激活该键,而且以 debounce delay 指定的时间间隔启动一个 bounce keys 计时器。编码
若是 bounce keys 计时器到期或者在计时器到期以前按下某个其余键,则 server 从新激活相应的键(以前取消激活的键)并停用计时器。bounce keys timer 的到期或停用都不会致使事件。lua
-
若是启用了 SlowKeys control,则不当即处理键事件,而是以 slow keys delay 指定的时间间隔设置 slow keys 计时器。相应的键释放将停用此计时器。指针
若是 slow keys 计时器到期,则 server 生成对应的键事件,发送 XkbAccessXNotify并停用计时器。code
-
XKB 正常处理键事件,无论 RepeatKeys control 是否启用,但若是启用了 RepeatKeys 而且该事件中的键启用了 per-key autorepeat,则 XKB 正常处理键事件,但它也以 autorepeat delay 指定的时间段初始化 autorepeat 计时器,相应的键释放将停用计时器。server
若是 autorepeat 计时器到期,则 server 为相应的键生成 release 和 press 事件,而且根据 autorepeat interval 从新安排计时器。blog
键事件由每一个全局 control 依次处理:若是 BounceKeys control 接受键事件,则 SlowKeys control 会考虑它。一旦 SlowKeys control 容许或合成事件,RepeatKeys control 就会对其进行操做。索引
键 Behavior
一旦事件被全部 controls 接受或由计时器生成,server 就会检查相应键的 pre-key behavior。此扩展目前定义了以下键 behaviors:事件
-
KB_Default —— press 和 release 事件被正常处理
-
KB_Lock —— 若是键是逻辑上的 up(即core key map 相应 bit 被清除),当它被按下再释放,press 被正常处理,但忽略相应的 release。若是键是逻辑上的 down,当它被按下再释放,press 被忽略但相应的 release 被正常处理。
-
KB_RadioGroup(flags: CARD8,index: CARD8) —— 若是 index 指定的 radio group 的另外一个成员是逻辑上的 down,当键被按下,server 为那个逻辑上 down 的成员合成 key release 事件,而后正常处理键的 press 事件。
若是键它本身是逻辑上的 down,当键被按下,press 事件被忽略,但根据 flags 中 RGAllowNone bit 的值处理相应键的释放 。 若是它设置了,则 release 被正常处理;不然 release 被忽略。
全部其余键 release 事件被忽略。
-
KB_Overlay1(key: KEYCODE) —— 若是 Overlay1 control 被启用,报告来自此键的事件,就好像它们来自 key 参数指定的键同样,不然,正常处理 press 和 release 事件。
-
KB_Overlay2(key: KEYCODE) —— 若是 Overlay2 control 被启用,报告来自此键的事件,就好像它们来自 key 参数指定的键同样,不然,正常处理 press 和 release 事件。
X server 使用键 behavior 来肯定是处理仍是过滤掉任何给定的键事件;键 behavior 是独立于键盘 modifier 和 group state 的(每一个键只能有一个behavior)。
键 behavior 能够用于模拟任何这些类型的键或去指示键的不可修改的物理、电器或软件驱动特征。一个可选的 permanent flag 能够修改任何支持的 behaviors 并指示此 behavior 描述了键盘的不可更改的物理、电器或软件方面。permanent behaviors 不能被 XkbSetMap 请求修改和设置。permanent flag 表示 XKB 不能影响的底层系统的特征,所以 XKB 将全部 permanent behaviors 视为 KB_Default 而且不过滤上表中描述的键事件。
我通过测试后,发现没法经过 GetMap 请求获取键 behaviors 了,回复中 totalKeyBehaviors 始终为 0。
键 Actions
一旦 server 应用了全局 controls 和 pre-key behaviors 并决定去处理键事件,它应用键 action 来肯定该键对 server 内部 state 的影响。键 action 由操做符和一些可选数据组成。XKB 支持如下 actions:
- 修改 modifier 或 group 的 基本、暂锁、锁定 state
- 移动核心指针或模拟核心指针按钮事件
- 改变键盘 behavior 的大多数方面
- 终止或挂起(suspend)server
- 给感兴趣的 clients 发送消息
- 模拟其余键的事件
每一个键都有一个可选的 actions 列表。若是存在,则该列表与键相关的符号平行(即与键相关的每一个符号有一个 action)。对于键 press 事件,server 使用和事件中的键相关的 key symbol mapping 从列表查找要被应用的 action,就像 client 查找符号同样;若是事件中的键没有任何 actions,则 server 使用 SA_NoAction, 而无论 modifier 或 group 的 state 如何。
键 action 实际上分为两半;当键被按下对 server 的效果和当键被释放的效果。被应用于键 press 事件的 action 决定进一步的actions,若是有,这些 action 被应用于相应键的 release 事件或当键持续按下时的事件。当键是 down 时 client 能够改变与键相关的 actions,且不修改下次键释放被应用的 action;后续的 press-release pairs 将会使用新绑定的键action。
大多数对键盘 modifier state 有影响的 actions 的参数有名为 mods 的 modifier 定义和名为 useModMap 的 boolean flag。这两个字段组合在一块儿指定受 action 影响的 modifiers: 若是 useModMap 是 True,则 action 设置经过 modifier mapping 绑定到初始化该 action 的键的任何 modifiers;不然, action 设置由参数 mods 指定的 modifiers。为简洁起见,咱们将 userModMap 和 mods 的这种组合称为“action modifiers”。
XKB 支持以下 actions:
-
SA_NoAction —— 无直接影响,尽管 SA_NoAction 可能会改变其余 server actions 的影响(见下文)。
-
SA_SetMods(mods: MOD_DEF,useModMap: BOOL,clearLocks: BOOL) ——
- 键 press 增长任何 action modifiers 到键盘的基本 modifiers。
- 键 release 清除在键盘基本 modifiers 中的任何 action modifiers。
- 若是没有和此键同时操做其余键,而且设置了 clearLocks ,release 解锁任何 action modifiers。
-
SA_LatchMods(mods: MOD_DEF,useModMap: BOOL,clearLocks: BOOL,latchToLock: BOOL) ——
- 键 press 和 release 事件与 SA_SetMods 具备相同效果;若是没有和正在暂锁 modifier 的键同时操做其余键,键 release 事件有以下附加效果:
- 由 clearLocks 而被解锁的 modifiers 没有进一步效果。
- 若是设置了 latchToLock,则键 release 会锁定而后解除暂锁已经被暂锁的任何剩余的 action modifiers。
- 最后,键 release 会暂锁任何未被 clearLocks 或 latchToLock flags 使用过的 action modifiers。
-
SA_LockMods (mods: MOD_DEF, useModMap: BOOL, noLock: BOOL, noUnlock: BOOL) ——
- 键 press 设置任何 action modifiers 的基本和可能的锁定 state。若是 noLock 是 True,则仅基本 state 被改变。
- 对于键 release 事件,清除键盘基本 modifiers 中的任何 action modifiers,前提是没有其余影响相同 modifiers 的键是 down。若是 noUnlock 是 False 且在相应键按下以前任何 action modifiers 被锁定,键 release 解锁它们。
-
SA_SetGroup(group: INT8,groupAbsolute: BOOL,clearLocks: BOOL) ——
- 若是设置了 groupAbsolute,则键 press 事件改变键盘基本 group 为参数 group;不然,把参数 group 增长到键盘基本 group。则任何一种状况下,生成的键盘有效 group 根据键盘的 GroupsWrap control 的值被带到范围内。
- 若是在按住此键的同时按下有SA_ISOLock action 的键,键 release 无效果,不然它取消 press 的效果。
- 若是没有和此键同时操做其余键,而且设置了 clearLocks ,键 release 也设置键盘锁定 group 为 Group1。
-
SA_LatchGroup(group: INT8,groupAbsolute: BOOL,clearLocks: BOOL,latchToLock: BOOL)——
- 键 press 和 release 事件和 SA_SetGroup action 有相同效果;若是没有和正在暂锁 group 的键同时操做其余键而且 clearLocks flag 没有设置或没有效果,键 release 有以下效果:
- 若是设置了 latchToLock 且键盘暂锁 group 不是 0,键 release 增长应用到相应键 press 的 delta 到键盘锁定 group,并从键盘暂锁 group 减去它。键盘锁定和有效 group 根据键盘的 GroupsWrap control 的值被带到范围内。
- 不然,键 release 增长键 press delta 到键盘暂锁 group。
注:这里的 delta 不太明确。
-
SA_LockGroup(group: INT8,groupAbsolute: BOOL) ——
- 若是设置了 groupAbsolute,键 press 设置键盘锁定 group 为参数 group。不然,键 press 把参数 group 增长到键盘锁定 group。在任何一种状况下,生成的键盘锁定和有效 group 根据键盘的 GroupsWrap control 的值被带到范围内。
- 键 release 没有效果。
-
SA_MovePtr(x, y: INT16,noAccel: BOOL,absoluteX: BOOL,absoluteY: BOOL)——
- 若是未启用 MouseKeys control,则此 action 行为相似于 SA_NoAction,不然此 action 取消任何此键即将触发的 repeat key timers,并具备如下附加效果。
- 键 press 生成核心指针 MotionNotify 事件而不是一般的 KeyPress 事件。若是 absoluteX 为 True,参数 x 指定新的指针 X 座标,不然参数 x 被增长到指针当前的X 座标; absoluteY 和参数 y 以相同的方式指定新的 Y 坐标。
- 若是 noAccel 为 False,而且启用了 MouseKeysAccel control,键 press 也为此键初始化 mouse keys 计时器;每次该计时器到期时,光标再次移动。光标在这些后续事件中移动的距离由鼠标键加速决定,如 MouseKeysAccel Control 中所述。
- 键 release 除了停用 mosue keys 计时器(若是它被相应键 press 初始化了),就没有其余效果并被忽略(不会生成任何类型的事件)。
-
SA_PtrBtn(button: CARD8,count: CARD8,useDfltBtn: BOOL) ——
- 若是未启用 MouseKeys control,则此 action 的行为相似于 SA_NoAction。
- 若是设置了useDfltBtn,则会为当前的默认核心按钮生成事件。不然,将为参数 button 指定的按钮生成事件。
- 若是此 action 的参数 button 指定的按钮是逻辑上 down,则键 press 和相应的 release 被忽略且无效。
- 不然,键 press 致使一个或多个核心指针按钮事件,而非一般的键 press 事件。若是 count 为 0,则键 press 会生成一个 ButtonPress 事件; 若是 count 大于 0,则键 press 会生成 count 对的 ButtonPress 和 ButtonRelease 事件。
- 若是 count 为 0,则键 relase 生成一个核心指针 ButtonRelease 事件,它与相应的键 press 生成的事件相匹配;若是 count 大于 0,则键 release 不会致使 ButtonRelease 事件。键 release 永远不会致使键 release 事件。
-
SA_LockPtrBtn(button: BUTTON,noLock: BOOL,noUnlock: BOOL,useDfltBtn: BOOL) ——
- 若是未启用 MouseKeys control,则此 action 的行为相似于 SA_NoAction。
- 不然,若是由参数 useDfltBtn 和 button 指定的按钮未被锁定,键 press 致使一个 ButtonPress 事件而非键 press 事件且锁定此按钮。若是此按钮已经被锁定或若是 noLock 是 True,键 press 被忽略且无效。
- 若是相应的键 press 被忽略,而且 noUnlock 为 False, 键 release 生成一个 ButtonRelease 事件而非键 release 事件且解锁指定的按钮。若是相应的键 press 锁定一个按钮,键 release 被忽略且无效。
-
SA_SetPtrDflt(affect: CARD8,value: CARD8,dfltBtnAbs: BOOL)——
- 若是未启用 MouseKeys control,则此 action 的行为相似于 SA_NoAction。
- 不然,键 press 和 release 都被忽略,除了键 press 修改指针由参数 affect 指定的指针值为参数 value,以下所示:
- 若是 affect 设置了 SA_AffectDfltBtn,参数 value 和 dfltBtnAbs 指定了被用于各类指针 action 的默认指针按钮,以下所示: 若是 dfltBtnAbs 是 True,参数 value 指定要被使用的按钮,不然,参数 value 指定要被增长到当前默认按钮的数量。 在任何一种状况下,非法的按钮选择都会被 wrap 回到范围内。
-
SA_ISOLock(dfltIsGroup: False,mods: MOD_DEF,useModMap: BOOL,noLock: BOOL,noUnlock: BOOL,noAffectMods: BOOL,noAffectGrp: BOOL,noAffectPtr: BOOL,noAffectCtrls: BOOL) 或 (dfltIsGroup: True,group: INT8,groupAbsolute: BOOL,noAffectMods: BOOL,noAffectGrp: BOOL,noAffectPtr: BOOL,noAffectCtrls: BOOL)——
- 若是 dfltIsGroup 为 True,则键 press 设置由参数 groupAbsolute 和 group 指定的基本 group, 不然,键 press 设置 action modifier 到键盘的基本 modifiers。
- 键 release 清除由键 press 设置的基本 modifiers 或 group;若是没有其余适当的 action 与 SA_ISOLock action 同时发生,它可能会产生额外的影响。
- 若是noAffectMods 为 False,则与此 action 同时发生的 SA_SetMods 或 SA_LatchMods action 将被视为 SA_LockMods action。
- 若是 noAffectGrp 为 False,则与此 action 同时发生的 SA_SetGroup 或 SA_LatchGroup action 将被视为SA_LockGroup action。
- 若是 noAffectPtr 为 False,则与此 action 同时发生的 SA_PtrBtn action 被视为 SA_LockPtrBtn action。
- 若是 noAffectCtrls 为 False,则与此 action 同时发生的 SA_SetControls action 将被视为 SA_LockControls action。
- 若是 SA_ISOLock action 未转换其余 action,则键 release 将锁定由 action 参数指定的 group 或 modifiers。
-
SA_TerminateServer ——
- 键 press 终止 server, 键 release 被忽略。
- 此 action 是可选的;servers 能够自由忽略它,若是被忽略,它的行为相似于 SA_NoAction。
-
SA_SwitchScreen(num: INT8,switchApp: BOOL,screenAbs: BOOL) ——
- 若是 server 支持此 action 和多个 screens 或 displays (虚拟或真实),则此 action 将 num 和 screnAbs 指定的 screen 改成活动 screen。 若是 screenAbs 为 True, num 指定新 screen 的索引;不然,num 指定从当前活动 screen 到新 screen 的偏移量。
- 若是 switchApp 是 False,则应切换到同一个 server 的另外一个 screen 上。不然,应切换到另外一个共享相同物理 display 的 X server 或应用程序。
- 此 action 是可选的; server 若是不支持请求的行为能够自由忽略它或它的任何 flags。若是 action 被忽略,它的行为相似于 SA_NoAction,不然键 press 或 release 都不会生成事件。
-
SA_SetControls(controls: KB_BOOLCTRLMASK) ——
- 键 press 启用 control 中指定的任何在键按下时还没有启用的 boolean controls,键 release 禁用相应键 press 启用的任何 controls。 此 action 可致使 XkbControlsNotify 事件。
-
SA_LockControls(controls: KB_BOOLCTRLMASK,noLock: BOOL,noUnlock: BOOL )——
- 若是 noLock 为 False,则键 press 锁定和启用参数 controls 中指定的且在键按下时还没有被锁定的任何 controls。若是 noUnlock 为 False,键 release 解锁和禁用任何在参数 controls 中指定且相应键按下时还没有被启用的任何 controls。
-
SA_ActionMessage(pressMsg: BOOL,releaseMsg: BOOL,genEvent: BOOL,message: STRING)——
- 若是 pressMsg 为 True,则键 press 生成 XkbActionMessage 事件,该事件报告 keycode,event type 和 message 的内容。
- 若是 releaseMsg 为 True, 则键 release 生成 XkbActionMessage 事件,该事件报告 keycode,event type 和 message 的内容。
- 若是 genEvent为True,则键 press 和 release 都会生成 key press 和 key release 事件,不管它们是否也致使XkbActionMessage 事件。
-
SA_RedirectKey(newKey: KEYCODE,modsMask: KEYMASK,mods: KEYMASK,vmodsMask: CARD16,vmods: CARD16) ——
- 键 press 致使参数 newKey 指定的键的 key press 事件,而非实际的键。事件中报告的 state 字段的当前有效 modifier 修改以下:任何在 modsMask 中指定的真实 modifiers 都被设置为 mods 中的相应值。任何被绑定到 vmodsMask 中指定的虚拟 modifiers 的真实 modifier 都被设置或清除, 具体取决于 vmods 中的相应值。若是真实和虚拟 modifier 定义给单个 modifier 指定了冲突的值,真实 modifier 定义优先。
- 键 release 致使参数 newKey 指定的键的 key release 事件;对事件的 state 字段中的键盘的有效 modifiers 进行更改如上所述。
- 此 action 一般会重定向到同一设备的另外一个的键,好像此键或按钮致使了此事件,除非该设备不属于 input 扩展 KEYCLASS,这种状况下,此 action 会致使核心键盘设备上的事件。
-
SA_DeviceBtn(count: CARD8,button: BUTTON,device: CARD8) ——
- device 字段指定扩展设备的 ID;button 字段指定该设备上的按钮的索引。若是此 action 指定的按钮是逻辑上 down,则键 press 和相应的 release 被忽略且无效。若是此 action 指定的设备或按钮无效,则此 action 的行为相似于 SA_NoAction。
- 不然,键 press 会致使一个或多个 input 扩展设备按钮事件,而非一般的 key press 事件。若是 count 为 0,键 press 生成单个 DeviceButtonPress 事件;若是 count 大于 0,键 press 生成 count 对 DeviceButtonPress 和 DeviceButtonRelease 事件。
- 若是 count 为 0,键 release 生成一个 input 扩展 DeviceButtonRelease 事件,它匹配相应键 press 生成的事件;若是 count 大于 0,键 release 不致使 DeviceButtonRelease 事件。键 release 永远不会致使 key release 事件。
-
SA_LockDeviceBtn(button: BUTTON,device: CARD8,noLock: BOOL,noUnlock: BOOL ——
- device 字段指定扩展设备的 ID;button 字段指定该设备上的按钮的索引。若是此 action 指定的按钮是逻辑上 down,则键 press 和相应的 release 被忽略且无效。若是此 action 指定的设备或按钮无效,则此 action 的行为相似于 SA_NoAction。
- 不然,若是指定的按钮未锁定且 noLock 为 False,则键 press 会致使 input 扩展 DeviceButtonPress 事件而不是 key press 事件,并锁定按钮。若是该按钮已被锁定或者若是 noLock 为 True,则键 press 被忽略而且无效。
- 若是相应的键 press 被忽略了,而且 noUnlock 为 False,键 release 会生成 input 扩展 DeviceButtonRelease 事件,而不是核心协议或 input 扩展的键 release 事件,并解锁指定的按钮。若是相应的键 press 锁定按钮,则键 release 被忽略而且无效。
-
SA_DeviceValuator (device : CARD8,val1What : SA_DVOP,val1 : CARD8,val1Value : INT8,val1Scale : 0...7,val2What : SA_DVOP,val2 : CARD8,val2Value : INT8,val2Scale : 0...7)——
- device 字段指定扩展设备的 ID; val1 和 val2 指定该设备上的 valuators。若是 device 是无效的,或者 val1 和 val2 都没有指定有效的 valuator,则此 action 的行为相似于 SA_NoAction。
- 若是 valn 指定了有效的 valuator,而且 valnWhat 不是 SA_IgnoreVal,则按照 valnWhat 指定的方式调整指定的值:
- 若是 valnWhat 是 SA_SetValMin,则 valn 被设置为它的最小有效值。
- 若是 valnWhat 是 SA_SetValCenter,则 valn 被居中(为 (max-min)/2)。
- 若是 valnWhat 是 SA_SetValMax,则 valn 被设置为它的最大有效值。
- 若是 valnWhat 是 SA_SetValRelative,则
被增长到 valn。
- 若是 valnWhat 是 SA_SetValAbsolute,则 valn 被设置为
。
- SA_SetValRelative 或 SA_SetValAbsolute 致使的无效值被限制在范围内。
若是启用了 StickyKeys,则全部 SA_SetMods 和 SA_SetGroup actions 分别像 SA_LatchMods 和 SA_LatchGroup。若是设置了 LatchToLock AccessX option,则任一 action 都表现为设置了 SA_ClearLocks 和 SA_LatchToLock flags。
致使事件来自另外一个键或来自另外一个设备的按钮的 actions 当即生成指定的事件。这些 actions 不考虑绑定到事件重定向到的键或按钮的 behavior 或 actions(若是有)。
server actions 生成的核心事件包含在键事件发生时生效的键盘 state;报告的 state 不会反映因为致使它们的、绑定到键事件的 actions 而致使的 state 中的任何改变。
发送到未发出 XkbUseExtension 请求的 clients 的事件包含兼容 state,而不是实际的 XKB 键盘 state。有关此兼容性映射的说明,请参阅 XKB 对核心协议事件的影响。
传递键或按钮事件到 client
接收核心协议和 input 扩展的键或按钮事件的窗口和 client 使用由核心协议和 input 扩展指定的焦点策略、窗口层次结构和被动 grabs 来肯定,并进行如下更改:
- 若是 grab 中指定的 modifier state 与兼容性 grab state (在键盘 state 的兼容性组件中描述)匹配,则会触发被动 grab。 经过设置 GrabsUseXKBState per-client flag,clients 能够选择使用 XKB grab state。此 flag 影响全部由设置了它的 client 请求的全部被动 grabs,但不会影响其余 client 设置的被动 grabs。
- 致使了被动 grab 的事件的 state 字段报告在 grab 被触发时有效的 XKB 或兼容性 grab state;当键或按钮被释放,相应 release 事件的 state 字段报告相应的有效的 grab state。
- 若是设置了 LookupStateWhenGrabbed per-client flag,则在键盘或指针 grab 激活时发生的全部键或按钮事件包含 XKB 或兼容性 lookup state,具体取决于 GrabsUseXKBState per-client flag 的值。若是未设置 LookupStateWhenGrabbed,则它们包括 XKB 或兼容性 grab state。
- 另外,不触发被动 grab 报告的事件的 state 字段是从 XKB 有效 modifiers 和 group 派生的,如从 XKB State 计算 State 字段中所述。
- 若是键 release 事件是自动重复键正在被按下的结果,且要接收事件的 client 请求了可检测的自动重复,则事件不会传递到此 client。
如下部分说明了 XKB 与核心协议 grabs 的交互的意图和须要 pre-client flags 的缘由。
XKB 与核心协议 grabs 的交互
XKB 提供单独的 lookup 和 grab state,以帮助解决核心协议指定被动 grabs 方式的一些困难。不幸的是,许多 client 以不一样的方式解决这些问题,而XKB处理 grabs 和报告键盘 state 的方式有时会以意外和不愉快的方式与这些 client 的变通方法进行交互。
为了给知道 XKB 的 clients 提供更合理的行为,而不会致使不知道 XKB 的 clients 出现问题,XKB 提供两个 per-client flags (GrabsUseXKBState 和 LookupStateWhenGrabbed),用于指定 XKB 与核心协议应该如何交互。
-
最大的问题来自于 XKB State 字段在 bits 13-14 编码显式的键盘 group,而 pre-XKB clients 使用 8 个 modifiers 来选择哪一个键盘 group。为了使现有 client 行为合理,XKB 一般使用兼容性 grab state 而非 XKB grab state 来肯定是否触发被动 grabs。XKB-aware clients 能够设置 GrabsUseXKBState per-client flag,以指示它们使用 XKB state 指定被动 grabs。
-
当触发被动 grab 时,一些 toolkits 会开始主动 grab,以便更好地控制 grab 终止的条件。不幸的是,XKB 在 触发或终止 grabs 事件报告不一样 state 意味着此 grab 模拟在某些状况下没法终止 grab。要解决此问题,XKB 在 grab 激活时在全部事件中报告 grab state。不使用此类主动 grabs 的 clients 能够设置 LookupStateWhenGrabbed per-client flag,以便不管 grab 是否激活,收到相同的 state 组件。
GrabsUseXKBState per-client flag 也适用于在 grab 激活时发送的事件的 state。若是设置了,grab 期间的事件包含 XKB lookup 或 grab state;默认状况下,grab 期间的事件包含兼容性 lookup 或 grab state。
用于触发被动 grab 的 state 由 grab 注册时的 GrabsUseXKBState per-client flag 设置控制。修改此 flag 不会影响现有的被动 grabs。