jeudi 13 août 2015

GTK3 - attention à bien débuter, sinon vous risquez de perdre beaucoup de temps.


J'ai eu la faiblesse de croire que GTK, la librairie graphique sensée permettre de programmer facilement des applications graphiques, me ferait gagner du temps. Au départ, j'ai commencé à programmer avec Xlib (cad au niveau du serveur X Window). Par la suite, j'ai basculé mon développement en GTK (pour sa popularité et son ancienneté). Malheureusement, j'ai très vite déchanté: le gain de temps (cad en terme de réduction de code) ne fut pas évidente, car les appels aux fonctions à GTK sont finalement presque aussi nombreux que ceux à Xlib.

Mais le point le plus négatif fut le problème initialement sous-estimé des différentes versions de GTK. Pour faire simple, 3 versions majeurs de GTK ont donné lieu par deux fois, à un cortège de fonctions obsolètes ou disparues, et de modules remplaçant certains autres, et de concepts fondamentalement transformés. Le principal inconvénient concerne la documentation, mais surtout les différents exemples présents sur le Net. J'ai donc trop souvent perdu du temps à étudier un exemple de code écrit pour GTK1 ou GTK2, sans même le savoir, car trop souvent cette information n'est même pas mentionnée. On le découvre bien souvent lors de la compilation avec les options et librairies GTK3.

Ayant pris la décision dès le départ de développer en GTK 3, j'ai ainsi perdu trop d'énergie avec la documentation disponible sur le Net, qui très rarement ne concerne pas réellement GTK3. Idem pour les livres, qui bien souvent ne signale même pas le n° de version traitée par l'auteur.

Mon premier conseil: n'achetez pas de livre sur GTK dont la première édition date d'avant GTK3 (début 2011). Ils sont rares, voir inexistant. Sinon, vous risquez de perdre du temps à étudier des fondamentaux inutiles et de programmer avec des concepts de GTK2 (voir GTK1), dorénavant obsolètes.

Mon deuxième conseil est simple:
Pour étudier des exemples de code, n'utilisez que ceux présents sur gnome.org (ci-dessous). Malheureusement, tous les autres risquent de vous envoyer vers des solutions inadaptées, et de vous faire perdre beaucoup de temps. A noter que même sur les exemples GTK3 officiels, vous serez susceptible de rencontrer des fonctions obsolètes, car GTK3 évolue très rapidement.

Donc, ne perdez pas de temps (comme moi) avec des PDF ou documentation "offline" qui ne soit pas téléchargeable sur le site officiel, avec la dernière version en date. Oubliez donc dans un premier temps vos habitudes de recherche de code sur le Net "au petit bonheur la chance". Limitez-vous strictement vous au exemple de code du site officiel (ci-dessous). Tous les concepts y sont présents sans exception.

Et oubliez les conseils des anciens qui vous diront que GTK2 est bien suffisant, et que le passage de GTK2 vers GTK3 peut se faire à peu de frais. Les conseilleurs ne sont pas les payeurs.

Avec un peu de chance, vous ne perdrez pas les jours que j'ai pour ma part dépensé inutilement à cause de cela. Bonne continuation à vous.

Liens vers les exemples de code pour GTK3
Liens vers la référence pour GTK
Wiki concernant GTK


L'intelligence, c'est d'avoir raison la deuxième fois. Avoir raison la première fois, c'est simplement de la chance.

mardi 14 avril 2015

Ecran noir après une mise à jour ubuntu

Cela fait la deuxième fois, sur 2 machines différentes, et sur 2 Linux différents.  Après une simple mise à jour proposée par le logiciel de mise à jour intégré, impossible de rebooter normalement: écran noir.
La première fois, c'était sur un lubuntu, avec un PC de bureau. J'ai préféré réinstaller totalement le PC en question. Mais la deuxième fois, ce fut sur Xubuntu, et sur un portable Asus  relativement récent. Cette fois, j'ai préféré trouvé une solution ne nécessitant pas une réinstallation, et de perdre ainsi les différents profils ou logiciels déjà installés.

Voici donc ma solution, après quelques longues heures de tatonement et de recherches peu fructueuses sur le Net J'en profite tout de même pour rendre hommage à Linux pour sa modularité, et à sa communauté pour la quantité d'information disponible pour tous les publics.

Tout d'abord le contexte:

Portable Notebook Asus F200M-Bing
Xubuntu LTS 14.04.02
Date de la mise à jour fautive: 13/04/2015
Dernier kernel: linux 3.13.0.49
Précédent kernel : linux 3.13.0.39
Intel celeron N2840
VGA ValleyView Gen7

Dans cet état, mon notebook boootait normalement, sauf que j'avais un bel écran noir, et rien d'autre. Le disque dur ou le WIFI fonctionnait semble-t-il normalement. J'ai donc regardé sur le Net pour trouver une solution, avec un bagage de parfait néophyte (les informations ci-dessus ont été collectées après avoir glané différentes informations).

En résumé (et au lieu d'un compte rendu de nombreuses heures infructueuses), voici ma solution:

1- Activer le menu de Grub au démarrage.
Pour cela laisser appuyée la touche SHIFT (majuscule) pendant le boot.
Un menu en mode caractère devrait vous afficher 4 choix:
 Ubuntu
 Advanced options for Ubuntu
 Memory Test (....)
 Memory Test (.......)

2- Choisir l'option "options avancées"
Grub va ensuite vous proposer plusieurs "kernel", les derniers mis à jour logiquement. Il faut alors procéder par essais successifs, sans se poser de question. Personnellement, je les ai tous essayé. En mode recovery, tous fonctionnait. Sinon, les autres modes fonctionnaient, sauf pour le dernier kernel en date (qui est le kernel par défaut évidement).
Conclusion toute personnel: le dernier kernel en mode normal posait un problème (lapalissade tranquillisante).

3 - Supprimer le dernier kernel
en se référant à son nom, avec synaptic, en utilisant un kernel fonctionnel. L'avantage de synaptic, c'est que la suppression est automatique, et la gestion de Grub aussi semble-t-il. Il faut simplement le trouver dans les paquets déjà installés, avec le mot clé "linux-image" (avec un tiret). Après il faut le supprimer, prier, et rebooter. Pour ma part cela a fonctionné


J'avoue avoir rechercher un moyen de réparer le dernier kernel (en mode recovery), mais sans succès. Il faut savoir connaitre les limites d'un combat. Voici plusieurs pistes qui m'ont semblé prometteuses mais sans succès:

a- Réinstallation de xorg (en forçant): choux blanc.

b- Utilisation de l'installeur de driver graphique Intel, que l'on peut trouver facielement le Net. Malheureusement, cet installeur venait juste à l'instant (2 semaines avant) d'être déclaré incompatible avec ma distribution Ubuntu (14.04). C'est ballot. Les raisons de cette "deprecation" semblent lié à mon soucis, mais pas moyen de le déterminer à la lecture des posts traitant le sujet.

Pour finir, j'ai perdu beaucoup de temps à comprendre la logique de Grub (juste assez pour faire des essais). A signaler que même les raccourcis clavier CTRL-ALT-F1 ne fonctionnait pas (jusqu'à F7). En revanche, passer en aveugle la série CTRL-ALT-F1, permettait ensuite de faire un CTRL-ALT-SUPP salutaire pour rebooter relativement proprement après chaque essais infructueux de kernel dans Grub. J'ai aussi perdu du temps à modifier le paramétrage de Grub (GRUB_TERMINAL="console" et GRUB_CMDLINE_LINUX_DEFAUT="quiet")

Un grand merci à Grub, qui malgré son relativement manque d'ergonomie, m'a sauvé d'une perte totale en permettant un retour arrière.

Liens relatifs à cette problématique:

Explication de la non compatibilité de l'installateur Intel de pilote graphique pour linux

Grub et quelques explications

 Installateur (qui ne marche pas pour ma distribution)

PS: je regrette de ne pas avoir pu tester les options accessibles par la touche F6, en particulier l'option nomodeset, pour déterminer si cela aurait résolu mon soucis d'écran noir. Ce sera pour une prochaine fois:
Une belle explication de nomodeset
Une autre explication de la touche F6 et ses options

vendredi 10 avril 2015

Résoudre l'énigme "TOI+MOI+LUI=NOUS" .... en langage C

Il s'agit d'une petite énigme que les enfants s'échangent à la court de récréation (seulement les plus geek). L'énoncé est simple:

Il faut trouver les chiffres correspondant à chaque lettre de l'équation "MOI+TOI+LUI=NOUS", en faisant correspondre une et une seule lettre à chacune de ces huit lettre composant cette équation.

Par dépit vis à vis de ma fille qui m'a mis au défis, j'ai tenté de résoudre le code (cad la correspondance entre les lettres et les chiffres), en utilisant un outil informatique. J'avoue avoir perdu une bonne heure avec Excel, avant de m'apercevoir que le nombre de permutation (cad le nombre de possibilité de code différent à tester) était supérieur au million, ce qui dépasse le raisonnable dans une simple feuille de tableur.

J'ai donc refait l'exercice en langage C, pour tester une à une (de manière récursive pour le plaisir) chacune des près de 2 millions de possibilités. Pour rappel, les permutations possibles de codes différents pour résoudre l'équation se calcule comme cela: 10 x 9 x 8 x 7 x 6 x 5 x 4 x 3 (10 chiffres à répartir parmis 8 lettres, dans tous les ordres possibles). Mon erreur de débutant fut au début de confondre les combinaisons et les permutations (c'est évident après coup, et encore plus après avoir perdu une heure sur cette erreur). Pour rappel, les combinaisons de 8 chiffres parmi 10 sont seulement de 45.


Pour ceux que cela intéresse, le code est en pièce jointe, avec les fichiers de compilation sous linux.
Le résultat des courses: il existe 216 solutions à cette équation. Pour finir, je me suis amusé à étudier les combinaisons les plus prolixes parmi les 45 possibles, cette fois avec un tableur, en quelques minutes. Cela donne 18 solutions pour une seule combinaison de chiffres. Et le chiffre le plus représenté parmi les 216 solutions de code est le "1" (204 fois sur 216 tout de même). Je l'aurais parié. Mais c'est encore mieux de le prouver par la démonstration, avec un compilateur C et un tableur.

Parfaitement inutile, donc totalement indispensable.


0 1 2 3 4 5 6 7 8 9
nb de solution 216
1 1 1 1 1 1 1 1 0 0 1111111100 6
1 1 1 1 1 1 1 0 1 0 1111111010 0
1 1 1 1 1 1 0 1 1 0 1111110110 6
1 1 1 1 1 0 1 1 1 0 1111101110 0
1 1 1 1 0 1 1 1 1 0 1111011110 6
1 1 1 0 1 1 1 1 1 0 1110111110 0
1 1 0 1 1 1 1 1 1 0 1101111110 0
1 0 1 1 1 1 1 1 1 0 1011111110 0
0 1 1 1 1 1 1 1 1 0 0111111110 6
1 1 1 1 1 1 1 0 0 1 1111111001 6
1 1 1 1 1 1 0 1 0 1 1111110101 6
1 1 1 1 1 0 1 1 0 1 1111101101 6
1 1 1 1 0 1 1 1 0 1 1111011101 6
1 1 1 0 1 1 1 1 0 1 1110111101 6
1 1 0 1 1 1 1 1 0 1 1101111101 0
1 0 1 1 1 1 1 1 0 1 1011111101 0
0 1 1 1 1 1 1 1 0 1 0111111101 12
1 1 1 1 1 1 0 0 1 1 1111110011 6
1 1 1 1 1 0 1 0 1 1 1111101011 0
1 1 1 1 0 1 1 0 1 1 1111011011 12
1 1 1 0 1 1 1 0 1 1 1110111011 0
1 1 0 1 1 1 1 0 1 1 1101111011 6
1 0 1 1 1 1 1 0 1 1 1011111011 0
0 1 1 1 1 1 1 0 1 1 0111111011 6
1 1 1 1 1 0 0 1 1 1 1111100111 12
1 1 1 1 0 1 0 1 1 1 1111010111 18
1 1 1 0 1 1 0 1 1 1 1110110111 6
1 1 0 1 1 1 0 1 1 1 1101110111 6
1 0 1 1 1 1 0 1 1 1 1011110111 6
0 1 1 1 1 1 0 1 1 1 0111110111 18
1 1 1 1 0 0 1 1 1 1 1111001111 0
1 1 1 0 1 0 1 1 1 1 1110101111 6
1 1 0 1 1 0 1 1 1 1 1101101111 0
1 0 1 1 1 0 1 1 1 1 1011101111 0
0 1 1 1 1 0 1 1 1 1 0111101111 12
1 1 1 0 0 1 1 1 1 1 1110011111 0
1 1 0 1 0 1 1 1 1 1 1101011111 6
1 0 1 1 0 1 1 1 1 1 1011011111 6
0 1 1 1 0 1 1 1 1 1 0111011111 6
1 1 0 0 1 1 1 1 1 1 1100111111 6
1 0 1 0 1 1 1 1 1 1 1010111111 0
0 1 1 0 1 1 1 1 1 1 0110111111 12
1 0 0 1 1 1 1 1 1 1 1001111111 0
0 1 0 1 1 1 1 1 1 1 0101111111 0


Le paquet Kado contenant le source et les résultats.





mardi 14 octobre 2014

Excel: comment afficher dans une case le libellé de sa colonne avec le format A, B, ...AA, AB, ...

Voici un petit exercice pour se dégourdir l'esprit:
comment afficher dans une case, le libellé de la colonne de cette case, avec le format A, B, C, ...., Z, AA, AB, .....
J'ai eu besoin de cette fonction pour réaliser l'inventaire des colonnes d'un tableau. En d'autre terme, j'avais besoin de faire correspondre à chaque libellé de colonne, son libellé de colonne Excel.
Malheureusement, la fonction "=colonne()" sans argument est parfaite pour obtenir le n° d'indice de la colonne (à partir de 1), mais pas pour obtenir l'équivalent du format traditionnel, à savoir A, B, C, etc....

Pour cela, j'ai choisi de traduire le numéro d'indice de la colonne en base 26 (car il y a 26 lettres dans notre alphabet, de A à Z). Par simplicité, l'opération se fait en deux temps. Sur une première case, je récupère le numéro d'indice, c'est dire le résultat de la fonction "=COLONNE( )". Ci dessous, on peut voir que j'obtiens 3 pour la colonne C, 4 pour la colonne D, etc...
Ensuite, sur la case juste en dessous de la première contenant le n° d'indice de la colonne, j'utilise cette formule:

=SI(C1 < 27;CAR(64+C1);CAR(ENT((C1-1)/26)+64) & CAR(MOD(C1-1;26)+65))

Explications:
  • 65 est le code ASCII de la lettre majuscule "A".
  • MOD( ), la fonction qui donne le reste de la division entière (cad modulo).
  • ENT( ), la fonction qui donne la partie entière d'une division.
  • CAR( ), la fonction qui renvoie le caractère d'un code ASCII: CAR(65)='A'
Remarque importante:
Cette fonction n'est valable que pour le valeurs d'indice de 1 à 26*26 (cad 676). Pour les colonnes au delà de 676, je vous laisse libre de trouver soit une autre formule, soit la même en ajoutant un étage supplémentaire de "=SI( C1 < 677 ; ..... )" .

En résumé, voici les deux formules pour les 676 premières colonnes.
Formule en C1: =COLONNE( )
Formule en C2: =SI(C1 < 27;CAR(64+C1);CAR(ENT((C1-1)/26)+64) & CAR(MOD(C1-1;26)+65))

A votre bon cœur pour trouver une formule plus élégante, car il faut bien l'admettre, celle que je propose étant plutôt rustique.

vendredi 28 mars 2014

Paramétrer un lecteur code barre Sumikon (de chez Pearl)

Acheter un lecteur code barre a toujours été une idée que j'ai repoussé à cause du prix. Heureusement, les prix de ces lecteurs se sont démocratisés. J'ai acheté le mien pour 39€.


Malheureusement, il n'a pas voulu fonctionner, loi de Murphy oblige. J'ai perdu pas mal de temps pour y arriver. Le symptôme était simple: à chaque fois que je scannais un code barre de livre ou de CD (constitué de 13 digits), j'obtenais à la place une série de lettres.

J'ai donc fait une demande au support de mon vendeur, sans succès: celui-ci m'enjoignait de paramétrer mon lecteur code barre en majuscule, ce qui n'a eu aucun effet positif, mis à part récupérer la même série de lettres mais cette fois en majuscules.

Ma méthode pour trouver le bon paramétrage fut d'essayer systématiquement tous les codes de paramétrages imprimés dans le livret "mode d'emploi". Voici la méthode:

- Ouvrir un éditeur de texte pour afficher chaque test de lecture d'un code barre (un livre par exemple, et toujours le même évidement).
- A chaque test, je scanne  "Paramétrages d'usine".
- Je scanne"Démarrer réglages"
- Je scanne alors un paramètre (un à la fois dans un premier temps, et l'un après l'autre)
- Je scanne"Arrêter réglages"
- Je teste à nouveau (dans l'éditeur de texte)
- Si j'obtiens encore des lettres, je recommence avec un autre paramétrage (sans oublier "Paramètres d'usine")

Voici donc la solution qui m'a permis de résoudre mon soucis:
  • je scanne  "Paramétrages d'usine".
  • Je scanne"Démarrer réglages"
  • Ensuite paramétrage "Francais" page 48 de mon livret mode d'emploi.
    Ce paramétrage est dans la catégorie "réglages de base", sous rubrique "réglage de la langue".
  • Pour finaliser, paramétrage du caractère de fin de lecture: "CR"
    (au lieu de "CR-LF")
  • Puis "Arrêter réglages"
  • Penser à scanner la fonction "Enregistrer réglages" à la fin, sous peine de devoir recommencer ce paramétrage lors du prochain branchement du code barre.

Et depuis, ce lecteur de code barre est un véritable plaisir. Je regrette d'avoir attendu si longtemps, tant le gain de temps est significatif. Je signale que j'utilise ce code barre sous lubuntu (linux) sans aucun soucis. Je vais pouvoir travailler dorénavant sur la saisie de mes collections de livres, CD, DVD et autres.

vendredi 21 mars 2014

Sudoku: aide à la résolution sous Libre Office Calc (plutôt qu'Excel)

Une des choses qui caractérise un véritable geek, c'est sa manière de résoudre des problèmes simples à l'aide de solutions complexes.
C'est pour cela que je me suis donné comme objectif de résoudre un Sudoku, à l'aide d'un tableur (Libre Office Calc plutôt qu'Excel). Avec une contrainte (sinon c'est pas drôle): ne pas utiliser le langage de programmation du tableur. C'est donc à l'aide des fonctions natives du tableur (exemple RechercheV), et de la mise en forme conditionnelle (Exemple, colorer en rouge les doublons d'une grille).
Et voilà le résultat, après une bonne journée de travail (avec l'age on apprécie prendre son temps). J'ai surtout dû réapprendre à utiliser Libre Office Calc.


Le fichier est réalisé avec Libre Office Calc (v4.1.5.3). Il contient 3 onglets:
  1. Onglet "grille"=> à remplir uniquement avec la grille de départ
  2. Onglet "vérification" =>C'est cette grille qu'il faut remplir et qui permet en temps réel de vérifier l'absence de doublons
  3. Onglet "possibilités" => cet onglet permet de 'tricher' en affichant les cases faciles à remplir

Il doit rester quelques bugs, mais globalement il fonctionne. Il reste encore quelques cases inutiles (suite à des essais itératifs), mais l'essentiel est opérationnel. Je vous entend déjà dire qu'en C ou en PHP, on aurait pu le faire plus simplement. Mais parfois, c'est justement dans l’adversité que l'on trouve du plaisir.
A noter que ce fichier n'est pas compatible Excel (il pourrait l'être à peu de frais). Mais je préfère des outils pérennes dans leur forme et leur ergonomie, contrairement à Microsoft qui tous les 3 ou 4 ans révolutionne les deux sans aucune justification, mettant dans la panade des millions d'utilisateurs. Ce fichier Suduko sera ma petite contribution pour tenter de désintoxiquer les utilisateurs de MS Office.

Fichier pour résoudre un Suduko (à télécharger)
Règles du Sudoku

mercredi 1 janvier 2014

Xlib, C magnifique (avec l'exemple de WM_NAME)

Et oui, je suis membre de la petite minorité de personne aimant programmer directement en X11 avec Xlib. Je ne suis pas un foudre de programmation, mais plutôt un dilettante de la programmation C. Le fait d'utiliser Xlib directement est pour moi comparable à faire un Sudoku: C'est long, parfois ennuyeux, toujours sources d'erreur, magnifiquement vain, mais tellement distrayant. On peut ainsi passer une journée entière pour parvenir simplement à afficher une simple fenêtre à l'écran avec Xlib. Pour résumer, Xlib est une API (liste de fonctions) permettant de programmer pour X Windows et dont la dernière version est la version nommée X11.

Xlib est pour distrayante, car elle oblige à devoir passer un temps fou sur la toile pour glaner quelques infos ou tutoriels, car contrairement aux librairies graphiques plus évoluées (exemple GTK, Xt, Qt), on doit lire des pages et des pages de sites ou de documentation avant de comprendre le début d'une explication pour les choses les plus simples.

Prenons l'exemple par exemple d'une fonction permettant de déterminer le nom d'une fenêtre X (au sens X11 évidement). Cette simple fonctionnalité est déjà toute une histoire, car on doit s'intéresser à un élément périphérique à X11: le Window Manager (WM pour les initiés ou pour les amis les plus proches). Le WM est le chef d'orchestre des fenêtres dans X11. Il possède évidement des privilèges spécifiques lui permettant d’exécuter les tâches qui lui sont dévouées, comme par exemple gérer la barre de titres et différentes "décorations" associées à une fenêtre (cette fois au sens du WM).

Dans mon cas personnel, j'utilise le WM le plus simple, celui qui est inclus à Lubuntu: OpenBox. Normalement, l'usage des nom des fenêtres (ceux qui apparaissent par exemple dans le gestionnaire de taches par exemple), n'est pas tributaire de votre WM. En théorie, l'exemple suivant devrait fonctionner quelques soit votre WM.

Donc voici le résultat de mes recherches: une fonction C permettant de récupérer les noms de chaque fenêtre actives dans X:

/*----------------------------------------------
 * Fonction récupérant le nom d'une fenêtre
 * retour=0 si problème
 * sinon retour=1
 * Le nom_fentre est un buffer fourni par l'appelant
 * dont la longueur est spécifié en argument
 * --------------------------------------------*/
int X11vb_recuperer_nom_fenetre( Display * d, Window w, char * nom_fenetre, int nb_c_nom_fenetre)
{
char **liste;
int i=0;
XTextProperty text_property;

if (nb_c_nom_fenetre<1 class="Apple-tab-span" span="" style="white-space: pre;">
return 0; nom_fenetre[0]=0;

//---- récupération de la property texte WMName
if(!XGetWMName (d, w, &text_property))
{
return 0;
}
if (!XTextPropertyToStringList( &text_property, &liste, &i))
{
printf("XStringListToTextProperty - out of memory\n");
return 0;
}
if (!i)
{
printf("XTextPropertyToStringList=>liste=0\n");
return 0;
}
if (!*liste)
{
printf("XTextPropertyToStringList=>liste[0]=vide\n");
return 0;
}
//------ copie du résultat
strncpy(nom_fenetre, *liste, nb_c_nom_fenetre);
nom_fenetre[nb_c_nom_fenetre-1]=0;
XFreeStringList(liste);
return 1;
}

Pour l'utiliser, voici un source additionnel pour par exemple lister les fenêtres qui possède un nom (et oui, toutes les fenêtre n'ont pas de nom, et pourtant nullement orpheline).

#include
#include
#include
#include
#include
#include



int X11vb_recuperer_nom_fenetre( Display * d, Window w, char * nom_fenetre, int nb_c_nom_fenetre);

// ERROR HANDLER, GENERIC
static int ErrorHandler (Display *display, XErrorEvent *error)
{
   //printf ("\r\n error! \r\n");
   return 0;
}
// END ERROR HANDLER



void ListerWindows (Display *display, Window window, int niveau, char * filtre)
{
static int nb_w=0;
Window parent;
Window root;
Window *enfant;
XWindowAttributes windowattr; 
int nb_enfant=0;
int i=0, h=0, l=0, x=0, y=0;
char nom_fenetre[40]; //---le nom de la fenêtre affiché sera limité à 39 caract.
   
if (filtre) if (!*filtre) filtre=NULL;

//-----récupérer le nom de la fenêtre
if (!X11vb_recuperer_nom_fenetre(display, window, nom_fenetre, sizeof(nom_fenetre)))
*nom_fenetre=0; ;
//---- attributs de la fenêtre
if (XGetWindowAttributes(display, window,   &windowattr) == 0)
printf("failed to get window attributes");
else
{
x= windowattr.x;
y= windowattr.y;
l= windowattr.width;
h= windowattr.height;
}
// les enfants de cette fenêtre----
if (!XQueryTree (display, window, &root, &parent, &enfant, &nb_enfant))
nb_enfant=0;
if (*nom_fenetre)
{
if (!filtre || strstr(nom_fenetre, filtre)) 
printf ("%03i (niv.=%i; enfant=%i) - window: '%s' (x=%i,y=%i;L=%i,H=%i) w=%i\r\n", ++nb_w, niveau,nb_enfant, nom_fenetre, x,y,l,h,(int)window);
}

for (i=0; i < nb_enfant; i++)
ListerWindows (display, enfant[i], niveau+1, filtre);
   
XFree ((char*) enfant);
}


int main(int argc, char *argv[])
{
   // CONNECT TO THE XSERVER
   Display *display;
   int depth;
   int screen;
   int connection;
   char *filtre=NULL;
   Window rootWindow;
      
   display= XOpenDisplay (NULL);
   screen= DefaultScreen (display);
   depth= DefaultDepth (display, screen);
   connection= ConnectionNumber (display);
   XSetErrorHandler (ErrorHandler);
   
   printf ("Lister X11 window ayant un nom pour le Window Manager (WMName)\r\n");
   printf ("--------------------------------------------------------------\r\n");
   printf ("Display: %s\r\n", XDisplayName((char*)display));
   printf ("Width: %d\r\n", DisplayWidth(display, screen));
   printf ("Height: %d\r\n", DisplayHeight(display, screen));
   printf ("Connection: %d\r\n", connection);
   printf ("Color Depth: %d\r\n", depth);
  
   
if (argc>1)
filtre= argv[1];
if (filtre)
printf("=====>filtre sur le nom des fenêtres contenant:%s\n",filtre);
else
printf ("--en option:\r\n--mettre en argument un filtre sur le nom\r\n");
rootWindow = RootWindow (display, screen);  
ListerWindows (display, rootWindow, 0, filtre);
XCloseDisplay (display);

return 0;
}


Pour ne rien oublier, voici le makefile que j'utilise. Vous pourrez donc le tester en réel sur votre machine linux, si votre gcc (compilateur C) est opérationnel.

liste_w: lister_w.c
gcc -o lister_w lister_w.c -L/usr/X11R6/lib -lX11

On peut remarquer à quel point cet exemple est délicieusement complexe pour une opération aussi élémentaire. Pour être complet sur la question, vous avez un utilitaire permettant globalement de faire la même chose en ligne de commande sous linux: xdotool. Un petit tour sur la page d'aide de cet utilistaire vous permettra d'en comprendre toute la puissance. Il peut par exemple vous permettre d'envoyer des touches 'clavier' vers une X window. xprop et xwinfo sont deux utilitaires qui complète xdotool.

Liens:
Excellente page Wiki sur Xlib
Livre important: Xlib programming manual Volume 1.
Page du source que j'ai adapté et adopté