staging.inyokaproject.org

[Howto][Anleitung + Code] Maus reparieren per Skript: Prell‑Fix für Logitech Anywhere

Status: Gelöst | Ubuntu-Version: Kein Ubuntu
Antworten |

otto67at

Avatar von otto67at

Anmeldungsdatum:
26. Oktober 2018

Beiträge: 4

Besitzer einer Logitech Anywhere (und ähnlicher Modelle) kennen das Problem: Nach einiger Zeit beginnt die linke Maustaste zu „prellen“ – ein einfacher Klick wird oft als Doppelklick erkannt.

Statt die Maus zu entsorgen oder den Mikroschalter zu tauschen, kann man das Prellen auch softwareseitig filtern.

Das folgende Python‑Skript nutzt evdev und uinput, um Klick‑Ereignisse der linken Maustaste in einem kurzen Zeitfenster zu puffern und nur saubere Klick‑ Muster an das System weiterzugeben.

**Vorteile:** - Keine Hardware‑Modifikation nötig - Funktioniert unter Linux/X11 und Wayland (je nach Input‑Setup) - Doppelklick‑Erkennung optional abschaltbar

**Voraussetzungen:** - Python 3 - Pakete installieren: [code=bash] sudo apt install python3-evdev python3-uinput [/code] - Zugriff auf das richtige /dev/input/eventX-Gerät (per evtest herausfinden) [code=bash] sudo evtest [/code] - Skript ausführbar machen: [code=bash] chmod +x mausfilter.py [/code]

**Start:** [code=bash] sudo ./mausfilter.py [/code]

**Beenden:** Strg+C im Terminal

–-

[code=python] #!/usr/bin/env python3 import evdev, time, uinput, select, signal, sys

DEVICE_PATH = "/dev/input/event11" WINDOW = 0.08 # 80 ms Beobachtungsfenster ENABLE_DOUBLECLICK = True # hier ein/aus schalten

device = evdev.InputDevice(DEVICE_PATH) device.grab() # exklusiver Zugriff, verhindert doppelte Events

ui = uinput.Device([ uinput.BTN_LEFT, uinput.BTN_RIGHT, uinput.BTN_MIDDLE, uinput.REL_X, uinput.REL_Y, uinput.REL_WHEEL ])

print(f"Starte {WINDOW*1000:.0f} ms Fenster-Filter für BTN_LEFT – STRG+C zum Beenden. DblClk={'AN' if ENABLE_DOUBLECLICK else 'AUS'}")

window_start = None buffer = [] holding_sent = False last_state = None # 1=gedrückt, 0=losgelassen

def cleanup_and_exit(sig=None, frame=None): try: device.ungrab() except Exception: pass print("Beendet, Grab freigegeben.") sys.exit(0)

signal.signal(signal.SIGINT, cleanup_and_exit) signal.signal(signal.SIGTERM, cleanup_and_exit)

try: while True: now = time.time() r, _, _ = select.select([device.fd], [], [], 0.01)

if r: for event in device.read(): # Nur BTN_LEFT filtern if event.type == evdev.ecodes.EV_KEY and event.code == evdev.ecodes.BTN_LEFT: last_state = event.value if window_start is None: window_start = now buffer = [(event.value, now)] else: buffer.append[1]

# Alles andere sofort durchreichen elif event.type in (evdev.ecodes.EV_KEY, evdev.ecodes.EV_REL): ui.emit

[2]
  • 1: event.value, now
  • 2: event.type, event.code), event.value) # Fensterende prüfen if window_start is not None and (now - window_start) >= WINDOW: pattern = [v for v, t in buffer] if not pattern: # Kein neues BTN_LEFT-Event im Fenster if holding_sent and last_state == 0: # Letzter Zustand war losgelassen → jetzt UP senden ui.emit(uinput.BTN_LEFT, 0) holding_sent = False window_start = None else: # Taste (vermutlich) noch gedrückt → weiteres Fenster anhängen window_start = now buffer = [] continue # Exakte Muster if pattern == [1, 0]: # Einfachklick ui.emit(uinput.BTN_LEFT, 1) ui.emit(uinput.BTN_LEFT, 0) holding_sent = False window_start = None buffer = [] elif pattern == [1, 0, 1, 0]: # Doppelklick (vorsichtig, nur bei exakt diesem Muster) if ENABLE_DOUBLECLICK: ui.emit(uinput.BTN_LEFT, 1); ui.emit(uinput.BTN_LEFT, 0) ui.emit(uinput.BTN_LEFT, 1); ui.emit(uinput.BTN_LEFT, 0) else: # Fallback: zwei Einzelklicks (bewusst; OS kann daraus ggf. Doppelklick machen) ui.emit(uinput.BTN_LEFT, 1); ui.emit(uinput.BTN_LEFT, 0) ui.emit(uinput.BTN_LEFT, 1); ui.emit(uinput.BTN_LEFT, 0) holding_sent = False window_start = None buffer = [] else: # Anderes Muster → DOWN halten, bis echtes UP + leeres Folgefenster kommt if not holding_sent and pattern[0] == 1: ui.emit(uinput.BTN_LEFT, 1) holding_sent = True window_start = now buffer = [] except KeyboardInterrupt: cleanup_and_exit() except Exception: cleanup_and_exit() raise [/code] –- **Lizenz:** MIT – frei nutzbar und anpassbar **Getestet unter:** Ubuntu 24.04, X11, Logitech Anywhere MX

    Moderiert von schwarzheit:

    Dem Spamfilter entrissen.

    Moderiert von schwarzheit:

    Thema in einen passenden Forenbereich verschoben. Bitte beachte die als wichtig markierten Themen („Welche Themen gehören hier her und welche nicht?“) in jedem Forenbereich. Danke.

schwarzheit Team-Icon

Supporter
Avatar von schwarzheit

Anmeldungsdatum:
31. Dezember 2007

Beiträge: 5329

Und wer bitte soll das in dieser Form lesen und nutzen können?

Versuchs nochmal und beachte dabei die Forensyntax und benutze bitte den Vorschaubutton um zu sehen was aus deinem Text wird.

otto67at

(Themenstarter)
Avatar von otto67at

Anmeldungsdatum:
26. Oktober 2018

Beiträge: 4

Besitzer einer Logitech Anywhere (und ähnlicher Modelle) kennen das Problem:
Nach einiger Zeit beginnt die linke Maustaste zu „prellen“ – ein einfacher Klick wird oft als Doppelklick erkannt.

Statt die Maus zu entsorgen oder den Mikroschalter zu tauschen, kann man das Prellen auch softwareseitig filtern.

Das folgende Python‑Skript nutzt evdev und uinput, um Klick‑Ereignisse der linken Maustaste in einem kurzen Zeitfenster zu puffern und nur saubere Klick‑Muster an das System weiterzugeben.

Vorteile:

  • Keine Hardware‑Modifikation nötig

  • Funktioniert unter Linux/X11 und Wayland (je nach Input‑Setup)

  • Doppelklick‑Erkennung optional abschaltbar

Voraussetzungen:

  • Python 3

  • Pakete installieren:

1
sudo apt install python3-evdev python3-uinput
  • Zugriff auf das richtige /dev/input/eventX‑Gerät (per evtest herausfinden):

1
sudo evtest
  • Skript ausführbar machen:

1
chmod +x mausfilter.py

Start:

1
sudo ./mausfilter.py

Beenden:
Strg+C im Terminal

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
#!/usr/bin/env python3
import evdev, time, uinput, select, signal, sys

DEVICE_PATH = "/dev/input/event11"
WINDOW = 0.08  # 80 ms Beobachtungsfenster
ENABLE_DOUBLECLICK = True  # hier ein/aus schalten

device = evdev.InputDevice(DEVICE_PATH)
device.grab()  # exklusiver Zugriff, verhindert doppelte Events

ui = uinput.Device([
    uinput.BTN_LEFT,
    uinput.BTN_RIGHT,
    uinput.BTN_MIDDLE,
    uinput.REL_X,
    uinput.REL_Y,
    uinput.REL_WHEEL
])

print(f"Starte {WINDOW*1000:.0f} ms Fenster-Filter für BTN_LEFT – STRG+C zum Beenden. DblClk={'AN' if ENABLE_DOUBLECLICK else 'AUS'}")

window_start = None
buffer = []
holding_sent = False
last_state = None  # 1=gedrückt, 0=losgelassen

def cleanup_and_exit(sig=None, frame=None):
    try:
        device.ungrab()
    except Exception:
        pass
    print("Beendet, Grab freigegeben.")
    sys.exit(0)

signal.signal(signal.SIGINT, cleanup_and_exit)
signal.signal(signal.SIGTERM, cleanup_and_exit)

try:
    while True:
        now = time.time()
        r, _, _ = select.select([device.fd], [], [], 0.01)

        if r:
            for event in device.read():
                # Nur BTN_LEFT filtern
                if event.type == evdev.ecodes.EV_KEY and event.code == evdev.ecodes.BTN_LEFT:
                    last_state = event.value
                    if window_start is None:
                        window_start = now
                        buffer = [(event.value, now)]
                    else:
                        buffer.append((event.value, now))

                # Alles andere sofort durchreichen
                elif event.type in (evdev.ecodes.EV_KEY, evdev.ecodes.EV_REL):
                    ui.emit((event.type, event.code), event.value)

        # Fensterende prüfen
        if window_start is not None and (now - window_start) >= WINDOW:
            pattern = [v for v, t in buffer]

            if not pattern:
                if holding_sent and last_state == 0:
                    ui.emit(uinput.BTN_LEFT, 0)
                    holding_sent = False
                    window_start = None
                else:
                    window_start = now
                buffer = []
                continue

            if pattern == [1, 0]:
                ui.emit(uinput.BTN_LEFT, 1)
                ui.emit(uinput.BTN_LEFT, 0)
                holding_sent = False
                window_start = None
                buffer = []

            elif pattern == [1, 0, 1, 0]:
                if ENABLE_DOUBLECLICK:
                    ui.emit(uinput.BTN_LEFT, 1); ui.emit(uinput.BTN_LEFT, 0)
                    ui.emit(uinput.BTN_LEFT, 1); ui.emit(uinput.BTN_LEFT, 0)
                else:
                    ui.emit(uinput.BTN_LEFT, 1); ui.emit(uinput.BTN_LEFT, 0)
                    ui.emit(uinput.BTN_LEFT, 1); ui.emit(uinput.BTN_LEFT, 0)
                holding_sent = False
                window_start = None
                buffer = []

            else:
                if not holding_sent and pattern[0] == 1:
                    ui.emit(uinput.BTN_LEFT, 1)
                    holding_sent = True
                window_start = now
                buffer = []

except KeyboardInterrupt:
    cleanup_and_exit()
except Exception:
    cleanup_and_exit()
    raise

Lizenz: MIT – frei nutzbar und anpassbar
Getestet unter: Debian Trixie, X11, Logitech Anywhere MX

trollsportverein

Avatar von trollsportverein

Anmeldungsdatum:
21. Oktober 2010

Beiträge: 5232

Dankeschön für das Anti-Prell Phyton Skript. 😎 👍
Auch uralte Cherry Mäuse können nach einem Jahrzehnt mal anfangen zu prellen. Ich schätze, gegenbenfalls mit kleinen Anpassungen, lässt sich auch bei anderen Mäusen noch das eine oder andere Betriebsjahr rauskitzeln.

Bis vielleicht dann doch mal die Lieblingsmaus gegen eine neue ausgetauscht wird. ¯\_(ツ)_/¯

von.wert

Anmeldungsdatum:
23. Dezember 2020

Beiträge: 12281

Statt an den Auswirkungen zu feilen, mit Software Hardware-Fehler abmildern zu wollen (Microcode für die Mouse, hrr), ist es sinnvoller, direkt an die Mikrotaster zu gehen. Prellen ist bei LT-Mäusen allgemein normal, bei weitem nicht erst jetzt und schon nach kurzer Zeit selbst bei neuen Mäusen.

Es genügt, die Maus aufzuschrauben (sofern das je nach Modell möglich ist) und auf die Mikrotaster einen Tropfen Propylalkohol, Äthanol oder behelfsweise äthanolhaltiges Rasierwasser zu geben und dann mehrfach den Taster zu drücken. Trocknen lassen und zusammenbauen!

Übler ist das Gegenteil, wenn das Drücken der Maustaste nichts mehr bewirkt, sprich kein mechanischer Kontakt mehr zum Mikrotaster besteht. Dann kann man ein dünnes Blättchen auf den Stift, der auf den Mikrotaster drücken soll, kleben. Fitzelarbeit. Spätestens dann fragt man sich, weshalb man wieder LT gekauft hat.

Dakuan

Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6532

Ich habe hier bei meinen Rechnern auch etliche Maus Fabrikate im Einsatz. Probleme hatte ich eigentlich nur mit SpeedLink. Die wollte nicht so richtig, wenn die Sonne auf meinem Schreibtisch brennt. Deshalb hatte ich die Innenseite des Gehäuses schwarz lackiert.

Meine vier Logitech Mäuse benehmen sich eigentlich normal, bis auf die Maus meines Hauptrechners. Die fing von einem Tag auf den anderen an zu spinnen. Da wurde, gefühlt, jede Aktion gewürfelt. Ich hatte die Maus dann aufgeschraubt und gesäubert. Nach den Staubflusen, die ich da raus geholt hatte, hatte ich den Eindruck, dass die Maus ihre Hauptaufgabe darin gesehen hatte meinen Schreibtisch vom Staub zu befreien.

Nach der Reinigung war alles wieder normal. Bei der Reinigung sollte man sich besonders die Lücken im Mausrad ansehen.

von.wert

Anmeldungsdatum:
23. Dezember 2020

Beiträge: 12281

Dakuan schrieb:

Deshalb hatte ich die Innenseite des Gehäuses schwarz lackiert.

ROFL. Was man sich so einfallen läßt.

Nach den Staubflusen, die ich da raus geholt hatte,

Ist das noch eine mit Kugel? Wobei sich da alles als Ring um die beiden Rollen abgesetzt hat.

die Maus ihre Hauptaufgabe darin gesehen hatte meinen Schreibtisch vom Staub zu befreien.

Wenn die größer ist und in der Wohnung herumfährt, ist das womöglich gar keine Maus. 😀

otto67at

(Themenstarter)
Avatar von otto67at

Anmeldungsdatum:
26. Oktober 2018

Beiträge: 4

Es ist natürlich klar, dass das nicht die endgültige Lösung ist. Es ging bei dem Projekt mehr um den Spass, mal was Neues zu machen und ein kleines Problem schnell mal zu bügeln. Das Problem wird mittlerweile allerdings laufend grösser, vorallem die Aus-Zeiten werden länger und lassen sich immer weniger in sinnvollen Fenstergrössen filtern. Ich glaube, der Workaround neigt sich dem Ende zu ☺

Antworten |