Modifier Keys

Introduction

When using bind to handle keyboard events, Modifier keys can change the effect of a keystroke. This is described on the manual page bind(n) .

The present page describes the effects of Modifier keys on different platforms. This information has been obtained by experimentation with Tcl/Tk 8.5.8. Some results might depend on the specific hardware used: if you get different results, please document this (a suitable test script is at the end of this page). If you use a different platform or keyboard (e.g. Sun, Space Cadet [L1 ]), please add a section to this page.

PC running Linux

A standard PC keyboard on Linux never applies the Modifiers

    Extended
    Meta, M
    Mod3, M3

The PC keyboard's Modifier keys on Linux are:

KeyKeyPress %KKeyRelease %KBinding ModifierPE [1]AR [2]%A [3]Notes
ExtendedNot used in Linux.
Num LockNum_LockNum_LockOption, Mod2, M2YM
Scroll LockScroll_LockScroll_LockYNOT a Modifier key in Linux.
Caps LockCaps_LockCaps_LockLockYM
Shift (Left)Shift_LShift_LShiftM
Shift (Right)Shift_RShift_RShiftM
Control (Left)Control_LControl_LControl-Exceptions to [3] include: for the numerals 0, 1, or 9 with the Control Modifier, %A is the unmodified numeral.
Control (Right)Control_RControl_RControlY-Exceptions to [3]: as for Control (Left).
"Windows" (Left)Super_LSuper_LMod4, M4YU
"Windows" (Right)Super_RSuper_RMod4, M4YU
Alt (Left)Alt_LAlt_LAltUA binding with Modifier Alt is overridden by a binding with Modifier Command, Mod1, or M1.
Alt Gr [4]ISO_Level3_Shift??Mod5, M5YMThe event KeyRelease-ISO_Level3_Shift is not recognised: it is reported as KeyRelease-??.

[1] Column PE means "Persistent". If marked "Y", the key is pressed and released to activate the Modifier; the Modifier is applied to subsequent keystrokes until the Modifier key is pressed and released again. If not marked "Y", the key must be held down to activate its Modifier; the Modifier is applied to subsequent keystrokes until the Modifier key is released.
[2] Column AR means "Autorepeat". If marked "Y", the key has autorepeat enabled.
[3] Column %A indicates the value supplied as the binding value %A.

  • If marked "U", the same value is supplied as for the unmodified event.
  • If marked "M", a modified value is supplied:
    • for "Caps Lock" or "Shift" or (Mac/Aqua only) both, a change of case; but (Linux, Windows, Mac/X11 only) no change if both Modifiers are present
    • for "Num Lock", a numerical value instead of {} when a numerical keypad key is pressed; otherwise unmodified
    • for "Alt Gr", a different character (or none)
    • for "Command" (Mac only), many characters are unmodified; some characters are modified; some events <Command-KeyPress> are intercepted by the operating system.
  • If marked "-", the value supplied as %A is either the string "{}", or an unprintable symbol, or in a few cases (different for each platform) an exception to this rule - example exceptions are listed in the "Notes" column of the Table. In the text widget, these complications are suppressed by a binding to <Control-KeyPress> that prevents the symbol %A from being inserted into the widget.

[4] The "Right Alt" or "Alt Gr" key is used in combination with certain other keys for composing characters that are not otherwise available on the keyboard. This functionality is provided by the operating system, without use of the Mod5/M5 Modifier (Linux) or the Control-Alt Modifier (Windows), to generate the value supplied as %A; that value is not necessarily the same for Windows and Linux, or the same as the value produced by the Option key on the Mac.

PC running Windows

A standard PC keyboard on Windows never applies the Modifiers

    Meta, M
    Mod4, M4
    Mod5, M5

The PC keyboard's Modifier keys on Windows are:

KeyKeyPress %KKeyRelease %KBinding ModifierPE [1]AR [2]%A [3]Notes
ExtendedUIn Windows, this Modifier is automatically applied to certain keys of the "Extended" keyboard. See bind(n) for details.
Num LockNum_LockNum_LockCommand, Mod1, or M1YYM
Scroll LockScroll_LockScroll_LockMod3, or M3YYU
Caps LockCaps_LockCaps_LockLockYYM
Shift (Left)Shift_LShift_LShiftYM
Shift (Right)Shift_RShift_LShiftYM
Control (Left)Control_LControl_LControlY-Exceptions to [3] include: <Control-Return> emits a newline as %A.
Control (Right)Control_RControl_LControlY-Exceptions to [3]: as for Control (Left).
"Windows" (Left)Win_LWin_LYNOT a Modifier key in Windows.
"Windows" (Right)Win_RWin_RYNOT a Modifier key in Windows.
Alt (Left)Alt_LAlt_LAltYUA binding with Modifier Alt is overridden by a binding with Modifier Option, Mod2, or M2.
Alt Gr [4]Control_L, Alt_RControl_L, Alt_LControl-AltYMA binding with Modifier Alt is overridden by a binding with Modifier Option, Mod2, or M2. When the Modifier key is pressed, two KeyPress events occur: the first with keysym Control_L, the second with keysym Alt_R.
If the operating system supplies a replacement character, the Tk KeyPress event does not have the Control or Alt Modifiers: it is an unmodified KeyPress event, e.g. <KeyPress-&#8364;>. A binding to <Control-Alt-KeyPress> will not capture such events - instead it captures events on keys where the operating system does not supply a replacement character. This mechanism is unique to Windows - keyboard events with "Alt Gr" (in Linux) and "Option" (in MacOS X) Modifier keys always carry the expected binding Modifiers.

[1], [2], [3], [4] Same as footnotes on Linux table (above).

Mac running MacOS X (Aqua version of Tk)

This documentation applies to the Aqua/Carbon interface used by versions of Tk to 8.5.12 inclusive. The new Aqua/Cocoa interface used by Tk 8.5.13 and 8.6.0 differs in several details, which have been filed as Tk bug report 3607200 [L2 ]. Documentation here will be updated depending on how these differences are resolved. [5]

A Mac keyboard does not use the Modifiers

   Alt
   Extended
   Meta, M
   Mod4, M4
   Mod5, M5

The Mac keyboard's Modifier keys on Mac OS X (Carbon) are:

KeyKeyPress %KKeyRelease %KBinding ModifierPE [1]AR [2]%A [3]Notes
Caps LockCaps_LockCaps_LockLockYM
Shift (Left or Right)Shift_LShift_LShiftMThe left and right keys emit the same %K.
Control (Left or Right)Control_LControl_LControl-Control (ctrl) keys.
The left and right keys emit the same %K.
Exceptions to [3] include: for any numeral with the Control Modifier, %A is the unmodified numeral.
Command (Left or Right)Meta_LMeta_LCommand, Mod1, M1MCommand (Apple or &#8984;) keys.
The left and right keys emit the same %K.
Alt (Left or Right) [4]Alt_LAlt_LOption, Mod2, M2MOption (Alt or alt) keys.
The left and right keys emit the same %K.
Mod3, M3This modifier is applied to keys in the numeric keypad, and to the cursor keys Up, Down, Left, Right.

[1], [2], [3] Same as footnotes on Linux table (above).
[4] The "Alt" or "Option" key is used in combination with other keys for composing characters that are not otherwise available on the keyboard. This functionality is provided by the operating system, without use of the Option/Mod2/M2 Modifier, to generate the value supplied as %A; that value is not necessarily the same as the value produced by the "Right Alt" or "Alt Gr" key of a PC keyboard on Windows or Linux.

The Binding Modifier "Alt" is not recognized on the Mac, even though some Mac keyboards label the "Option" key "alt".

Using a PC Keyboard on the Mac
The PC keyboard behaves very much like the Mac keyboard described above (for Tk/Aqua) and below (for Tk/X11). The "Windows" Modifier key takes the role of the Command/Apple/&#8984; key. The Left-Alt and Right-Alt keys perform the same role, as on a Mac keyboard (and on Aqua they produce the same keysym). The "Num Lock" and "Scroll Lock" keys are not recognized as Modifiers: on Aqua, "Num Lock" behaves as "Clear", the Mac key in the same position; on X11, it corresponds to "Escape". Pressing or releasing the "Scroll Lock" key does not trigger an event.

[5] The history of native Tk on OS X is somewhat complicated. Apple began shipping an Aqua/Carbon Tk 8.4 with OS X 10.4 (Tiger) and continues to do so (at least through the current OS X 10.8 Mountain Lion). Due to limitations of the Carbon APIs, Aqua/Carbon Tk only runs in 32-bit processes. In addition, as of OS X 10.6 (Snow Leopard), Apple also began shipping a backport to 8.5 of Aqua/Cocoa Tk which runs in either 64-bit or 32-bit processes. ActiveState switched their OS X Tcl/Tk 8.5 from Aqua/Carbon to the Aqua/Cocoa backport as of their 8.5.9.1 release. As of Tk 8.5.13, the Aqua/Cocoa backport was integrated into the Tk 8.5 mainline by the Tk project and building 8.5 as Aqua/Carbon is no longer supported.

Mac running MacOS X (X11 version of Tk)

Using Tcl/Tk 8.6.0 with the XQuartz X11 server on OS X Mountain Lion, the following behavior was found.

The Mac keyboard under X11 does not use the Modifiers

   Alt
   Extended
   Meta, M
   Mod3, M3
   Mod4, M4
   Mod5, M5

The Mac keyboard's Modifier keys on Mac OS X when using X11 are:

KeyKeyPress %KKeyRelease %KBinding ModifierPE [1]AR [2]%A [3]Notes
Caps LockCaps_LockCaps_LockLockYM[5]
Shift (Left) Shift_LShift_LShiftM
Shift (Right)Shift_RShift_RShiftM
Control (Left)Control_LControl_LControl-Control (ctrl) key.
Control (Right)Control_RControl_RControl-Control (ctrl) key.
Command (Left)Meta_LMeta_LOption, M2 or Mod2MCommand (Apple or &#8984;) key.
Command (Right)Meta_RMeta_ROption, M2 or Mod2MCommand (Apple or &#8984;) key.
Alt (Left) [4]Alt_LAlt_LCommand, M1 or Mod1UOption (Alt or alt) key.
Alt (Right) [4]Alt_RAlt_RCommand, M1 or Mod1UOption (Alt or alt) key.

[1], [2], [3] Same as footnotes on Linux table (above).
[4] The table shows how the Alt keys behave if the XQuartz X11 server has been configured so that the Alt keys send the "Alt_L", "Alt_R" keysyms. The default behavior, in contrast, is that the Alt keys send the "Mode_switch" keysym: the "Alt" key is used in combination with other keys for composing characters that are not otherwise available on the keyboard. In this case, when an "Alt" key is held down and another key is pressed, an alternative character is emitted with different %K and %A and no Modifier. The character is the same as that produced by the same keystrokes in an Aqua application, but is not necessarily the same as the value produced by the "Right Alt" or "Alt Gr" key of a PC keyboard on Windows or Linux.
[5] When using X11, the "Caps Lock" operation is reversed by holding down the "Shift" key: i.e. <Shift-Lock-KeyPress-s> emits the character "s" (as the value of %A for the event). In contrast, for Tk/Aqua, and for Mac applications in general, "Caps Lock" is not reversed by "Shift".

Cross-Platform Development

The following suggestions attempt to follow the style expected for an application on each platform, while keeping code simple, and avoiding conflicts between different platforms.

  • Don't define event bindings with the Command or Option Modifiers, except on the Mac platform.
    • On other platforms, these bindings will fire under inappropriate conditions: when an Alt key is pressed (overriding the corresponding binding that uses the Alt Modifier); or when "Num Lock" has been pressed.
  • On the Mac platform, it is not usually necessary to define bindings with the Control modifier. If this is done, ensure that the bindings are not defined on other platforms unless this is appropriate.
  • Don't use the "Windows" Modifier keys (the Mod4 binding Modifier) on Linux: use the Alt and Control keys only.
    • The "Windows" keys have no counterpart on platforms other than Linux: they do not function as Modifier keys on Windows; and although they correspond to the "Command" keys on the Mac, Mac style typically requires that the "Command" keys perform the same role as the "Control" keys on Windows or Linux.
  • Unicode characters supplied by the operating system (when using the "Alt Gr" or "Option" keys) do not need special bindings - they trigger the <KeyPress> binding without Modifiers.
    • Because (for Windows) such an event does not have the Modifier(s) normally associated with the "Alt Gr" key; or (for Linux, MacOS X) the Modifiers do not precisely match the bindings provided by default, so the event triggers the less specific <KeyPress> binding.
  • Don't use bindings to the Shift or Lock modifiers to distinguish upper-case and lower-case characters: use the value of %A, which is simple and correct, but platform-dependent.
    • For the value of %A, the "Shift" key cancels the "Caps Lock" key in Linux and Windows, but not in Mac OS X. This conforms with the style of each platform.
  • The value of %A for a <Control-KeyPress> event is rarely useful, and should usually be suppressed by a suitable binding. The same technique can be used to prevent other modified keystrokes from being interpreted as simple (unmodified) keystrokes.
    • Cf. the text widget: in the Text binding tag, the <Control-KeyPress> binding does nothing, but its existence prevents an event with a Control Modifier key from binding to the <KeyPress> binding, and thereby having its %A written to the widget. The same technique is used in the Text binding tag to suppress keystrokes with the modifiers Alt, Meta, and (MacOS X only) Command (see file lib/tk8.x/text.tcl).

Discussion

There are clearly many differences between different platforms. In some cases, there is a reason: e.g.

  • On the Mac, the "Shift" key does not cancel the effect of "Caps Lock" [3]. This makes Tcl/Tk applications behave in the same way as other Mac applications.

Other differences might have a good reason (if so, please add it to the list immediately above). However, some features may exist for historical reasons that are no longer valid. While these features must be retained in the Tcl/Tk 8.x series in order to preserve compatibility, it might be desirable to rationalise the keyboard Modifiers in Tcl/Tk 9.0, in order to simplify cross-platform development. See Tk 9.0 WishList.

Test Script

The script below can be used to test keyboard events and modifier keys.

#! /usr/bin/env wish

text .t -height 10
pack .t

text .u -bg yellow
pack .u

focus -force .t
.t insert end "Test keyboard events by typing here.\n"
.u insert end "Logs will be written here.\n"
.u insert end "Combinations of modifier keys are not reported as such, except those\ninvolving Shift, Lock and up to one other modifier.\n"

proc show {msg} {
    .u insert end "$msg\n"
    .u see end-1c
    return
}

# No combinations handled except those involving Shift and Lock.
foreach modifier {
    {}
    Control
    Alt
    Extended
    Meta M
    Mod1 M1 Command
    Mod2 M2 Option
    Mod3 M3
    Mod4 M4
    Mod5 M5
    Button1 B1
    Button2 B2
    Button3 B3
    Button4 B4
    Button5 B5
} {
    set modif1 $modifier
    if {$modifier eq {}} {
    } else {
        append modif1 -
    }
    foreach modif2 {{} Shift- Lock- Shift-Lock-} {
        if {"$modif2$modif1" eq {}} {
            set word Unmodified
        } else {
            set word Modified
        }
        bind .t <${modif2}${modif1}KeyPress> [list show "$word <${modif2}${modif1}KeyPress> with <%%K> equal to <%K> and <%%A> equal to <%A>"]
        bind .t <${modif2}${modif1}KeyRelease> [list show "$word <${modif2}${modif1}KeyRelease> with <%%K> equal to <%K> and <%%A> equal to <%A>"]
    }
}