#include <stdlib.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>

GLXContext context;

int
area_start(GtkWidget * widget, void *data)
{
	GdkWindow *window;
	Display *display;
	int id;

	window = gtk_widget_get_window(widget);
	display = gdk_x11_display_get_xdisplay(gdk_window_get_display(window));
	id = gdk_x11_window_get_xid(window);

	if (glXMakeCurrent(display, id, context) == TRUE) {
		glEnable(GL_DEPTH_TEST);
		glDepthFunc(GL_LEQUAL);
		glEnable(GL_CULL_FACE);
		glCullFace(GL_BACK);
		glDisable(GL_DITHER);
		glShadeModel(GL_SMOOTH);
	}

	return TRUE;
}

int
area_expose(GtkWidget * widget, cairo_t * cr, void *data)
{
	GdkWindow *window;
	Display *display;
	int id;

	window = gtk_widget_get_window(widget);
	display = gdk_x11_display_get_xdisplay(gdk_window_get_display(window));
	id = gdk_x11_window_get_xid(window);

	if (glXMakeCurrent(display, id, context) == TRUE) {
		glClear(GL_DEPTH_BUFFER_BIT);

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glOrtho(0, 100, 100, 0, -1, 1);

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();

		glClearColor(0, 0, 0, 1);
		glClear(GL_COLOR_BUFFER_BIT);
		glColor3f(1, 1, 1);
		glBegin(GL_TRIANGLES);
		glVertex2f(10, 10);
		glVertex2f(10, 90);
		glVertex2f(90, 90);
		glEnd();

		glXSwapBuffers(display, id);
	}

	return TRUE;
}

int
area_configure(GtkWidget * widget, GdkEvent * event, void *data)
{
	GtkAllocation allocation;
	GdkWindow *window;
	Display *display;
	int id;

	window = gtk_widget_get_window(widget);
	display = gdk_x11_display_get_xdisplay(gdk_window_get_display(window));
	id = gdk_x11_window_get_xid(window);

	if (glXMakeCurrent(display, id, context) == TRUE) {
		gtk_widget_get_allocation(widget, &allocation);
		glViewport(0, 0, allocation.width, allocation.height);
	}

	return TRUE;
}

int
main(int argc, char **argv)
{
	GtkWidget *window;
	GtkWidget *area;
	GdkVisual *visual;
	GdkScreen *screen;
	XVisualInfo *xvisual;
	Colormap xcolormap;
	Display *display;
	Window root;
	int xscreen;
	int attributes[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1,
		GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, True, GLX_DEPTH_SIZE, 12,
		None
	};

	gtk_init(&argc, &argv);

	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_window_set_title(GTK_WINDOW(window), "GLX");

	area = gtk_drawing_area_new();
	gtk_widget_set_double_buffered(area, FALSE);

	display = gdk_x11_get_default_xdisplay();
	xscreen = DefaultScreen(display);
	screen = gdk_screen_get_default();
	xvisual = glXChooseVisual(display, xscreen, attributes);
	visual = gdk_x11_screen_lookup_visual(screen, xvisual->visualid);
	root = RootWindow(display, xscreen);
	xcolormap = XCreateColormap(display, root, xvisual->visual, AllocNone);
	gtk_widget_set_visual(window, visual);
	context = glXCreateContext(display, xvisual, NULL, TRUE);

	free(xvisual);

	gtk_container_add(GTK_CONTAINER(window), area);
	gtk_widget_set_size_request(area, 100, 100);
	g_signal_connect(area, "draw", G_CALLBACK(area_expose), window);
	g_signal_connect(area, "configure-event", G_CALLBACK(area_configure),
			 window);
	g_signal_connect(area, "realize", G_CALLBACK(area_start), window);

	gtk_widget_set_events(GTK_WIDGET(area), GDK_EXPOSURE_MASK |
			      GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
			      GDK_POINTER_MOTION_MASK |
			      GDK_POINTER_MOTION_HINT_MASK | GDK_KEY_PRESS_MASK
			      | GDK_KEY_RELEASE_MASK);
	gtk_widget_show(area);

	gtk_widget_show(window);

	gtk_main();

	glXDestroyContext(display, context);
	XFreeColormap(display, xcolormap);
	XFree(xvisual);
	g_object_unref(G_OBJECT(visual));

	return 0;
}
