[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#263073: xlibs: Super still Super+Hyper



On Mon, Sep 13, 2004 at 09:03:46AM +0200, Christian Marillat wrote:
> barbier@linuxfr.org (Denis Barbier) writes:
> 
> > On Sun, Sep 12, 2004 at 07:57:56PM +0000, Tim Bagot wrote:
> 
> [...]
> 
> > Sawfish maintainer, do you believe that this bug should be cloned and
> > reassigned to sawfish?
> 
> No I don't think thi is a bug in sawfish (never seen this problem
> before, never reported and this work with my keyboard) i think the
> problem come from GNOME which modify the keyborad layout without asking
> something to users.
> 
> See bugs  #250814, #251116, #251126, #251127, #251168, #251406,
> #251542,#245848, #242932
> 
> Should be fixed soon...
> 
> Tim could you try to reconfigure your keyboard in the control center ?
> Keyborad icon and layouts tab.
> 
> Denis if you reassign this bug to the capplets package change the
> severity to important nad merge with others bugs.

Christian, thanks for your reply, but I believe that sawfish will still
have trouble when capplets is fixed.  The attached test-sawfish-mods.c
file helped me to understand how sawfish (and emacs) manage modifiers.
It is copied from src/keys.c

  $ setxkbmap -layout us -model pc105 -option ""
  $ ./test-sawfish-mods
  Keysym Alt_L column: 0   keycode=0x40 pos: 0
  Keysym Meta_L column: 0   keycode=0x40 pos: 1
  Keysym Alt_L column: 1   keycode=0x7d pos: 1
  Keysym Meta_L column: 2   keycode=0x9c pos: 1
  Keysym Num_Lock column: 0   keycode=0x4d pos: 0
  Keysym Super_L column: 0   keycode=0x7f pos: 1
  Keysym Hyper_L column: 1   keycode=0x80 pos: 1
  Up to 4 symbols per modifier
    alt_mod=8
    meta_mod=8
    super_mod=64
    hyper_mod=64

The 2 last lines are important, they show that the direct_modifiers
function (also in src/keys.c) won't catch Super_* modifiers because
it contains:
    if (hyper_mod != 0 && (mods & EV_MOD_HYPER))
        mods = (mods & ~EV_MOD_HYPER) | hyper_mod;
    if (super_mod != 0 && (mods & EV_MOD_SUPER))
        mods = (mods & ~EV_MOD_SUPER) | super_mod;

As hyper_mod is equal to super_mod, the mods variable is modified after
the first test and the second test fails.  And this is indeed what I
observed: if you set binding modifier to Super, tabbing does not work,
but it works when set to Hyper with this X setting and also with
altwin:super_win option.

Some people claim that Super and Hyper should not be bound to the same
modifier to be ICCCM-compliant, but here is the relevant part from this
spec:
  Clients should determine the meaning of a modifier bit from the
  KeySyms being used to control it.
They argue that the current 'us' default breaks this rule, and at the
same time add tricks to work around problems in their implementation
when Alt and Meta are bound to the same modifier.
The other point of view is that this sentence only tells that applications
should not hardcode mod1-5 but use KeySyms instead.

My previous patch discards keysyms when it is a "fake key" (ie. no
symbol is found at position 0).  It should work quite well, but a
better fix is to let XKB query modifiers when XKB is in use, I
will try this path.

Denis
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>

#define PRINT(s) fprintf(stderr, "Keysym %s column: %d   keycode=0x%x pos: %d\n", \
                s, col, code, code_col)

/*  Copied from sawfish/src/keys.c (find_meta)
    Compile with:
       gcc -Wall -o test-sawfish-mods test-sawfish-mods.c \
           -I/usr/X11R6/include -L /usr/X11R6/lib -lX11
 */

int
main(void)
{
    Display *display = XOpenDisplay(":0");
    int min_code, max_code;
    KeySym *syms;
    int syms_per_code;
    XModifierKeymap *mods;
    unsigned int num_lock_mod, scroll_lock_mod;
    unsigned int meta_mod, alt_mod, hyper_mod, super_mod;

    meta_mod = alt_mod = hyper_mod = super_mod = 0;
    num_lock_mod = scroll_lock_mod = 0;
    XDisplayKeycodes (display, &min_code, &max_code);
    syms = XGetKeyboardMapping (display, min_code, max_code - min_code + 1,
        &syms_per_code);
    mods = XGetModifierMapping (display);
    {
        int row, col;

        for (row = 3; row < 8; row++)
        {
            for (col = 0; col < mods->max_keypermod; col++)
            {
                int code_col;
                KeyCode code = mods->modifiermap[(row * mods->max_keypermod)
                                                + col];
                if (code == 0)
                    continue;
                for (code_col = 0; code_col < syms_per_code; code_col++)
                {
                    int sym = syms[((code - min_code) * syms_per_code)
                                  + code_col];
                    switch (sym)
                    {
                    case XK_Meta_L:
                        meta_mod = 1 << row;
                        PRINT("Meta_L");
                        break;
                    case XK_Meta_R:
                        meta_mod = 1 << row;
                        PRINT("Meta_R");
                        break;
                    case XK_Alt_L:
                        alt_mod = 1 << row;
                        PRINT("Alt_L");
                        break;
                    case XK_Alt_R:
                        alt_mod = 1 << row;
                        PRINT("Alt_R");
                        break;
                    case XK_Hyper_L:
                        hyper_mod = 1 << row;
                        PRINT("Hyper_L");
                        break;
                    case XK_Hyper_R:
                        hyper_mod = 1 << row;
                        PRINT("Hyper_R");
                        break;
                    case XK_Super_L:
                        super_mod = 1 << row;
                        PRINT("Super_L");
                        break;
                    case XK_Super_R:
                        super_mod = 1 << row;
                        PRINT("Super_R");
                        break;
                    case XK_Num_Lock:
                        num_lock_mod = 1 << row;
                        PRINT("Num_Lock");
                        break;
                    case XK_Scroll_Lock:
                        scroll_lock_mod = 1 << row;
                        PRINT("Scroll_Lock");
                        break;
                    }
                }
            }
        }
        fprintf(stderr, "Up to %d symbols per modifier\n", syms_per_code);
        fprintf(stderr, "  alt_mod=%d\n", alt_mod);
        fprintf(stderr, "  meta_mod=%d\n", meta_mod);
        fprintf(stderr, "  super_mod=%d\n", super_mod);
        fprintf(stderr, "  hyper_mod=%d\n", hyper_mod);
    }
    return(0);
}

Reply to: