fix(groups): sort groups by unique_key to ensure stable group naming#1325
Conversation
|
Thank you At the beginning of the run method there is a large comment explaining the reasoning for the current way of sorting things. Does your code break what is described there? Sorting a list using 14 lines of code is a bit much, why is it important to use the shortest_name as a sorting key, can't it just use the name for the same result? Would something like sorted(
grouped,
key=lambda group: group[0][0]
)suffice? This should sort them by their name. |
|
Ah, no, you are sorting it by device.phys, not the name, sorry. Anyhow, I'd like you to try to find a less complex solution for this. I don't think sorting a list by device.phys should require so much code. The old run method is already not exactly a short and easy method, making a less complex solution even more important. This code might overwrite the sorting above |
|
And please check if the issue in the code-comment there is still fixed when sorting by device.phys |
simplified the sorting down to a clean concise dictionary grouping and sorting implementation: How it works:
Why shortest_name is necessary: A single physical device group (like a keyboard) can expose multiple sub-devices with different names (e.g., "Corsair deterministic listing order for different devices, and stable naming/preset association for identical devices. |
|
by using black the change have 10 logic lines but it could go smt like this |
Previously, the naming order depended entirely on the To fix this, I grouped the devices by their base name first and then sorted them alphabetically by their This keeps different devices in their original discovery order (preserving test compatibility), but identical devices are sorted stably based on their USB port. |
This is what case 1: one corsair keyboard (device1, device2) and some other device (device3):grouped:
ordered_groups:
case 2: two corsair keyboards (device1 + device2 and device4 + device5) and some other device (device3):grouped:
ordered_groups:
Did I get that right? If we sorted the device using |
|
You could even modify |
Regarding the idea of prepending f"{classify(device)}" to get_unique_key : I considered doing this to group similar devices together (like all keyboards next to each other), but there is a catch. A single physical hardware device often exposes multiple virtual sub-devices with different classifications If we prepended classify(device) to the unique key, these sub-devices would receive different unique keys and get split into separate groups in the GUI, instead of staying grouped under the same physical device. So keeping get_unique_key strictly hardware-based is necessary to ensure all virtual sub-devices of the same physical device are grouped together correctly. |
|
ah, good catch. Thanks. It looks much cleaner now. Once you mark it as ready, I'll merge it |
|
thx you rly make me think a bit to get it better to be fair |
Context
When multiple identical or similar input devices (e.g., identical wireless USB receivers, mice, or keyboards with empty/generic
device.uniqserial numbers) are connected to a system:input-remappergenerates human-readable keys dynamically during device scanning (like"Corsair Receiver","Corsair Receiver 2", etc.) in the order they are populated in thegroupeddictionary./dev/input/eventXX) returned byevdev.list_devices().config.jsonget swapped between identical devices, causing the wrong profile to be loaded.Changes
groupeddictionary in insertion order (which is non-deterministic and depends on event numbers), we now sort the groups alphabetically by their stable unique keys (unique_keyingrouped.keys()) before generating the human-readable group keys.unique_keydepends on the immutable hardware attributes and the physical USB port topology path, making it completely stable across reboots, port swaps, and device reconnections.Verification / Testing
event10andevent11swapped) originally caused their configurations to swap.This PR addresses the duplicate USB receiver confusion described in #1300.