xkbcommon / libxkbcommon

keymap handling library for toolkits and window systems
https://xkbcommon.org
Other
278 stars 123 forks source link

How to clear modifier without RedirectKey? #145

Open sandangel opened 4 years ago

sandangel commented 4 years ago

Hi, I'm trying to remap Super+C to Ctrl+C using xkb, but I don't want to remap Super to Ctrl because I'm still using Super for other shortcuts. I have achieved this X using interpret F13 { RedirectKey(keys=c,modifiers=Control,clearmodifiers=Super) } and set symbols c to [c, C, F13]

I have tried set symbols c to [c, C, XF86Copy] on Mod4 xkb type but XF86Copy doesn't work with some applications because I still have modifier Super set when pressing Super+C

It would be great to have a way to clear modifier without using RedirectKey, or should I do something else.

wismill commented 10 months ago

Implementing full support of RedirectKey is unlikely, see #18. While I re-assess some parts of this feature, you may to have a look at solutions like kmonad, keyd, Kanata and the likes.

cxandru commented 10 months ago

I use the neo layout and layer 4 (the navigation layer) uses modifiers to input arrow keys, return, backspace, delete and home/end. I use the following xkb_keymap file to clear modifiers, because some applications will not interpret arrow keys etc as such when input with modifiers:

xkb_keymap {
  xkb_keycodes  {
        //source https://unix.stackexchange.com/questions/188164/override-a-few-keycodes-with-xkb#188179
        include "evdev+aliases(qwerty)"
        //Custom changes for hp elitebook 8470p
        <LCTL> = 64; // LALT
        <LALT> = 37; // LCTL
        <RTSH> = 133; // LWIN
        <LALT> = 108; //RALT
        <LWIN> = 135; //COMP
        };
  xkb_types     {  include "complete"  };
  xkb_compat {
        include "complete+caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock)"
        interpret osfLeft {
            action = RedirectKey(keycode=<LEFT>, clearmods=Mod3);
        };
        interpret osfRight {
            action = RedirectKey(keycode=<RGHT>, clearmods=Mod3);
        };
        interpret osfUp {
            action = RedirectKey(keycode=<UP>, clearmods=Mod3);
        };
        interpret osfDown {
            action = RedirectKey(keycode=<DOWN>, clearmods=Mod3);
        };
        interpret osfBeginLine {
            action = RedirectKey(keycode=<HOME>, clearmods=Mod3);
        };
        interpret osfEndLine {
            action = RedirectKey(keycode=<END>, clearmods=Mod3);
        };
        // interpret osfPageUp {
        //     action = RedirectKey(keycode=<PGUP>, clearmods=Mod3);
        // };
        // interpret osfPageDown {
        //     action = RedirectKey(keycode=<PGDN>, clearmods=Mod3);
        // };
        interpret osfDelete {
            action = RedirectKey(keycode=<DELE>, clearmods=Mod3);
        };
        interpret osfBackSpace {
            action = RedirectKey(keycode=<BKSP>, clearmods=Mod3);
        };
        interpret osfReturn {
            action = RedirectKey(keycode=<RTRN>, clearmods=Mod3); //doesn't work (no clue why)
        };
    };
  xkb_symbols   {
      include "pc+de(neo)+inet(evdev)+terminate(ctrl_alt_bksp)+group(lwin_toggle)"

      //Bypass modifiers to directly input movement keys
      key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC_WITH_LEVEL5_LOCK";

      key <AD02> { [ v,                       V,                       underscore,              NoSymbol,                osfBackSpace,               osfBackSpace,               radical,                 NoSymbol                 ]
      };
      key <AD03> { [ l,                       L,                       bracketleft,             Greek_lambda,            osfUp,                      osfUp,                      Greek_LAMBDA,            NoSymbol                 ]
      };
      key <AD04> { [ c,                       C,                       bracketright,            Greek_chi,               osfDelete,                  osfDelete,                  U2102,                   NoSymbol                 ]
      };

      key <AC01> { [ u,                       U,                       backslash,               lessthanequal,                osfBeginLine,                    osfBeginLine,                    includedin,              NoSymbol                 ]
      };
      key <AC02> { [ i,                       I,                       slash,                   Greek_iota,              osfLeft,                    osfLeft,                    integral,                NoSymbol                 ]
      };
      key <AC03> { [ a,                       A,                       braceleft,               Greek_alpha,             osfDown,                    osfDown,                    U2200,                   NoSymbol                 ]
      };
      key <AC04> { [ e,                       E,                       braceright,              Greek_epsilon,           osfRight,                   osfRight,                   U2203,                   NoSymbol                 ]
      };
      key <AC05> { [ o,                       O,                       asterisk,                Greek_omicron,           osfEndLine,                     osfEndLine,                     elementof,               NoSymbol                 ]
      };

      //custom greaterthanequal
      key <AB01> { [ udiaeresis,              Udiaeresis,              numbersign,              greaterthanequal,                Escape,                  Escape,                  union,                   NoSymbol                 ]
      };

      key <AB04> { symbols[Group1]=[ p,                       P,                       asciitilde,              Greek_pi,                Return,                  Return,                  Greek_PI,                NoSymbol                 ],
                   actions[Group1]=[NoAction(),NoAction(),NoAction(),NoAction(),RedirectKey(keycode=<RTRN>, clearmods=Mod3),RedirectKey(keycode=<RTRN>, clearmods=Mod3),NoAction(),NoAction()]};

  };
  xkb_geometry  { include "pc(pc104)" };
};
hadabascus commented 6 months ago

I am using Vim-like arrow keys as detailed in the Arch Wiki. This also only needs the support for clearing modifiers.

notnout commented 3 months ago

My usecase for clearMods: I'm trying to make <CTRL>+<LEFT> jump to the beginning of the line on my laptop that doesn't have reachable Home button: so I want <CTRL>+<LEFT> act as <Home>, but not act as <CTRL>+<Home> (which jumps to the beginning of the page by default).

On X this could be done with:

    override key <LEFT> {
        type = "PC_CONTROL_LEVEL2",
        repeat = Yes,
        symbols[Group1] = [ Left, NoSymbol ],
        actions[Group1] = [ NoAction(), RedirectKey(key=<HOME>, clearMods=Control) ]
    };

On Wayland I have not yet found a viable option (without clearMods).

ronny-rentner commented 2 months ago

I also need clearmods because I've mapped my cursor keys to the home row and Chrome and other apps like Gnome file manager seem to look at keycodes and not keysyms. For Chrome, I can make it use X11 as a workaround (using ozone setting).

wismill commented 2 months ago

@ronny-rentner have you reported the issue to the respective projects? Their keyboard handling looks wrong.

Meanwhile, you may want to have a look at solutions such as KMonad, keyd, Kanata and the likes.

hadabascus commented 2 months ago

@wismill Last time I checked, only very few apps handled keyboard correctly. Creating issues in hundreds of projects is a waste of time, they will not be fixed. This really needs to be fixed here.

wismill commented 2 months ago

So I checked if we could implement at least the clearMods feature: unfortunately it is not possible.

XOrg implement RedirectKey by sending key event with modified keycode and modifiers, then restoring the state, but we cannot: we do not send key events, we only update a global state, which affect all keys.

So this is a feature that should be implemented at compositor level.

@whot @bluetech we could, however, add new minimal API:

Then the compositor may detect there is a key redirection looking for XKB_STATE_REDICTECT_KEY and handle it with the new API, or ignore it completely. Handling it requires some work:

Is it likely that compositors will implement this? We would need to consult at least KDE & Gnome.