Xfce Forum

Sub domains
 

You are not logged in.

#1 2016-01-31 23:11:47

FrozenFoods
Member
Registered: 2016-01-31
Posts: 1

Keys mappings, modifier keys, and Xfce shortcuts

I've trying to use xmodmap to map keys such as CAPS LOCK to something more useful, but it is not working as I had hoped. I mapped Menu to Hyper_R, but is still gets treated as Alt by "Window Manager" under the keyboard tab.  I am left with three questions:

1) Is there a way to make Xfce distinguish between the left and right versions of modifier keys (e.g. Shift_L and Shift_R)?

2) Is there a way for me to add new modifier keys (or for me to map to a key such as XF86WebCam, and use that as a modifier key)?

3) Am I stuck with only Control, Shift, Super, and Alt as modifier keys? I keep on seeing Mod, Meta, Hyper, Lock, but I know neither what they do nor what they are.

Offline

#2 2016-02-13 15:16:07

xyzdragon
Member
Registered: 2015-12-06
Posts: 17

Re: Keys mappings, modifier keys, and Xfce shortcuts

1.) Yes. E.g. with

xmodmap - <<EOF
  clear shift
  add shift = Shift_L
  add control = Shift_R
EOF

    Now Shift_R + a selects all the text in most text editors while Shift_L + a still prints a capital 'A'.

2.) Yes. This works the same as above. There is no discerning between 'normal keycodes' and 'modifier keycodes'.
    xmodmap <( echo 'add control = F1' )
    Now F1+a selects all text in my favorite editor. (tested)

3.) Isn't this the same question as 2.? X provides 8 modifier keys. They can be shown with `xmodmap -pm`. They are sent to X programs in a state byte with 8 bits which can be set or not set. The X client has to map "bit (un)set + key" to corresponding actions. The only mappings which can be done globally are:

shift + key
Mode_switch + key
shift + Mode_switch + key
mod5 + key
shift + mod5 + key

    Mode_switch seems to be the only weird one here, because it is not read from a modifier state like shift or mod5.
    Meta, Hyper and Super are basically the same. The refer to the key with the Windows, Mac or Linux logo on it. In my long rant below I do many things with Super_R.

If you want to understand a bit more about everything you could retrace my steps below:

|                                                                                                                            |

The first thing I would do, is trying to understand the current keyboard mapping. For that you can use xev, press keys and look at the output:

xev
    left  control : keycode  37 (keysym 0xffe3, Control_L       ), Hex: 0x25
    right control : keycode 105 (keysym 0xffe4, Control_R       ), Hex: 0x69
    left  alt     : keycode  64 (keysym 0xffe9, Alt_L           ), Hex: 0x40
    right alt     : keycode 108 (keysym 0xfe03, ISO_Level3_Shift), Hex: 0x6C
    left  shift   : keycode  50 (keysym 0xffe1, Shift_L         ), Hex: 0x32
    right shift   : keycode  62 (keysym 0xffe2, Shift_R         ), Hex: 0x3E
    left  meta    : keycode 133 (keysym 0xffeb, Super_L         ), Hex: 0x85
    right meta    : keycode 134 (keysym 0xffec, Super_R         ), Hex: 0x86
    num    lock   : keycode  77 (keysym 0xff7f, Num_Lock        ), Hex: 0x4D
    caps   lock   : keycode  66 (keysym 0xffe5, Caps_Lock       ), Hex: 0x42
    scroll lock   : keycode  78 (keysym 0xff14, Scroll_Lock     ), Hex: 0x4E
    pause / break : keycode 127 (keysym 0xff13, Pause           ), Hex: 0x7F
    menu key      : keycode 135 (keysym 0xff67, Menu            ), Hex: 0x87
    (right of meta_r)

    convert keycodes to hexadecimal (needed later):

echo "obase=16; 37; 105; 64; 108; 50; 62; 133; 134; 77; 66; 78; 127; 135" | bc

    I use a USB-keyboard, meaning the keycodes should be universal for all other USB-keyboards
        -> `man setkeycodes`
           > USB keyboards have standardized keycodes and setkeycodes doesn't affect them at all.
           https://www.win.tue.nl/~aeb/linux/kbd/scancodes-14.html

Next you can assert that these outputs are correct. For that you can output the current keycode->keysym mapping with xmodmap:

xmodmap -pke > ~/.Xmodmaprc.org
    keycode  37 = Control_L NoSymbol Control_L
    keycode 105 = Control_R NoSymbol Control_R
    keycode  64 = Alt_L Meta_L Alt_L Meta_L
    keycode 108 = ISO_Level3_Shift NoSymbol ISO_Level3_Shift
    keycode  50 = Shift_L NoSymbol Shift_L
    keycode  62 = Shift_R NoSymbol Shift_R
    keycode  66 = Caps_Lock NoSymbol Caps_Lock
    [...]

   So, yes the mapping we saw is of course correct

Now we can assert how the modifier keys work. For that we can rewrite some test key to some dummy values on all columns, because very column should map to a different modifier key. The first column being no modifier keys, the second column shift and the rest I can't say yet:

# create a new xmodmap containing the following two lines after the next line
vim ~/.Xmodmap
    !keycode  13 = 4 dollar 4 dollar onequarter currency
    keycode  13 = a b c d e f g h i j k l m
xmodmap ~/.Xmodmap

Now we can try out what modifier key + '4'-key prints. To make this easier we can grep for only 'KeyPress' events and then only for keycode. For me KeyPress events are 6 or 7 lines long. In order to see the output in real time instead of only when closing the program we need to add '--line-buffered'

xev | grep 'KeyPress' --line-buffered -A7 | grep --line-buffered 'keycode'
    no modifier   + 4 : keycode 13 (keysym 0x61, a)
    left  control + 4 : state 0x10, keycode 37 (keysym 0xffe3, Control_L), same_screen YES,
                        state 0x14, keycode 13 (keysym 0x61, a), same_screen YES,
    right control + 4 : state 0x10, keycode 105 (keysym 0xffe4, Control_R), same_screen YES,
                        state 0x14, keycode 13 (keysym 0x61, a), same_screen YES,
    left  alt     + 4 : state 0x10, keycode 64 (keysym 0xffe9, Alt_L), same_screen YES,
                        state 0x18, keycode 13 (keysym 0x61, a), same_screen YES,
    right alt     + 4 : state 0x10, keycode 108 (keysym 0xfe03, ISO_Level3_Shift), same_screen YES,
                        XKeysymToKeycode returns keycode: 92
                        state 0x90, keycode 13 (keysym 0x65, e), same_screen YES,
    left  shift   + 4 : state 0x10, keycode 50 (keysym 0xffe1, Shift_L), same_screen YES,
                        state 0x11, keycode 13 (keysym 0x62, b), same_screen YES,
                        XKeysymToKeycode returns keycode: 56
    right shift   + 4 : state 0x10, keycode 62 (keysym 0xffe2, Shift_R), same_screen YES,
                        state 0x11, keycode 13 (keysym 0x62, b), same_screen YES,
                        XKeysymToKeycode returns keycode: 56
    left  meta    + 4 : state 0x0, keycode 133 (keysym 0xffeb, Super_L), same_screen YES,
    right meta    + 4 : state 0x0, keycode 134 (keysym 0xffec, Super_R), same_screen YES,
    num    lock   + 4 : state 0x10, keycode 77 (keysym 0xff7f, Num_Lock), same_screen YES,
                        state 0x10, keycode 13 (keysym 0x61, a), same_screen YES,
    caps   lock   + 4 : state 0x12, keycode 66 (keysym 0xffe5, Caps_Lock), same_screen YES,
                        state 0x12, keycode 13 (keysym 0x41, A), same_screen YES,
                        XKeysymToKeycode returns keycode: 38
    scroll lock   + 4 : state 0x10, keycode 78 (keysym 0xff14, Scroll_Lock), same_screen YES,
                        state 0x10, keycode 13 (keysym 0x61, a), same_screen YES,
    pause / break + 4 : state 0x10, keycode 127 (keysym 0xff13, Pause), same_screen YES,
                        state 0x10, keycode 13 (keysym 0x61, a), same_screen YES,
    menu key      + 4 : state 0x10, keycode 135 (keysym 0xff67, Menu), same_screen YES,
                        state 0x10, keycode 13 (keysym 0x61, a), same_screen YES,

The following thought on the output:

  • I'm not sure why there is mapping from Alt_R (108) to 92
            keycode  92 = ISO_Level3_Shift NoSymbol ISO_Level3_Shift
        The same XKeysymToKeycode message appears for left and right shift
            keycode  56 = b B b B leftdoublequotemark leftsinglequotemark
        But in this case it is the correct mapped output we wanted.
        The same is true for all other working modifier+4 combinations

  • The only columns we can actually reproduce are:
            'a' : [no modifier keys]
            'b' : Shift_L Shift_R
            'e' : ISO_Level3_Shift [right alt]

  • Basically non-working modifier keys:
            Alt_L Ctrl_L Ctrl_R Num_Lock Pause Menu Scroll_Lock

  • Super_L and Super_R produce no symbol for some reason, but looking at the full output of xev they seem to produce some kind of window control sequence:

    KeyPress event, serial 37, synthetic NO, window 0x5c00001,
        root 0x29e, subw 0x0, time 252830107, (76,-166), root:(947,276),
        state 0x0, keycode 133 (keysym 0xffeb, Super_L), same_screen YES,
        XLookupString gives 0 bytes:
        XmbLookupString gives 0 bytes:
        XFilterEvent returns: False
    
    FocusOut event, serial 37, synthetic NO, window 0x5c00001,
        mode NotifyGrab, detail NotifyAncestor
    
    FocusIn event, serial 37, synthetic NO, window 0x5c00001,
        mode NotifyUngrab, detail NotifyAncestor
    
    KeymapNotify event, serial 37, synthetic NO, window 0x0,
        keys:  4294967198 0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
               32  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    
    KeyRelease event, serial 37, synthetic NO, window 0x5c00001,
        root 0x29e, subw 0x0, time 252830844, (76,-166), root:(947,276),
        state 0x40, keycode 133 (keysym 0xffeb, Super_L), same_screen YES,
        XLookupString gives 0 bytes:
        XFilterEvent returns: False

Now let's take a look at the current modifier mapping to see if this output is what it should be:

xmodmap -pm
    xmodmap:  up to 4 keys per modifier, (keycodes in parentheses):

    shift       Shift_L (0x32),  Shift_R (0x3e)
    lock
    control     Control_L (0x25),  Caps_Lock (0x42),  Control_R (0x69)
    mod1        Alt_L (0x40),  Meta_L (0xcd)
    mod2        Num_Lock (0x4d)
    mod3
    mod4        Super_L (0x85),  Super_R (0x86),  Super_L (0xce),  Hyper_L (0xcf)
    mod5        ISO_Level3_Shift (0x5c),  Mode_switch (0xcb)

Observations:

  • modifier 'shift' returns correctly column 2 with 'b' and 'mod5' column 5 with 'e'

  • The above observation gives neither an ordering for the columns nor does it explain, why all other modifiers don't seem to map to a column

  • The assigned keycodes for shift, control, mod1, mod2, mod4 look correct, althoughthere seem to be some dupes like 'Super_L (0xce)'

  • mod5 looks weird, but it seems 0x6C is somehow translated to 0x5C, but I can't see where !!

To restore the original setting you can load the output of the earlier xmodmap-call

xmodmap ~/.Xmodmaprc.org

man xmodmap
   keycode NUMBER = KEYSYMNAME ...
       The list of keysyms is assigned to the indicated keycode (which may be specified in decimal, hex  or octal and can be determined by running the xev program). Up to eight keysyms may be attached to a key, however the last four are not used in any major X server implementation. The first keysym is used when no modifier key is pressed in conjunction with this key, the second with Shift, the third when the Mode_switch key is used with this key and the fourth when both the Mode_switch and Shift keys are used.

Look at the manual above I have forgotten to try out multiple modifier key combinations:

CtrlL+Alt+4:
    state 0x10, keycode 37 (keysym 0xffe3, Control_L), same_screen YES,
    state 0x14, keycode 64 (keysym 0xffe9, Alt_L), same_screen YES,
    state 0x1c, keycode 13 (keysym 0x61, a), same_screen YES,
CtrlL+Shift+4
    state 0x10, keycode 37 (keysym 0xffe3, Control_L), same_screen YES,
    state 0x14, keycode 50 (keysym 0xffe1, Shift_L), same_screen YES,
    state 0x15, keycode 13 (keysym 0x62, b), same_screen YES,
    XKeysymToKeycode returns keycode: 56
CtrlL+AltR+4
    state 0x10, keycode 37 (keysym 0xffe3, Control_L), same_screen YES,
    state 0x14, keycode 108 (keysym 0xfe03, ISO_Level3_Shift), same_screen YES,
    XKeysymToKeycode returns keycode: 92
    state 0x94, keycode 13 (keysym 0x65, e), same_screen YES,
    XKeysymToKeycode returns keycode: 26
CtrlL+ShiftR+4
    state 0x10, keycode 37 (keysym 0xffe3, Control_L), same_screen YES,
    state 0x14, keycode 62 (keysym 0xffe2, Shift_R), same_screen YES,
    state 0x15, keycode 13 (keysym 0x62, b), same_screen YES,
    XKeysymToKeycode returns keycode: 56
CtrlR+*+a has the same effect as CtrlL+...
Shift+AltR+4
    state 0x10, keycode 50 (keysym 0xffe1, Shift_L), same_screen YES,
    state 0x11, keycode 108 (keysym 0xfe03, ISO_Level3_Shift), same_screen YES,
    XKeysymToKeycode returns keycode: 92
    state 0x91, keycode 13 (keysym 0x66, f), same_screen YES,
    XKeysymToKeycode returns keycode: 41

The only new keystroke I could reproduce with all these combinations is 'f', the 6th column when pressing Shift_L + right alt. The manual says this should be the 4th column ... So either something is wrong or AltGr is not the Mode_switch key the manual speaks of,  http://unix.stackexchange.com/questions … difier-for
This site https://wiki.ubuntuusers.de/Xmodmap/ says that the second and third are for Alt and Shift+Alt. I can't reproduce that.
But we could map some other key like Ctrl_R to modeswitch, for that add the following line to ~/.Xmodmap

keycode 37 = Mode_switch NoSymbol Mode_switch

Now I can actually produce the output of column 3 and 4 with xev!

Strg_R + 4:
    state 0x10, keycode 105 (keysym 0xff7e, Mode_switch), same_screen YES,
    state 0x2010, keycode 13 (keysym 0x63, c), same_screen YES,
    XKeysymToKeycode returns keycode: 54
Strg_R + Shift + a:
    state 0x10, keycode 105 (keysym 0xff7e, Mode_switch), same_screen YES,
    state 0x2010, keycode 50 (keysym 0xffe1, Shift_L), same_screen YES,
    state 0x2011, keycode 13 (keysym 0x64, d), same_screen YES,
    XKeysymToKeycode returns keycode: 40

I think one important thing to understand is from this link: https://en.wikipedia.org/wiki/X_Window_ … l#Mappings
    "The server therefore sends the keycode and the modifier state without attempting to translate them into a specific character. It is a responsibility of the client to do this conversion."
    "The X server works with at most eight modifiers. However, each modifier can be associated with more than one key."

What I am deducing from all this, is that normally Ctrl+key and Alt+Key is something the client itself has to convert to the wanted actions and/or (escape) codes. That's why it's not easily possible to remap Ctrl+Backspace for xfce4-terminal using xmodmap ?!

The modifier keys http://unix.stackexchange.com/questions … super-keys can be seen with xev in the 'state' variable:

xev | grep --line-buffer 'state'
    Shift_L  :  state 0x01  bit 0
    Shift_R  :  state 0x01
    Caps_Lock:  state 0x02  bit 1
    Ctrl_L   :  state 0x04  bit 2
    Ctrl_R   :  state 0x04
    Alt_L    :  state 0x08  bit 3
    Num_Lock :  state 0x10  bit 4
    ?        :  state 0x20  bit 5   # nothing assigned to mod3
    Meta_L   :  state 0x40  bit 6
    Meta_R   :  state 0x40
    Alt_R    :  state 0x80  bit 7

Bit 8 is always set if Num_lock is on, even if it is not pressed. Similar is Caps_Lock with bit 2. Now we see what mod1 to mod5 are for. They map to bit 3 to 7. These modifiers have nothing to do with the columns in a key assignment, with the notable exception of 'shift'.

There are 3 basic commands for modifier keys (man xmodmap):

clear MODIFIERNAME
   This  removes  all entries in the modifier map for the given modifier,
   where valid name are: Shift, Lock, Control, Mod1,  Mod2,  Mod3,  Mod4,
   and  Mod5  (case  does  not matter in modifier names, although it does
   matter for all other names).  For example, ``clear Lock'' will  remove
   all any keys that were bound to the shift lock modifier.

add MODIFIERNAME = KEYSYMNAME ...
   This adds all keys containing the given keysyms to the indicated modi-
   fier map.  The keysym names are evaluated after all input  expressions
   are  read  to  make it easy to write expressions to swap keys (see the
   EXAMPLES section).

remove MODIFIERNAME = KEYSYMNAME ...
   This removes all keys containing the given keysyms from the  indicated
   modifier  map.  Unlike add, the keysym names are evaluated as the line
   is read in.  This allows you to remove keys from  a  modifier  without
   having to worry about whether or not they have been reassigned.

You can produce the 2nd column with capslock+key by adding capslock to the shift-modifier:

xmodmap <(echo 'remove mod4 = Super_R')
xmodmap <(echo 'add shift = Super_R')

Now pressing Super_R+'t' produces 'T'. (Super_R+4 = b.)

xmodmap <(echo 'remove shift = Super_R')
xmodmap <(echo 'add mod5 = Super_R')

Now Super_R+4 = e, the same as AltGr.

xmodmap <(echo 'remove mod5 = Super_R')
xmodmap <(echo 'add control = Super_R')

About mod1 to 6:

    mod1 is interpreted by programs as alt. E.g. Alt+F to open the file menu
    mod2 is num lock
    mod3 ? this is not set by default so it may not have any function
    mod4 is super key
    mod5 is AltGr key, e.g. for printing { and ~ on German keyboards. Assigning Super_R to this makes those symbols printable with Super_R+7 and Super_R+'+'

Note: Adding Super_R to mod2 is a very bad idea. For some reason it seems that then Super_R is always assumed as being pressed, meaning if you have shortcuts like Super+'d' to show the desktop you can't print 'd' anymore, which is needed to input 'xmodmap' smile so yeah. Also for some reason Super_R will only turn the Num_Lock LED off, but it can't turn it on when pressing it again. Turning it on still works with Num_Lock though.

xmodmap <(printf 'remove control = Super_R\nadd mod2 = Super_R')
xmodmap <(printf 'remove mod2 = Super_R')

When trying to assign Super_R to multiple modifiers I get the following error message:

X Error of failed request:  BadValue (integer parameter out of range for operation)
  Major opcode of failed request:  118 (X_SetModifierMapping)
  Value in failed request:  0x17
  Serial number of failed request:  11
  Current serial number in output stream:  11

Last edited by xyzdragon (2016-02-13 19:08:17)

Offline

Board footer

Powered by FluxBB