LINUX.ORG.RU

Как забиндить Alt+Caps на капслок?

 , , ,


1

1

Использую включалки раскладок Caps (en) и Shift+Caps (ru). Можно ли повесить собственно капслок на Alt+Caps? Использую i3. Спасибо.



Последнее исправление: tongubin (всего исправлений: 1)

Не смотрел, что там в правилах, но если используется grp:shift_caps_switch, то стоит проверить, не работает ли оно уже как хочется.

anonymous
()
Ответ на: комментарий от anonymous

но если используется grp:shift_caps_switch, то стоит проверить, не работает ли оно уже как хочется.

Нет.

Там сложную заумь для этого придётся вписать. Я пока не осилил. На сегодня пока брошу это дело.

А так ТС мне напомнил, что сам давно хочу такое же слепить.

wandrien ★★
()
Ответ на: комментарий от wandrien

Не должно быть особо сложно, посмотри как в grp:caps_switch сделано. Насколько я помню, настоящий ад там со слоями, а голые модификаторы ещё ничего.

anonymous
()
Ответ на: комментарий от t184256

Достаточно в keyd повесить на Caps и Shift+Caps какие-то другие комбинации, на которые назначить включение соответствующих раскладок, а на Alt+Caps, соответственно, сам Caps.

Но ещё лучше не страдать чем попало и переназначить Caps на Ctrl/Esc.

sudopacman ★★★★★
()
Ответ на: комментарий от sudopacman

Но ещё лучше не страдать чем попало и переназначить Caps на Ctrl/Esc.

Истину глаголешь.

t184256 ★★★★★
()

Хотел по-быстрому накидать сишный код, чтобы повесить на хоткей. Сделал такой черновик:

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <X11/X.h>
#include <X11/XKBlib.h>

struct mod_map {
    unsigned int mod;
    const char * mod_name;
};

struct mod_map mod_map[] = {
    {ShiftMask, "Shift"},
    {LockMask, "Lock"},
    {ControlMask, "Control"},
    {ControlMask, "Ctrl"},
    {Mod1Mask, "Mod1"},
    {Mod2Mask, "Mod2"},
    {Mod3Mask, "Mod3"},
    {Mod4Mask, "Mod4"},
    {Mod5Mask, "Mod5"},
    {0, 0}
};

unsigned int lookup_mod(const char * name)
{
    struct mod_map * m = mod_map;
    while (m->mod_name) {
        if (strcmp(m->mod_name, name) == 0)
            return m->mod;
        m++;
    }

    fprintf(stderr, "invalid mod name: %s\n", name);
    exit(1);
}

int report_state(Display *display)
{
    XkbStateRec xkb_state;
    Status status = XkbGetState(display, XkbUseCoreKbd, &xkb_state);
    if (status) {
        fprintf(stderr, "XkbGetState returned %d\n", status);
        return 1;
    }
    printf("state.group=0x%x\n", xkb_state.group);
    printf("state.locked_group=0x%x\n", xkb_state.locked_group);
    printf("state.base_group=0x%x\n", xkb_state.base_group);
    printf("state.latched_group=0x%x\n", xkb_state.latched_group);
    printf("state.mods=0x%x\n", xkb_state.mods);
    printf("state.base_mods=0x%x\n", xkb_state.base_mods);
    printf("state.latched_mods=0x%x\n", xkb_state.latched_mods);
    printf("state.locked_mods=0x%x\n", xkb_state.locked_mods);
    printf("state.compat_state=0x%x\n", xkb_state.compat_state);
    printf("state.grab_mods=0x%x\n", xkb_state.grab_mods);
    printf("state.compat_grab_mods=0x%x\n", xkb_state.compat_grab_mods);
    printf("state.lookup_mods=0x%x\n", xkb_state.lookup_mods);
    printf("state.compat_lookup_mods=0x%x\n", xkb_state.compat_lookup_mods);
    printf("state.ptr_buttons=0x%x\n", xkb_state.ptr_buttons);
    return 0;
}

int get_mod_lock(Display *display, const char * name)
{
    unsigned int mod = lookup_mod(name);

    XkbStateRec xkb_state;
    Status status = XkbGetState(display, XkbUseCoreKbd, &xkb_state);
    if (status) {
        fprintf(stderr, "XkbGetState returned %d\n", status);
        exit(1);
    }

    return (xkb_state.locked_mods & mod) != 0;
}

void set_mod_lock(Display *display, const char * name, unsigned int value)
{
    unsigned int mod = lookup_mod(name);

    Bool sent = XkbLockModifiers(display, XkbUseCoreKbd, mod, value);

    if (!sent) {
        fprintf(stderr, "Couldn't send XkbLatchLockState\n");
        exit(1);
    }
}


int main(int argc, char ** argv)
{
    Display *display = XOpenDisplay(NULL);
    if (display == NULL) {
        fprintf(stderr, "Couldn't open display\n");
        return 2;
    }

    int flags, opt;
    int nsecs, tfnd;

    nsecs = 0;
    tfnd = 0;
    flags = 0;
    while ((opt = getopt(argc, argv, "rgts")) != -1) {
        switch (opt) {
        case 'r':
            return report_state(display);
        case 'g':
            if (optind >= argc){
                fprintf(stderr, "Expected argument after option -g\n");
                return 1;
            }
            printf("%s=%u\n", argv[optind], get_mod_lock(display, argv[optind]));
            optind++;
            break;
        case 't':
            if (optind >= argc){
                fprintf(stderr, "Expected argument after option -t\n");
                return 1;
            }
            set_mod_lock(display, argv[optind], !get_mod_lock(display, argv[optind]));
            optind++;
            break;
        case 's':
            if (optind + 1>= argc){
                fprintf(stderr, "Expected 2 arguments after option -s\n");
                return 1;
            }
            set_mod_lock(display, argv[optind], atoi(argv[optind+1]));
            optind += 2;
            break;
        default:
            fprintf(stderr, "Usage: %s [-r] [-g mod] [-t mod] [-s mod value]\n", argv[0]);
            return 1;
        }
    }



    int err = XCloseDisplay(display);
    if (err) {
        fprintf(stderr, "XCloseDisplay returned %d\n", err);
        return 1;
    }
    return 0;
}

В итоге на снятие лока, код работает. А на взведение лока падает с этим:

vadim@aquila:~/.bin$ ./xmodstate -t Lock -g Lock
X Error of failed request:  BadMatch (invalid parameter attributes)
  Major opcode of failed request:  135 (XKEYBOARD)
  Minor opcode of failed request:  5 (XkbLatchLockState)
  Serial number of failed request:  8
  Current serial number in output stream:  9
Status: 1
vadim@aquila:~/.bin$ 

Вот у чувака такой же вопрос и нет ответов: https://www.unix.com/unix-for-dummies-questions-and-answers/248760-capslock-python-question.html

Я хз. Пойду спать.

wandrien ★★
()
Ответ на: комментарий от wandrien

Это всё потому что у тебя 0 вместо NULL для указателя в массиве с названиями локов.

firkax ★★★★★
()
Ответ на: комментарий от wandrien

так сработало:

./a.out -s Lock 2

Учитывая что LockMask=2, а для нумлока (Mod2Mask=16) оно работает с 16, видимо надо value=mask ставить.

Ну и конечно зарепортить баг (не знаю уж, в мане или в коде, надо посмотреть практику использования этой функции в другом софте) который они проигнорят.

edit: А нет, там в первой части мана просто забыли указать что values это тоже битовая маска. Если дальше почитать становится понятно.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от firkax

Спасибо

Отлично! Можно пользоваться с такой правкой:

    Bool sent = XkbLockModifiers(display, XkbUseCoreKbd, mod, value ? mod : 0);

Завтра оформлю в отдельной репе на гитхабе.

wandrien ★★
()
Последнее исправление: wandrien (всего исправлений: 1)
Ответ на: комментарий от t184256

Может, но ненамного. У такого варианта есть более заметные плюсы, чем количество строк.

anonymous
()
Ответ на: комментарий от sudopacman

Но ещё лучше не страдать чем попало и переназначить Caps на Ctrl/Esc.

А это у взрослых людей сделано в клавиатуре, чтобы не удивляться потом, что клавиши работают как-то не так в загрузчике, EFI или LiveUSB.

anonymous
()

Можно при помощи xkbcomp. Хочешь с этой штукой пободаться? Только она тебя перебодает. :)

Zubok ★★★★★
()

Ниже вариант. en+ru(winkeys) и включен _правый_ Alt как переключатель третьего уровня (так быстрее просто было). Закидываешь на сервер xkbcomp <file.xkb> $DISPLAY. Ну и в автозагрузку это все добавить. На комбинации Right_Alt+Caps Lock будет Caps Lock. Просто Caps Lock - первая группа, Shift+Caps Lock - последняя группа. Если у тебя какие-то еще есть опции, то сам их добавляй в include.

xkb_keymap {
        xkb_keycodes  { include "evdev+aliases(qwerty)" };
        xkb_types     { include "complete"      };
        xkb_compat    { include "complete"      };
        xkb_geometry  { include "pc(pc105)"     };
        xkb_symbols   {
                include "pc+us+ru(winkeys):2+inet(evdev)+level3(ralt_switch)"
                key <CAPS> {  [ ISO_First_Group, ISO_Last_Group, Caps_Lock, Caps_Lock ] };
        };
};
Zubok ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.