Итак, вы потратили много денег на красивую, удобную игровую мышь. Мышь действительно хорошо сидит в руке, приятно светится всеми цветами радуги, имеет целых 6 дополнительных кнопок в дополнение к 5 стандартным, гибко настраивается... Разумеется, вы хотите использовать её возможности полностью! Стоп, гибко настраивается? Разумеется, разработчики ASUS так не считают!
Фирменный софт Armoury Crate (как и предыдущие версии) даёт вам довольно скромный выбор настроек кнопок мыши:

  1. Функция мыши

  2. Функция клавиатуры

  3. Мультимедиа

  4. Макрос

Остальные так или иначе сводятся к этим четырем
Остальные так или иначе сводятся к этим четырем

На первый взгляд, это нормальный набор, однако дьявол в деталях. Вы думаете, вы можете забиндить любую клавишу клавиатуры? Зависит от того, что вы считаете клавиатурой. Разработчики ASUS, например, считают стандартную 100% клавиатуру.

Возникает логичный вопрос - а зачем мне нужны дополнительные кнопки котрые могут только дублировать функциональность уже имеющихся? Не, для некоторых программ это имеет смысл, например при трассировке плат смену слоя, Num *, очень удобно иметь на мыши. Но это не серьёзно, раз мы купили все клавиши, то надо использовать все клавиши.

Push to Talk

Вот истинная причина, почему я вообще занялся тем, что описано в статье. Понимаете ли, я частенько зависаю в голосовых чатах. И у нас там не принято пользоваться активацией по голосу — просто как правило приличия. Для активации по кнопке, разумеется, нужна кнопка. Но какая? Я параллельно, зависая в чате, могу заниматься вообще чем угодно: играми, веб-сёрфингом, программированием или даже CAD. Собственно, необходимость набора текста сразу исключает все цифро-буквенные клавиши вместе с Ctrl и Shift, а остальные занятия — практически все оставшиеся клавиши! Единственной остаётся Scroll Lock, но согласитесь: постоянно мигать светодиодом на клавиатуре — такое себе.

Есть ли выход? Конечно, есть: ведь ваша клавиатура на самом деле неполная. Что? Да! Как минимум существуют ещё F13–F24. Поддерживаются ли они системами ввода? Естественно:
https://learn.microsoft.com/en-us/windows/win32/inputdev/about-keyboard-input
Даже существуют в дикой природе.

Unicomp PC122, продаётся по сей день
Unicomp PC122, продаётся по сей день

Итак, наша задача становится простой: надо забиндить F13 на дополнительную кнопку мыши. Но как именно?

Наивная попытка №1: Макросы

Собственно, в Armoury Crate можно забиндить клавишу клавиатуры двумя способами: выбрать её на виртуальной клавиатуре или же нажать на физической. Тогда просто ставим AHK, биндим её и Armoury Crate получает нажатие нужной кнопки? Ага, сейчас, размечтались. Armoury Crate принимает только клавиши, которые есть выше на виртуальной клавиатуре.
Редактирование асусовских макросов также не дало результата, тем более что их в последних обновлениях вынесли в отдельный загружаемый модуль для Armoury Crate. Вы уже начинаете понимать уровень шизофрении у этих разработчиков, да?

Наивная попытка №2: Редактируем профиль руками

Разумеется если вы прогеймер и профессионально настроили мышь, вы бы хотели поделиться этими настройками с миром. И Armoury Crate предоставляет нам такую возможность:

Сохраняемый профиль идёт в формате .rog, внутри содержится странная, на первый взгляд, строка в UTF-8. Разумеется это base-64, в него закодирован url-закодированный json.

Твое лицо когда разрабатываешь серьёзный формат для серьёзных девайсов
Твое лицо когда разрабатываешь серьёзный формат для серьёзных девайсов

Декодируем профиль парой строк на питоне и кодируем обратно также.

Функции декодирования и кодирования
// Функция для декодирования: base64 -> URL-decode -> JSON -> файл
function decodeProfile(base64String, outputFile = 'decoded_profile.json') {
  try {
    // Шаг 1: Декодируем base64 в Buffer
    const buffer = Buffer.from(base64String, 'base64');
    
    // Шаг 2: Преобразуем в строку (UTF-8)
    let decodedString = buffer.toString('utf8');
    
    // Шаг 3: URL-декодируем
    decodedString = decodeURIComponent(decodedString);
    
    // Шаг 4: Парсим JSON
    const jsonData = JSON.parse(decodedString);
    
    // Шаг 5: Сохраняем pretty-printed JSON в файл
    const prettyJson = JSON.stringify(jsonData, null, 2);
    fs.writeFileSync(outputFile, prettyJson, 'utf8');
    
    console.log(`Профиль успешно декодирован и сохранён в файл: ${outputFile}`);
    console.log('Предпросмотр:');
    console.log(prettyJson.substring(0, 500) + '...'); // Первые 500 символов для preview
    
    return jsonData; // Возвращаем, если нужно дальше использовать
  } catch (error) {
    console.error('Ошибка декодирования:', error.message);
  }
}
// Функция для кодирования: JSON -> URL-encode -> base64 -> файл
function encodeProfile(jsonData, outputFile = 'encoded_profile.rog') {
  try {
    // Шаг 1: Преобразуем JSON в строку (minified для consistency, без пробелов)
    const jsonString = JSON.stringify(jsonData);
    
    // Шаг 2: URL-кодируем строку
    const urlEncoded = encodeURIComponent(jsonString);
    
    // Шаг 3: Преобразуем в Buffer (UTF-8)
    const buffer = Buffer.from(urlEncoded, 'utf8');
    
    // Шаг 4: Кодируем в base64
    const base64String = buffer.toString('base64');
    
    // Шаг 5: Сохраняем base64 в файл
    fs.writeFileSync(outputFile, base64String, 'utf8');
    
    console.log(`Профиль успешно закодирован и сохранён в файл: ${outputFile}`);
    console.log('Предпросмотр base64 (первые 100 символов):');
    console.log(base64String.substring(0, 100) + '...');
    
    return base64String; // Возвращаем, если нужно дальше использовать
  } catch (error) {
    console.error('Ошибка кодирования:', error.message);
  }
}

Дальше надо выяснить используемые асусом коды клавиш. Вот так выглядит запись настройки одной кнопки:

"13": {
  "buttonFunction": "1",
  "key_1": 6,
  "key_2": "-1",
  "key_3": "-1",
  "layout": "en-US"
}

И тут нас ждёт сюрприз. Как вы думаете какая кнопка клавиатуры тут забиндена? А вот не угадали, это F6. Если немного побиндить разные кнопки, то вырисовывается довольно странная картина:  

  • Scroll lock - 267

  • Pause - 523

  • F1 - 1

  • F3 - 3

  • F8 - 8

  • F9 - 9

  • F10 - 10

  • F11 - 1541

  • F12 - 1797

  • Insert - 1544

  • Home - 1545

  • PgUp - 1547

  • NumLock - 1036

  • Num/ - 1037

  • L-Alt - 1796

  • L-Shift - 1024

  • G - 771

Это не соответствует ни одной известной таблице сканкодов! Конечно можно найти какие-то закономерности, чатгпт и грок смело предположили что для F13 кодом должно быть 2053. Окей, попытка не пытка, пытаемся скоромить это Armoury Crate.

Результат превзошёл все ожидания
Результат превзошёл все ожидания

Именно так выглядит профессиональная обработка ошибок в профессиональном приложении на электроне для настройки железа! После этого пользоваться страницей устройства становится невозможно! Удалить данные UWP программы тот ещё квест, проще всего оказалось просто переустановить Armoury Crate, а для удаления вам ещё потребуется отдельно скачивать деинсталлятор который подотрёт за ней всё, штатные средства винды тут не помогут.

Попытка №3: опенсорс нас спасёт?

К этому моменту становится ясно, что ковыряться в софте ASUS дальше бесполезно. Мы, как обычно, оказываемся в мире без софта. Есть ли что‑то уже готовое? Ну, есть G‑Helper, но он позволяет настраивать только подсветку. Я уже хотел вооружиться Wireshark и полезть реверсить протокол ASUS, как мне в одном чате подсказали, что я — поехавший, но посоветовали вместе с тем проект libratbag, где уже всё отреверсили за меня.

Libratbag — это демон D‑Bus, позволяющий настраивать высококлассные игровые мыши, в том числе от ASUS. Хорошее начало, но использовать его как есть не выйдет — мы же на Винде. Конечно, можно пробросить мышь целиком в виртуалку, но может, сначала изучим, можно ли тут сделать то, что мне надо?
Находим issue как раз с моей проблемой: libratbag крашится при попытке забиндить F13. А в чем причина? Быстро находим в исходниках такую таблицу:

/* key mapping, the index is actual ASUS code */
static const unsigned char ASUS_KEY_MAPPING[] = {
/* 00 */	0,		0,		0,		0,
/* 04 */	KEY_A,		KEY_B,		KEY_C,		KEY_D,
/* 08 */	KEY_E,		KEY_F,		KEY_G,		KEY_H,
/* 0C */	KEY_I,		KEY_J,		KEY_K,		KEY_L,
/* 0E */	KEY_M,		KEY_N,		KEY_O,		KEY_P,
/* 14 */	KEY_Q,		KEY_R,		KEY_S,		KEY_T,
/* 18 */	KEY_U,		KEY_V,		KEY_W,		KEY_X,
/* 1C */	KEY_Y,		KEY_Z,		KEY_1,		KEY_2,
/* 1E */	KEY_3,		KEY_4,		KEY_5,		KEY_6,
/* 24 */	KEY_7,		KEY_8,		KEY_9,		KEY_0,
/* 28 */	KEY_ENTER,	KEY_ESC,	KEY_BACKSPACE,	KEY_TAB,
/* 2C */	KEY_SPACE,	KEY_MINUS,	KEY_KPPLUS,	0,
/* 2E */	0,		0,		0,		0,
/* 34 */	0,		KEY_GRAVE,	KEY_EQUAL,	0,
/* 38 */	KEY_SLASH,	0,		KEY_F1,		KEY_F2,
/* 3C */	KEY_F3,		KEY_F4,		KEY_F5,		KEY_F6,
/* 3E */	KEY_F7,		KEY_F8,		KEY_F9,		KEY_F10,
/* 44 */	KEY_F11,	KEY_F12,	0,		0,
/* 48 */	0,		0,		KEY_HOME,	KEY_PAGEUP,
/* 4C */	KEY_DELETE,	0,		KEY_PAGEDOWN,	KEY_RIGHT,
/* 4E */	KEY_LEFT,	KEY_DOWN,	KEY_UP,		0,
/* 54 */	0,		0,		0,		0,
/* 58 */	0,		KEY_KP1,	KEY_KP2,	KEY_KP3,
/* 5C */	KEY_KP4,	KEY_KP5,	KEY_KP6,	KEY_KP7,
/* 5E */	KEY_KP8,	KEY_KP9,	0,
};

О нет! Неужели это всё, что можно забиндить? Неужели инженеры ASUS захардкодили таблицу допустимых клавиш напрямую в мышь? Хотя это нелогично: час работы хорошего эмбед‑разработчика стоит сильно больше, чем час работы веб‑индусов, которые писали Armoury Crate, а кое‑как делать прошивку для мыши не получится — в конце концов, их и покупают именно за высокую скорость отклика. Это не умная лампочка с линуксом, которая может переключаться за пару секунд. Вряд ли ASUS стали добавлять ещё и проверку на валидность клавиши — усложняет прошивку. Да и секундочку: а почему в таблице нет Ctrl, Shift и Alt, а разве не напоминает нам эта таблица что‑то знакомое? Да это же HID‑сканкоды клавиатуры в чистом виде!

Фрагмент таблицы из документа HID Usage Tables for Universal Serial Bus (USB)
Фрагмент таблицы из документа HID Usage Tables for Universal Serial Bus (USB)

Собственно, Ctrl, Shift и Alt находятся ближе к концу и начинаются с 0xE0. Вообще, мне сильно понравилась эта таблица: вы правда думаете, что F13–F24 — это что-то экзотическое? А как насчёт Keypad XOR? Или, скажем, Keyboard Execute, Currency Unit? У меня уже в голове смутно вырисовывается концепция библейски точной клавиатуры, на которой будут вообще все клавиши из стандарта!

Видение сгенерированное ChatGPT
Видение сгенерированное ChatGPT

Автор драйвера для ROGатых мышей видимо составил эту таблицу экспериментально и не занимался выяснением, а не стандартная ли это вещь. Отлично, теперь кода мы точно знаем что можно забиндить кнопки в диапазоне от 0x03 до 0xE8, вероятность что в мыши всё же есть какой-то фильтр становится малой. Теперь надо проверить что мы можем это сделать в действительности. Как я уже говорил, libratbag это для линуксов, поэтому на винде нам потребуется написать свою минимальную реализацию драйвера.  

Итак, приступим, драйвера конечно надо писать на лучшем для этого языке программирования, а именно python. Что? Это всего лишь пруф оф концепт. Так вот, берем python, к нему либу hidapi и начинаем.

Первым делом надо найти устройство с интересующим нас VID, PID и открыть его. Нам нужен интерфейс 02, т.к. это составное USB устройство:

def open_mi02_interface(vid, pid):
    devices = hid.enumerate(vid, pid)
    for dev_info in devices:
        if dev_info.get('interface_number') == 2:
            path = dev_info['path']
            print(f"Открываем MI_02: {dev_info.get('product_string', 'Unknown')} (Path: {path})")
            device = hid.device()
            device.open_path(path)
            return device, path
    print("MI_02 не найден.")
    return None, None

Далее, прежде чем что-то писать, надо сначала что-то прочитать. Получим текущие бинды мыши:

def asus_get_binding_data(device, path, group=0, max_retries=2):
    try:
        cmd_bytes = struct.pack('<H', ASUS_CMD_GET_BUTTON_DATA)
        request_data = [REPORT_ID] + list(cmd_bytes) + [group] + [0] * (ASUS_PACKET_SIZE - 3)
        
        print(f"Output запрос на {path}: {request_data[:8]}... (65 байт)")
        
        bytes_written = device.write(request_data)
        if bytes_written != ASUS_PACKET_SIZE + 1:
            return {'error': f'Write failed: {bytes_written} байт'}
        
        print("Output отправлен. Читаем response...")
        
        response = device.read(ASUS_PACKET_SIZE, timeout_ms=1000)
        retry_count = 0
        while retry_count < max_retries:
            if response and len(response) == ASUS_PACKET_SIZE:
                resp_code = struct.unpack('<H', bytes(response[0:2]))[0]
                print(f"Read code: 0x{resp_code:04x} (ожидаемо 0x{ASUS_CMD_GET_BUTTON_DATA:04x})")
                if resp_code == ASUS_CMD_GET_BUTTON_DATA:
                    print("Valid response.")
                    break
                else:
                    print(f"Unexpected code 0x{resp_code:04x}, retry {retry_count+1}...")
                    time.sleep(0.1)
                    response = device.read(ASUS_PACKET_SIZE, timeout_ms=500)
            else:
                print(f"Read len={len(response) if response else 0}, retry {retry_count+1}...")
                time.sleep(0.1)
                response = device.read(ASUS_PACKET_SIZE, timeout_ms=500)
            retry_count += 1
        
        if not response or len(response) != ASUS_PACKET_SIZE:
            return {'error': f'Read failed after retries (len={len(response) if response else 0})'}
        
        raw_hex = ''.join(f'{b:02x}' for b in response)
        print(f"Raw hex: {raw_hex}")
        
        resp_code = struct.unpack('<H', bytes(response[0:2]))[0]
        if resp_code == 0xaaff:
            return {'error': 'ASUS_STATUS_ERROR'}
        
        # Парсинг (offset=4)
        bindings = []
        for i in range(ASUS_MAX_NUM_BUTTON):
            offset = 4 + i * 2
            if offset + 2 > len(response):
                break
            action = response[offset]
            typ = response[offset + 1]
            
            if action == 0xff:
                desc = 'Disabled'
            elif typ == 0:
                desc = HID_KEY_MAPPING.get(action, f'Unknown Key 0x{action:02x}')
            else:
                desc = ASUS_BUTTON_MAPPING.get(action, f'Unknown Button 0x{action:02x}')
            
            ratbag_idx = BUTTON_MAPPING.get(action, 'N/A') if typ == 1 else 'N/A'
            
            bindings.append({
                'internal_index': i,
                'action': hex(action),
                'type': typ,
                'description': desc,
                'ratbag_index': ratbag_idx
            })
        
        return {
            'group': group,
            'path': path,
            'bindings': bindings,
            'raw_hex': raw_hex
        }
    except Exception as e:
        return {'error': f'Ошибка: {str(e)}'}

Выполняем, смотрим ответ:

Bindings:
  Internal 0: 0xf0 — Mouse Left (button 1)  (ratbag 0) [active (type=1)]
  Internal 1: 0xf1 — Mouse Right (button 2)  (ratbag 1) [active (type=1)]
  Internal 2: 0xf2 — Mouse Middle (button 3)  (ratbag 2) [active (type=1)]
  Internal 3: 0x47 — ScrollLock  [active (type=0)]
  Internal 4: 0x55 — KP_Asterisk  [active (type=0)]
  Internal 5: 0xe6 — DPI Cycle Up  (ratbag 5) [active (type=1)]
  Internal 6: 0x0 — Unknown Key 0x00  [active (type=0)]
  Internal 7: 0xe8 — Wheel Up  (ratbag 7) [active (type=1)]
  Internal 8: 0xe9 — Wheel Down  (ratbag 8) [active (type=1)]
  Internal 9: 0xe4 — Mouse Back (button 4)  (ratbag 3) [active (type=1)]
  Internal 10: 0xe5 — Mouse Forward (button 5)  (ratbag 4) [active (type=1)]

Ура! Мы успешно прочитали что есть что. Теперь попробуем забиндить клавишу Internal 4 на F13. Для этого уже потребуется 2 команды, настройка клавиши и сохранение профиля:

def asus_set_button_action(device, path, src_code, dst_code, asus_type):
    try:
        cmd_bytes = struct.pack('<H', ASUS_CMD_SET_BUTTON)
        request_data = [REPORT_ID] + list(cmd_bytes) + [0, 0, src_code, 1, dst_code, asus_type] + [0] * (ASUS_PACKET_SIZE - 6)
        
        print(f"Output set на {path}: src=0x{src_code:02x}, dst=0x{dst_code:02x}, type={asus_type}")
        print(f"Request hex: {''.join(f'{b:02x}' for b in request_data[:10])}...")
        
        bytes_written = device.write(request_data)
        if bytes_written != ASUS_PACKET_SIZE + 1:
            return {'error': f'Write failed: {bytes_written} байт'}
        
        time.sleep(0.1)
        response = device.read(ASUS_PACKET_SIZE, timeout_ms=500)
        if response:
            resp_code = struct.unpack('<H', bytes(response[0:2]))[0]
            print(f"Ack code: 0x{resp_code:04x}")
        
        print("Set отправлен.")
        return {'success': True, 'path': path}
    except Exception as e:
        return {'error': f'Ошибка: {str(e)}'}

def asus_save_profile(device, path):
    try:
        cmd_bytes = struct.pack('<H', ASUS_CMD_SAVE)
        request_data = [REPORT_ID] + list(cmd_bytes) + [0] * (ASUS_PACKET_SIZE - 2)
        
        print(f"Save на {path}: (65 байт)")
        
        bytes_written = device.write(request_data)
        if bytes_written != ASUS_PACKET_SIZE + 1:
            return {'error': f'Save write failed: {bytes_written} байт'}
        
        time.sleep(0.5)
        print("Save отправлен.")
        return {'success': True, 'path': path}
    except Exception as e:
        return {'error': f'Ошибка: {str(e)}'}

Выполняем, считываем снова настройки клавиш.

Bindings:
  Internal 0: 0xf0 — Mouse Left (button 1)  (ratbag 0) [active (type=1)]
  Internal 1: 0xf1 — Mouse Right (button 2)  (ratbag 1) [active (type=1)]
  Internal 2: 0xf2 — Mouse Middle (button 3)  (ratbag 2) [active (type=1)]
  Internal 3: 0x68 — Unknown Key 0x68  [active (type=0)]
  Internal 4: 0x55 — KP_Asterisk  [active (type=0)]
  Internal 5: 0xe6 — DPI Cycle Up  (ratbag 5) [active (type=1)]
  Internal 6: 0x0 — Unknown Key 0x00  [active (type=0)]
  Internal 7: 0xe8 — Wheel Up  (ratbag 7) [active (type=1)]
  Internal 8: 0xe9 — Wheel Down  (ratbag 8) [active (type=1)]
  Internal 9: 0xe4 — Mouse Back (button 4)  (ratbag 3) [active (type=1)]
  Internal 10: 0xe5 — Mouse Forward (button 5)  (ratbag 4) [active (type=1)]

Проверим работу где-нибудь, под руку попался OBS Studio.

Работает!
Работает!

Отлично! Вот теперь наша мышь стала действительно полезной!

Ложка дёгтя

Вроде всё хорошо, но мне стало интересно, а как ж себя поведет с этим Armoury Crate? При открытии страницы настройки мыши мы получим краш и наконец-то не сможем пользоваться этим отвратительным софтом? Учитывая результат попыток редактирования профиля вручную это было бы ожидаемым исходом, но здесь разработчики Armoury Crate превзошли все ожидания. Не произошло ничего. Вообще. Бинды стояли те же которые были установлены в ней в последний раз. Если в меню выбрать синхронизацию профилей, то после этого кнопка 4 снова станет ScrollLock. Вывод: Armoury Crate вообще не умеет читать конфигурацию с устройства.
И нет, на этом беды не заканчиваются. Я выше назвал разработчиков шизофрениками, так вот, здесь мои сомнения в их адекватности только усилились. При перезагрузке ПК бинд снова слетел на ту конфигурацию, которая сохранена в Armoury Crate. Просто гениально! Зачем вообще мыши нужна внутренняя память если софт всё равно затирает конфигурацию в ней каждый раз своей? Впрочем это ожидаемо, потому что найти хорошие отзывы об Armoury Crate достаточно сложно, а вот недовольства им хоть отбавляй, особенно на фоне устаревшей фирменной утилиты Armoury II.

Вместо заключения

Какие-то выводы сделать сложно. Ну кроме того, что, я занимаюсь опять какой-то ерундой и надо было брать Logitech. Насколько я глубоко искал в интернете, я первый кто смог забиндить нестандартную клавишу на кнопки мыши Asus, хотя тему поднимали, интересовались на форумах Asus и реддите.
Код был написан за один вечер с помощью Grok4 и представляет совсем уж proof-of-concept для ровно одной мыши, доступен ниже на github. Возможно кто-то с этими знаниями добавит в g-helper настройку клавиш мыши, возможно этим когда-нибудь даже займусь я.

Ссылки и источники

Мой Proof-of-Concept

libratbag

Сканкоды USB-HID

Комментарии (11)


  1. dartraiden
    04.11.2025 01:03

    А мышь не позволяет на свои клавиши повесить не одиночный хоткей, а составной? То есть, активацию микрофона повесить на условный Ctrl+Alt+Shift+Win+T и на кнопку мыши навесить эмуляцию этого хоткея.

    Таким образом, используем те клавиши, про которые знают разработчики Asus.


    1. VO_Obsidian Автор
      04.11.2025 01:03

      Можно, но вроде как только до 3 клавиш, плюс Ctrl и Shift часто используются в играх отдельно. Так что вариант, но не без недостатков


    1. mr_octopus514
      04.11.2025 01:03

      Позволяет, как и любая другая более-менее современная мышь.


  1. Hesed
    04.11.2025 01:03

    Если покопаться в недрах ПО для игровых устройств, можно потерять веру в человечество. Логитековский G-Hub в какой-то момент у меня стал затирать настройки при обновлении и я искал, как их бэкапить. Нашёл. В SQLite файле, в котором есть одна единственная таблица с одним единственным текстовым полем, лежит конфиг в виде JSON'а. Смерть кощеева какая-то.


    1. dartraiden
      04.11.2025 01:03

      Программисту дали задачу «положить конфиг в базу» - он положил ¯\_(ツ)_/¯


    1. radioxoma
      04.11.2025 01:03

      Говорят в SQLIte удобные функции для работы с JSON. /s


  1. Lev3250
    04.11.2025 01:03

    Armory crate это главная причина, почему больше ни одно устройство в семье больше не будет от Asus (хотя в пике абсолютно все ноуты были от asus)


  1. gaussssss
    04.11.2025 01:03

    Асус и их программисты это уже притча во языцех. Чего стоит зависающее на 99 процентах обновление биоса. Перезагружать вручную ноут, когда на экране огромными буквами написано это не делать и грозят библейскими карами - крайне интересный опыт.


  1. nomorewar
    04.11.2025 01:03

    Вся эта проприетарщина - лютый колхоз студента под наркотой за бешеные деньги. Прям удивление берет иногда. Ощущение, что мегакорпорации соревнуются в дисциплине: «Всратый софт, за который люди еще платят деньги». Пытаются нащупать грань, видимо. Поэтому только open source решения. В мире клавиатур это чуть ли не стандарт, а вот в мире мышей - хз, есть ли решения.


  1. tommycruzo
    04.11.2025 01:03

    автор, ты красавчик! Я тоже мучился, пытался настроить ряд F13, F24 и забиндить его на кнопки своей мыши Asus Spatha. Не получалось, и меня это совсем бомбило — кнопок много, но за биндить можно только какие-то убогие сочетания. Я потратил несколько часов, экспериментируя с разными комбинациями, и сейчас у меня что-то глючит, конфликтует. Просто не хочу с этим разбираться.

    от Razer есть игровая панель у меня, и там как будто классный софт и весь ряд F в наличии. Я даже подумал, что, возможно, стоит покупать разные мыши для разных сетапов. Может, себе и Razer какую-то классную мышку прикуплю, да и logitech mx4 сейчас выйдет - я бы ее тоже потрогал.
    Очень расстроен, что не получилось довести до рабочего решения у тебя эту идею, но статья интересная, спасибо!)


  1. Compiller
    04.11.2025 01:03

    Во времена моды на мультимедиа клавиатуры была хорошая утилита для Windows MKey

    сейчас её офсайта уже нет, но скачать её можно. многое она позволяет делать даже на Windows 11.