So ändern Sie die Scrollgeschwindigkeit des Mausrads pro Anwendung

9

Ist es möglich, eine unterschiedliche Scrollgeschwindigkeit des Mausrads zu haben, je nachdem, welche Anwendung oben ausgeführt wird (fokussiert)?

Wie eine langsamere Bildlaufgeschwindigkeit für Guake zum einfachen Lesen und eine höhere für Webbrowser, um schneller zu scrollen.

Braiam
quelle
Beben Sie das Terminal? Was hat "Mausgeschwindigkeit" mit irgendetwas zu tun?
Braiam
1
@Braiam Ich denke, OP hat diese nur als Beispiele ausgewählt. Der Name der Anwendung ist irrelevant, aber ein wichtiger Teil ist die Änderung der Bildlaufgeschwindigkeit pro beliebiger Anwendung
Sergiy Kolodyazhnyy
@Serg, wie Anwendungen die Mausradereignisse interpretieren, ist äußerst relevant. dh. Firefox interpretiert eine Schaltfläche 5 (wie xorg meine Maus nach unten scrollen sieht) als "drei Zeilen reibungslos nach unten bewegen". Ebenso können andere Anwendungen anderen Kriterien folgen, aber die übliche ist 3 Zeilen und dies wird nicht vom xserver gesteuert.
Braiam

Antworten:

8

Einführung

Mit dem folgenden Skript dynamic_mouse_speed.py können Sie festlegen, wie hoch der Mauszeiger und / oder die Bildlaufgeschwindigkeit sein sollen, wenn das benutzerdefinierte Fenster den Fokus hat.

Wichtig : Für das Skript ist ein imwheelProgramm erforderlich , um die Bildlaufgeschwindigkeit zu erhöhen. Bitte installieren Sie es übersudo apt-get install imwheel

Verwendungszweck

Wie durch -hFlagge gezeigt :

usage: dynamic_mouse_speed.py [-h] [-q] [-p POINTER] [-s SCROLL] [-v]

Sets mouse pointer and scroll speed per window

optional arguments:
  -h, --help            show this help message and exit
  -q, --quiet           Blocks GUI dialogs.
  -p POINTER, --pointer POINTER
                        mouse pointer speed,floating point number from -1 to 1
  -s SCROLL, --scroll SCROLL
                        mouse scroll speed,integer value , -10 to 10
                        recommended
  -v, --verbose         prints debugging information on command line

Mit dem Skript können Benutzer das Fenster auswählen, das sie mit einem Mausklick verfolgen möchten. Der Mauszeiger wird zu einem Kreuz und der Benutzer kann ein gewünschtes Fenster auswählen.

Wenn Sie python3 dynamic_mouse_speed.pyalleine laufen, wird nur der Popup-Dialog angezeigt und es wird nichts für sich getan.

Laufen python3 dynamic_mouse_speed.py -s 5erhöht die Bildlaufgeschwindigkeit, während die python3 dynamic_mouse_speed.py -s -5Bildlaufgeschwindigkeit verlangsamt wird. python3 dynamic_mouse_speed.py -p -0.9verringert die Zeigergeschwindigkeit, während python3 dynamic_mouse_speed.py -p 0.9die Zeigergeschwindigkeit erhöht wird. -sund -pOptionen können gemischt werden. -vErzeugt Debugging-Informationen in der Befehlszeile.

Quelle

Auch als GitHub-Kern verfügbar

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Author: Sergiy Kolodyazhnyy
Date:  August 2nd, 2016
Written for: /ubuntu//q/806212/295286
Tested on Ubuntu 16.04 LTS

usage: dynamic_mouse_speed.py [-h] [-q] [-p POINTER] [-s SCROLL] [-v]

Sets mouse pointer and scroll speed per window

optional arguments:
  -h, --help            show this help message and exit
  -q, --quiet           Blocks GUI dialogs.
  -p POINTER, --pointer POINTER
                        mouse pointer speed,floating point number from -1 to 1
  -s SCROLL, --scroll SCROLL
                        mouse scroll speed,integer value , -10 to 10
                        recommended
  -v, --verbose         prints debugging information on command line


"""
from __future__ import print_function
import gi
gi.require_version('Gdk', '3.0')
gi.require_version('Gtk', '3.0')
from gi.repository import Gdk, Gtk,Gio
import time
import subprocess
import sys
import os
import argparse


def run_cmd(cmdlist):
    """ Reusable function for running shell commands"""
    try:
        stdout = subprocess.check_output(cmdlist)
    except subprocess.CalledProcessError:
        print(">>> subprocess:",cmdlist)
        sys.exit(1)
    else:
        if stdout:
            return stdout



def get_user_window():
    """Select two windows via mouse. 
       Returns integer value of window's id"""
    window_id = None
    while not window_id:
        for line in run_cmd(['xwininfo', '-int']).decode().split('\n'):
            if 'Window id:' in line:
                window_id = line.split()[3]
    return int(window_id)

def gsettings_get(schema,path,key):
    """Get value of gsettings schema"""
    if path is None:
        gsettings = Gio.Settings.new(schema)
    else:
        gsettings = Gio.Settings.new_with_path(schema,path)
    return gsettings.get_value(key)

def gsettings_set(schema,path,key,value):
    """Set value of gsettings schema"""
    if path is None:
        gsettings = Gio.Settings.new(schema)
    else:
        gsettings = Gio.Settings.new_with_path(schema,path)
    return gsettings.set_double(key,value)

def parse_args():
    """ Parse command line arguments"""
    arg_parser = argparse.ArgumentParser(
                 description="""Sets mouse pointer and scroll """ + 
                             """speed per window """)
    arg_parser.add_argument(
                '-q','--quiet', action='store_true',
                help='Blocks GUI dialogs.',
                required=False)

    arg_parser.add_argument(
                '-p','--pointer',action='store',
                type=float, help=' mouse pointer speed,' + 
                'floating point number from -1 to 1', required=False)

    arg_parser.add_argument(
                '-s','--scroll',action='store',
                type=int, help=' mouse scroll speed,' + 
                'integer value , -10 to 10 recommended', required=False)

    arg_parser.add_argument(
                '-v','--verbose', action='store_true',
                help=' prints debugging information on command line',
                required=False)
    return arg_parser.parse_args()

def get_mouse_id():
    """ returns id of the mouse as understood by
        xinput command. This works only with one
        mouse attatched to the system"""
    devs = run_cmd( ['xinput','list','--id-only']   ).decode().strip()
    for dev_id in devs.split('\n'):
        props = run_cmd( [ 'xinput','list-props', dev_id  ]   ).decode()
        if "Evdev Scrolling Distance" in props:
            return dev_id


def write_rcfile(scroll_speed):
    """ Writes out user-defined scroll speed
        to ~/.imwheelrc file. Necessary for
        speed increase"""

    number = str(scroll_speed)
    user_home = os.path.expanduser('~')
    with open( os.path.join(user_home,".imwheelrc") ,'w'  ) as rcfile:
        rcfile.write( '".*"\n' )
        rcfile.write("None, Up, Button4, " + number + "\n"   )   
        rcfile.write("None, Down, Button5, " + number + "\n")
        rcfile.write("Control_L, Up,   Control_L|Button4 \n" +
                     "Control_L, Down, Control_L|Button5 \n" +
                     "Shift_L,   Up,   Shift_L|Button4 \n" +
                     "Shift_L,   Down, Shift_L|Button5 \n" )



def set_configs(mouse_speed,scroll_speed,mouse_id):
    """ sets user-defined values
        when the desired window is in focus"""
    if mouse_speed:
        gsettings_set('org.gnome.desktop.peripherals.mouse',None, 'speed', mouse_speed)

    if scroll_speed:
       if scroll_speed > 0:
           subprocess.call(['killall','imwheel'])
           # Is it better to write config here
           # or in main ?
           write_rcfile(scroll_speed)
           subprocess.call(['imwheel'])
       else:
           prop="Evdev Scrolling Distance"
           scroll_speed = str(abs(scroll_speed))
           run_cmd(['xinput','set-prop',mouse_id,prop,scroll_speed,'1','1']) 



def set_defaults(mouse_speed,scroll_speed,mouse_id):
    """ restore values , when user-defined window
        looses focus"""
    if mouse_speed:
        gsettings_set('org.gnome.desktop.peripherals.mouse', None, 
                      'speed', mouse_speed)

    if scroll_speed:
        if scroll_speed > 0:
           subprocess.call(['killall','imwheel'])
        if scroll_speed < 0:
           prop="Evdev Scrolling Distance"
           run_cmd(['xinput','set-prop',mouse_id,prop,'1','1','1'])


def main():
    """Entry point for when program is executed directly"""
    args = parse_args()

    # Get a default configs
    # gsettings returns GVariant, but
    # setting same schema and key requires 
    # floating point number
    screen = Gdk.Screen.get_default()
    default_pointer_speed = gsettings_get('org.gnome.desktop.peripherals.mouse', 
                                          None, 
                                          'speed')
    default_pointer_speed = float(str(default_pointer_speed))


    # Ask user for values , or check if those are provided via command line
    if not args.quiet:
       text='--text="Select window to track"'
       mouse_speed = run_cmd(['zenity','--info',text])

    user_window = get_user_window() 

    scroll_speed = args.scroll    
    pointer_speed = args.pointer
    mouse_id = get_mouse_id()

    if pointer_speed: 
        if pointer_speed > 1 or pointer_speed < -1:

           run_cmd(['zenity','--error',
                    '--text="Value out of range:' + 
                    str(pointer_speed) + '"'])
           sys.exit(1)

    # ensure that we will raise the user selected window
    # and activate all the preferences 
    flag = True
    for window in screen.get_window_stack():
        if user_window == window.get_xid():
            window.focus(time.time())
            window.get_update_area()
    try:
        while True:
            time.sleep(0.25) # Necessary for script to catch active window
            if  screen.get_active_window().get_xid() == user_window:
                if flag:
                    set_configs(pointer_speed,scroll_speed,mouse_id) 
                    flag=False

            else:
               if not flag:
                  set_defaults(default_pointer_speed, scroll_speed,mouse_id)
                  flag = True

            if args.verbose: 
                print('ACTIVE WINDOW:',str(screen.get_active_window().get_xid()))
                print('MOUSE_SPEED:', str(gsettings_get(
                                          'org.gnome.desktop.peripherals.mouse',
                                           None, 'speed')))
                print('Mouse ID:',str(mouse_id))
                print("----------------------")
    except:
        print(">>> Exiting main, resetting values")
        set_defaults(default_pointer_speed,scroll_speed,mouse_id)

if __name__ == "__main__":
    main()

Anmerkungen

  • Mehrere Skriptinstanzen ermöglichen das Einstellen der Geschwindigkeit für jedes einzelne Fenster.
  • Wenn Popup-Dialoge über die Befehlszeile ausgeführt werden, wird die folgende Meldung angezeigt: Gtk-Message: GtkDialog mapped without a transient parent. This is discouraged.Diese können ignoriert werden.
  • Konsultieren Wie kann ich neue Launcher-Elemente in Unity von Hand bearbeiten / erstellen? zum Erstellen eines Launchers oder einer Desktop-Verknüpfung für dieses Skript, wenn Sie es mit einem Doppelklick starten möchten
  • Informationen zum Verknüpfen dieses Skripts mit einer Tastenkombination für den einfachen Zugriff finden Sie unter Hinzufügen von Tastenkombinationen.
  • Es wird empfohlen, nur eine Maus zu verwenden, wenn das Skript ausgeführt wird, da es auf dem ersten Gerät ausgeführt wird, dessen Evdev Scrolling DistanceEigenschaft gefunden wurde
  • Es können mehrere Instanzen gestartet werden, um mehrere Fenster zu steuern. Dies wird jedoch aus Gründen der Leistung nicht empfohlen
Sergiy Kolodyazhnyy
quelle
Erstaunliche Antwort. Ich würde Ihnen 50 Wiederholungen gewähren, wenn das möglich wäre.
4
@luchonacho Sie können jederzeit Kopfgeld auf die Frage anbieten, wenn Sie dies wünschen, aber es ist erst nach 2 Tagen verfügbar, seit die Frage veröffentlicht wurde :)
Sergiy Kolodyazhnyy
2
Die Frage fragt nach der Änderung der Bildlaufgeschwindigkeit. Es sieht nicht so aus, wie dieses Skript es tut, aber vielleicht kann es dafür angepasst werden. Das tatsächliche Ändern der Geschwindigkeit, mit der sich der Mauszeiger je nach Fenster bewegt, würde sich wahrscheinlich so verhalten, wie es die meisten Benutzer für unvorhersehbar halten. Dies gilt umso mehr, wenn Geschwindigkeitsänderungen mit Verzögerung auftreten.
Kasperd
@kasperd In der Tat war der Fragentitel etwas irreführend, und das Skript ändert die Zeigergeschwindigkeit und nicht die Bildlaufgeschwindigkeit. Es ist jedoch kein großes Problem, und tatsächlich kann ich das Skript so anpassen, dass es die Bildlaufgeschwindigkeit einschließt. Dies erfordert jedoch die Installation eines imwheelPakets, was es etwas komplizierter macht. Ich werde Sie informieren, sobald ich meine Antwort aktualisiere. Was Sie über das unvorhersehbare Verhalten von Benutzern gesagt haben, sehe ich nicht, wie unvorhersehbar dies ist. Könnten Sie mehr erklären?
Sergiy Kolodyazhnyy
@Serg Wenn sich der Mauszeiger in der Mitte eines Benutzers ändert, der ihn bewegt, ist es unwahrscheinlich, dass er den Punkt erreicht, auf den er tatsächlich abzielt. Und wenn die Änderung mit einer Verzögerung von bis zu ¼ Sekunde erfolgt, kann der Benutzer nicht einmal wissen, wie groß ein Teil der Bewegung mit jeder Geschwindigkeit ist. Der Cursor kann sich in 250 Millisekunden ziemlich weit bewegen. Und das Verhalten ist nicht jedes Mal dasselbe, selbst wenn Sie die Maus physisch genauso bewegen, da die Verzögerung gleichmäßig zwischen 0 und 250 Millisekunden verteilt ist.
Kasperd