Archivo

Entradas Etiquetadas ‘teclado’

Creando macros de escritorio I: xmacroplay

Martes, 17 de Agosto de 2010 Gaspar Fernández Sin comentarios

Voy a hablar de dos programas para crear macros, aunque hay más, claro que sí. Los dos programas están basados en la grabación de acciones del servidor X y la simulación de movimientos del ratón, clicks y acciones de teclado.

En principio xmacroplay; lo podemos ejecutar así:

$ xmacrorec2 > mi_macro

donde mi_macro es el archivo donde vamos a grabar; este archivo, si vemos su contenido tendrá los comandos en un lenguaje muy sencillo e inteligible, lo que nos permite crear macros directamente programándolos, no grabándolos.
Lo primero que debemos hacer tras ejecutar xmacrorec2 es pulsar una tecla, ésta tecla será la que deberemos pulsar para detener la grabación.

Para ejecutar las macros, lo podemos hacer de la siguiente forma:

$ xmacroplay :0 < mi_macro

donde :0 es la pantalla, el DISPLAY y mi_macro es el nombre de la macro.

Aunque, al menos en la versión 20000911, la última descargable desde sf.net (del año 2001, un poco antigua), se lleva un poco mal con los arrastres de ratón; vamos para hacer macros con clicks bien, pero cuando arrastramos algo, a veces no se reproducen bien las opciones. Se debe a un bug en xmacroplay.cpp, en las siguientes líneas dentro de la función eventLoop(), hay que añadir el código que tiene comentario

1
2
3
4
5
6
7
8
9
10
11
12
13
14
else if (!strcasecmp("ButtonPress",ev))
        {
          cin >> b;
          cout << "ButtonPress: " << b << endl;
          XTestFakeButtonEvent ( RemoteDpy, b, True, Delay );
          XFlush ( RemoteDpy ); /* AÑADIR */
}
        else if (!strcasecmp("ButtonRelease",ev))
        {
          cin >> b;
          cout << "ButtonRelease: " << b << endl;
          XTestFakeButtonEvent ( RemoteDpy, b, False, Delay );
          XFlush ( RemoteDpy );/* AÑADIR */
        }

Con esta modificación todo debe ir bien, podemos, por ejemplo programar ciertas teclas en nuestro ordenador para automáticamente grabar y reproducir macros de teclado y ratón.

Aunque como dije antes, siempre podemos programar nosotros las macros a mano, o modificar lo que hemos grabado para un mejor comportamiento con los siguientes comandos:

  • MotionNotify X Y : Mueve el rató a un punto X,Y de la pantalla
  • ButtonPress N : Pulsa el botón N del ratón (1=izquierdo, 2=rerecho, 3=centro, 4,5=rueda del ratón en algunos sistemas, etc)
  • Delay N : Retrasa el script N segundos, deteniendo su ejecución un tiempo
  • ButtonRelease N : Suelta el botón N del ratón
  • KeyCodePress C : Pulsa la tecla con el código C (podemos usar xev para ver los códigos de teclas)
  • KeyCodeRelease C : Suelta la tecla con el código C
  • KeyStrPress S : Pulsa la tecla llamada S (Es el nombre de forma de cadena de caracteres, por ejemplo “Escape”, “F5″, “Control_L”, etc; podemos utilizar xev para ver los nombres también)
  • KeyStrRelease S : Suelta la tecla llamada S

Obtener UNA tecla

Domingo, 24 de Mayo de 2009 blakeyed 2 comentarios

Hace mucho tiempo, cuando empezaba con la programación, tenía la librería conio.h de Borland (en la que aún se siguen basando en muchos sitios), que nos permitía entre otras cosas borrar la pantalla, posicionarnos dentro de la pantalla, escribir con colores, y pedir una tecla al usuario.
Bien, vayámonos al último caso, pedir una tecla al usuario, se hacía con la función getch, y con sólo pulsar la tecla, salía de la función, es decir, no hacía falta pulsar enter.
Pero cuando nos vamos a linux, nos damos cuenta de que tenemos que utilizar getchar() y esa función estará pidiendo letras del teclado hasta que pulsemos enter.

Podemos optar por varias soluciones:

  1. Utilizar ncurses (que le da mil vueltas a conio.h)
  2. Si sólo queremos algo puntual, la que os propongo a continuación

La solución la encontré hace un tiempo y la tenía por aquí archivada, y la primera publicación del código que he encontrado ha sido esta por kermi3, la función original la publicó VvV.

La solución que propongo tiene un pequeño cambio en el que podemos elegir si queremos que se muestre dicha tecla pulsada o no (echo), y está comentada:

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
#include <stdio.h>
#include <termios.h>
#include <unistd.h>

int mygetch(int echo)
{
  struct termios oldt, newt;
  int ch;

  /* Obtenemos atributos del terminal */
  tcgetattr( STDIN_FILENO, &oldt );
  newt = oldt;
  /* Eliminamos el modo canónico: caracteres especiales */
  newt.c_lflag &= ~ICANON;
  /* Eliminamos el echo a voluntad */
    if (!echo)
      newt.c_lflag &= ~ECHO;
  /* Definimos los nuevos atributos al terminal */
  tcsetattr( STDIN_FILENO, TCSANOW, &newt );
  ch = getchar();
  /* Ponemos los atributos como estaban al principio */
  tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
  return ch;
}

int main()
{
  int tecla;
  printf("Pulsa una tecla (sin echo): ");
  tecla=mygetch(0);
  printf("\nHas pulsado la tecla %c (%c)\n", tecla, tecla);

  printf("Pulsa una tecla (con echo): ");
  tecla=mygetch(1);
  printf("\nHas pulsado la tecla %c (%c)", tecla, tecla);
}

La incluiré en la próxima revisión de strutils.

Categories: C/C++, Linux Tags: , , , , ,

Buffer de teclado en linux

Sábado, 23 de Mayo de 2009 blakeyed 1 comentario

A veces, mientras se está desarrollando un pequeño programa en C en el que hay entradas del usuario por teclado, hay veces que parece que se pulsan teclas solas, esto es debido a una entrada de teclado anterior que no ha llegado a volcarse entera en nuestras variables.
En principio tenemos fflush(), es una función para el volcado de buffer de escritura, escritura de ficheros o escritura en la pantalla; pero bueno, funciona cuando hacemos fflush(stdin) y compilamos en Windows, pero no en Linux… tenemos un par de soluciones (aunque seguro que se nos ocurren muchas más):

  1. __fpurge() - Aunque no es una función estandar, y en alguna ocasión me ha dado algún problema (no ha hecho su trabajo como debía).
  2. La otra solución, parece un poco más rudimentaria, pero no me ha dejado tirado:
1
2
int ch;
while ((ch = getchar()) != '\n' && ch != EOF);
Categories: C/C++, Linux Tags: , , , ,

Visita otras webs de la red