Compare commits
11 Commits
7da129c72e
...
372ad0e380
Author | SHA1 | Date |
---|---|---|
|
372ad0e380 | |
|
bdb0e9589b | |
|
0335dd003c | |
|
8bea0121cc | |
|
a3ce172bef | |
|
95ac6d5670 | |
|
b465be2468 | |
|
6d06cd9561 | |
|
d1796d2950 | |
|
0dac92deb2 | |
|
6bfd6a7b94 |
72
CHANGELOG.md
72
CHANGELOG.md
|
@ -1,3 +1,75 @@
|
|||
# 1.1.15rc1
|
||||
|
||||
* Center labels and remove buggy entry resizing logic
|
||||
* Add shape keys from Key POP Icon
|
||||
* Device and Action rule conditions match on codename and name
|
||||
* Fix listing hidpp10 devices - bytes vs string concatenation (#2856)
|
||||
* Add present flag, unset when internal error occurs, set when notification appears
|
||||
* Pause setting up features when error occurs; use ADC message to signal connection and disconnection
|
||||
* Fix listing of hidpp10 peripherals
|
||||
* Complete DEVICE_FEATURES to DeviceFeature transition for hidpp10 devices
|
||||
* Fix NOTIFICATION_FLAG to NotificationFlag transition leftovers
|
||||
* Fix github workflow stopping all matrix jobs when one of them fails
|
||||
* Fix ubuntu github CI
|
||||
* Update index.md
|
||||
* Python documentation appears to be broken so don't set it up
|
||||
* Improve documentation on onboard profiles
|
||||
* Use correct LOD values for extended adjustable dpi
|
||||
* Better support RGB Effects - not readable
|
||||
* Fix crash when asking for help about config
|
||||
* Fix error when updating ChoiceControlBig box
|
||||
* Add uninstallation docs
|
||||
* Handle unknown power switch locations again
|
||||
* Correctly handle selection of [empty] in rule editor
|
||||
* Handle `HIDError` in `hidapi.hidapi_impl._match()` (#2804)
|
||||
* Give ghost devices a path
|
||||
* Guard against typeerror when setting the value of a control box
|
||||
* Recover from errors in ping
|
||||
* Replace spaces by underscores when looking up features
|
||||
* Rewrote string concatenation/format with f strings
|
||||
* Fix logo not showing in about dialog box
|
||||
* Make typing-extensions dependency mandatory
|
||||
* Properly ignore unsupported locale
|
||||
* hidapi: skip unsupported devices and handle exception on open
|
||||
* Ignore macOS junk files and pipenv config
|
||||
* Fix ui desktop notifications test
|
||||
* hidpp20: Remove dependency to NamedInts
|
||||
* Estimate accurate battery level for some rechargable devices (#2745)
|
||||
* Upgrade desktop notifications tests to take notifications availability into account
|
||||
* Update tests to run on Python 3.13
|
||||
* Remove outdated logger enabled checks
|
||||
* Introduce GTK signal types
|
||||
* Introduce error types
|
||||
* Remove alias for SupportedFeature
|
||||
* Refactor process_device_notification
|
||||
* Refactor process_receiver_notification
|
||||
* Refactor receiver event handling
|
||||
* Introduce custom logger
|
||||
* Refactor notifications
|
||||
* Rename variable to full name notification
|
||||
* Test notifications
|
||||
* Test extraction of serial and max. devices
|
||||
* Refactor extraction of serial and max. devices
|
||||
* macOS: Fix int.from_bytes, int.to_bytes for show.py
|
||||
* macOS: Remove udev rule warning
|
||||
* macOS: Add support for Bluetooth devices
|
||||
* Add back and forward mouseclick actions
|
||||
* Speedup lookup of known receivers
|
||||
* Refactor device filtering
|
||||
* Reorder private functions and variable definitions
|
||||
* Turn filter_products_of_interest into a public function
|
||||
* Improve tests of known receivers
|
||||
* Refactor: Remove NamedInts and move enums where used
|
||||
* Add docstrings and type hints
|
||||
* Enforce rules on RuleComponentUI subclasses
|
||||
* Simplify settings UI class
|
||||
* Remove diversion alias
|
||||
* Refactor: Convert Kind to IntEnum
|
||||
* Split up huge settings module
|
||||
* Remove Python 2 specific path handling
|
||||
* Delete logging temp file on exit
|
||||
* Update Swedish translation
|
||||
|
||||
# 1.1.14
|
||||
|
||||
* Handle fake feature enums in show
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
## Version 1.1.15
|
||||
|
||||
* Device and Action rule conditions match on device codename and name
|
||||
* Solaar supports configuration of Bluetooth devices on macOS.
|
||||
|
||||
## Version 1.1.13
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
solaar show
|
||||
rules cannot access modifier keys in Wayland, accessing process only works on GNOME with Solaar Gnome extension installed
|
||||
solaar version 1.1.14-2
|
||||
|
||||
Unifying Receiver
|
||||
Device path : /dev/hidraw1
|
||||
USB id : 046d:C52B
|
||||
Serial : EC219AC2
|
||||
C Pending : ff
|
||||
0 : 12.11.B0032
|
||||
1 : 04.16
|
||||
3 : AA.AA
|
||||
Has 2 paired device(s) out of a maximum of 6.
|
||||
Notifications: wireless (0x000100)
|
||||
Device activity counters: 1=195, 2=74
|
||||
|
||||
1: Wireless Mouse M175
|
||||
Device path : /dev/hidraw2
|
||||
WPID : 4008
|
||||
Codename : M175
|
||||
Kind : mouse
|
||||
Protocol : HID++ 2.0
|
||||
Report Rate : 8ms
|
||||
Serial number: 16E46E8C
|
||||
Model ID: 000000000000
|
||||
Unit ID: 00000000
|
||||
0: RQM 40.00.B0016
|
||||
The power switch is located on the base.
|
||||
Supports 21 HID++ 2.0 features:
|
||||
0: ROOT {0000} V0
|
||||
1: FEATURE SET {0001} V0
|
||||
2: DEVICE FW VERSION {0003} V0
|
||||
Firmware: 0 RQM 40.00.B0016 4008
|
||||
Unit ID: 00000000 Model ID: 000000000000 Transport IDs: {}
|
||||
3: DEVICE NAME {0005} V0
|
||||
Name: Wireless Mouse M185
|
||||
Kind: mouse
|
||||
4: BATTERY STATUS {1000} V0
|
||||
Battery: 70%, 0, next level 5%.
|
||||
5: unknown:1830 {1830} V0 internal, hidden
|
||||
6: unknown:1850 {1850} V0 internal, hidden
|
||||
7: unknown:1860 {1860} V0 internal, hidden
|
||||
8: unknown:1890 {1890} V0 internal, hidden
|
||||
9: unknown:18A0 {18A0} V0 internal, hidden
|
||||
10: unknown:18C0 {18C0} V0 internal, hidden
|
||||
11: WIRELESS DEVICE STATUS {1D4B} V0
|
||||
12: unknown:1DF3 {1DF3} V0 internal, hidden
|
||||
13: REPROG CONTROLS {1B00} V0
|
||||
14: REMAINING PAIRING {1DF0} V0 hidden
|
||||
Remaining Pairings: 117
|
||||
15: unknown:1E00 {1E00} V0 hidden
|
||||
16: unknown:1E80 {1E80} V0 internal, hidden
|
||||
17: unknown:1E90 {1E90} V0 internal, hidden
|
||||
18: unknown:1F03 {1F03} V0 internal, hidden
|
||||
19: VERTICAL SCROLLING {2100} V0
|
||||
Roller type: standard
|
||||
Ratchet per turn: 24
|
||||
Scroll lines: 0
|
||||
20: MOUSE POINTER {2200} V0
|
||||
DPI: 1000
|
||||
Acceleration: low
|
||||
Override OS ballistics
|
||||
No vertical tuning, standard mice
|
||||
Battery: 70%, 0, next level 5%.
|
|
@ -24,7 +24,6 @@ which is MIT licensed.
|
|||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import atexit
|
||||
import ctypes
|
||||
import logging
|
||||
|
|
|
@ -28,6 +28,7 @@ import subprocess
|
|||
import sys
|
||||
import time
|
||||
import typing
|
||||
import threading
|
||||
|
||||
from typing import Any
|
||||
from typing import Dict
|
||||
|
@ -46,6 +47,8 @@ if platform.system() in ("Darwin", "Windows"):
|
|||
else:
|
||||
import evdev
|
||||
|
||||
|
||||
from . import language_switcher as _language_switcher
|
||||
from .common import NamedInt
|
||||
from .hidpp20 import SupportedFeature
|
||||
from .special_keys import CONTROL
|
||||
|
@ -57,7 +60,7 @@ if typing.TYPE_CHECKING:
|
|||
from .base import HIDPPNotification
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
switcher = _language_switcher.LanguageSwitcher()
|
||||
#
|
||||
# See docs/rules.md for documentation
|
||||
#
|
||||
|
@ -1550,7 +1553,22 @@ def process_notification(device, notification: HIDPPNotification, feature) -> No
|
|||
thumb_wheel_displacement = 0
|
||||
thumb_wheel_displacement += signed(notification.data[0:2])
|
||||
|
||||
GLib.idle_add(evaluate_rules, feature, notification, device)
|
||||
def switch_and_evaluate(feature, notification, device):
|
||||
done_switching = threading.Event()
|
||||
|
||||
def switch_language():
|
||||
switcher.evaluate()
|
||||
done_switching.set()
|
||||
|
||||
def evaluate_rules():
|
||||
done_switching.wait() # Wait until the language has been switched
|
||||
rules.evaluate(feature, notification, device, True)
|
||||
switcher.set_previous_language()
|
||||
|
||||
GLib.idle_add(switch_language)
|
||||
GLib.idle_add(evaluate_rules)
|
||||
|
||||
GLib.idle_add(switch_and_evaluate, feature, notification, device)
|
||||
|
||||
|
||||
_XDG_CONFIG_HOME = os.environ.get("XDG_CONFIG_HOME") or os.path.expanduser(os.path.join("~", ".config"))
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
import logging
|
||||
import subprocess
|
||||
|
||||
from xkbgroup import X11Error
|
||||
from xkbgroup import XKeyboard
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# it would be better to use xkbgroup to switch language, but I don't know how to work with it
|
||||
class LanguageSwitcher:
|
||||
def __init__(self):
|
||||
self.xkb = None
|
||||
try:
|
||||
self.xkb = XKeyboard()
|
||||
except X11Error as e:
|
||||
logger.error(f"Cannot initialize XKeyboard: {e}")
|
||||
self.previous_layout = None
|
||||
|
||||
def get_current_layout(self):
|
||||
"""Gets the current keyboard layout (language)."""
|
||||
try:
|
||||
result = subprocess.run(["setxkbmap", "-query"], capture_output=True, text=True)
|
||||
for line in result.stdout.splitlines():
|
||||
if "layout:" in line:
|
||||
return line.split(":")[1].strip()
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to get current keyboard layout: {e}")
|
||||
return None
|
||||
|
||||
def get_current_language(self):
|
||||
"""Gets the current keyboard layout (language)."""
|
||||
try:
|
||||
# xkb used because setxkbmap shows only layout, but not language. So we need to use xkb to check current language
|
||||
return self.xkb.group_symbol
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to get current keyboard layout: {e}")
|
||||
return None
|
||||
|
||||
def remember_layout(self, language):
|
||||
"""Remembers the previous language."""
|
||||
self.previous_layout = language
|
||||
logger.debug(f"Remembered language: {self.previous_layout}")
|
||||
|
||||
# switch to english using setxkbmap because xkbgroup switching seems to be asynctounous and I don't know how work with it
|
||||
# you can use xkbgroup to switch to english. just remember previous_language instead of layout
|
||||
# and use self.xkb.group_symbol = "us", self.xkb.group_symbol = previous_language
|
||||
def switch_language_to_english(self):
|
||||
"""Switches the keyboard layout to English."""
|
||||
try:
|
||||
subprocess.run(["setxkbmap", "us"], check=True)
|
||||
logger.debug("Switched keyboard layout to English.")
|
||||
except subprocess.CalledProcessError as e:
|
||||
logger.error(f"Failed to switch to English layout: {e}")
|
||||
|
||||
def set_previous_language(self):
|
||||
"""Sets the keyboard layout back to the previously remembered language."""
|
||||
if self.previous_layout:
|
||||
try:
|
||||
subprocess.run(["setxkbmap", self.previous_layout], check=True)
|
||||
logger.debug(f"Restored keyboard layout to {self.previous_layout}.")
|
||||
except subprocess.CalledProcessError as e:
|
||||
logger.error(f"Failed to restore previous layout: {e}")
|
||||
finally:
|
||||
self.previous_layout = None
|
||||
else:
|
||||
logger.warning("No previous language was remembered.")
|
||||
|
||||
def evaluate(self):
|
||||
"""Evaluate the current language and switch to English if it's not already English."""
|
||||
if not self.xkb:
|
||||
logger.warning("X11 display not accessible. Skipping get_current_language.")
|
||||
return None
|
||||
|
||||
current_language = self.get_current_language()
|
||||
logger.debug(f"Current language: {current_language}")
|
||||
|
||||
if current_language != "us":
|
||||
current_layout = self.get_current_layout()
|
||||
logger.debug(f"Current layout: {current_layout}")
|
||||
self.remember_layout(current_layout)
|
||||
self.switch_language_to_english()
|
|
@ -90,7 +90,6 @@ def process_receiver_notification(receiver: Receiver, notification: HIDPPNotific
|
|||
Notification.RAW_INPUT,
|
||||
Notification.POWER,
|
||||
]
|
||||
|
||||
logger.warning(f"{receiver}: unhandled notification {notification}")
|
||||
|
||||
|
||||
|
|
|
@ -678,7 +678,6 @@ class FeatureRWMap(FeatureRW):
|
|||
reply = device.feature_request(self.feature, self.write_fnid, key_bytes, data_bytes, no_reply=self.no_reply)
|
||||
return reply if not self.no_reply else True
|
||||
|
||||
|
||||
class ActionSettingRW:
|
||||
"""Special RW class for settings that turn on and off special processing when a key or button is depressed"""
|
||||
|
||||
|
|
Loading…
Reference in New Issue