Forum Programmation.c Xlib - bords actifs - demande conseils

Posté par  (site web personnel) .
Étiquettes : aucune
0
14
août
2005
Depuis pas mal de temps, je trouve une fonctionnalité qui manque et qui existe depuis très longtemps chez macOS ... la possibilité d'executer certaines tâches lorsque la souris atteint un coin de l'écran.

Au début, il sagissait de choses simples comme mettre en veille (ou empêcher la mise en veille). Mais maintenant, on peut utiliser exposé, et je trouve ça très pratique.

Je voulais donc une petite application qui surveillait lorsque la souris atteint un bord et me permette d'executer certaines choses .. et comme je nai pas trouvé, je l'ai fait.
Je suppsoe que c'est bien imparfait car le c½ur du programme est une boucle infinie qui récupère la position de la souris pour la tester ... et si la souris atteint un bors, un petit programme externe est lancé (system()).
Il y a aussi le malloc pour la variable execute_programm passée en paramètre ... pour que ce paramètre survive entre les deux fonctions, je n'ai pas trouvé mieux (après des heures de Segfault) ...

Voila donc le programme:
#include <X11/Xlib.h>
#include <stdlib.h>
#include <stdio.h>

Display * display;
Window root;
int width=0;
int height=0;
int screen;
static char *execute_programm="==ERR==";

#define ERR_ARG 1
#define ERR_MEM 2
#define ERR_DISPLAY 3


void execute(char *id, int x, int y){
printf(" Detected: %s\n", id);
char *cmd = (char *) malloc(strlen(execute_programm)+strlen(id)+64);
if(cmd==NULL){
fprintf(stderr, "Can't allocate memory.\n");
exit(ERR_MEM);
}
sprintf(cmd, "%s %s %i %i", execute_programm, id, x, y);
printf(" Execute: %s\n", cmd);
system(cmd);
free(cmd);
}

int main(int argc, char *argv[]){
if(argc<2){
fprintf(stderr, "Must take at least 1 argument.\n");
exit(ERR_ARG);
}
execute_programm = (char *) malloc(strlen(argv[1]));
if(execute_programm==NULL){
fprintf(stderr, "Can't allocate memory.\n");
exit(ERR_MEM);
}
sprintf(execute_programm, "%s", argv[1]);
printf("Will execute: %s \n", "--");

display = XOpenDisplay(getenv("DISPLAY"));
if(display == NULL){
fprintf(stderr, "Can't open DISPLAY.\n");
exit(ERR_DISPLAY);
}
screen = DefaultScreen(display);
root = RootWindow (display, screen);
width = DisplayWidth (display, screen);
height = DisplayHeight(display, screen);

printf("Screen Number: %i\n", screen);
printf("Screen Width: %i Height: %i\n", width, height);

Window rootR;
Window childR;
int root_xR;
int root_yR;
int win_xR;
int win_yR;
unsigned int maskR;
# define x root_xR+1
# define y root_yR+1
while(1){
XQueryPointer(display, root, &rootR, &childR, &root_xR, &root_yR, &win_xR, &win_yR, &maskR);
printf("Mouse position x: %i y: %i\n", x, y);
if(x==1 && y==1) execute( "top-left" , x, y );
else if(x==1 && y==height) execute( "bottom-left" , x, y );
else if(x==1) execute( "left" , x, y );
else if(x==width && y==1) execute( "top-right" , x, y );
else if(x==width && y==height) execute( "bottom-right" , x, y );
else if(x==width) execute( "right" , x, y );
else if(y==1) execute( "top" , x, y );
else if(y==height) execute( "bottom" , x, y );
}
# undef x
# undef y
free(execute_programm);
XFree(display);
}


Compilez par:
gcc test.c -o test -L/usr/X11R6/lib -lX11

Le programme est en lui même assez simple et très verbeux.

Dernière chose: existe-il une commande shell qui permette d'afficher le menu des fenêtres de WindowMaker ?
  • # XEvent

    Posté par  . Évalué à 2.

    man XEvent

    Ton programme n'est pas entièrement mauvais, mais tu ne gères pas du tout les événements renvoyés par X-Window. L'idée générale est de configurer ta connexion au serveur X de façon à ce que celui-ci ne t'envoie que les événements qui t'intéressent, ici les mouvements de souris. Cette première phase rendra déjà beaucoup de temps au système. Ensuite tu te mets en attente d'un signe du serveur X avec XNextEvent().

    C'est en fait comme cela que fonctionnent tous les programmes X-Window, et d'une manière générale tous ceux qui utilisent une interface graphique commune. Une boucle principale, un test de la nature de l'événement avant d'appeler la routine correspondante, avant de retourner dans la boucle et attendre le prochain événement.
  • # wm

    Posté par  . Évalué à 2.

    il sagit plus souvent de fonctionnalités supportée ou pas par le wm,
    ainsi sous fvwm les fonctions EdgeCommand et EdgeLeaveCommand permettent d'associer ce que tu veux a de tels "evenements", eventuellement associés a une variable d'etat pour gerer les coins comme les bords :)

    potasser la doc de ton WM et eventuellement lui rajouter de telles possibilitées serait sans doute plus judicieux que de creer une Xeme
    app gerant cela.
  • # Bin ça existe déjà, mais ...

    Posté par  . Évalué à 2.

    ... pour Gnome:
    http://home.jesus.ox.ac.uk/~ecatmur/brightside/(...)

    Et même un paquet Debian:
    http://packages.debian.org/testing/gnome/brightside(...)

    Et non, ça marche pas avec Window Maker

    « Dernière chose: existe-il une commande shell qui permette d'afficher le menu des fenêtres de WindowMaker ? »

    Pas a ma connaissance, mais en simulant l'appuie sur la touche F12. Il me semble avoir vu un programme permettant de simuler la frappe d'une touche.
  • # Je veux pas chipoter mais ...

    Posté par  . Évalué à 3.

    Ne t'etonnes pas si tu as des segfault :

    execute_programm = (char *) malloc(strlen(argv[1]))


    et le caractère nul a la fin ?

    execute_programm = (char *) malloc(strlen(argv[1])+1)


    char *cmd = (char *) malloc(strlen(execute_programm)+strlen(id)+64);


    La je comprends pas le 64 a la fin ... si c'est pour les deux entiers si je calcule ca nous fait 10 caracteres ( voir 11 pour les negatifs ) l'entier donc la vingtaine les deux, les quelques espaces etc etc... on va dire la trentaine le tout ?.

    Bon je chipotte... ==================>[ ]

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.