Cómo cambiar la velocidad de desplazamiento de la rueda del mouse por aplicación

9

¿Es posible tener una velocidad de desplazamiento de la rueda del mouse diferente en función de la aplicación que se ejecuta en la parte superior (enfocada)?

Como una velocidad de desplazamiento más lenta para guake para una lectura fácil y más alta para que el navegador web se desplace más rápido.

Braiam
fuente
¿Temblor en la terminal? ¿Qué tiene que ver la "velocidad del mouse" con algo?
Braiam
1
@Braiam Creo que OP simplemente eligió estos como ejemplos. El nombre de la aplicación es irrelevante, pero una parte importante es el cambio de velocidad de desplazamiento por aplicación arbitraria
Sergiy Kolodyazhnyy,
@Serg cómo las aplicaciones interpretan los eventos de la rueda del mouse es extremadamente relevante. es decir. Firefox interpreta un botón 5 (cómo xorg ve que mi mouse se desplaza hacia abajo) como "mover tres líneas hacia abajo sin problemas", del mismo modo, otras aplicaciones pueden seguir otros criterios, pero el común es 3 líneas y esto no está controlado por el servidor x.
Braiam

Respuestas:

8

Introducción

El siguiente script dynamic_mouse_speed.py permite especificar qué puntero del mouse y / o velocidad de desplazamiento debe ser cuando la ventana definida por el usuario tiene el foco.

Importante : el script requiere un imwheelprograma para aumentar la velocidad de desplazamiento. Por favor, instálelo a través desudo apt-get install imwheel

Uso

Como se muestra por -hbandera:

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

El script permite al usuario seleccionar la ventana que desea rastrear con un clic del mouse. El puntero del mouse se convertirá en una cruz y el usuario puede seleccionar la ventana que desee.

Ejecutar python3 dynamic_mouse_speed.pysolo solo muestra un cuadro de diálogo emergente y no hace nada por sí mismo.

Correr python3 dynamic_mouse_speed.py -s 5aumenta la velocidad de desplazamiento, mientras que python3 dynamic_mouse_speed.py -s -5disminuye la velocidad de desplazamiento hacia abajo. python3 dynamic_mouse_speed.py -p -0.9disminuye la velocidad del puntero, mientras que python3 dynamic_mouse_speed.py -p 0.9aumenta la velocidad del puntero. -sy las -popciones se pueden mezclar. -vproduce información de depuración en la línea de comando.

Fuente

También disponible como GitHub Gist

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Author: Sergiy Kolodyazhnyy
Date:  August 2nd, 2016
Written for: https://askubuntu.com/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()

Notas

  • Múltiples instancias de script permiten establecer la velocidad por cada ventana separada.
  • Cuando se ejecuta desde la línea de comandos, los cuadros de diálogo emergentes generan el siguiente mensaje: Gtk-Message: GtkDialog mapped without a transient parent. This is discouraged.Estos pueden ignorarse.
  • Consultar ¿Cómo puedo editar / crear nuevos elementos de iniciador en Unity a mano? para crear un iniciador o acceso directo de escritorio para este script, si desea iniciarlo con doble clic
  • Para vincular esta secuencia de comandos a un atajo de teclado para un acceso fácil, consulte ¿Cómo agregar atajos de teclado?
  • Se recomienda usar solo un mouse cuando la secuencia de comandos se está ejecutando, ya que funciona en el primer dispositivo que tiene Evdev Scrolling Distancepropiedades
  • Se pueden iniciar varias instancias para controlar varias ventanas, pero no se recomienda por razones de rendimiento.
Sergiy Kolodyazhnyy
fuente
Respuesta asombrosa Te otorgaría 50 repeticiones si eso fuera posible.
44
@luchonacho Siempre puedes ofrecer recompensas por la pregunta si lo deseas, pero solo está disponible después de 2 días desde que se publica la pregunta :)
Sergiy Kolodyazhnyy
2
La pregunta se refiere a cambiar la velocidad de desplazamiento. No parece que eso sea lo que hace este script, pero tal vez se pueda adaptar para hacerlo. En realidad, cambiar la velocidad a la que se mueve el cursor del mouse según la ventana probablemente se comportaría de una manera que la mayoría de los usuarios encuentran impredecible. Más aún cuando los cambios de velocidad ocurren con retraso.
Kasperd
@kasperd De hecho, el título de la pregunta fue un poco engañoso, y el script cambia la velocidad del puntero, en lugar de la velocidad de desplazamiento. Sin embargo, no es un gran problema, y ​​de hecho puedo adaptar el script para incluir la velocidad de desplazamiento. Sin embargo, eso requiere la instalación del imwheelpaquete, lo que lo hará un poco más complicado. Te lo haré saber una vez que actualice mi respuesta. En cuanto a lo que dijo sobre el comportamiento de búsqueda de usuarios impredecible, no veo cómo esto es impredecible. ¿Podrías explicar más?
Sergiy Kolodyazhnyy
@Serg Si el cursor del mouse cambia en el medio de un usuario que lo mueve, es poco probable que llegue al punto al que realmente apunta. Y si el cambio ocurre con un retraso de hasta ¼ de segundo, el usuario ni siquiera puede saber qué tan grande es una parte del movimiento con cada velocidad. El cursor puede moverse bastante lejos en 250 milisegundos. Y el comportamiento no será el mismo cada vez, incluso si mueve físicamente el mouse exactamente de la misma manera, porque el retraso se distribuirá de manera uniforme entre 0 y 250 milisegundos.
Kasperd