openrazer / openrazer

Open source driver and user-space daemon to control Razer lighting and other features on GNU/Linux
https://openrazer.github.io
GNU General Public License v2.0
3.65k stars 529 forks source link

Keypad Keybindings (eg. Orbweaver) #167

Open mjtorn opened 7 years ago

mjtorn commented 7 years ago

Hi!

As discussed in https://github.com/lah7/polychromatic/issues/47 it would be very useful to rebind some keys on the Orbweaver, and why not others as well.

Here's a Synapse/Windows screenshot for reference keypad-customize 2017-01-22

The backtick key is quite useless while ESC would be priceless. And why not have a shift key while at it.

Apparently the daemon would have to support this.

What are some of the solutions? I can think of intercepting and rewriting the scan codes, which probably sucks hard performance-wise but might be easy-ish to implement. Another solution would be along the lines of xmodmap, which is lower-level and should work faster but would require maintaining a bunch of external maps and such.

Is this on the roadmap?

Thanks!

tildearrow commented 7 years ago

Why would intercept-rewrite be slower than xmodmapping, if the remapping can be done in the kernel driver?

mjtorn commented 7 years ago

@tildearrow chances are it wouldn't be, I'm not very well versed in these things. I was thinking it would be perhaps done by the daemon, not the kernel. Computers are pretty fast at that level ;)

Either way, I'm asking because I want to learn and understand.

terricain commented 7 years ago

Guys what are we after? Make a list

mjtorn commented 7 years ago

@terrycain the ability to rebind the key scancodes would be really nice. Like in the screenshot, having 01 bound to ESC instead of the backtick. This is useful just about whenever, but even more so in a (console-case PC) case that doesn't have a keyboard attached all the time.

The rest was just musing about how this could be implemented.

Is this on the roadmap or has it been discussed before?

terricain commented 7 years ago

Its been discussed before, I would like it too just for a matter of completeness. Is it on the roadmap, technically no as the roadmap is whatever I feel like doing next ;-)

Its all about the best way of going about it. Remapping is easily done in the driver (though there'll need to be a fair bit of restructuring)

Macro support exists in a rather crippled not too great implementation in the daemon, it finds the input file in /dev/input/by-id, gets exclusive read on it so nothing else receives key presses and then when it receives them it will run xdotool to run macros

stale[bot] commented 6 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

nicodemus144 commented 6 years ago

Has there been any developments on this? Any thoughts about next steps? Razer users really need this functionality, and it doesn't seem like Razer is in a hurry to help.

Thanks for all you do!

blob42 commented 6 years ago

I just stumbled on this project and indeed macro keys don't work and the documentation is very light on the subject. I would gladly hack a bit or at least update the doc if I knew where to look in the code or where to start.

arnauddupuis commented 6 years ago

Hi guys, First thanks for all the love and work! I really appreciate and I know I'm not alone! (sometimes it's just good to know that. So just to make it clear, right now to change the keyboard mapping we are still stuck to xkb_comp and xmodmap right? The driver does not manage key mapping yet, am I correct? (I'm also trying to validate my own installation here ^^). Best and again thanks!

z3ntu commented 6 years ago

No, the driver doesn't do any keymapping yet. If you have any problems with your installation, feel free to join our community chat, either via Telegram (https://t.me/joinchat/A1E4RT9TxhnxyetdQCSj7Q) or via Matrix (https://matrix.to/#/#openrazer:matrix.org)

chestm007 commented 6 years ago

Hey guys, Straight up I'm no expert in low level code or kernel modules. I would love this feature as i have an Orbweaver as well and recently switched my gaming PC to Linux.

Having cloned and read through the code, as well as all the information/requests i can find in this project, requirements for this change as i understand it are: (PLEASE correct me if I'm wrong)

From how i understand the code base, possibly the earliest hook point (at least as far as keyboards are concerned) would be in driver/razerkbd.c:razer_event (https://github.com/openrazer/openrazer/blob/cec084208ef93c4fbef10fec106b6f5b2d5fbb67/driver/razerkbd_driver.c#L1528).

It should be fairly easy to implement a /proc data store for the "current" profile, then have the daemon write to that the key mappings.

Assuming that's all as you envision it, i believe we could leave the existing macro code in the daemon for backwards compatibility/so we don't break existing tools.

As far as storing profiles i almost feel like that should be a front end responsibility exposed via an API in the daemon.

I'm more then keen to take this on as a project, though i will most likely need some form of guidance - i promise i wont be a burden.

Cheers!

terricain commented 6 years ago

implement keybinding in the driver, rather then the daemon.

Hmm, ideally we want to reduce the code in the driver and do it in userspace. As the less code that is in the driver the more chances it'll get merged to mainline. You'd probably want to grab an exclusive read on the appropriate device in /dev/input and then use uinput to send key events. Probs best written in c/c++

Assuming that's all as you envision it, i believe we could leave the existing macro code in the daemon for backwards compatibility/so we don't break existing tools.

I'd say we have a separate daemon to deal with all things macro, then I can purge all the horrible macro code from the current daemon

As far as storing profiles i almost feel like that should be a front end responsibility exposed via an API in the daemon.

yes


Thoughts?

chestm007 commented 6 years ago

Hmm, ideally we want to reduce the code in the driver and do it in userspace. As the less code that is in the driver the more chances it'll get merged to mainline.

That makes perfect sense.

You'd probably want to grab an exclusive read on the appropriate device in /dev/input and then use uinput to send key events. Probs best written in c/c++

I've done a bit of experimentation and that seems to capture modifier keys also so should work perfectly - aslong as there is a way to tell when a key was pressed and subsequently released. Given we wouldnt need too do much heavy lifting really (playing back recorded macros, rather then straight keybindings may be trickier, but still do-able in C)

I'd say we have a separate daemon to deal with all things macro, then I can purge all the horrible macro code from the current daemon

haha, yeah... that macro code looks nasty


I don't think the overall implementation would be too difficult, one thing i did like about the synapse software was the ability to map profiles too keys. I'm not sure how implementable that would be this far down the stack.

terricain commented 6 years ago

I reckon it wouldn't be too bad, but get the bulk of it working first then we can plan out that

chestm007 commented 6 years ago

yeah easy, ill start off with single keystroke rebinding - we can build from there.

terricain commented 6 years ago

@chestm007 👍

TheDavidFactor commented 6 years ago

Any progress on this? I've got an OrbWeaver and some basic coding ability so I'm willing to test/help

derrickmehaffy commented 6 years ago

Just checking in to see if anyone has messed with this (also latching on for updates)

Conzar commented 5 years ago

I am the developer for Keyboarding Master. I have implemented key rebinding in user space (ages ago). Checkout my project here: https://kbmaster.atlassian.net/wiki/spaces/KBM/overview

I would be interested in integrating with openrazer as KBM currently does not support LEDs. However, I am having trouble finding up2date documentation regarding integration.

z3ntu commented 5 years ago

Pull requests with a POC of the integration are welcome :) we don't have any direct docs on that but you should just put it somewhere into the daemon.

Conzar commented 5 years ago

@z3ntu Without documentation, I have no idea where to even start.

z3ntu commented 5 years ago

The driver/ directory contains the kernel drivers and the daemon/ directory contains the user space daemon where you will probably want to put this. For more you need to ask more specific questions. But for starting, just write a simple python script that interacts with keyboarding master. That would be enough POC to me :)

Conzar commented 5 years ago

I was thinking that keyboarding master continues to use jinput for managing the key rebinds. The first thing I can work on is just integrating the color management from the openrazer drivers. Thoughts on that?

chestm007 commented 5 years ago

Hey, been a while.

So i have SOMEWHAT of a working prototype - albeit very incomplete, but it works for basic single key remapping, key modifiers are handled as expected also.

Theres also barely/no input lag and it handles multiple/fast keystrokes well (as its just intercepting and modifying the incoming stream of events)

import evdev
from evdev import UInput, ecodes

# here i just build a dict of the keycode this code receives (just a standard keycode of the original key mapping)
custom_map = dict(
    _41=ecodes.KEY_1,
    _15=ecodes.KEY_ESC,
    _58=ecodes.KEY_LEFTSHIFT,
    _42=ecodes.KEY_LEFTCTRL
)

dev = evdev.device.InputDevice('/dev/input/event7')  # this can be pulled from RazerDevice.event_files, will need some sort of filtering

with dev.grab_context():      
    with UInput() as ui:
        for event in dev.read_loop():
            if event.type == ecodes.EV_KEY:
                print(event.code, event.value)

                # this rewrites the keystroke as our desired key, doing the same action as the pressed 
                # key (down, up, hold, etc) - if no key is mapped, just send the key we recieved (default)
                ui.write(ecodes.EV_KEY, custom_map.get('_{}'.format(event.code), event.code), event.value)  
                ui.syn()

Due to the info this would need it would either need to be embedded into the daemon or have the daemon expose the RazerDevice.event_files attribute - im actually half thinking it might be better off in the daemon as by the looks of things it could be nicely kept from sprawling all over the codebase.

tildearrow commented 5 years ago

I fear mentioning this but I've been working on key rebinding pretty recently out of the intense desire to remap/assign keys.

The only minor problem is that it will "disable" the ripple effect (but this would also happen with any application that grabs input devices)...

chestm007 commented 5 years ago

@tildearrow

The only minor problem is that it will "disable" the ripple effect (but this would also happen with any application that grabs input devices)...

would having a hook in the openrazer daemon to feed those events into be too much of a hack?

tildearrow commented 5 years ago

@tildearrow

The only minor problem is that it will "disable" the ripple effect (but this would also happen with any application that grabs input devices)...

would having a hook in the openrazer daemon to feed those events into be too much of a hack?

I was planning to do this as part of the OpenRazer integration I'll be writing soon, but the OpenRazer daemon would need to provide a way to be able to feed it with events.

Another method is for the OpenRazer daemon to listen for events on all devices, and trigger ripples on MSC_SCAN events (which will have proper positions).

TherinS commented 5 years ago

Its great to see people making projects for the Tartarus/Orbweaver and Belkin gameboards, and Conzar's KeyboardingMaster works nice. However, if you want to get input working and macro support NOW, I would recommend looking at Pystromo. It has lots of configuration available including macro support. It has been around since 2008 but has no GUI. The configuration files are human readable, however, and it has worked great for me for years, until I made the fateful decision to upgrade from Ubuntu 16.04 to 18.04.

The v0.6.0 no longer remaps my keys, though it DOES seem to work, as evidenced by the 3 LED keys changing state. The v0.6.1 had the lib files upgrade to work with Python3 (or so the dev claims) but I cannot get the remapper to run, as the terminal returns several 'unable to load module' errors.

I think the OpenRazer project could get instant Nostromo/Tartarus/Orbweaver key re-binding and macro support using Pystromo and would only need to make a GUI to populate the .map files, if only the program worked in 18.04. Since it is entirely Python scripts and just about all Linux distros have Python installed, the actual backend files are less than 100kb (!), not including configuration map files.

If anyone knows Python and what changed between 16.04 and 18.04, please let me know what I need to do to get this wonderful bunch of code working again, even without any GUI. I have made install and activation scripts to streamline using Pystromo and it starts up nearly instantly.

v0.6.0 https://github.com/byrongibson/Pystromo

v0.6.1 (Python3 compliant? Fails to run for me) https://github.com/booms8/Pystromo

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

chabad360 commented 4 years ago

I'm going to suggest tildearrow/input-modifer for the meantime (till #880 is merged), it's the next best solution.