Précédent   Forum du club des développeurs et IT Pro > Général Développement > Programmation système > Linux > GTK > GTK+
GTK+ Forum d'entraide sur le développement avec GTK+. Avant de poster -> FAQ GTK+
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 18/02/2013, 02h37   #1
Le Farfadet Spatial
Membre éclairé
 
Avatar de Le Farfadet Spatial
 
Inscription : avril 2008
Messages : 135
Détails du profil
Informations forums :
Inscription : avril 2008
Messages : 135
Points : 341
Points : 341
Par défaut GtkGLExtmm : crash au passage en plein écran

Salut à tous !

J’ai converti le deuxième tutoriel de NeHe sur OpenGL de telle sorte qu’il utilise GtkGlExtmm. Cependant, j’ai une bogue surprenante : sur mon ordinateur portable, utilisant le pilote libre pour processeur graphique Intel Sandy bridge mobile sur Debian Wheezy, tout ce passe bien. En particulier, je peux commencer immédiatement en mode plein écran.

En revanche, sur mon ordinateur fixe, qui utilise Flgrx toujours sur Debian Wheezy, si je peux basculer en (puis quitter le) mode plein écran à partir du moment où je commence en mode fenêtré, le serveur X crash (écran entièrement noir) si je veux commencer immédiatement en mode plein écran. Dans ce cas-là, plus possible d’obtenir une console virtuelle. Cependant, je suis certain que seul X crash, dans la mesure où j’entends encore la musique que j’écoutais éventuellement à ce moment-là et je peux me connecter par SSH sur l’ordinateur fixe depuis le portable (c’est ce que je fais pour reprendre la main).

Je ne sais pas trop comment résoudre le problème, je suis donc preneur de toute aide éventuelle.

Je génère le code à l’aide de CMake. Le fichier « CMakeLists.txt » associé se situe dans la racine du projet, tandis que tous les codes sont dans le sous-répertoire « src/ ».

Fichier « CMakeLists.txt » :

Code :
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
## Génération des tutoriels OpenGL de NeHe version Gtkmm.
 
cmake_minimum_required(VERSION 2.6)
 
project(Tutoriel1)
 
# Répertoire où placer l’exécutable.
set(EXECUTABLE_OUTPUT_PATH bin/${CMAKE_BUILD_TYPE})
# Nom de l’exécutable.
set(EXECUTABLE_NAME tutoriel1)
 
find_package(OpenGL)
 
find_package(PkgConfig)
 
pkg_check_modules(Glibmm glibmm-2.4>=2.4.0)
pkg_check_modules(GTKmm gtkmm-2.4>=2.4.0)
pkg_check_modules(GLExtmm gtkglextmm-1.2>=1.2.0)
link_directories(
        ${OPENGL_LIBRARY_DIRS}
        ${Glibmm_LIBRARY_DIRS}
        ${GTKmm_LIBRARY_DIRS}
        ${GLExtmm_LIBRARY_DIRS}
)
include_directories(
        ${OPENGL_INCLUDE_DIRS}
        ${Glibmm_INCLUDE_DIRS}
        ${GTKmm_INCLUDE_DIRS}
        ${GLExtmm_INCLUDE_DIRS}
)
 
file(
        GLOB_RECURSE
        source_files
        src/*
)
 
add_executable(
        ${EXECUTABLE_NAME}
        ${source_files}
)
 
target_link_libraries(
        ${EXECUTABLE_NAME}
        ${OPENGL_LIBRARIES}
        ${Glibmm_LIBRARIES}
        ${GTKmm_LIBRARIES}
        ${GLExtmm_LIBRARIES}
)
Fichier « src/erreurs.hpp » :

Code :
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
#ifndef ERREURS_HPP
#define ERREURS_HPP
 
/*
 * Exceptions pour la gestions des erreurs.
 */
 
#include <exception>
 
/* Espace de nommage pour la gestion des erreurs. */
namespace Erreurs {
/* -- Erreurs provoquées par l’interface graphique. ---------------------- */
  class ErreurInterface: public std::exception {
    public:
      /* Constructeur par défaut. */
      ErreurInterface () throw () {}
 
      /* Destructeur. */
      virtual ~ErreurInterface () throw () {}
 
      /* Génére le message d’erreur. */
      virtual const char* what () const throw () {
        return "une erreur s’est produite dans l’interface graphique";
      }
  };
 
/* -- Erreur lors de la configuration d’OpenGL. -------------------------- */
  class ErreurConfigurationGL: public ErreurInterface {
    public:
      /* Constructeur par défaut. */
      ErreurConfigurationGL () throw () {}
 
      /* Destructeur. */
      virtual ~ErreurConfigurationGL () throw () {}
 
      /* Génère le message d’erreur. */
      virtual const char* what () const throw () {
        return "erreur lors de la configuration d’OpenGL";
      }
  };
 
/* -- Erreur lors de la création du contexte OpenGL. --------------------- */
  class ErreurCreationContexte: public ErreurInterface {
    public:
      /* Constructeur par défaut. */
      ErreurCreationContexte () throw () {}
 
      /* Destructeur. */
      virtual ~ErreurCreationContexte () throw () {}
 
      /* Génère le message d’erreur. */
      virtual const char* what () const throw () {
        return "impossible de créer un contexte OpenGL";
      }
  };
 
/* -- Erreur à l’obtention du contexte OpenGL. --------------------------- */
  class ErreurObtentionContexte: public ErreurInterface {
    public:
      /* Constructeur par défaut. */
      ErreurObtentionContexte () throw () {}
 
      /* Destructeur. */
      virtual ~ErreurObtentionContexte () throw () {}
 
      /* Génère le message d’erreur. */
      virtual const char* what () const throw () {
        return "impossible d’obtenir le contexte OpenGL";
      }
  };
}
 
#endif  // #ifndef ERREURS_HPP
Fichier « src/fenetre.hpp » :

Code :
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
#ifndef FENETRE_HPP
#define FENETRE_HPP
 
/*
 * Définitions des classes gérants le fenêtrage OpenGL.
 */
 
#include <gtkmm/window.h>
#include <gtkmm/drawingarea.h>
#include <gtkglmm.h>
 
#include "erreurs.hpp"
 
/* Espace de nommage pour la gestion de l’interface. */
namespace Interface {
  /* Classe pour la zone de rendu OpenGL. */
  class GlDrawingArea: public Gtk::DrawingArea,
                       public Gtk::GL::Widget<GlDrawingArea> {
    public:
      GlDrawingArea ();
      virtual ~GlDrawingArea ();
 
    protected:
      /* -- Controleurs: */
 
      /* À l’initialisation de la fenêtre. */
      virtual void on_realize ();
 
      /* À la demande d’affichage. */
      virtual bool on_expose_event (GdkEventExpose* event);
 
      /* Au changement de taille de la fenêtre. */
      virtual bool on_configure_event (GdkEventConfigure* event);
  };
 
/* ----------------------------------------------------------------------- */
 
  /* Classe pour la fenetre principale. */
  class Fenetre: public Gtk::Window {
    public:
      Fenetre ();
      virtual ~Fenetre();
 
    protected:
      /* -- Controleurs : */
 
      /* Gestion des évènements clavier. */
      bool on_key_release (GdkEventKey* evenement);
 
      /* Lors du passage du mode fenêtré au mode plein écran. */
      bool on_window_state_event (GdkEventWindowState *pEven);
 
      /* -- Composant membre : */
 
      /* Zone de rendu OpenGL. */
      GlDrawingArea zoneRendu;
 
    private:
      /* Indique si on se trouve en mode plein écran. */
      bool enPleinEcran;
  };
}
 
#endif  // #ifndef FENETRE_HPP
Fichier « src/fenetre.cpp »

Code :
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
/*
 * Implémentations du fenêtrage OpenGL.
 */
 
#include <glibmm/error.h>
#include <cstdlib>
#include <GL/gl.h>
#include <GL/glu.h>
#include <sstream>
#include <gtkmm/messagedialog.h>
#include <gdk/gdkkeysyms.h>
 
#include "fenetre.hpp"
 
/* -- Constructeur par défaut de GlDrawingArea. -------------------------- */
Interface::GlDrawingArea::GlDrawingArea (): Gtk::DrawingArea () {
  /* Configuration d’OpenGL */
  Glib::RefPtr<Gdk::GL::Config> configuration;
 
  /* Tente d’ouvrir une espace à double tampon. */
  configuration = Gdk::GL::Config::create(Gdk::GL::MODE_RGBA   |
                                          Gdk::GL::MODE_DEPTH  |
                                          Gdk::GL::MODE_DOUBLE);
  if (!configuration) {
    /* Message d’avertissement. */
    std::stringstream message;
    message << "Impossible de configurer OpenGL en mode double tampon, "
            << "tente le mode simple tampon.\n";
    g_warning(message.str().c_str());
    /* Tente de configurer un tampon simple. */
    configuration = Gdk::GL::Config::create(Gdk::GL::MODE_RGBA  |
                                            Gdk::GL::MODE_DEPTH);
    if (!configuration) throw Erreurs::ErreurConfigurationGL ();
  }
 
  /* Donne accès à OpenGL au composant. */
  set_gl_capability(configuration);
}
 
/* -- Destructeur de GlDrawingArea. -------------------------------------- */
Interface::GlDrawingArea::~GlDrawingArea () {
}
 
/* -- Initialisation du contexte OpenGL. --------------------------------- */
void Interface::GlDrawingArea::on_realize () {
  /* D’abord l’initialisation standard. */
  Gtk::Widget::on_realize();
 
  if (!create_gl_context()) throw Erreurs::ErreurCreationContexte ();
  /* Fenêtre OpenGL. */
  Glib::RefPtr<Gdk::GL::Window> fenetreGl = get_gl_window();
  if (!fenetreGl) throw Erreurs::ErreurObtentionContexte ();
 
  fenetreGl->gl_begin(get_gl_context());
 
    /* Permet un joli ombrage. */
    glShadeModel(GL_SMOOTH);
 
    /* Fond noir. */
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 
    /* Mis en place du tampon de profondeur. */
    glClearDepth(1.0f);
    /* Mis en place du test de profondeur. */
    glEnable(GL_DEPTH_TEST);
    /* Le type de test de profondeur . */
    glDepthFunc(GL_LEQUAL);
 
    /* Très jolis calculs de perspective. */
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
 
  fenetreGl->gl_end();
}
 
/* -- À la demande  d’affichage de GlDrawingArea. ------------------------ */
bool Interface::GlDrawingArea::on_expose_event (GdkEventExpose* event) {
  /* Fenêtre OpenGL. */
  Glib::RefPtr<Gdk::GL::Window> fenetreGl = get_gl_window();
  if (!fenetreGl)  throw Erreurs::ErreurObtentionContexte ();
 
  fenetreGl->gl_begin(get_gl_context());
 
    /* Vide l'écran et le Z-Buffer (Depth Buffer : contient les informations
       de profondeur de chaque pixel). */
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    /* Repositionne la caméra. */
    glLoadIdentity();
 
    /* Bouge de 1.5 unités vers la gauche et de 6.0 unités vers l'intérieur
       de l'écran. */
    glTranslatef(-1.5f,0.0f,-6.0f);
 
    /* Dessiner un Triangle. */
    glBegin(GL_TRIANGLES);
      /* Point du haut. */
      glVertex3f( 0.0f, 1.0f, 0.0f);
      /* Point en bas à gauche. */
      glVertex3f(-1.0f,-1.0f, 0.0f);
      /* Point en bas à droite */
      glVertex3f( 1.0f,-1.0f, 0.0f);
    /* Le dessin du Triangle est fini */
    glEnd();
 
    /* Bouge de 3.0f unités vers la droite. */
    glTranslatef(3.0f,0.0f,0.0f);
 
    /* Dessin d'un quadrilatère. */
    glBegin(GL_QUADS);
      /* Haut Gauche. */
      glVertex3f(-1.0f, 1.0f, 0.0f);
      /* Haut Droite. */
      glVertex3f( 1.0f, 1.0f, 0.0f);
      /* Bas Droite. */
      glVertex3f( 1.0f,-1.0f, 0.0f);
      /* Bas Gauche. */
      glVertex3f(-1.0f,-1.0f, 0.0f);
    glEnd();
 
  fenetreGl->gl_end();
  fenetreGl->swap_buffers();
 
  /* Partie standard de la la procédure d’affichage. */
  return Gtk::Widget::on_expose_event(event);
}
 
/* -- Lorsque la fenêtre est redimensionnée. ----------------------------- */
bool Interface::GlDrawingArea::on_configure_event (GdkEventConfigure* event) {
  /* Fenêtre OpenGL. */
  Glib::RefPtr<Gdk::GL::Window> fenetreGl = get_gl_window();
  if (!fenetreGl)  throw Erreurs::ErreurObtentionContexte ();
 
  fenetreGl->gl_begin(get_gl_context());
 
    /* Choisir la matrice de projection. */
    glMatrixMode(GL_PROJECTION);
    /* Remettre a zéro de la matrice de projection. */
    glLoadIdentity();
 
    /* Calculer le ratio pour la perspective de la fenêtre. */
    gluPerspective(45.0f, static_cast<GLfloat>(get_width())
                            / static_cast<GLfloat>(get_height()),
                   0.1f,100.0f);
    /* Choisir la matrice de modélisation. */
    glMatrixMode(GL_MODELVIEW);
    /* Remetre à zéro la matrice de modélisation. */
    glLoadIdentity();
 
  fenetreGl->gl_end();
 
  /* Partie standard du redimensionnement. */
  return Gtk::Widget::on_configure_event(event);
}
 
/* -- Constructeur par défaut de la fenêtre. ----------------------------- */
Interface::Fenetre::Fenetre (): Gtk::Window (), zoneRendu () {
  set_title("Tutoriel 2");
  set_default_size(640, 480);
  /* Taille minimum pour éviter les divisions par zéro. */
  set_size_request(1, 1);
 
  add(zoneRendu);
 
  add_events(Gdk::KEY_RELEASE_MASK);
 
  signal_key_release_event().connect(sigc::mem_fun(*this,
                                                  &Fenetre::on_key_release));
  signal_window_state_event().connect(sigc::mem_fun(*this,
                                           &Fenetre::on_window_state_event));
 
  /* Boîte de dialogue pour le plein écran. */
  Gtk::MessageDialog pleinEcran (*this, "Passer en mode plein écran ?",
                                 false, Gtk::MESSAGE_QUESTION,
                                 Gtk::BUTTONS_YES_NO);
  /* Choix de l’utilisateur. */
  int choix = pleinEcran.run();
 
  if (choix == Gtk::RESPONSE_YES) {
    enPleinEcran = true;
    fullscreen();
  }
  else {
    set_border_width(2);
    enPleinEcran = false;
  }
 
  show_all_children();
}
 
/* -- Destructeur de la fenêtre. ----------------------------------------- */
 
Interface::Fenetre::~Fenetre () {
}
 
/* -- Gestion des évènements claviers. ----------------------------------- */
bool Interface::Fenetre::on_key_release (GdkEventKey* evenement) {
  switch (evenement->keyval) {
    case GDK_KEY_Escape:
      hide();
      break;
    case GDK_KEY_F1:
      if (enPleinEcran) {
        enPleinEcran = false;
	set_border_width(2);
        unfullscreen();
      }
      else {
        enPleinEcran = true;
	set_border_width(0);
        fullscreen();
      }
  }
 
  return true;
}
 
/* -- Lors du passage du mode plein écran au mode fenêtré. --------------- */
bool Interface::Fenetre::on_window_state_event(GdkEventWindowState* pEven) {
  /* Résultat de la mise à jour standard de la fenêtre. */
  const bool resultat = Gtk::Widget::on_window_state_event(pEven);
 
  if (resultat) {
    /* Vérifie que l’écran est bien dans le mode souhaité. */
    if (enPleinEcran
        && (pEven->changed_mask != GDK_WINDOW_STATE_FULLSCREEN)) {
      set_border_width(2);
      enPleinEcran = false;
      unfullscreen();
 
      /* Boîte de dialogue signifiant l’échec de l’opération. */
      Gtk::MessageDialog pleinEcran (*this,
                                  "Impossible de passer en mode plein écran",
                                     false, Gtk::MESSAGE_QUESTION,
                                     Gtk::BUTTONS_YES_NO);
      pleinEcran.set_secondary_text("Rester en mode fenêtré ?");
      /* Choix de l’utilisateur. */
      int choix = pleinEcran.run();
      if (choix == Gtk::RESPONSE_NO) return false;
    }
  }
 
  return resultat;
}
Fichier « src/main.cpp » :

Code :
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
/*
 * Deuxième tutoriel : création d’un triangle et d’un carré.
 */
 
#include <iostream>
#include <gtkmm/main.h>
#include <sstream>
#include <glibmm/error.h>
#include <exception>
 
#include "erreurs.hpp"
#include "fenetre.hpp"
 
/*
 * Principale fonction du programme.
 * Entrées :
 *   argc  Nombre d’arguments.
 *   argv  Valeures des arguments.
 * Retourne :
 *   0 si tout s’est bien passé.
 *   -1 en cas d’erreur venant de la GLib ou de ses dérivés.
 *   -2 en cas d’erreur en provenance d’OpenGL.
 *   -3 en cas d’erreur en provenance de la bibliothèque standard.
 *   -4 en cas d’erreur non standard.
 */
int main (int argc, char** argv) {
  try {
    /* Boucle d’évènements. */
    const Gtk::Main kit(argc, argv);
    Gtk::GL::init(argc, argv);
 
    /* Fenêtre principale. */
    Interface::Fenetre principale;
 
    kit.run(principale);
 
    return 0;
  }
  catch(const Glib::Error &ex) {
    /* Message d’erreur. */
    std::ostringstream message;
    message << "Erreur venant de GLib : " <<  ex.what() << '\n';
    g_warning(message.str().c_str());
    return -1;
  }
  catch (const Erreurs::ErreurInterface &e) {
    /* Message d’erreur. */
    std::stringstream message;
    message << "Erreur de contexte OpenGL : " << e.what() << ".\n";
    g_critical(message.str().c_str());
    return -2;
  }
  catch (const std::exception &e) {
    /* Message d’erreur. */
    std::stringstream message;
    message << "Erreur venant de la bibliothèque standard : " << e.what()
            << '\n';
    g_critical(message.str().c_str());
    return -3;
  }
  catch (...) {
    g_critical("Exception non-standard.\n");
    return -4;
  }
}
À bientôt.

Le Farfadet Spatial
Le Farfadet Spatial est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/02/2013, 15h44   #2
Le Farfadet Spatial
Membre éclairé
 
Avatar de Le Farfadet Spatial
 
Inscription : avril 2008
Messages : 135
Détails du profil
Informations forums :
Inscription : avril 2008
Messages : 135
Points : 341
Points : 341
Salut à tous !

Au cas où, j’essaye de relancer le sujet. Ça ressemble vraiment à un problème dans la configuration de Gtkmm, mais je n’arrive pas à déterminer ce que j’ai mal fait. Quelqu’un a-t-il déjà utilisé le mode plein écran avec Gtkmm ?

À bientôt.

Le Farfadet Spatial
Le Farfadet Spatial est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 24/02/2013, 18h04   #3
Le Farfadet Spatial
Membre éclairé
 
Avatar de Le Farfadet Spatial
 
Inscription : avril 2008
Messages : 135
Détails du profil
Informations forums :
Inscription : avril 2008
Messages : 135
Points : 341
Points : 341
Salut à tous !

Après pas mal d'errements et de découragement, j'en suis finalement arrivé à un code qui parvient à s'amorcer en plein écran. Tout d'abord, j'explique les raisons de ce que j'ai fait, si quelqu'un peut confirmer que je ne me trompe pas ou bien au contraire m'indiquer ce que j'ai mal compris, je lui en saurais gré.

Donc, en cherchant sur le web, il ressort que visiblement un composant Gtk+ suit les étapes suivantes au cours de son existence :
  • Création ;
  • configuration (usuellement faite dans le constructeur) ;
  • réalisation (assigne une ressource système tel qu'une fenêtre X Window) ;
  • mapping (qui rend le composant visible sur l'écran) ;
  • « show » (qui réalise les deux précédentes étapes) ;
  • unmapping (qui supprime le composant de l'écran) ;
  • « hide » (une version plus simple de l'étape précédente) ;
  • destruction.

J'ai fait appel à « show(); » juste avant de basculer en mode plein-écran et alors le code peut s'initialiser directement en plein écran. J'avais essayé avec uniquement « realize(); », mais ce n'était pas suffisant.

Donc, ce qu'il me semble, c'est que Gtk+ ne peut pas passer en plein-écran un composant qui n'a pas déjà une fenêtre associée. Est-ce que quelqu'un peut confirmer cela ?

Le code actuel.

Fichier « CMakeLists.txt » :

Code :
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
## Génération des tutoriels OpenGL de NeHe version Gtkmm.
 
cmake_minimum_required(VERSION 2.6)
 
project(Tutoriel2 CXX)
 
# Répertoire où placer l’exécutable.
set(EXECUTABLE_OUTPUT_PATH bin/${CMAKE_BUILD_TYPE})
# Nom de l’exécutable.
set(EXECUTABLE_NAME tutoriel2)
 
find_package(PkgConfig REQUIRED)
 
pkg_check_modules(Glibmm glibmm-2.4>=2.4.0)
pkg_check_modules(GTKmm gtkmm-2.4>=2.4.0)
pkg_check_modules(GLExtmm gtkglextmm-1.2>=1.2.0)
 
link_directories(
        ${Glibmm_LIBRARY_DIRS}
        ${GTKmm_LIBRARY_DIRS}
        ${GLExtmm_LIBRARY_DIRS}
)
include_directories(
        ${Glibmm_INCLUDE_DIRS}
        ${GTKmm_INCLUDE_DIRS}
        ${GLExtmm_INCLUDE_DIRS}
)
 
file(
        GLOB_RECURSE
        source_files
        src/*
)
 
add_executable(
        ${EXECUTABLE_NAME}
        ${source_files}
)
 
target_link_libraries(
        ${EXECUTABLE_NAME}
        ${Glibmm_LIBRARIES}
        ${GTKmm_LIBRARIES}
        ${GLExtmm_LIBRARIES}
)
Fichier « src/erreurs.hpp » :

Code :
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
#ifndef ERREURS_HPP
#define ERREURS_HPP
 
/*
 * Exceptions pour la gestions des erreurs.
 */
 
#include <exception>
 
/* Espace de nommage pour la gestion des erreurs. */
namespace Erreurs {
/* -- Erreurs provoquées par l’interface graphique. ---------------------- */
  class ErreurInterface: public std::exception {
    public:
      /* Constructeur par défaut. */
      ErreurInterface () throw () {}
 
      /* Destructeur. */
      virtual ~ErreurInterface () throw () {}
 
      /* Génére le message d’erreur. */
      virtual const char* what () const throw () {
        return "une erreur s’est produite dans l’interface graphique";
      }
  };
 
/* -- Erreur lors de la configuration d’OpenGL. -------------------------- */
  class ErreurConfigurationGL: public ErreurInterface {
    public:
      /* Constructeur par défaut. */
      ErreurConfigurationGL () throw () {}
 
      /* Destructeur. */
      virtual ~ErreurConfigurationGL () throw () {}
 
      /* Génère le message d’erreur. */
      virtual const char* what () const throw () {
        return "erreur lors de la configuration d’OpenGL";
      }
  };
 
/* -- Erreur lors de la création du contexte OpenGL. --------------------- */
  class ErreurCreationContexte: public ErreurInterface {
    public:
      /* Constructeur par défaut. */
      ErreurCreationContexte () throw () {}
 
      /* Destructeur. */
      virtual ~ErreurCreationContexte () throw () {}
 
      /* Génère le message d’erreur. */
      virtual const char* what () const throw () {
        return "impossible de créer un contexte OpenGL";
      }
  };
 
/* -- Erreur à l’obtention du contexte OpenGL. --------------------------- */
  class ErreurObtentionContexte: public ErreurInterface {
    public:
      /* Constructeur par défaut. */
      ErreurObtentionContexte () throw () {}
 
      /* Destructeur. */
      virtual ~ErreurObtentionContexte () throw () {}
 
      /* Génère le message d’erreur. */
      virtual const char* what () const throw () {
        return "impossible d’obtenir le contexte OpenGL";
      }
  };
}
 
#endif  // #ifndef ERREURS_HPP
Fichier « src/fenetre.hpp » :

Code :
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
#ifndef FENETRE_HPP
#define FENETRE_HPP
 
/*
 * Définitions des classes gérants le fenêtrage OpenGL.
 */
 
#include <gtkmm/window.h>
#include <gtkmm/drawingarea.h>
#include <gtkglmm.h>
 
#include "erreurs.hpp"
 
/* Espace de nommage pour la gestion de l’interface. */
namespace Interface {
  /* Classe pour la zone de rendu OpenGL. */
  class GlDrawingArea: public Gtk::DrawingArea,
                       public Gtk::GL::Widget<GlDrawingArea> {
    public:
      GlDrawingArea ();
      virtual ~GlDrawingArea ();
 
    protected:
      /* -- Controleurs: */
 
      /* À l’initialisation de la fenêtre. */
      virtual void on_realize ();
 
      /* À la demande d’affichage. */
      virtual bool on_expose_event (GdkEventExpose* event);
 
      /* Au changement de taille de la fenêtre. */
      virtual bool on_configure_event (GdkEventConfigure* event);
  };
 
/* ----------------------------------------------------------------------- */
 
  /* Classe pour la fenetre principale. */
  class Fenetre: public Gtk::Window {
    public:
      Fenetre ();
      virtual ~Fenetre();
 
    protected:
      /* -- Controleurs : */
 
      /* Gestion des évènements clavier. */
      bool on_key_release (GdkEventKey* evenement);
 
      /* Lors du passage du mode fenêtré au mode plein écran. */
      bool on_window_state_event (GdkEventWindowState *pEven);
 
      /* -- Composant membre : */
 
      /* Zone de rendu OpenGL. */
      GlDrawingArea zoneRendu;
 
    private:
      /* Indique si on se trouve en mode plein écran. */
      bool enPleinEcran;
  };
}
 
#endif  // #ifndef FENETRE_HPP
Fichier « src/fenetre.cpp » :

Code :
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
/*
 * Implémentations du fenêtrage OpenGL.
 */
 
#include <glibmm/error.h>
#include <cstdlib>
#include <GL/gl.h>
#include <GL/glu.h>
#include <sstream>
#include <gtkmm/messagedialog.h>
#include <gdk/gdkkeysyms.h>
#include <gdkmm/cursor.h>
 
#include "fenetre.hpp"
 
/* -- Constructeur par défaut de GlDrawingArea. -------------------------- */
Interface::GlDrawingArea::GlDrawingArea (): Gtk::DrawingArea () {
  /* Configuration d’OpenGL */
  Glib::RefPtr<Gdk::GL::Config> configuration;
 
  /* Tente d’ouvrir une espace à double tampon. */
  configuration = Gdk::GL::Config::create(Gdk::GL::MODE_RGBA   |
                                          Gdk::GL::MODE_DEPTH  |
                                          Gdk::GL::MODE_DOUBLE);
  if (!configuration) {
    /* Message d’avertissement. */
    std::stringstream message;
    message << "Impossible de configurer OpenGL en mode double tampon, "
            << "tente le mode simple tampon.\n";
    g_warning(message.str().c_str());
    /* Tente de configurer un tampon simple. */
    configuration = Gdk::GL::Config::create(Gdk::GL::MODE_RGBA  |
                                            Gdk::GL::MODE_DEPTH);
    if (!configuration) throw Erreurs::ErreurConfigurationGL ();
  }
 
  /* Donne accès à OpenGL au composant. */
  set_gl_capability(configuration);
}
 
/* -- Destructeur de GlDrawingArea. -------------------------------------- */
Interface::GlDrawingArea::~GlDrawingArea () {
}
 
/* -- Initialisation du contexte OpenGL. --------------------------------- */
void Interface::GlDrawingArea::on_realize () {
  /* D’abord l’initialisation standard. */
  Gtk::Widget::on_realize();
 
  if (!create_gl_context()) throw Erreurs::ErreurCreationContexte ();
  /* Fenêtre OpenGL. */
  Glib::RefPtr<Gdk::GL::Window> fenetreGl = get_gl_window();
  if (!fenetreGl) throw Erreurs::ErreurObtentionContexte ();
 
  fenetreGl->gl_begin(get_gl_context());
 
    /* Permet un joli ombrage. */
    glShadeModel(GL_SMOOTH);
 
    /* Fond noir. */
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 
    /* Mis en place du tampon de profondeur. */
    glClearDepth(1.0f);
    /* Mis en place du test de profondeur. */
    glEnable(GL_DEPTH_TEST);
    /* Le type de test de profondeur . */
    glDepthFunc(GL_LEQUAL);
 
    /* Très jolis calculs de perspective. */
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
 
  fenetreGl->gl_end();
}
 
/* -- À la demande  d’affichage de GlDrawingArea. ------------------------ */
bool Interface::GlDrawingArea::on_expose_event (GdkEventExpose* event) {
  /* Fenêtre OpenGL. */
  Glib::RefPtr<Gdk::GL::Window> fenetreGl = get_gl_window();
  if (!fenetreGl)  throw Erreurs::ErreurObtentionContexte ();
 
  fenetreGl->gl_begin(get_gl_context());
 
    /* Vide l'écran et le Z-Buffer (Depth Buffer : contient les informations
       de profondeur de chaque pixel). */
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    /* Repositionne la caméra. */
    glLoadIdentity();
 
    /* Bouge de 1.5 unités vers la gauche et de 6.0 unités vers l'intérieur
       de l'écran. */
    glTranslatef(-1.5f,0.0f,-6.0f);
 
    /* Dessiner un Triangle. */
    glBegin(GL_TRIANGLES);
      /* Point du haut. */
      glVertex3f( 0.0f, 1.0f, 0.0f);
      /* Point en bas à gauche. */
      glVertex3f(-1.0f,-1.0f, 0.0f);
      /* Point en bas à droite */
      glVertex3f( 1.0f,-1.0f, 0.0f);
    /* Le dessin du Triangle est fini */
    glEnd();
 
    /* Bouge de 3.0f unités vers la droite. */
    glTranslatef(3.0f,0.0f,0.0f);
 
    /* Dessin d'un quadrilatère. */
    glBegin(GL_QUADS);
      /* Haut Gauche. */
      glVertex3f(-1.0f, 1.0f, 0.0f);
      /* Haut Droite. */
      glVertex3f( 1.0f, 1.0f, 0.0f);
      /* Bas Droite. */
      glVertex3f( 1.0f,-1.0f, 0.0f);
      /* Bas Gauche. */
      glVertex3f(-1.0f,-1.0f, 0.0f);
    glEnd();
 
  fenetreGl->gl_end();
  fenetreGl->swap_buffers();
 
  /* Partie standard de la la procédure d’affichage. */
  return Gtk::Widget::on_expose_event(event);
}
 
/* -- Lorsque la fenêtre est redimensionnée. ----------------------------- */
bool Interface::GlDrawingArea::on_configure_event (GdkEventConfigure* event) {
  /* Fenêtre OpenGL. */
  Glib::RefPtr<Gdk::GL::Window> fenetreGl = get_gl_window();
  if (!fenetreGl)  throw Erreurs::ErreurObtentionContexte ();
 
  /* Largeur de la zone de rendu. */
  const GLsizei largeur = static_cast<GLsizei>(get_width());
  /* Hauteur de la zone de rendu. */
  const GLsizei hauteur = static_cast<GLsizei>(get_height());
 
  fenetreGl->gl_begin(get_gl_context());
 
    /* Fixer la taille de la zone de rendue. */
    glViewport(0, 0, largeur, hauteur);
    /* Choisir la matrice de projection. */
    glMatrixMode(GL_PROJECTION);
    /* Remettre a zéro de la matrice de projection. */
    glLoadIdentity();
 
    /* Calculer le ratio pour la perspective de la fenêtre. */
    gluPerspective(45.0f, static_cast<GLfloat>(largeur)
                            / static_cast<GLfloat>(hauteur), 0.1f,100.0f);
    glMatrixMode(GL_MODELVIEW);
    /* Remetre à zéro la matrice de modélisation. */
    glLoadIdentity();
 
  fenetreGl->gl_end();
 
  /* Partie standard du redimensionnement. */
  return Gtk::Widget::on_configure_event(event);
}
 
/* -- Constructeur par défaut de la fenêtre. ----------------------------- */
Interface::Fenetre::Fenetre (): Gtk::Window (), zoneRendu () {
  set_title("Tutoriel 2");
  set_default_size(640, 480);
  /* Taille minimum pour éviter les divisions par zéro. */
  set_size_request(1, 1);
 
  add(zoneRendu);
 
  add_events(Gdk::KEY_RELEASE_MASK);
 
  signal_key_release_event().connect(sigc::mem_fun(*this,
                                                  &Fenetre::on_key_release));
  signal_window_state_event().connect(sigc::mem_fun(*this,
                                           &Fenetre::on_window_state_event));
 
  /* Boîte de dialogue pour le plein écran. */
  Gtk::MessageDialog pleinEcran (*this, "Passer en mode plein écran ?",
                                 false, Gtk::MESSAGE_QUESTION,
                                 Gtk::BUTTONS_YES_NO);
  /* Choix de l’utilisateur. */
  int choix = pleinEcran.run();
 
  if (choix == Gtk::RESPONSE_YES) {
    enPleinEcran = true;
    show();
    fullscreen();
 
    /* Créé un curseur vide. */
    const Gdk::Cursor cursor (Gdk::Display::get_default(),
                              Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true,
                                                  8, 1, 1), 0, 0);
    /* Affiche le curseur vide, ce qui efface donc le curseur. */
    get_window()->set_cursor(cursor);
  }
  else {
    set_border_width(2);
    enPleinEcran = false;
  }
 
  show_all_children();
}
 
/* -- Destructeur de la fenêtre. ----------------------------------------- */
 
Interface::Fenetre::~Fenetre () {
}
 
/* -- Gestion des évènements claviers. ----------------------------------- */
bool Interface::Fenetre::on_key_release (GdkEventKey* evenement) {
  switch (evenement->keyval) {
    case GDK_KEY_Escape:
      hide();
      break;
    case GDK_KEY_F1:
      if (enPleinEcran) {
        enPleinEcran = false;
        set_border_width(2);
        unfullscreen();
        /* Revient au curseur par défaut, ce qui donc l’affiche de
           nouveau. */
        get_window()->set_cursor();
      }
      else {
        enPleinEcran = true;
        set_border_width(0);
        fullscreen();
        /* Créé un curseur vide. */
        const Gdk::Cursor cursor (Gdk::Display::get_default(),
                                  Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB,
                                                      true, 8, 1, 1), 0, 0);
        /* Affiche le curseur vide, ce qui efface donc le curseur. */
        get_window()->set_cursor(cursor);
      }
  }
 
  return true;
}
 
/* -- Lors du passage du mode plein écran au mode fenêtré. --------------- */
bool Interface::Fenetre::on_window_state_event(GdkEventWindowState* pEven) {
  /* Résultat de la mise à jour standard de la fenêtre. */
  const bool resultat = Gtk::Widget::on_window_state_event(pEven);
 
  if (resultat) {
    /* Vérifie que l’écran est bien dans le mode souhaité. */
    if (enPleinEcran
        && (pEven->changed_mask != GDK_WINDOW_STATE_FULLSCREEN)) {
      set_border_width(2);
      enPleinEcran = false;
      unfullscreen();
 
      /* Boîte de dialogue signifiant l’échec de l’opération. */
      Gtk::MessageDialog pleinEcran (*this,
                                  "Impossible de passer en mode plein écran",
                                     false, Gtk::MESSAGE_QUESTION,
                                     Gtk::BUTTONS_YES_NO);
      pleinEcran.set_secondary_text("Rester en mode fenêtré ?");
      /* Choix de l’utilisateur. */
      int choix = pleinEcran.run();
      if (choix == Gtk::RESPONSE_NO) return false;
    }
  }
 
  return resultat;
}
Fichier « src/main.cpp » :

Code :
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
/*
 * Deuxième tutoriel : création d’un triangle et d’un carré.
 */
 
#include <iostream>
#include <gtkmm/main.h>
#include <sstream>
#include <glibmm/error.h>
#include <exception>
 
#include "erreurs.hpp"
#include "fenetre.hpp"
 
/*
 * Principale fonction du programme.
 * Entrées :
 *   argc  Nombre d’arguments.
 *   argv  Valeures des arguments.
 * Retourne :
 *   0 si tout s’est bien passé.
 *   -1 en cas d’erreur venant de la GLib ou de ses dérivés.
 *   -2 en cas d’erreur en provenance d’OpenGL.
 *   -3 en cas d’erreur en provenance de la bibliothèque standard.
 *   -4 en cas d’erreur non standard.
 */
int main (int argc, char** argv) {
  try {
    /* Boucle d’évènements. */
    const Gtk::Main kit(argc, argv);
    Gtk::GL::init(argc, argv);
 
    /* Fenêtre principale. */
    Interface::Fenetre principale;
 
    kit.run(principale);
 
    return 0;
  }
  catch(const Glib::Error &ex) {
    /* Message d’erreur. */
    std::ostringstream message;
    message << "Erreur venant de GLib : " <<  ex.what() << '\n';
    g_critical(message.str().c_str());
    return -1;
  }
  catch (const Erreurs::ErreurInterface &e) {
    /* Message d’erreur. */
    std::stringstream message;
    message << "Erreur de contexte OpenGL : " << e.what() << ".\n";
    g_critical(message.str().c_str());
    return -2;
  }
  catch (const std::exception &e) {
    /* Message d’erreur. */
    std::stringstream message;
    message << "Erreur venant de la bibliothèque standard : " << e.what()
            << '\n';
    g_critical(message.str().c_str());
    return -3;
  }
  catch (...) {
    g_critical("Exception non-standard.\n");
    return -4;
  }
}
Je laisse un peu de temps avant de passer le sujet en résolu, pour le cas où quelqu’un aurait une réponse à apporter.

À bientôt.

Le Farfadet Spatial
Le Farfadet Spatial est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/02/2013, 17h57   #4
Le Farfadet Spatial
Membre éclairé
 
Avatar de Le Farfadet Spatial
 
Inscription : avril 2008
Messages : 135
Détails du profil
Informations forums :
Inscription : avril 2008
Messages : 135
Points : 341
Points : 341
Salut à tous !

Ma demande d’aide sur la liste de diffusion de Gtkmm a fini par trouver une réponse. Il en ressort que si les étapes de la vie d’un composant Gtk+ que j’ai donné dans le message précédent sont bonnes, en revanche il n’est pas nécessaire d’attendre un « show() » avant de passer une fenêtre en plein-écran. Le problème, c’est que j’avais oublié des étapes. Pour passer une fenêtre Gtk+ en plein écran, il faut réaliser les étapes suivantes :
  1. Supprimer la décoration de la fenêtre, c’est-à-dire la barre de titre (« set_decorated(false); ») ;
  2. maximiser la fenêtre (« maximize(); ») ;
  3. passer en mode plein-écran (« fullscreen(); »).

En revanche, pour effacer le curseur de la souris, il faut faire appel à la fonction « get_window(); » qui ne renvoie un pointeur non-nul que si la fenêtre a été réalisée.

Voici donc le code final :

Fichier « CMakeLists.txt » :

Code :
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
## Génération des tutoriels OpenGL de NeHe version Gtkmm.
 
cmake_minimum_required(VERSION 2.6)
 
project(Tutoriel2 CXX)
 
# Répertoire où placer l’exécutable.
set(EXECUTABLE_OUTPUT_PATH bin/${CMAKE_BUILD_TYPE})
# Nom de l’exécutable.
set(EXECUTABLE_NAME tutoriel2)
 
find_package(PkgConfig REQUIRED)
 
pkg_check_modules(Glibmm glibmm-2.4>=2.4.0)
pkg_check_modules(GTKmm gtkmm-2.4>=2.4.0)
pkg_check_modules(GLExtmm gtkglextmm-1.2>=1.2.0)
 
link_directories(
        ${Glibmm_LIBRARY_DIRS}
        ${GTKmm_LIBRARY_DIRS}
        ${GLExtmm_LIBRARY_DIRS}
)
include_directories(
        ${Glibmm_INCLUDE_DIRS}
        ${GTKmm_INCLUDE_DIRS}
        ${GLExtmm_INCLUDE_DIRS}
)
 
file(
        GLOB_RECURSE
        source_files
        src/*
)
 
add_executable(
        ${EXECUTABLE_NAME}
        ${source_files}
)
 
target_link_libraries(
        ${EXECUTABLE_NAME}
        ${Glibmm_LIBRARIES}
        ${GTKmm_LIBRARIES}
        ${GLExtmm_LIBRARIES}
)
Fichier « src/erreurs.hpp »

Code :
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
#ifndef ERREURS_HPP
#define ERREURS_HPP
 
/*
 * Exceptions pour la gestions des erreurs.
 */
 
#include <exception>
 
/* Espace de nommage pour la gestion des erreurs. */
namespace Erreurs {
/* -- Erreurs provoquées par l’interface graphique. ---------------------- */
  class ErreurInterface: public std::exception {
    public:
      /* Constructeur par défaut. */
      ErreurInterface () throw () {}
 
      /* Destructeur. */
      virtual ~ErreurInterface () throw () {}
 
      /* Génére le message d’erreur. */
      virtual const char* what () const throw () {
        return "une erreur s’est produite dans l’interface graphique";
      }
  };
 
/* -- Erreur lors de la configuration d’OpenGL. -------------------------- */
  class ErreurConfigurationGL: public ErreurInterface {
    public:
      /* Constructeur par défaut. */
      ErreurConfigurationGL () throw () {}
 
      /* Destructeur. */
      virtual ~ErreurConfigurationGL () throw () {}
 
      /* Génère le message d’erreur. */
      virtual const char* what () const throw () {
        return "erreur lors de la configuration d’OpenGL";
      }
  };
 
/* -- Erreur lors de la création du contexte OpenGL. --------------------- */
  class ErreurCreationContexte: public ErreurInterface {
    public:
      /* Constructeur par défaut. */
      ErreurCreationContexte () throw () {}
 
      /* Destructeur. */
      virtual ~ErreurCreationContexte () throw () {}
 
      /* Génère le message d’erreur. */
      virtual const char* what () const throw () {
        return "impossible de créer un contexte OpenGL";
      }
  };
 
/* -- Erreur à l’obtention du contexte OpenGL. --------------------------- */
  class ErreurObtentionContexte: public ErreurInterface {
    public:
      /* Constructeur par défaut. */
      ErreurObtentionContexte () throw () {}
 
      /* Destructeur. */
      virtual ~ErreurObtentionContexte () throw () {}
 
      /* Génère le message d’erreur. */
      virtual const char* what () const throw () {
        return "impossible d’obtenir le contexte OpenGL";
      }
  };
}
 
#endif  /* #ifndef ERREURS_HPP */
Fichier « src/fenetre.hpp » :

Code :
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
#ifndef FENETRE_HPP
#define FENETRE_HPP
 
/*
 * Définitions des classes gérants le fenêtrage OpenGL.
 */
 
#include <gtkmm/window.h>
#include <gtkmm/drawingarea.h>
#include <gtkglmm.h>
 
#include "erreurs.hpp"
 
/* Espace de nommage pour la gestion de l’interface. */
namespace Interface {
  /* Classe pour la zone de rendu OpenGL. */
  class GlDrawingArea: public Gtk::DrawingArea,
                       public Gtk::GL::Widget<GlDrawingArea> {
    public:
      GlDrawingArea ();
      virtual ~GlDrawingArea ();
 
    protected:
      /* -- Controleurs: */
 
      /* À l’initialisation de la fenêtre. */
      virtual void on_realize ();
 
      /* À la demande d’affichage. */
      virtual bool on_expose_event (GdkEventExpose* event);
 
      /* Au changement de taille de la fenêtre. */
      virtual bool on_configure_event (GdkEventConfigure* event);
  };
 
/* ----------------------------------------------------------------------- */
 
  /* Classe pour la fenetre principale. */
  class Fenetre: public Gtk::Window {
    public:
      Fenetre ();
      virtual ~Fenetre();
 
    protected:
      /* -- Controleurs : */
 
      /* Gestion des évènements clavier. */
      bool on_key_release (GdkEventKey* evenement);
 
      /* Lors du passage du mode fenêtré au mode plein écran. */
      bool on_window_state_event (GdkEventWindowState* pEven);
 
      /* -- Composant membre : */
 
      /* Zone de rendu OpenGL. */
      GlDrawingArea zoneRendu;
 
    private:
      /* Change de mode d’affichage : de fenêtré à plein-écran et
         inversement. */
      void echangeModeAffichage ();
  };
}
 
#endif  /* #ifndef FENETRE_HPP */
Fichier « src/fenetre.cpp » :

Code :
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
/*
 * Implémentations du fenêtrage OpenGL.
 */
 
#include <glibmm/error.h>
#include <cstdlib>
#include <GL/glu.h>
#include <sstream>
#include <gtkmm/messagedialog.h>
#include <gdk/gdkkeysyms.h>
#include <gdkmm/cursor.h>
 
#include "fenetre.hpp"
 
/* -- Constructeur par défaut de GlDrawingArea. -------------------------- */
Interface::GlDrawingArea::GlDrawingArea (): Gtk::DrawingArea () {
  #ifndef GLIBMM_DEFAULT_SIGNAL_HANDLERS_ENABLED
    /* Connecte les contrôleurs de signaux s’il ne s’agit pas déjà de
       méthodes virtuelles surchargées : */
    signal_realize().connect(sigc::mem_fun(*this,
                                           &GlDrawingArea::on_realize),
                             false);
    signal_expose_event().connect(sigc::mem_fun(*this,
                                            &GlDrawingArea::on_expose_event),
                                  false);
    signal_configure_event().connect(sigc::mem_fn(*this,
                                         &GlDrawingArea::on_configure_event),
                                     false);
  #endif  /* #ifndef GLIBMM_DEFAULT_SIGNAL_HANDLERS_ENABLED */
 
  /* Configuration d’OpenGL */
  Glib::RefPtr<Gdk::GL::Config> configuration;
 
  /* Tente d’ouvrir une espace à double tampon. */
  configuration = Gdk::GL::Config::create(Gdk::GL::MODE_RGBA   |
                                          Gdk::GL::MODE_DEPTH  |
                                          Gdk::GL::MODE_DOUBLE);
  if (!configuration) {
    /* Message d’avertissement. */
    std::stringstream message;
    message << "Impossible de configurer OpenGL en mode double tampon, "
            << "tente le mode simple tampon.\n";
    g_warning(message.str().c_str());
    /* Tente de configurer un tampon simple. */
    configuration = Gdk::GL::Config::create(Gdk::GL::MODE_RGBA  |
                                            Gdk::GL::MODE_DEPTH);
    if (!configuration) throw Erreurs::ErreurConfigurationGL ();
  }
 
  /* Donne accès à OpenGL au composant. */
  set_gl_capability(configuration);
}
 
/* -- Destructeur de GlDrawingArea. -------------------------------------- */
Interface::GlDrawingArea::~GlDrawingArea () {
}
 
/* -- Initialisation du contexte OpenGL. --------------------------------- */
void Interface::GlDrawingArea::on_realize () {
  /* D’abord l’initialisation standard. */
  Gtk::Widget::on_realize();
 
  if (!create_gl_context()) throw Erreurs::ErreurCreationContexte ();
  /* Fenêtre OpenGL. */
  Glib::RefPtr<Gdk::GL::Window> fenetreGl = get_gl_window();
  if (!fenetreGl) throw Erreurs::ErreurObtentionContexte ();
 
  fenetreGl->gl_begin(get_gl_context());
 
    /* Permet un joli ombrage. */
    glShadeModel(GL_SMOOTH);
 
    /* Fond noir. */
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 
    /* Mis en place du tampon de profondeur. */
    glClearDepth(1.0f);
    /* Mis en place du test de profondeur. */
    glEnable(GL_DEPTH_TEST);
    /* Le type de test de profondeur . */
    glDepthFunc(GL_LEQUAL);
 
    /* Très jolis calculs de perspective. */
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
 
  fenetreGl->gl_end();
}
 
/* -- À la demande  d’affichage de GlDrawingArea. ------------------------ */
bool Interface::GlDrawingArea::on_expose_event (GdkEventExpose* event) {
  /* Fenêtre OpenGL. */
  Glib::RefPtr<Gdk::GL::Window> fenetreGl = get_gl_window();
  if (!fenetreGl)  throw Erreurs::ErreurObtentionContexte ();
 
  fenetreGl->gl_begin(get_gl_context());
 
    /* Vide l'écran et le Z-Buffer (Depth Buffer : contient les informations
       de profondeur de chaque pixel). */
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    /* Repositionne la caméra. */
    glLoadIdentity();
 
    /* Bouge de 1.5 unités vers la gauche et de 6.0 unités vers l'intérieur
       de l'écran. */
    glTranslatef(-1.5f,0.0f,-6.0f);
 
    /* Dessiner un Triangle. */
    glBegin(GL_TRIANGLES);
      /* Point du haut. */
      glVertex3f( 0.0f, 1.0f, 0.0f);
      /* Point en bas à gauche. */
      glVertex3f(-1.0f,-1.0f, 0.0f);
      /* Point en bas à droite */
      glVertex3f( 1.0f,-1.0f, 0.0f);
    /* Le dessin du Triangle est fini */
    glEnd();
 
    /* Bouge de 3.0f unités vers la droite. */
    glTranslatef(3.0f,0.0f,0.0f);
 
    /* Dessin d'un quadrilatère. */
    glBegin(GL_QUADS);
      /* Haut Gauche. */
      glVertex3f(-1.0f, 1.0f, 0.0f);
      /* Haut Droite. */
      glVertex3f( 1.0f, 1.0f, 0.0f);
      /* Bas Droite. */
      glVertex3f( 1.0f,-1.0f, 0.0f);
      /* Bas Gauche. */
      glVertex3f(-1.0f,-1.0f, 0.0f);
    glEnd();
 
  fenetreGl->gl_end();
  fenetreGl->swap_buffers();
 
  /* Partie standard de la la procédure d’affichage. */
  return Gtk::Widget::on_expose_event(event);
}
 
/* -- Lorsque la fenêtre est redimensionnée. ----------------------------- */
bool Interface::GlDrawingArea::on_configure_event
    (GdkEventConfigure* event) {
  /* Fenêtre OpenGL. */
  Glib::RefPtr<Gdk::GL::Window> fenetreGl = get_gl_window();
  if (!fenetreGl)  throw Erreurs::ErreurObtentionContexte ();
 
  /* Largeur de la zone de rendu. */
  const GLsizei largeur = static_cast<GLsizei>(get_width());
  /* Hauteur de la zone de rendu. */
  const GLsizei hauteur = static_cast<GLsizei>(get_height());
 
  fenetreGl->gl_begin(get_gl_context());
 
    /* Fixer la taille de la zone de rendue. */
    glViewport(0, 0, largeur, hauteur);
    /* Choisir la matrice de projection. */
    glMatrixMode(GL_PROJECTION);
    /* Remettre a zéro de la matrice de projection. */
    glLoadIdentity();
 
    /* Calculer le ratio pour la perspective de la fenêtre. */
    gluPerspective(45.0f, static_cast<GLfloat>(largeur)
                            / static_cast<GLfloat>(hauteur), 0.1f,100.0f);
    glMatrixMode(GL_MODELVIEW);
    /* Remetre à zéro la matrice de modélisation. */
    glLoadIdentity();
 
  fenetreGl->gl_end();
 
  /* Partie standard du redimensionnement. */
  return Gtk::Widget::on_configure_event(event);
}
 
/* -- Constructeur par défaut de la fenêtre. ----------------------------- */
Interface::Fenetre::Fenetre (): Gtk::Window (), zoneRendu () {
  set_title("Tutoriel 1");
  set_default_size(640, 480);
  /* Taille minimum pour éviter les divisions par zéro. */
  set_size_request(1, 1);
 
  add(zoneRendu);
 
  set_border_width(2);
 
  add_events(Gdk::KEY_RELEASE_MASK);
 
  signal_key_release_event().connect(sigc::mem_fun(*this,
                                                  &Fenetre::on_key_release));
  signal_window_state_event().connect(sigc::mem_fun(*this,
                                           &Fenetre::on_window_state_event));
 
  /* Boîte de dialogue pour le plein écran. */
  Gtk::MessageDialog pleinEcran (*this, "Passer en mode plein écran ?",
                                 false, Gtk::MESSAGE_QUESTION,
                                 Gtk::BUTTONS_YES_NO);
  /* Choix de l’utilisateur. */
  int choix = pleinEcran.run();
 
  if (choix == Gtk::RESPONSE_YES) {
    show();
    echangeModeAffichage();
  }
 
  show_all_children();
}
 
/* -- Destructeur de la fenêtre. ----------------------------------------- */
 
Interface::Fenetre::~Fenetre () {
}
 
/* -- Échange de mode d’affichage. --------------------------------------- */
void Interface::Fenetre::echangeModeAffichage () {
  set_decorated(!get_decorated());
  if (get_decorated()) {
    unfullscreen();
    unmaximize();
    /* Revient au curseur par défaut, ce qui donc l’affiche de
       nouveau. */
    get_window()->set_cursor();
    set_border_width(2);
  }
  else {
    set_border_width(0);
    /* Créé un curseur vide. */
    const Gdk::Cursor cursor (Gdk::Display::get_default(),
                              Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true,
                                                  8, 1, 1), 0, 0);
    /* Affiche le curseur vide, ce qui efface donc le curseur. */
    get_window()->set_cursor(cursor);
    maximize();
    fullscreen();
  }
}
 
/* -- Gestion des évènements claviers. ----------------------------------- */
bool Interface::Fenetre::on_key_release (GdkEventKey* evenement) {
  switch (evenement->keyval) {
    case GDK_KEY_Escape:
      hide();
      break;
    case GDK_KEY_F1:
      echangeModeAffichage();
  }
 
  return true;
}
 
/* -- Lors du passage du mode plein écran au mode fenêtré. --------------- */
bool Interface::Fenetre::on_window_state_event(GdkEventWindowState* pEven) {
  /* Résultat de la mise à jour standard de la fenêtre. */
  const bool resultat = Gtk::Widget::on_window_state_event(pEven);
 
  if (resultat) {
    /* Vérifie que l’écran est bien dans le mode souhaité. */
    if (!get_decorated()
        && (pEven->changed_mask != GDK_WINDOW_STATE_FULLSCREEN)) {
      unfullscreen();
      unmaximize();
      set_decorated(true);
      /* Curseur par défaut. */
      get_window()->set_cursor();
      set_border_width(2);
 
      /* Boîte de dialogue signifiant l’échec de l’opération. */
      Gtk::MessageDialog pleinEcran (*this,
                                  "Impossible de passer en mode plein écran",
                                     false, Gtk::MESSAGE_QUESTION,
                                     Gtk::BUTTONS_YES_NO);
      pleinEcran.set_secondary_text("Rester en mode fenêtré ?");
      /* Choix de l’utilisateur. */
      int choix = pleinEcran.run();
      if (choix == Gtk::RESPONSE_NO) return false;
    }
  }
 
  return resultat;
}
Fichier « src/main.cpp » :

Code :
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
/*
 * Deuxième tutoriel : création d’un triangle et d’un carré.
 */
 
#include <iostream>
#include <gtkmm/main.h>
#include <sstream>
#include <glibmm/error.h>
#include <exception>
 
#include "erreurs.hpp"
#include "fenetre.hpp"
 
/*
 * Principale fonction du programme.
 * Entrées :
 *   argc  Nombre d’arguments.
 *   argv  Valeures des arguments.
 * Retourne :
 *   0 si tout s’est bien passé.
 *   -1 en cas d’erreur venant de la GLib ou de ses dérivés.
 *   -2 en cas d’erreur en provenance d’OpenGL.
 *   -3 en cas d’erreur en provenance de la bibliothèque standard.
 *   -4 en cas d’erreur non standard.
 */
int main (int argc, char** argv) {
  try {
    /* Boucle d’évènements. */
    const Gtk::Main kit(argc, argv);
    Gtk::GL::init(argc, argv);
 
    /* Fenêtre principale. */
    Interface::Fenetre principale;
 
    kit.run(principale);
 
    return 0;
  }
  catch(const Glib::Error &ex) {
    /* Message d’erreur. */
    std::ostringstream message;
    message << "Erreur venant de GLib : " <<  ex.what() << '\n';
    g_critical(message.str().c_str());
    return -1;
  }
  catch (const Erreurs::ErreurInterface &e) {
    /* Message d’erreur. */
    std::stringstream message;
    message << "Erreur de contexte OpenGL : " << e.what() << ".\n";
    g_critical(message.str().c_str());
    return -2;
  }
  catch (const std::exception &e) {
    /* Message d’erreur. */
    std::stringstream message;
    message << "Erreur venant de la bibliothèque standard : " << e.what()
            << '\n';
    g_critical(message.str().c_str());
    return -3;
  }
  catch (...) {
    g_critical("Exception non-standard.\n");
    return -4;
  }
}
Cette fois-ci, je passe le sujet en résolu.

À bientôt.

Le Farfadet Spatial
Le Farfadet Spatial est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 20h43.


 
 
 
 
Partenaires

Hébergement Web