X crash when switching in full-screen mode




        Hello everybody out there!

        To train myself in Gtkmm and GtkGLExtmm, I am converting NeHe’s OpenGL
tutorials (<http://nehe.gamedev.net/>) into Gtkmm. I eventually created
a tricky bug, and cannot find my way out of it.

        I am giving some code at the end of the message. On my laptop computer
using an Intel Sandy bridge mobile graphical unit and running Debian
Wheezy, everything runs the way it should. Especially, I can start in
full-screen mode.

        However, on my desktop computer, things are not going so well. The
computer is also running Debian Wheezy, and it is using a Radeon HD 4350
graphical unit (with Fglrx). With this computer, I can run full-screen
mode after initialising in windowed mode. But if I try and start in
full-screen mode, then X server crashes: the screen turns black and
there is no way to even get a virtual console.

        I certainly have made some mistakes in configuring Gtk, but since a
week I am working on it, I have not been able to find out what is wrong.
Maybe someone can help me here.

        I am using CMake for code generation. The file “CMakeLists.txt” is in
the top-level directory of the project. All source files are in a
sub-directory called “src”. I have translated the code from French to
English, I hope there is no error in naming.

        Regards.


CMakeLists.txt:


## Generating NeHe's OpenGL tutorials in Gtkmm version.

cmake_minimum_required(VERSION 2.6)

project(Lesson1 CXX)

# Where to find executable.
set(EXECUTABLE_OUTPUT_PATH bin/${CMAKE_BUILD_TYPE})
# Executable name.
set(EXECUTABLE_NAME lesson1)

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}
)


src/erros.hpp:


#ifndef ERRORS_HPP
#define ERRORS_HPP

/*
 * Exceptions for errors gestion.
 */

#include <exception>

/* Namespace for errors gestion. */
namespace Errors {
/* -- Graphical interface errors. ---------------------- */
  class InterfaceError: public std::exception {
    public:
      /* Default constructor. */
      InterfaceError () throw () {}

      /* Destructor. */
      virtual ~InterfaceError () throw () {}

      /* Generates error message. */
      virtual const char* what () const throw () {
        return "graphical interface error";
      }
  };

/* -- OpenGL configuration error. -------------------------- */
  class GLConfigurationError: public InterfaceError {
    public:
      /* Default constructor. */
      GLConfigurationError () throw () {}

      /* Destructeur. */
      virtual ~GLConfigurationError () throw () {}

      /* Generates error message. */
      virtual const char* what () const throw () {
        return "OpenGL configuration error";
      }
  };

/* -- OpenGL context creation error. --------------------- */
  class ContextCreationError: public InterfaceError {
    public:
      /* Default constructor. */
      ContextCreationError () throw () {}

      /* Destructor. */
      virtual ~ContextCreationError () throw () {}

      /* Generates error message. */
      virtual const char* what () const throw () {
        return "OpenGL context creation error";
      }
  };

/* -- Error while getting OpenGL context. --------------------------- */
  class GettingContextError: public InterfaceError {
    public:
      /* Default constructor. */
      GettingContextError () throw () {}

      /* Destructor. */
      virtual ~GettingContextError () throw () {}

      /* Generates error message. */
      virtual const char* what () const throw () {
        return "impossible to get OpenGL context";
      }
  };
}

#endif  // #ifndef ERRORS_HPP


src/interface.hpp:


#ifndef INTERFACE_HPP
#define INTERFACE_HPP

/*
 * Classes definitions for OpenGL window.
 */

#include <gtkmm/window.h>
#include <gtkmm/drawingarea.h>
#include <gtkglmm.h>

#include "errors.hpp"

/* Namespace for the interface. */
namespace Interface {
  /* OpenGL drawing area. */
  class GlDrawingArea: public Gtk::DrawingArea,
                       public Gtk::GL::Widget<GlDrawingArea> {
    public:
      GlDrawingArea ();
      virtual ~GlDrawingArea ();

    protected:
      /* -- Handlers: */

      /* Window initialisation. */
      virtual void on_realize ();

      /* Displaying the window. */
      virtual bool on_expose_event (GdkEventExpose* event);

      /* Resizing the window. */
      virtual bool on_configure_event (GdkEventConfigure* event);
  };

/*
----------------------------------------------------------------------- */

  /* Main window. */
  class MainWindow: public Gtk::Window {
    public:
      MainWindow ();
      virtual ~MainWindow ();

    protected:
      /* -- Handlers: */

      /* Dealing with keyboard events. */
      bool on_key_release (GdkEventKey* event);

      /* When switching into full-screen mode. */
      bool on_window_state_event (GdkEventWindowState *pEven);

      /* -- Child widgets: */

      /* OpenGL area. */
      GlDrawingArea drawingArea;

    private:
      /* Indicates whether or not we are in full-screen mode. */
      bool inFullScreen;
  };
}

#endif  // #ifndef INTERFACE_HPP


src/interface.cpp:


/*
 * OpenGL window implementation.
 */

#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 "interface.hpp"

/* -- GlDrawingArea default constructor. -------------------------- */
Interface::GlDrawingArea::GlDrawingArea (): Gtk::DrawingArea () {
  /* OpenGL configuration. */
  Glib::RefPtr<Gdk::GL::Config> configuration;

  /* Trying double buffer mode. */
  configuration = Gdk::GL::Config::create(Gdk::GL::MODE_RGBA   |
                                          Gdk::GL::MODE_DEPTH  |
                                          Gdk::GL::MODE_DOUBLE);
  if (!configuration) {
    /* Warning message. */
    std::stringstream message;
    message << "Impossible to configure double buffered OpenGL mode, "
            << "trying single buffered mode.\n";
    g_warning(message.str().c_str());
    /* Trying to configure single buffered mode. */
    configuration = Gdk::GL::Config::create(Gdk::GL::MODE_RGBA  |
                                            Gdk::GL::MODE_DEPTH);
    if (!configuration) throw Errors::GLConfigurationError ();
  }

  /* Guves OpenGL capability to the widget. */
  set_gl_capability(configuration);
}

/* -- GlDrawingArea destructor. -------------------------------------- */
Interface::GlDrawingArea::~GlDrawingArea () {
}

/* -- OpenGL context configuration. --------------------------------- */
void Interface::GlDrawingArea::on_realize () {
  /* First standard initialisation. */
  Gtk::Widget::on_realize();

  if (!create_gl_context()) throw Erreurs::ContextCreationError ();
  /* OpenGL window. */
  Glib::RefPtr<Gdk::GL::Window> glWindow = get_gl_window();
  if (!glWindow) throw Errors::GettingContextError ();

  glWindow->gl_begin(get_gl_context());

    /* Great shading. */
    glShadeModel(GL_SMOOTH);

    /* Black foreground. */
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    /* Initialising depth buffer. */
    glClearDepth(1.0f);
    /* Enabling depth test. */
    glEnable(GL_DEPTH_TEST);
    /* Setting depth test mode. */
    glDepthFunc(GL_LEQUAL);

    /* Nice perspective computation. */
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

  fenetreGl->gl_end();
}

/* -- When displaying GlDrawingArea. ------------------------ */
bool Interface::GlDrawingArea::on_expose_event (GdkEventExpose* event) {
  /* OpenGL window. */
  Glib::RefPtr<Gdk::GL::Window> glWindow = get_gl_window();
  if (!glWindow)  throw Errors::GettingContextError ();

  glWindow->gl_begin(get_gl_context());

    /* Clear screen and Z-Buffer (Depth Buffer: contains each pixel
       depth). */
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    /* Camera re-positionning. */
    glLoadIdentity();

    /* Moves 1.5 units left and 6.0 units inside screen. */
    glTranslatef(-1.5f,0.0f,-6.0f);

    /* Drawing a triangle. */
    glBegin(GL_TRIANGLES);
      /* Upper vertex. */
      glVertex3f( 0.0f, 1.0f, 0.0f);
      /* Low left vertex. */
      glVertex3f(-1.0f,-1.0f, 0.0f);
      /* Low right vertex */
      glVertex3f( 1.0f,-1.0f, 0.0f);
    /* End of triangle drawing. */
    glEnd();

    /* Moves 3 units right. */
    glTranslatef(3.0f,0.0f,0.0f);

    /* Quad drawing. */
    glBegin(GL_QUADS);
      /* Upper left. */
      glVertex3f(-1.0f, 1.0f, 0.0f);
      /* Upper right. */
      glVertex3f( 1.0f, 1.0f, 0.0f);
      /* Lower right. */
      glVertex3f( 1.0f,-1.0f, 0.0f);
      /* Lower left. */
      glVertex3f(-1.0f,-1.0f, 0.0f);
    glEnd();

  fenetreGl->gl_end();
  fenetreGl->swap_buffers();

  /* Standard drawing procedure. */
  return Gtk::Widget::on_expose_event(event);
}

/* -- When resizing window. ----------------------------- */
bool Interface::GlDrawingArea::on_configure_event (GdkEventConfigure*
event) {
  /* OpenGL window. */
  Glib::RefPtr<Gdk::GL::Window> glWindow = get_gl_window();
  if (!fenetreGl)  throw Errors::GettingContextError ();

  fenetreGl->gl_begin(get_gl_context());

    /* Picking projection matrix. */
    glMatrixMode(GL_PROJECTION);
    /* Clearing projection matrix. */
    glLoadIdentity();

    /* Perspective ratio for the window. */
    gluPerspective(45.0f, static_cast<GLfloat>(get_width())
                            / static_cast<GLfloat>(get_height()),
                   0.1f,100.0f);
    /* Picking modelling matrix. */
    glMatrixMode(GL_MODELVIEW);
    /* Clearing modelling matrix. */
    glLoadIdentity();

  fenetreGl->gl_end();

  /* Standard part of resizing. */
  return Gtk::Widget::on_configure_event(event);
}

/* -- MainWindow default constructor. ----------------------------- */
Interface::MainWindow::MainWindow (): Gtk::Window (), zoneRendu () {
  set_title("Tutoriel 1");
  set_default_size(640, 480);
  /* Minimum size, to avoid zero devide. */
  set_size_request(1, 1);

  add(drawingArea);

  add_events(Gdk::KEY_RELEASE_MASK);

  signal_key_release_event().connect(sigc::mem_fun(*this,

&MainWindow::on_key_release));
  signal_window_state_event().connect(sigc::mem_fun(*this,

&MainWindow::on_window_state_event));

  /* Dialogue box for full-screen mode. */
  Gtk::MessageDialog fullScreen(*this, "Switching in full-screen mode?",
                                false, Gtk::MESSAGE_QUESTION,
                                Gtk::BUTTONS_YES_NO);
  /* User’s choice. */
  int choice = fullScreen.run();

  if (choice == Gtk::RESPONSE_YES) {
    inFullScreen = true;
    fullscreen();
  }
  else {
    set_border_width(2);
    inFullScreen = false;
  }

  show_all_children();
}

/* -- MainWindow destructor. ----------------------------------------- */

Interface::MainWindow::~MainWindow () {
}

/* -- Handling keyboard events. ----------------------------------- */
bool Interface::Fenetre::on_key_release (GdkEventKey* event) {
  switch (event->keyval) {
    case GDK_KEY_Escape:
      hide();
      break;
    case GDK_KEY_F1:
      if (inFullScreen) {
        inFullScreen = false;
        set_border_width(2);
        unfullscreen();
      }
      else {
        inFullScreen = true;
        set_border_width(0);
        fullscreen();
      }
  }

  return true;
}

/* -- When switching in full-screen mode --------------- */
bool Interface::Fenetre::on_window_state_event(GdkEventWindowState* pEven) {
  /* Standard window updating result. */
  const bool result = Gtk::Widget::on_window_state_event(pEven);

  if (result) {
    /* Make sure screen is in intended mode. */
    if (inFullScreen
        && (pEven->changed_mask != GDK_WINDOW_STATE_FULLSCREEN)) {
      set_border_width(2);
      inFullScreen = false;
      unfullscreen();

      /* Error message box. */
      Gtk::MessageDialog pleinEcran (*this,
                                  "Impossible to switch in full-screen
mode",
                                     false, Gtk::MESSAGE_QUESTION,
                                     Gtk::BUTTONS_YES_NO);
      pleinEcran.set_secondary_text("Keep on with windowed mode?");
      /* User’s choice. */
      int choice = pleinEcran.run();
      if (choice == Gtk::RESPONSE_NO) return false;
    }
  }

  return resultat;
}


src/main.cpp:


/*
 * Second lesson: Draing a triangle and a square.
 */

#include <iostream>
#include <gtkmm/main.h>
#include <sstream>
#include <glibmm/error.h>
#include <exception>

#include "errors.hpp"
#include "interface.hpp"

/*
 * Main function of the program.
 * Entry:
 *   argc  Number of arguments.
 *   argv  Values of arguments.
 * Retourne :
 *   0 if everything went well.
 *   -1 in case of GLib error.
 *   -2 in case of OpenGL error.
 *   -3 in case of standard library error.
 *   -4 in case of a non standard error.
 */
int main (int argc, char** argv) {
  try {
    /* Events loop. */
    const Gtk::Main kit(argc, argv);
    Gtk::GL::init(argc, argv);

    /* Main window. */
    Interface::MainWindow mainWindow;

    kit.run(mainWindow);

    return 0;
  }
  catch(const Glib::Error &ex) {
    /* Error message. */
    std::ostringstream message;
    message << "GLib error: " <<  ex.what() << '\n';
    g_warning(message.str().c_str());
    return -1;
  }
  catch (const Erreurs::InterfaceError &e) {
    /* Error message. */
    std::stringstream message;
    message << "OpenGL error: " << e.what() << ".\n";
    g_critical(message.str().c_str());
    return -2;
  }
  catch (const std::exception &e) {
    /* Error message. */
    std::stringstream message;
    message << "Standard library error: " << e.what()
            << '\n';
    g_critical(message.str().c_str());
    return -3;
  }
  catch (...) {
    g_critical("Non-standard exception.\n");
    return -4;
  }
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]