web-dev-qa-db-fra.com

Comment définir un raccourci AutoKey qui envoie la même frappe à la fenêtre avec un titre donné

Comment définir un raccourci global Ctrl+a1 avec AutoKey qui envoie la même frappe Ctrl+a1 à la fenêtre avec le titre 'gnu screen'? S'il n'y a pas de fenêtre nommée de ce type, un message contextuel "Impossible de trouver la fenêtre de destination" doit s'afficher.

6
zuba
  1. Installez libnotify-bin qui fournit notify-send

    Sudo apt-get install libnotify-bin
    
  2. Créer un nouveau script:

    import time
    import subprocess
    
    #no need
    #keyboard.release_key("<ctrl>")
    
    # wait_for_keypress does not return any thing to distinguish between target key pressed or timeout reached.
    # So if time is less than the timeout then it was key press.
    start_time = time.time()
    keyboard.wait_for_keypress("1", timeOut=1)
    if (time.time()-start_time < 0.9):
        time.sleep(0.2)
        window.activate("gnu screen")
        time.sleep(0.1)
        active_title = window.get_active_title()
        # if it doesn't get same title, then no window titled as gnu screen
        # it sends a notify message otherwise send the key sequence.
        if (active_title == "gnu screen"):
            keyboard.press_key("<ctrl>")
            keyboard.send_key("a")
            keyboard.release_key("<ctrl>")
            keyboard.send_key("1")
        else:
            subprocess.Popen(['notify-send', "Couldn't find destination window"])
    
  3. Configurez sa touche de raccourci comme suit: Ctrl+a

Pour le déclencher: Ctrl+a ensuite 1 (en <1sec)


Déboguer

  1. Lancer X Event Tester dans une fenêtre de terminal séparée

    xev -event keyboard
    
  2. Vérifiez son titre de fenêtre, le mien montre Event Tester

    $ wmctrl -l
    0x03000012 -1       N/A Desktop — Plasma
    0x030000c1 -1       N/A Desktop — Plasma
    0x0300001b -1       N/A Plasma
    0x06a00098  0        PC User User - Ask Ubuntu - Mozilla Firefox
    0x01a00067  0       N/A user : screen
    0x01a000cd  0       N/A user : xev
    0x04600001  0       N/A Event Tester
    0x01e0015d  0        PC AutoKey
    
  3. Modifiez le script pour cibler la fenêtre Event Tester.

    import time
    import subprocess
    
    start_time = time.time()
    keyboard.wait_for_keypress("1", timeOut=1)
    if (time.time()-start_time < 0.9):
        time.sleep(0.2)
        window.activate("Event Tester")
        time.sleep(0.1)
        keyboard.press_key("<ctrl>")
        keyboard.send_key("a")
        keyboard.release_key("<ctrl>")
        keyboard.send_key("1")
    
  4. Si xev reçoit la séquence de touches. Sa sortie devrait être quelque chose de similaire à:

    KeyPress event, serial 34, synthetic NO, window 0x4600001,
        root 0xb2, subw 0x0, time 55057700, (1053,140), root:(945,303),
        state 0x0, keycode 105 (keysym 0xffe4, Control_R), same_screen YES,
        XLookupString gives 0 bytes: 
        XmbLookupString gives 0 bytes: 
        XFilterEvent returns: False
    
    KeyPress event, serial 34, synthetic YES, window 0x4600001,
        root 0xb2, subw 0x0, time 0, (1,1), root:(1,1),
        state 0x0, keycode 38 (keysym 0x61, a), same_screen YES,
        XLookupString gives 1 bytes: (61) "a"
        XmbLookupString gives 1 bytes: (61) "a"
        XFilterEvent returns: False
    
    KeyRelease event, serial 35, synthetic YES, window 0x4600001,
        root 0xb2, subw 0x0, time 0, (1,1), root:(1,1),
        state 0x0, keycode 38 (keysym 0x61, a), same_screen YES,
        XLookupString gives 1 bytes: (61) "a"
        XFilterEvent returns: False
    
    KeyRelease event, serial 35, synthetic NO, window 0x4600001,
        root 0xb2, subw 0x0, time 55057701, (1053,140), root:(945,303),
        state 0x4, keycode 105 (keysym 0xffe4, Control_R), same_screen YES,
        XLookupString gives 0 bytes: 
        XFilterEvent returns: False
    
    KeyPress event, serial 35, synthetic YES, window 0x4600001,
        root 0xb2, subw 0x0, time 0, (1,1), root:(1,1),
        state 0x0, keycode 10 (keysym 0x31, 1), same_screen YES,
        XLookupString gives 1 bytes: (31) "1"
        XmbLookupString gives 1 bytes: (31) "1"
        XFilterEvent returns: False
    
    KeyRelease event, serial 35, synthetic YES, window 0x4600001,
        root 0xb2, subw 0x0, time 0, (1,1), root:(1,1),
        state 0x0, keycode 10 (keysym 0x31, 1), same_screen YES,
        XLookupString gives 1 bytes: (31) "1"
        XFilterEvent returns: False
    

Notez que j'ai supprimé la condition if pour vérifier le titre actif. Le script active/déclenche la fenêtre xev mais la vérification ne trouve pas le titre correct. Je viens de recevoir le message de notification.

2
user.dz

Je pensais dans le même sens que "Mostafa Najafiyazdi" et j'ai utilisé sa fonction wmctrl comme base pour la première version de script de la fonction avec quelques modifications.

Ce n'est pas spécifique à l'autokey et ce n'est donc pas un script python. J'utilise une configuration similaire pour activer, commuter et effectuer des tâches sur mon media-pc (mythtv) avec un seul bouton de contrôle à distance.

Il est difficile de définir un raccourci/une fenêtre pour exécuter ce script avec des touches combinées et ctrl + a est généralement différent. Si vous décidez d'utiliser quelque chose comme ctrl + f7 pour la clé d'activation, l'appel de ce script doit faire ce que vous voulez.

Ceci requie xdotool et libnotify-bin. Cela ne changera pas la fenêtre active en "écran GNU", voir la section commentée pour passer à la même fonctionnalité que pour le script activate_window_and_send_keys.

~/bin/focus_window_and_send_keys "gnu screen" "ctrl+a+1"

Et le script:

#!/bin/bash
## copy these files to ~/bin = (~ = is your home directory)
### finding window and keys
## requires xdotool
### notify
## libnotify-bin

# Usage:
# ~/bin/focus_window_and_send_keys "window title" "keys" "morekeys" ...
# ~/bin/focus_window_and_send_keys "gnu screen" "ctrl+a+1"

title=${1:-NOT_FOUND_EMPTY_TITLE}
shift
## get current window
CURWIN=$(xdotool getactivewindow)
TARGETWIN=$(xdotool search --name "$title" | head -n 1)
if [ -z $TARGETWIN ]; then
 notify-send -i face-crying "Can't find specified window!"
else
  ## use this to activate window
  #xdotool windowactive "$TARGETWIN"
  ## changes focus, does not change to the window on display
  xdotool windowfocus "$TARGETWIN"
  ## send keys if window was found
  for keypress in "$@"
  do
    xdotool key --window "$TARGETWIN" "$keypress"
  done
fi
## comment next line if focus should stay with activated window
xdotool windowfocus "$CURWIN"

Ma première version nécessitait ces fonctions et est fonctionnelle (ci-dessous), mais utilise un wrapper supplémentaire et nécessite que la fenêtre soit active. La version de xdotool n’exige pas cela.

Cela nécessite xautomation libnotify-bin et wmctrl

c'est ~/bin/activate_window_and_send_keys scipt Pour faire ce que vous voulez de cmdline, appelez ceci avec

# this is press ctrl, a, 1, release ctrl
~/bin/activate_window_and_send_keys "gnu screen" "ctrl+a+1"
# this is press ctrl, a, release ctrl, 1
~/bin/activate_window_and_send_keys "gnu screen" "ctrl+a" "1"

N'oubliez pas de chmod u + x sur vos scripts ~/bin/*

#!/bin/bash
## copy these files to ~/bin (~ = is your home directory)
### finding window
## requires wmctrl
### notify
## libnotify-bin
### tool to send keypresses
## requires xautomation

# Usage:
# ~/bin/activate_window_and_send_keys "window title" "keys" "morekeys" ...
# ~/bin/activate_window_and_send_keys "gnu screen" "ctrl+a+1"

export PATH=$PATH:~/bin


## helper function to find correct window
## modified version of Mostafa Najafiyazdi answer
## http://askubuntu.com/a/637897/41757
function find_window_and_activate_window {
  # Get the list of all windows
  # and select the line containing a substring given as
  # an argument to the script
  title=$1
  window_found=`wmctrl -l | grep "$title" | awk '{print $3}'`
  # If nothing is found, echo a message
  if [ -z "$window_found" ]; then
    notify-send -i face-crying "Can't find specified window!"
    return -1
  else
    wmctrl -a "$title"
  fi
}

title=${1:-NOT_FOUND_EMPTY_TITLE}
shift
echo "$title"
find_window_and_activate_window "$title" && {
   ## send keys if window was found
   for keypress in "$@"
   do
     sendkey "$keypress"
   done
}

Ceci est ~/bin/sendkey C'est simplement un wrapper autour de xte pour simplifier la syntaxe xte

#!/usr/bin/Perl

my @keys=@ARGV;
for my $key (@keys) {
  my @keycomb=split(/\+/, $key);
  my $k = pop(@keycomb);
  #print "$k\n";
  my $modup   = "";
  my $moddown = "";
  my $press   = " 'key $k' ";
  for my $m (@keycomb) {
    $m =~ s/ctrl/Control_L/gi;
    $m =~ s/alt/Alt_L/gi;
    $m =~ s/shift/Shift_L/gi;
    $moddown = $moddown.' "keydown '.$m.'"';
    $modup   = ' "keyup '.$m.'"'.$modup;
  }
  system("xte $moddown $press $modup");
}
1
Manwe

La première chose qui me vient à l’esprit est de casser ce que vous voulez faire en deux parties:

  1. Ecrire une fonction bash qui recherche une fenêtre intitulée ce que vous voulez, ce serait pour vous un "écran de gnou", sinon, un message disant "Impossible de trouver la fenêtre de destination!" Pour cela, vous devez d’abord installer wmctrl

    Sudo apt-get install wmctrl
    

    Il s’agit d’un contrôleur Windows que vous pouvez utiliser pour obtenir des informations Windows, notamment son PID, son titre, sa position, sa taille, son numéro de bureau, etc. Ajoutez le code suivant dans votre .bash_aliases:

    function find_window {
      # Get the list of all windows 
      # and select the line containing a substring given as 
      # an argument to the script
      title=$1
    
      window_found=`wmctrl -l | grep $title | awk '{print $3}'`
    
      # If nothing is found, echo a message
      if [ -z "$window_found" ]; then
        notify-send -i face-crying "Can't find specified window!"
      else
        wmctrl -a $1
      fi
    }
    

    Vous pouvez modifier l'aspect de la notification. Il suffit de voir la page de manuel pour notify-send.

  2. Définissez un raccourci personnalisé à l'aide de vos paramètres système. Voir ici Ajoutez simplement find_window "gnu screen" comme commande à exécuter. Vous définissez les séquences du clavier comme vous le souhaitez.

EDIT: Si la fenêtre existe, elle basculera sur cette fenêtre! C'est ce que fait la else dans le if then else.

0