[GtkGLExt] Gtk::GL::DrawingArea and multi headed environment



Hi,
I'm trying to move a previously opened Gtk::GL::DrawingArea (on a
multi headed platform) from a screen to another, but if I try to set
the screen (using set_screen) from the parent widget the program
crashed with the message:

...
INFO : GearsScene::on_realize() :
this->get_screen()->make_display_name () : :0.2
The program 'testGTKMultiHead' received an X Window System error.
This probably reflects a bug in the program.
The error was 'BadMatch (invalid parameter attributes)'.
  (Details: serial 95362 error_code 8 request_code 1 minor_code 0)
  (Note to programmers: normally, X errors are reported asynchronously;
  that is, you will receive the error a while after causing it.
  To debug your program, run it with the --sync command line
  option to change this behavior. You can then get a meaningful
  backtrace from your debugger if you break on the gdk_x_error() function.)
...


The code works whitout Gtk::GL::DrawingArea, and the widget is moved
from a screen to another by setting the screen with set_screen.
I initialize the set_gl_capability with:
        glconfig = Gdk::GL::Config::create (pDestScreen,
Gdk::GL::MODE_RGB | Gdk::GL::MODE_DEPTH | Gdk::GL::MODE_DOUBLE );
and the window appear on the selected monitor, but if I try to
redefine the scren the application crashes.

If I try to redefine set_gl_capability with the new screen It say:
(testGTKMultiHead:13135): GtkGLExt-CRITICAL **:
gtk_widget_set_gl_capability: assertion `!GTK_WIDGET_REALIZED
(widget)' failed

My question is:
there is a way to redefine the screen in order to display the widget
with the Gtk::GL::DrawingArea on a different monitor? If yes How can I
do that?
Or do I have to reopen the window?

I'm using gtkglextmm version 1.2.0
The monitors I'm using are different in resolution and color Depth.

Thanks in advance for any help provided.
bye
Angelo

ps.
if needed the source code is attached to the mail, is a modified
version of gear.
// -*- C++ -*-
/*
 * 3-D gear wheels.  This program is in the public domain.
 *
 * Brian Paul
 */
 
/*
 * Modified by Angelo Leto <angleto gmail com>
 * in order to make it working in a multi headed environment
 * added functionality for switching screen
 */

/* Conversion to gtkglextmm by Naofumi Yasufuku */

#include <iostream>
#include <sstream>
#include <cstdlib>
#include <cmath>

#include <gtkmm.h>

#include <gtkglmm.h>

#include <GL/gl.h>
#include <GL/glu.h>

#include <gdk/gdk.h>
#include <gtk/gtkgl.h>

//
// OpenGL frame buffer configuration utilities.
//

struct GLConfigUtil
{
	static void print_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig,
			const char* attrib_str,
			int attrib,
			bool is_boolean);

	static void examine_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig);
};

//
// Print a configuration attribute.
//
void GLConfigUtil::print_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig,
		const char* attrib_str,
		int attrib,
		bool is_boolean)
{
	int value;

	if (glconfig->get_attrib(attrib, value))
	{
		std::cout << attrib_str << " = ";
		if (is_boolean)
			std::cout << (value == true ? "true" : "false") << std::endl;
		else
			std::cout << value << std::endl;
	}
	else
	{
		std::cout << "*** Cannot get "
			<< attrib_str
			<< " attribute value\n";
	}
}

//
// Print configuration attributes.
//
void GLConfigUtil::examine_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig)
{
	std::cout << "\nOpenGL visual configurations :\n\n";

	std::cout << "glconfig->is_rgba() = "
		<< (glconfig->is_rgba() ? "true" : "false")
		<< std::endl;
	std::cout << "glconfig->is_double_buffered() = "
		<< (glconfig->is_double_buffered() ? "true" : "false")
		<< std::endl;
	std::cout << "glconfig->is_stereo() = "
		<< (glconfig->is_stereo() ? "true" : "false")
		<< std::endl;
	std::cout << "glconfig->has_alpha() = "
		<< (glconfig->has_alpha() ? "true" : "false")
		<< std::endl;
	std::cout << "glconfig->has_depth_buffer() = "
		<< (glconfig->has_depth_buffer() ? "true" : "false")
		<< std::endl;
	std::cout << "glconfig->has_stencil_buffer() = "
		<< (glconfig->has_stencil_buffer() ? "true" : "false")
		<< std::endl;
	std::cout << "glconfig->has_accum_buffer() = "
		<< (glconfig->has_accum_buffer() ? "true" : "false")
		<< std::endl;

	std::cout << std::endl;

	print_gl_attrib(glconfig, "Gdk::GL::USE_GL",           Gdk::GL::USE_GL,           true);
	print_gl_attrib(glconfig, "Gdk::GL::BUFFER_SIZE",      Gdk::GL::BUFFER_SIZE,      false);
	print_gl_attrib(glconfig, "Gdk::GL::LEVEL",            Gdk::GL::LEVEL,            false);
	print_gl_attrib(glconfig, "Gdk::GL::RGBA",             Gdk::GL::RGBA,             true);
	print_gl_attrib(glconfig, "Gdk::GL::DOUBLEBUFFER",     Gdk::GL::DOUBLEBUFFER,     true);
	print_gl_attrib(glconfig, "Gdk::GL::STEREO",           Gdk::GL::STEREO,           true);
	print_gl_attrib(glconfig, "Gdk::GL::AUX_BUFFERS",      Gdk::GL::AUX_BUFFERS,      false);
	print_gl_attrib(glconfig, "Gdk::GL::RED_SIZE",         Gdk::GL::RED_SIZE,         false);
	print_gl_attrib(glconfig, "Gdk::GL::GREEN_SIZE",       Gdk::GL::GREEN_SIZE,       false);
	print_gl_attrib(glconfig, "Gdk::GL::BLUE_SIZE",        Gdk::GL::BLUE_SIZE,        false);
	print_gl_attrib(glconfig, "Gdk::GL::ALPHA_SIZE",       Gdk::GL::ALPHA_SIZE,       false);
	print_gl_attrib(glconfig, "Gdk::GL::DEPTH_SIZE",       Gdk::GL::DEPTH_SIZE,       false);
	print_gl_attrib(glconfig, "Gdk::GL::STENCIL_SIZE",     Gdk::GL::STENCIL_SIZE,     false);
	print_gl_attrib(glconfig, "Gdk::GL::ACCUM_RED_SIZE",   Gdk::GL::ACCUM_RED_SIZE,   false);
	print_gl_attrib(glconfig, "Gdk::GL::ACCUM_GREEN_SIZE", Gdk::GL::ACCUM_GREEN_SIZE, false);
	print_gl_attrib(glconfig, "Gdk::GL::ACCUM_BLUE_SIZE",  Gdk::GL::ACCUM_BLUE_SIZE,  false);
	print_gl_attrib(glconfig, "Gdk::GL::ACCUM_ALPHA_SIZE", Gdk::GL::ACCUM_ALPHA_SIZE, false);

	std::cout << std::endl;
}

class GearsScene : public Gtk::GL::DrawingArea
{
	public:
		explicit GearsScene(bool is_sync = true, Glib::RefPtr< Gdk::Screen > pDestScreen = Gdk::Screen::get_default());
		virtual ~GearsScene();

	protected:

		void gear(GLfloat inner_radius,
				GLfloat outer_radius,
				GLfloat width,
				GLint   teeth,
				GLfloat tooth_depth);

	protected:
		// signal handlers:
		virtual void on_realize();
		virtual bool on_configure_event(GdkEventConfigure* event);
		virtual bool on_expose_event(GdkEventExpose* event);
		virtual bool on_map_event(GdkEventAny* event);
		virtual bool on_unmap_event(GdkEventAny* event);
		virtual bool on_visibility_notify_event(GdkEventVisibility* event);
		virtual bool on_idle();

	public:

		void invalidate()
		{
			gdk_threads_enter();
			Gdk::Rectangle rect = get_allocation();
			get_window()->invalidate_rect(rect, false);
			gdk_flush();
			gdk_threads_leave();
		}

		// Update window synchronously (fast).
		void update()
		{ get_window()->process_updates(false); }

	protected:
		// idle signal connection:
		SigC::Connection m_ConnectionIdle;

	public:
		// get & set view rotation values.
		void get_view_rot(GLfloat& x, GLfloat& y, GLfloat& z)
		{ x = m_ViewRotX; y = m_ViewRotY; z = m_ViewRotZ; }

		void set_view_rot(GLfloat x, GLfloat y, GLfloat z)
		{ m_ViewRotX = x; m_ViewRotY = y; m_ViewRotZ = z; }
		Glib::RefPtr<Gdk::GL::Config> ConfigureGLWindow(Glib::RefPtr< Gdk::Screen > pDestScreen);

	protected:
		// OpenGL scene related variables:
		GLint m_Gear1;
		GLint m_Gear2;
		GLint m_Gear3;

		GLfloat m_ViewRotX;
		GLfloat m_ViewRotY;
		GLfloat m_ViewRotZ;

		GLfloat m_Angle;

		bool m_IsSync;

	protected:
		// frame rate evaluation stuff:
		Glib::Timer m_Timer;
		int m_Frames;
};


Glib::RefPtr<Gdk::GL::Config> GearsScene::ConfigureGLWindow(Glib::RefPtr< Gdk::Screen > pDestScreen)
{
	Glib::RefPtr<Gdk::GL::Config> glconfig;

	// Try double-buffered visual
	std::cout << "Gdk::GL::Config::create" << std::endl;
	glconfig = Gdk::GL::Config::create (pDestScreen, Gdk::GL::MODE_RGB | Gdk::GL::MODE_DEPTH | Gdk::GL::MODE_DOUBLE );

	if (glconfig == 0)
	{
		std::cerr << "*** Cannot find the double-buffered visual.\n"
			<< "*** Trying single-buffered visual.\n";

		// Try single-buffered visual
		glconfig = Gdk::GL::Config::create(pDestScreen, Gdk::GL::MODE_RGB | Gdk::GL::MODE_DEPTH);
		if (glconfig == 0)
		{
			std::cerr << "*** Cannot find any OpenGL-capable visual.\n";
			std::exit(1);
		}
	}

	GLConfigUtil::examine_gl_attrib(glconfig);

	if(!set_gl_capability(glconfig) || !is_gl_capable())
		{
		Gtk::MessageDialog e("Couldn't set OpenGL capability.\nPlease ensure that OpenGL drivers are installed correctly.", Gtk::MESSAGE_ERROR);
					e.run();
		}

	return glconfig;
}


	GearsScene::GearsScene(bool is_sync, Glib::RefPtr< Gdk::Screen > pDestScreen)
: m_Gear1(0), m_Gear2(0), m_Gear3(0),
	m_ViewRotX(20.0), m_ViewRotY(30.0), m_ViewRotZ(0.0),
	m_Angle(0.0), m_IsSync(is_sync),
	m_Frames(0)
{
	//
	// Configure OpenGL-capable visual.
	//

	Glib::RefPtr<Gdk::GL::Config> glconfig = this->ConfigureGLWindow(pDestScreen);

	// Add events.

	add_events(Gdk::VISIBILITY_NOTIFY_MASK);

	std::cout << "INFO : GearsScene::GearsScene : this->get_screen()->make_display_name () : " << this->get_screen()->make_display_name () << std::endl;
	std::cout << "INFO : GearsScene::GearsScene : glconfig->get_screen()->make_display_name () : " << glconfig->get_screen()->make_display_name () << std::endl;

}

GearsScene::~GearsScene()
{
}

/*
 * Draw a gear wheel.  You'll probably want to call this function when
 * building a display list since we do a lot of trig here.
 *
 * Input:  inner_radius - radius of hole at center
 * outer_radius - radius at center of teeth
 * width - width of gear
 * teeth - number of teeth
 * tooth_depth - depth of tooth
 */

void GearsScene::gear(GLfloat inner_radius,
		GLfloat outer_radius,
		GLfloat width,
		GLint   teeth,
		GLfloat tooth_depth)
{
	GLint i;
	GLfloat r0, r1, r2;
	GLfloat angle, da;
	GLfloat u, v, len;

	r0 = inner_radius;
	r1 = outer_radius - tooth_depth / 2.0;
	r2 = outer_radius + tooth_depth / 2.0;

	da = 2.0 * G_PI / teeth / 4.0;

	glShadeModel(GL_FLAT);

	glNormal3f(0.0, 0.0, 1.0);

	/* draw front face */
	glBegin(GL_QUAD_STRIP);
	for (i = 0; i <= teeth; i++) {
		angle = i * 2.0 * G_PI / teeth;
		glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
		glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
		if (i < teeth) {
			glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
			glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
		}
	}
	glEnd();

	/* draw front sides of teeth */
	glBegin(GL_QUADS);
	da = 2.0 * G_PI / teeth / 4.0;
	for (i = 0; i < teeth; i++) {
		angle = i * 2.0 * G_PI / teeth;

		glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
		glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
		glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5);
		glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
	}
	glEnd();

	glNormal3f(0.0, 0.0, -1.0);

	/* draw back face */
	glBegin(GL_QUAD_STRIP);
	for (i = 0; i <= teeth; i++) {
		angle = i * 2.0 * G_PI / teeth;
		glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
		glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
		if (i < teeth) {
			glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
			glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
		}
	}
	glEnd();

	/* draw back sides of teeth */
	glBegin(GL_QUADS);
	da = 2.0 * G_PI / teeth / 4.0;
	for (i = 0; i < teeth; i++) {
		angle = i * 2.0 * G_PI / teeth;

		glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
		glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5);
		glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
		glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
	}
	glEnd();

	/* draw outward faces of teeth */
	glBegin(GL_QUAD_STRIP);
	for (i = 0; i < teeth; i++) {
		angle = i * 2.0 * G_PI / teeth;

		glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
		glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
		u = r2 * cos(angle + da) - r1 * cos(angle);
		v = r2 * sin(angle + da) - r1 * sin(angle);
		len = sqrt(u * u + v * v);
		u /= len;
		v /= len;
		glNormal3f(v, -u, 0.0);
		glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
		glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
		glNormal3f(cos(angle), sin(angle), 0.0);
		glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5);
		glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5);
		u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
		v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
		glNormal3f(v, -u, 0.0);
		glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
		glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
		glNormal3f(cos(angle), sin(angle), 0.0);
	}

	glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
	glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);

	glEnd();

	glShadeModel(GL_SMOOTH);

	/* draw inside radius cylinder */
	glBegin(GL_QUAD_STRIP);
	for (i = 0; i <= teeth; i++) {
		angle = i * 2.0 * G_PI / teeth;
		glNormal3f(-cos(angle), -sin(angle), 0.0);
		glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
		glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
	}
	glEnd();

}

void GearsScene::on_realize()
{
	// We need to call the base on_realize()
	std::cout << "INFO : GearsScene::on_realize() : this->get_screen()->make_display_name () : " << this->get_screen()->make_display_name () << std::endl;
	//Glib::RefPtr<const Gtk::Window> lParentW = Gtk::DrawingArea::get_root_window();
	Gtk::DrawingArea::on_realize();

	//
	// Get GL::Drawable.
	//

	Glib::RefPtr<Gdk::GL::Drawable> gldrawable = get_gl_drawable();

	//
	// GL calls.
	//

	// *** OpenGL BEGIN ***
	if (!gldrawable->gl_begin(get_gl_context()))
		return;

	static GLfloat pos[4] = {5.0, 5.0, 10.0, 0.0};
	static GLfloat red[4] = {0.8, 0.1, 0.0, 1.0};
	static GLfloat green[4] = {0.0, 0.8, 0.2, 1.0};
	static GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0};

	glLightfv(GL_LIGHT0, GL_POSITION, pos);
	glEnable(GL_CULL_FACE);
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glEnable(GL_DEPTH_TEST);

	// Make the gears.
	m_Gear1 = glGenLists(1);
	glNewList(m_Gear1, GL_COMPILE);
	glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
	gear(1.0, 4.0, 1.0, 20, 0.7);
	glEndList();

	m_Gear2 = glGenLists(1);
	glNewList(m_Gear2, GL_COMPILE);
	glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
	gear(0.5, 2.0, 2.0, 10, 0.7);
	glEndList();

	m_Gear3 = glGenLists(1);
	glNewList(m_Gear3, GL_COMPILE);
	glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
	gear(1.3, 2.0, 0.5, 10, 0.7);
	glEndList();

	glEnable(GL_NORMALIZE);

	std::cout << "GL RENDERER AND DRIVER INFORMATIONS" << std::endl;

	std::cout << "GL_RENDERER   = " << glGetString(GL_RENDERER)   << std::endl;
	std::cout << "GL_VERSION    = " << glGetString(GL_VERSION)    << std::endl;
	std::cout << "GL_VENDOR     = " << glGetString(GL_VENDOR)     << std::endl;
	std::cout << "GL_EXTENSIONS = " << glGetString(GL_EXTENSIONS) << std::endl;
	std::cout << std::endl;

	gldrawable->gl_end();
	// *** OpenGL END ***

	// Start timer.
	m_Timer.start();
}

bool GearsScene::on_configure_event(GdkEventConfigure* event)
{

	//std::cout << "Configure Event" << std::endl;
	//
	// Get GL::Drawable.
	//

	Glib::RefPtr<Gdk::GL::Drawable> gldrawable = get_gl_drawable();

	//
	// GL calls.
	//

	// *** OpenGL BEGIN ***
	if (!gldrawable->gl_begin(get_gl_context()))
		return false;

	GLfloat h = (GLfloat)(get_height()) / (GLfloat)(get_width());

	glViewport(0, 0, get_width(), get_height());
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glTranslatef(0.0, 0.0, -40.0);

	gldrawable->gl_end();
	// *** OpenGL END ***

	return true;
}

bool GearsScene::on_expose_event(GdkEventExpose* event)
{

	//std::cout << "Expose Event" << std::endl;
	//
	// Get GL::Drawable.
	//

	Glib::RefPtr<Gdk::GL::Drawable> gldrawable = get_gl_drawable();

	//
	// GL calls.
	//

	// *** OpenGL BEGIN ***
	if (!gldrawable->gl_begin(get_gl_context()))
		return false;

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glPushMatrix();
	glRotatef(m_ViewRotX, 1.0, 0.0, 0.0);
	glRotatef(m_ViewRotY, 0.0, 1.0, 0.0);
	glRotatef(m_ViewRotZ, 0.0, 0.0, 1.0);

	glPushMatrix();
	glTranslatef(-3.0, -2.0, 0.0);
	glRotatef(m_Angle, 0.0, 0.0, 1.0);
	glCallList(m_Gear1);
	glPopMatrix();

	glPushMatrix();
	glTranslatef(3.1, -2.0, 0.0);
	glRotatef(-2.0 * m_Angle - 9.0, 0.0, 0.0, 1.0);
	glCallList(m_Gear2);
	glPopMatrix();

	glPushMatrix();
	glTranslatef(-3.1, 4.2, 0.0);
	glRotatef(-2.0 * m_Angle - 25.0, 0.0, 0.0, 1.0);
	glCallList(m_Gear3);
	glPopMatrix();

	glPopMatrix();

	// Swap buffers.
	if (gldrawable->is_double_buffered())
		gldrawable->swap_buffers();
	else
		glFlush();

	gldrawable->gl_end();
	// *** OpenGL END ***

	//
	// Print frame rate.
	//

	++m_Frames;

	double seconds = m_Timer.elapsed();
	if (seconds >= 5.0)
	{
		// std::cout.setf(std::ios_base::fixed, std::ios_base::floatfield);
		std::cout.setf(std::ios::fixed, std::ios::floatfield);
		std::cout.precision(3);
		std::cout << m_Frames << " frames in "
			<< seconds << " seconds = "
			<< (m_Frames / seconds) << " FPS\n";
		m_Timer.reset();
		m_Frames = 0;
	}

	return true;
}

bool GearsScene::on_map_event(GdkEventAny* event)
{
	std::cout << "Map Event" << std::endl;
	if (!m_ConnectionIdle.connected())
		m_ConnectionIdle = Glib::signal_idle().connect(
				sigc::mem_fun(*this, &GearsScene::on_idle), GDK_PRIORITY_REDRAW);

	return true;
}

bool GearsScene::on_unmap_event(GdkEventAny* event)
{
	std::cout << "UnMap Event" << std::endl;
	if (m_ConnectionIdle.connected())
		m_ConnectionIdle.disconnect();

	return true;
}

bool GearsScene::on_visibility_notify_event(GdkEventVisibility* event)
{
	if (event->state == GDK_VISIBILITY_FULLY_OBSCURED)
	{
		if (m_ConnectionIdle.connected())
			m_ConnectionIdle.disconnect();
	}
	else
	{
		if (!m_ConnectionIdle.connected())
			m_ConnectionIdle = Glib::signal_idle().connect(
					sigc::mem_fun(*this, &GearsScene::on_idle), GDK_PRIORITY_REDRAW);
	}

	return true;
}

bool GearsScene::on_idle()
{
	m_Angle += 2.0;

	// Invalidate the whole window.
	invalidate();

	// Update window synchronously (fast).
	if (m_IsSync)
		update();

	return true;
}


//
// The application class.
//

class Gears : public Gtk::Window
{
	public:
		explicit Gears(bool is_sync = true, Glib::RefPtr< Gdk::Screen > pDestScreen = Gdk::Screen::get_default() );
		virtual ~Gears();

	protected:

		Glib::RefPtr<Gtk::UIManager> mRefUIManager;
		Glib::RefPtr<Gtk::ActionGroup> mRefActionGroup;
		Gtk::Menu* mChangeScreenMenu;
		void onChangeScreen(unsigned short screenN);
		void createChangeScreenActions();

		// signal handlers:
		void on_button_quit_clicked();
		void on_left_mouse_button_clicked();
		bool on_button_press_event(GdkEventButton* pEvent);
		virtual bool on_key_press_event(GdkEventKey* event);

	protected:
		// member widgets:
		Gtk::VBox m_VBox;
		GearsScene m_GearsScene;
		Gtk::Button m_ButtonQuit;
};

Gears::Gears(bool is_sync, Glib::RefPtr< Gdk::Screen > pDestScreen)
	: m_VBox(false, 0), m_GearsScene(is_sync, pDestScreen), m_ButtonQuit("Quit")
{
	//
	// Top-level window.

	set_title("Gears");

	// Get automatically redrawn if any of their children changed allocation.
	set_reallocate_redraws(true);

	add(m_VBox);

	set_screen (pDestScreen);

	add_events(Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK |
			Gdk::BUTTON_MOTION_MASK | Gdk::BUTTON1_MOTION_MASK | Gdk::BUTTON2_MOTION_MASK |
			Gdk::BUTTON3_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK |
			Gdk::KEY_PRESS_MASK | Gdk::KEY_RELEASE_MASK | Gdk::ENTER_NOTIFY_MASK |
			Gdk::LEAVE_NOTIFY_MASK);
	//
	// Gears scene.
	//

	m_GearsScene.set_size_request(300, 300);

	m_VBox.pack_start(m_GearsScene);

	//
	// Simple quit button.
	//

	m_ButtonQuit.signal_clicked().connect(
			sigc::mem_fun(*this, &Gears::on_button_quit_clicked));

	m_VBox.pack_start(m_ButtonQuit, Gtk::PACK_SHRINK, 0);

	//
	// Show window.
	//

	createChangeScreenActions();

	show_all();
}

bool Gears::on_button_press_event(GdkEventButton* pEvent)
{
	Glib::RefPtr< Gdk::Screen > lDestScreen = this->get_screen();
	mChangeScreenMenu->set_screen(lDestScreen);
	mChangeScreenMenu->popup(pEvent->button, pEvent->time);
	return true;
	//on_left_mouse_button_clicked();
}

void Gears::on_left_mouse_button_clicked()
{
	std::cout << "leftButton clicked !! " << std::endl;
}

void Gears::onChangeScreen(unsigned short screenN)
{
	std::cout << "screenN: " << screenN << std::endl;

	Glib::RefPtr< Gdk::Screen > lGdkScreen = Gdk::Screen::get_default();
	Glib::RefPtr< Gdk::Display > lMainDisplay = lGdkScreen->get_display();

	Glib::RefPtr< Gdk::Screen > lDestScreen = lMainDisplay->get_screen (screenN);

	std::cout << "Changing Screen : " << screenN << std::endl ;

	/*Gtk::MessageDialog lDialog("NEW SCREEN", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
	lDialog.set_screen (lDestScreen);
	lDialog.run();
	Glib::RefPtr< Gdk::Screen > lDestScreen2 = lMainDisplay->get_screen (2);
	lDialog.set_screen (lDestScreen2);
	lDialog.run();*/

	set_screen (lDestScreen);
	//m_GearsScene.ConfigureGLWindow(lDestScreen);

}

void Gears::createChangeScreenActions()
{
	mRefActionGroup = Gtk::ActionGroup::create();

	Glib::RefPtr< Gdk::Screen > lGdkScreen = Gdk::Screen::get_default();
	Glib::RefPtr< Gdk::Display > lMainDisplay = lGdkScreen->get_display();
	gint n_screens = lMainDisplay->get_n_screens ();

	std::string menuItems = "";
	for (unsigned short i = 0; i < n_screens; i++)
	{
		std::stringstream lTmpStrStr;
		lTmpStrStr << "Send to Screen: " << i;
		std::string lActionStr = lTmpStrStr.str();
		menuItems = menuItems + "    <menuitem action='" + lActionStr + "'/>";
		//std::cout << "Action String : " << lActionStr << std::endl;
		mRefActionGroup->add(Gtk::Action::create(lActionStr, lActionStr, lActionStr),
				sigc::bind<unsigned int> (sigc::mem_fun(*this, &Gears::onChangeScreen),i));
	}

	mRefUIManager = Gtk::UIManager::create();
	mRefUIManager->insert_action_group(mRefActionGroup);

	menuItems = "<ui> <popup name='PopupMenu'> " + menuItems + "  </popup> </ui> "; 

	Glib::ustring lPopupMenu =  menuItems;
	//std::cout << "xml: " << lPopupMenu << std::endl;

	try
	{
		mRefUIManager->add_ui_from_string(lPopupMenu);
	} catch (const Glib::Error& pE)
	{
		std::cerr << "Error : Creating Menu : " << pE.what() << std::endl;
		return ;
	}

	mChangeScreenMenu = dynamic_cast<Gtk::Menu*>(mRefUIManager->get_widget("/PopupMenu"));
}

Gears::~Gears()
{
}

void Gears::on_button_quit_clicked()
{
	Gtk::Main::quit();
}

bool Gears::on_key_press_event(GdkEventKey* event)
{
	GLfloat x, y, z;

	m_GearsScene.get_view_rot(x, y, z);

	switch (event->keyval)
	{
		case GDK_z:
			z += 5.0;
			break;
		case GDK_Z:
			z -= 5.0;
			break;
		case GDK_Up:
			x += 5.0;
			break;
		case GDK_Down:
			x -= 5.0;
			break;
		case GDK_Left:
			y += 5.0;
			break;
		case GDK_Right:
			y -= 5.0;
			break;
		case GDK_Escape:
			Gtk::Main::quit();
			break;
		default:
			return true;
	}

	m_GearsScene.set_view_rot(x, y, z);

	m_GearsScene.invalidate();

	return true;
}


//
// Main.
//


int main(int argc, char* argv[])
{
	Gtk::Main kit(argc, argv);

	//
	// Init gtkglextmm.
	//

	Gtk::GL::init(argc, argv);

	//
	// Parse arguments.
	//

	bool is_sync = true;


	unsigned short scrN = Gdk::Screen::get_default()->get_number ();

	for (int i = 1; i < argc; i++)
	{
		if (std::strcmp(argv[i], "-a") == 0)
			is_sync = false;
		else if (std::strcmp(argv[i], "-s") == 0)
		{
			int next_i=i+1;
			if (next_i < argc)
			{
				scrN = atoi(argv[next_i]);
				i=next_i;
			}
		}
	}

	//
	// Instantiate and run the application.
	//


	Glib::RefPtr< Gdk::Screen > lGdkScreen = Gdk::Screen::get_default();
	Glib::RefPtr< Gdk::Display > lMainDisplay = lGdkScreen->get_display();

	gint n_screens = lMainDisplay->get_n_screens ();

	if(scrN >= n_screens)
	{
		std::cout << "Display not found! : " << scrN << std::endl;
		return 1;
	}

	Glib::RefPtr< Gdk::Screen > destScreen = lMainDisplay->get_screen (scrN);
	std::cout << "DISPLAY=" <<  destScreen->make_display_name () << std::endl;

	Gears gears(is_sync, destScreen);
	//lWindow->add(gears);
	//gears.set_screen (destScreen);
	std::cout << "INFO : main : gears.get_screen()->make_display_name () : " << gears.get_screen()->make_display_name () << std::endl;
	//gears.reparent(*lWindow);

	//kit.run(*lWindow);
	kit.run(gears);

	return 0;
}



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