IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Bibliothèques, systèmes et outils C Discussion :

[Xlib] Tester le fonctionnement d'une fonction de dessin


Sujet :

Bibliothèques, systèmes et outils C

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    74
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 74
    Points : 56
    Points
    56
    Par défaut [Xlib] Tester le fonctionnement d'une fonction de dessin
    Bonjour je fais un petit programme simple pour me faire la main en Xlib.
    J'ai n'ai pas rencontré de problème dans mes autres testes, mais dans celui ci le "dessin" ne s'affiche pas ...

    J'ai tenté "if !NULL", gdb (peut être mal utilisé) et des print de debug. Pas d'erreur lors de la compilation "gcc CHD.c -g3 -Wextra -pedantic -W -Wall -L /usr/X11R6/lib -lX11 -lm -o CHD" (seulement deux unused ... logique j'ai pas fini.), pas de segfault a la fermeture du programme. Avec ses testes tout semble fonctionner correctement pourtant mon carré jaune n'est toujours pas affiché ... étrange.

    Pour afficher le carré j'utilise "XFillRectangle" après avoir def "XSetForeground" en bleu et un fond en noir.
    Je ne poste pas le code car j'ai vraiment envie de trouver tout seul. Mais j'aimerais connaitre quel piste exploreriez vous pour trouver "l'erreur". Après pourquoi pas afin d'avoir des avis et corrections.

    Merci.

    PS : Même en compilant avec -ansi, je n'ai pas d'erreur intéressante pour mon problème.

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 370
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 370
    Points : 23 625
    Points
    23 625
    Par défaut
    Bonjour,

    Citation Envoyé par papaye0 Voir le message
    Je ne poste pas le code car j'ai vraiment envie de trouver tout seul. Mais j'aimerais connaitre quel piste exploreriez vous pour trouver "l'erreur". Après pourquoi pas afin d'avoir des avis et corrections.
    Poste-le quand même car les causes d'erreur possibles sont nombreuses. On tâchera de te mettre sur la voie sans dévoiler la clé du mystère tout de suite. Mais d'ici là :

    • Es-tu sûr que la connexion au serveur X est bien établie ? Dans le cas contraire, prends-tu en charge les cas d'erreur ou les ignores-tu silencieusement ?
    • X-Window est un serveur graphique à fenêtres. Est-ce que tu as déjà réussi à créer une fenêtre et à la faire afficher, ou éventuellement à récupérer un handle sur l'une d'entre elles, par exemple la fenêtre racine qui gère le fond de l'écran ?
    • X-Window est également un système à événements, donc avec une boucle principale à mettre en place autour de XNextEvent(). Il est assez fréquent qu'une série d'ordres envoyés au serveur ne soient effectivement pris en charge que lorsque le client se met officiellement en attente du prochain événement, signalant ainsi et de fait qu'il a fini.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    74
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 74
    Points : 56
    Points
    56
    Par défaut
    Tout ça c'est bon. Malheureusement.
    Je vous passe le code, mais attention hein pas de troll !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <X11/X.h>
    #include <X11/Xlib.h>
    #include <X11/Xutil.h>
     
    /* ---- Global ---- */
    int	   	scr;
    unsigned int	DIMw, DIMh, DIMp;
     
    Display		*dsp;
    Window		fen;
    XEvent		ev;
    GC		cg;
     
    /* ---- Prototypage ---- */
    void openWindow(void);
    void closeWindow(void);
     
    unsigned long int couleurDef(short int, short int, short int);
     
    void encre(unsigned long int);
    void fond(unsigned long int);
    void rectangleFull(int, int, int, int);
     
    void eventManager(void);
     
    /* ---- Main ---- */
    int main(void)
    {
        int windowW, windowH;
     
        openWindow();
        windowW = DIMw / 2;
        windowH = DIMh / 2;
     
        XStoreName(dsp, fen, "Utilisez (q) pour quiter");
     
        encre(couleurDef(0, 0, 255));
        rectangleFull(windowW / 4, windowH / 4, windowW / 2, windowH / 2);
     
        eventManager();
     
        return 0;
    }
     
    /* ---- Fonctions ---- */
     
    /* --- Fenetre --- */
    void openWindow(void)
    {
        unsigned long    cw;
        XGCValues   vg;
        XSetWindowAttributes    att;
     
        if((dsp = XOpenDisplay(NULL)) == NULL)
        {
    	fprintf(stderr, "Impossible d'accéder au périphérique d'affichage %s.\n", getenv("DISPLAY"));
    	exit(1);
        }
     
        scr = DefaultScreen(dsp);
        DIMw = XDisplayWidth(dsp, scr);
        DIMh = XDisplayHeight(dsp, scr);
        DIMp = XDisplayPlanes(dsp, scr);
     
        cw = CWBackPixel | CWBorderPixel;
        att.border_pixel = WhitePixel(dsp, scr);
        att.background_pixel = BlackPixel(dsp, scr);
     
        fen = XCreateWindow(dsp, RootWindow(dsp, scr), 0, 0,
        DIMw / 2, DIMh / 2, 4, DefaultDepth(dsp, scr), InputOutput, NULL, cw, &att);
     
        XSelectInput(dsp, fen, KeyPressMask);
     
        cg = XCreateGC(dsp, fen, 0, &vg);
     
        XMapWindow(dsp, fen);
    }
     
    void closeWindow(void)
    {    
        XFreeGC(dsp, cg);
        XDestroyWindow(dsp, fen);
        XCloseDisplay(dsp);
     
        printf("A+ mon pote !\n");
    }
     
    /* --- Couleurs --- */
    unsigned long int couleurDef(short int r, short int v, short int b)
    {
        return (r << 16 | v << 8 | b);
    }
     
    /* --- Decos/Formes --- */
    void encre(unsigned long int col)
    {
        XSetForeground(dsp, cg, col);
    }
     
    void fond(unsigned long int col)
    {
        XSetWindowBackground(dsp, fen, col);
        XClearWindow(dsp, fen);
    }
     
    void rectangleFull(int x, int y, int w, int h)
    {
        XFillRectangle(dsp, fen, cg, x, y, w, h);
    }
     
    /* --- Actions --- */
    void eventManager(void)
    {
        int close = 0;
     
        while(!close)
        {
    	XNextEvent(dsp, &ev);
     
    	if (ev.type == KeyPress)
    	{
    	    char buffer;
    	    int bufsize=1;
     
    	    XLookupString(&(ev.xkey), &buffer, bufsize, NULL, NULL);
     
    	    switch(buffer) {
    		case 'q':
    		    close = 1;
    		    closeWindow();
    		    break;
    		case 'p':
    		    break;
    		case 'm':
    		    break;
    	    }
    	}
        }
    }
    Oui je sais, les X divisions mes c'est pas le plus simple et encore moins le plus opti.
    Pas de commentaire, c'est juste un petit code pour m'entrainer et que je ne comptais pas partager.

    EDIT : Je suis sur que c'est encore un oublie à la con ...

    EDIT2 : TROUVÉ ? J'ai un problème avec mon "XNextEvent(dsp, &ev);".
    j'ai testé avec un :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    do
        { XNextEvent(dsp, &ev); }
    while(ev.type != ButtonPress);
    juste aven l'affichage de ma forme et ça marche ... Il me reste a comprendre le comportement que j'ai mal appréhendé !

    EDIT3 :
    C'est fou comme poster son problème sur un forum fait mijoter ...
    Comme un con, les fonctions d’affichage n'étaient pas dans ma boucle d'événement ...
    Je l'avais dit oublie à la con !

  4. #4
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 370
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 370
    Points : 23 625
    Points
    23 625
    Par défaut
    Citation Envoyé par papaye0 Voir le message
    C'est fou comme poster son problème sur un forum fait mijoter ...
    Tu as remarqué aussi ?

    Comme un con, les fonctions d’affichage n'étaient pas dans ma boucle d'événement ... Je l'avais dit oublie à la con !
    Ce n'est pas forcément aussi trivial que cela en avait l'air : tu as bien mappé ta fenêtre, puis appelé tes primitives graphiques, puis enfin appelé ta boucle d'événements. En théorie, ça aurait pu être valable. La solution venait surtout du fait qu'il fallait déjà attendre un événement CreateNotify puis, surtout, Expose pour indiquer que la fenêtre est visible, car les fenêtres n'ont pas de buffer caché par défaut, ce qui oblige les programmes à mettre en place une fonction « Repaint » dans à peu près tous les serveurs graphiques similaires.

    Écueil suivant : ces événements ne sont pas sélectionnés par défaut dans le masque des événements à recevoir. Par contre, ils vont être purgés quand même parce que tu lis les suivants. Ceci t'oblige quand même à presser une touche pour voir le résultat de ton travail.

    Enfin, en collant quelques sleep() aux bons endroits, on s'aperçoit que non seulement le serveur X n'honore les requêtes qu'à partir du moment où le client se met à l'écoute des événements, mais que cela est valable également pour la création des fenêtres et leur exposition avec XMapWindow(), ce qui signifie concrètement qu'après avoir mappé ta fenêtre, celle-ci n'est en réalité pas encore réputée exploitable. Elle ne le sera qu'après avoir accusé réception de son exposition en récupérant l'événement Exposure. Ce qui nous ramène alors au premier point.

    En conclusion, la solution du problème était :
    • Ajouter ExposureMask soit à XSelectInput(), soit directement aux attributs de la fenêtre que tu passes à XCreateWindow() (mais l'un ou l'autre car XSelectInput() a l'air d'écraser tout le masque précédent) ;
    • Faire au moyen un XNextEvent() après XMapWindow(), voire un XMaskEvent() de manière à aller chercher explicitement celui que l'on attend.

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    74
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 74
    Points : 56
    Points
    56
    Par défaut
    J'avais modifié mon script pour utiliser directement ma boucle. Mais après tes conseil je me suis re fait le man et ta solution bien plus propre fonctionne vraiment impec !

    Malheureusement je ne trouve pas la doc super pointu sur les explication, donc en parallèle si je peux me permettre. Pourrais tu me donner une petite def de ExposureMask et XMaskEvent (Lui encore est relativement explicite ...).

    j'avais résolu mon "problème", mais je préfère ta solution.

    Autre petite question rien a voir, mais je ne pense pas qu'elle mérite un sujet dédié.
    J'ai passé plusieurs semaines a tenté de faire des truc avec Qt car on me le ventait simple, au final en quelque temps avec le man de X11 j'arrive a faire plus de truc (le code posté est amputé de 600lignes qui ne concernait pas le problème). Mais avec "l'arrivé" de wayland les choses ne semble pas aussi simple ex: Wayland n'a pas d'api de dessin. Adieu les truc simple comme "XDrawLine()" ? Devrais je utiliser des truc aussi tordu et compliqué que Qt, et entrer dans le monde insupportable du toolBox ?

    Encore merci

    EDIT : J'avais juste besoin de me concentrer un peu ... j'ai tout compris de ExposureMask et XMaskEvent, pas besoin de définition. C'est top !

  6. #6
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 370
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 370
    Points : 23 625
    Points
    23 625
    Par défaut
    Citation Envoyé par papaye0 Voir le message
    J'ai passé plusieurs semaines a tenté de faire des truc avec Qt car on me le ventait simple, au final en quelque temps avec le man de X11 j'arrive a faire plus de truc (le code posté est amputé de 600lignes qui ne concernait pas le problème).
    C'est aussi mon impression. J'ai toujours trouvé la Xlib élégante malgré ses quelques incohérences sur certains points. À l'instar des systèmes UNIX en général, elle a été bien pensée ce qui lui a permis de rester efficace sur une longue durée sans devenir trop vite obsolète. Qt est un bon produit également mais comme beaucoup de solutions modernes, spécialement quand elles sont orientées objet, il permet de résoudre efficacement un problème immédiat mais se complexifie inévitablement, comme tout le reste, dès qu'un le projet se sophistique.

    Mais avec "l'arrivé" de wayland les choses ne semble pas aussi simple ex: Wayland n'a pas d'api de dessin. Adieu les truc simple comme "XDrawLine()" ? Devrais je utiliser des truc aussi tordu et compliqué que Qt, et entrer dans le monde insupportable du toolBox ?
    C'est trop tôt pour répondre, car je n'ai pas encore essayé Wayland suffisamment pour en parler en connaissance de cause. Par contre, pour ce que j'en ai lu, c'est un projet qui suit la tendance des logiciels libres modernes, spécialement sous Linux : il est principalement orienté pour les utilisations desktop actuelles et fait l'économie de tout ce qui faisait l'âme des anciens logiciels. L'exemple-type repris dans toutes les actualités est la disparition — dans le tronc commun — de la possibilité de communiquer avec un serveur Wayland à travers le réseau, chose qui se faisait de manière transparente avec l'implémentation de la XLib actuelle et qui était optimisé par bibliothèque elle-même quand le serveur était en local, ce qui représente la quasi-totalité des infrastructures utilisées aujourd'hui.

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    74
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 74
    Points : 56
    Points
    56
    Par défaut
    Merci pour ton temps et toute ces infos
    Je retourne bosser mon "logiciel".

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Tester l'existence d'une fonction
    Par narmataru dans le forum Shell et commandes GNU
    Réponses: 3
    Dernier message: 14/10/2010, 18h03
  2. [XL-2003] Fonctionnement d'une fonction de recherche
    Par IMPERIAL3187 dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 14/04/2009, 18h42
  3. Tester le lancement d'une fonction
    Par vva dans le forum Général JavaScript
    Réponses: 31
    Dernier message: 03/02/2009, 10h52
  4. Tester l'existence d'une fonction
    Par alen dans le forum MFC
    Réponses: 2
    Dernier message: 28/03/2007, 10h33
  5. tester la presence d'une fonction
    Par maxvador dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 24/10/2006, 13h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo