Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
[X11] Contrôler X avec l'extension XTest
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index French
View previous topic :: View next topic  
Author Message
TGL
Bodhisattva
Bodhisattva


Joined: 02 Jun 2002
Posts: 1978
Location: Rennes, France

PostPosted: Mon Nov 14, 2005 1:33 am    Post subject: [X11] Contrôler X avec l'extension XTest Reply with quote

Bon alors, puisqu'on peut se servir de ce forum pour remettre à plat les conclusions de discussions qu'on a trouvées intéressantes, voilà un petit résumé des évènements de ce topic, initié par LostControl qui se demandait comment zoomer sous Xorg, comme avec un Ctrl+Alt+Plus, mais depuis une simple commande, sans clavier.


L'extension XTest

L'extension XTest est une extension X11 qui permet de générer des évenements, comme des pressions de touches du clavier ou des mouvements de souris. C'est vraiment une extension "de base" sous Xorg ou XFree, et il est à peu près certains qu'elle est déjà prête à l'emploi chez vous. Cette commande vous le confirmera :
Code:
grep -i xtest /var/log/Xorg.0.log


Les évenements XTest se distinguent de ceux qu'on utilise habituellement avec la Xlib en ça qu'ils ne sont pas destinés à une fenêtre/application particulière, mais au serveur X lui même. Ce sont donc des évenements de bas niveau, en toute chose similaires à ceux provenant d'un vrai périphérique, et qui suivront les même étapes de traitement ensuite.
Cette différence est importante dans l'exemple qui nous intérresse : si on génère, façon Xlib, un "Ctrl+Alt+Plus" à destination par exemple de la fenêtre qui a le focus, ça ne va provoquer un zoom de X, mais juste une tentative de raccourcis clavier pour l'application concernée.

On peut retrouver une documentation officielle de XTest par exemple ici.


Utiliser XTest en C

La première solution pour cette affaire de zoom de X a été trouvée en quelques lignes de C, inspirées par le programme numlockx, qui se sert lui de XTest pour générer un évenement clavier de "vérouillage du pavé numérique". Voilà donc xzoom.c dans sa version écrite par LostControl :
Code:
#include <stdio.h>
#include <string.h>
#include <X11/extensions/XTest.h>
#include <X11/keysym.h>

#define NBR_KEYS 3

void executeKeys(Display *disp, unsigned int *keys, int length) {
   int i;
   /* press */
   for (i=0; i<length; i++) {
      XTestFakeKeyEvent(disp, XKeysymToKeycode(disp, keys[i]), True,
                  CurrentTime);
   }
   /* release */
   for (i=length-1; i>=0; i--) {
      XTestFakeKeyEvent(disp, XKeysymToKeycode(disp, keys[i]), False,
                  CurrentTime);
   }
}

int main(int argc, char **argv) {
   Display* disp = XOpenDisplay(NULL);
   unsigned int zoom_in[NBR_KEYS] = {XK_Control_L, XK_Alt_L, XK_KP_Add};
   unsigned int zoom_out[NBR_KEYS] = {XK_Control_L, XK_Alt_L, XK_KP_Subtract};
   if (disp == NULL) return 1;
   if (argc != 2) {
      printf("Please specify a parameter: in|out\n");
      return 1;
   }
   if (strcmp(argv[1], "in") == 0) {
      executeKeys(disp, zoom_in, NBR_KEYS);
   } else if (strcmp(argv[1], "out") == 0) {
      executeKeys(disp, zoom_out, NBR_KEYS);
   } else {
      printf("Unknown parameter. Please specify a parameter: in|out\n");
   }
   XCloseDisplay(disp);
   return 0;
}
Ça se compile comme ça :
Code:
% gcc -o xzoom xzoom.c -lX11 -lXtst
...et ça s'utilise comme ça :
Code:
% ./xzoom in
(avec "in", on a l'équivalent d'un Ctrl+Alt+Plus, et avec "out", on aurait un Ctrl+Alt+Moins).


Utiliser XTest en Python

Une deuxième solution est d'utiliser le module Python Xlib (dans portage, dev-python/python-xlib). Voilà un petit programme d'exemple, xkeystroke :
Code:
#!/usr/bin/python
import sys
from Xlib import display, X, XK

def keystroke(sequence):
    global disp, valid_keys
    down_keycodes = []
    for key in sequence.split('+'):
        if key in valid_keys:
            keycode = disp.keysym_to_keycode(XK.string_to_keysym(key))
            disp.xtest_fake_input(X.KeyPress, keycode)
            down_keycodes.append(keycode)
        else: print >>sys.stderr, "%s: invalid key name" % key
    while down_keycodes:
        keycode = down_keycodes.pop()
        disp.xtest_fake_input(X.KeyRelease, keycode)

valid_keys = {}
for name in dir(XK):
    if name[:3] == 'XK_':
        valid_keys[name[3:]] = None

disp = display.Display()

for sequence in sys.argv[1:]:
    keystroke(sequence)
    disp.sync()
On peut lui demander de simuler n'importe quel séquence de touches clavier :
Code:
% ./xkeystroke Shift_L+a b Shift_L+c
AbC
La séquence "AbC" arrive ici jusqu'au xterm depuis lequel on a lancé le programme, parceque le serveur X n'a rien à faire de ces évenements, et donc il transmet au Window Manager, qui n'en a rien à faire non plus, et qui donc les transmet à la fenêtre ayant le focus, ici notre xterm, qui lui enfin les accepte et réagit.

Pour faire un "zoom in", on utiliserait :
Code:
% ./xkeystroke Ctrl_L+Alt_L+KP_Add
Notez qu'il faut utiliser des noms de touches valides pour Xorg (pour le "-" du pavé numérique, ça serait "KP_Substract").


Utiliser XTest sans le savoir

Avec un peu de retard (mais c'est tant mieux), on a en fait trouver un programme qui à pour vocation de générer des évennements via l'extension XTest. Il s'agit de x11-misc/xautomation, qui fournie la commande xte. Avec cette commande, notre "zoom in" pourrait s'écrire :
Code:
% xte 'keydown Control_L' 'keydown Alt_L' 'key KP_Add' 'keyup Alt_L' 'keyup Control_L'
Oui, c'est un peu long, mais c'est parcequ'on décompose chaque pression puis relâche des touches (sauf pour celle du milieu, 'key KP_Add' étant un raccourcis pour la séquence 'keydown KP_Add' 'keyup KP_Add'). Dans le cas du zoom, on peut bien sûr se faciliter un peu la tâche avec un petit script xzoom.sh qui prendrait juste "in" ou "out" en paramètre, et génèrerait les séquences de touches correspondantes :
Code:
#!/bin/bash

prog=$(basename "${0}")

xte=$(which xte 2>/dev/null)
if [[ -z "${xte}" ]] ; then
    echo "This scripts requires \"xte\" from \"x11-misc/xautomation\"" >&2
    exit 1
fi

mod_down[0]="keydown Control_L"
mod_down[1]="keydown Alt_L"
in[0]="key KP_Add"
out[0]="key KP_Substract"
mod_up[0]="keyup Control_L"
mod_up[1]="keyup Alt_L"
if [[ "${1}" == "in" || "${1}" == "out" ]]; then
    eval ${xte} \"\${mod_down[@]}\" \"\${${1}[@]}\" \"\${mod_up[@]}\"
else
    echo "Usage: ${prog} <in|out>" >&2
    exit 2
fi

Notez que le programme xte offre vraiment un accès très complet aux fonctionnalités de XTest, et permet aussi de générer par exemple des mouvements du curseur de la souris. Associé à visgrep, une autre commande du même paquet mais non liée à XTest elle et qui permet de trouver l'emplacement d'éléments graphiques à l'écran, on a ainsi une véritable solution pour automatiser des actions sur des GUI sous X.
Back to top
View user's profile Send private message
Enlight
Advocate
Advocate


Joined: 28 Oct 2004
Posts: 3519
Location: Alsace (France)

PostPosted: Tue Nov 15, 2005 10:31 am    Post subject: Reply with quote

Ah bah, grande classe les deux!!!
Back to top
View user's profile Send private message
Dominique_71
Veteran
Veteran


Joined: 17 Aug 2005
Posts: 1869
Location: Switzerland (Romandie)

PostPosted: Sun Jun 03, 2007 4:29 pm    Post subject: Reply with quote

Petite question bête et méchante: est-il possible de ne zoomer qu'une fenêtre avec ça? Chaque fois que j'essaie, cela fait la même chose que Ctrl-Alt-+.

Il y a une application qui fait presque cela, façon xmag mais en mieux: xzoom, et ses dépendances sont la glib et X. http://packages.debian.org/unstable/x11/xzoom
_________________
"Confirm You are a robot." - the singularity
Back to top
View user's profile Send private message
lalebarde
Guru
Guru


Joined: 03 Sep 2006
Posts: 464
Location: France, Haute-Garonne

PostPosted: Sun Oct 28, 2007 5:09 pm    Post subject: Reply with quote

:D :D :D Mille fois merci TGL ! :D :D :D .
Ca faisait une vingtaine d'heure cumulées que je recherchait ça sur la toile.
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index French All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum