added 3dengfx into the repo, probably not the correct version for this
[summerhack] / src / 3dengfx / src / fxwt / fxwt_gtk.cpp
1 /*
2 This file is part of fxwt, the window system toolkit of 3dengfx.
3
4 Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 /* main fxwt event handling and system abstraction.
22  *
23  * Author: John Tsiombikas 2004
24  */
25
26 #include "3dengfx_config.h"
27
28 #if GFX_LIBRARY == GTK
29
30 #include "gfx_library.h"
31
32 static GdkGLContext *gl_context;
33 static GdkGLDrawable *gl_drawable;
34
35 Vector2 fxwt::get_mouse_pos_normalized() {
36         //TODO: implement this
37         Vector2(0, 0);
38 }
39
40 void fxwt::set_window_title(const char *title) {
41         // TODO: implement this
42 }
43
44 void fxwt::swap_buffers() {
45         gdk_gl_drawable_swap_buffers(gl_drawable);
46 }
47
48 int fxwt::main_loop() {
49         set_verbosity(3);
50         gtk_main();
51         return 0;
52 }
53
54 static void gtk_idle_add(GtkWidget *widget);
55 static void gtk_idle_remove(GtkWidget *widget);
56 static gboolean gtk_key(GtkWidget *widget, GdkEventKey *event, gpointer data);
57 static gboolean gtk_idle(GtkWidget *widget);
58 static gboolean gtk_visible(GtkWidget *widget, GdkEventVisibility *event, gpointer data);
59 static gboolean gtk_map(GtkWidget *widget, GdkEventAny *event, gpointer data);
60 static gboolean gtk_unmap(GtkWidget *widget, GdkEventAny *event, gpointer data);
61 static gboolean gtk_expose(GtkWidget *widget, GdkEventExpose *event, gpointer data);
62 static gboolean gtk_realize(GtkWidget *widget, gpointer data);
63 //static gboolean gtk_reshape(GtkWidget *widget, GdkEventConfigure *event, gpointer data);
64
65 static bool realized; 
66 static unsigned int idle_id;
67
68 void set_gtk_callbacks(GtkWidget *widget) {
69         gtk_widget_add_events(widget, GDK_VISIBILITY_NOTIFY_MASK | GDK_KEY_PRESS_MASK);
70         
71         g_signal_connect_after(g_object(widget), "realize", g_callback(GtkRealize), 0);
72         //g_signal_connect(g_object(widget), "configure_event", g_callback(GtkReshape), 0);
73         g_signal_connect(g_object(widget), "expose_event", g_callback(GtkExpose), 0);
74         g_signal_connect(g_object(widget), "map_event", g_callback(GtkMap), 0);
75         g_signal_connect(g_object(widget), "unmap_event", g_callback(GtkUnmap), 0);
76         g_signal_connect(g_object(widget), "visibility_notify_event", g_callback(GtkVisible), 0);
77
78         g_signal_connect(g_object(widget), "key_press_event", g_callback(GtkKey), 0);
79 }
80
81 static gboolean gtk_key(GtkWidget *widget, GdkEventKey *event, gpointer data) {
82         std::cout << __func__ << std::endl;
83         if(event->type == GDK_KEY_PRESS) {
84                 list<void (*)(int)>::iterator iter = keyb_handlers.begin();
85                 while(iter != keyb_handlers.end()) {
86                         (*iter++)(event->keyval);
87                 }
88         }
89         return TRUE;
90 }
91
92 static void gtk_idle_add(GtkWidget *widget) {
93         if(!idle_id && !idle_handlers.empty()) {
94                 idle_id = g_idle_add_full(GDK_PRIORITY_REDRAW, (GSourceFunc)GtkIdle, widget, 0);
95         }
96 }
97
98 static void gtk_idle_remove(GtkWidget *widget) {
99         if(idle_id) {
100                 g_source_remove(idle_id);
101                 idle_id = 0;
102         }
103 }
104
105 static gboolean gtk_visible(GtkWidget *widget, GdkEventVisibility *event, gpointer data) {
106         if(event->state == GDK_VISIBILITY_FULLY_OBSCURED) {
107                 gtk_idle_remove(widget);
108         } else {
109                 gtk_idle_add(widget);
110         }
111         return TRUE;
112 }
113
114 static gboolean gtk_map(GtkWidget *widget, GdkEventAny *event, gpointer data) {
115         gtk_idle_add(widget);
116         return TRUE;
117 }
118
119 static gboolean gtk_unmap(GtkWidget *widget, GdkEventAny *event, gpointer data) {
120         gtk_idle_remove(widget);
121         return TRUE;
122 }
123
124 static gboolean gtk_expose(GtkWidget *widget, GdkEventExpose *event, gpointer data) {
125         gdk_gl_drawable_gl_begin(gl_drawable, gl_context);
126         
127         if(!realized) {
128                 return TRUE;
129         }
130
131         list<void (*)()>::iterator iter = disp_handlers.begin();
132         while(iter != disp_handlers.end()) {
133                 (*iter++)();
134         }
135
136         gdk_gl_drawable_gl_end(gl_drawable);
137         
138         return TRUE;
139 }
140
141 static gboolean gtk_idle(GtkWidget *widget) {
142         if(!realized) return TRUE;
143         
144         gdk_window_invalidate_rect(widget->window, &widget->allocation, FALSE);
145         gdk_window_process_updates(widget->window, FALSE);
146         
147         return TRUE;
148 }
149
150 static gboolean gtk_realize(GtkWidget *widget, gpointer data) {
151         gl_context = gtk_widget_get_gl_context(widget);
152         gl_drawable = gtk_widget_get_gl_drawable(widget);
153   
154         if(!gdk_gl_drawable_gl_begin(gl_drawable, gl_context)) {
155                 error("%s: this shouldn't happen", __func__);
156                 return FALSE;
157         }
158         
159         if(!start_gl()) {
160                 exit(-1);
161         }
162         
163         gdk_gl_drawable_gl_end(gl_drawable);
164
165         realized = true;
166         return TRUE;
167 }
168
169 #if 0
170 static gboolean gtk_reshape(GtkWidget *widget, GdkEventConfigure *event, gpointer data) {
171         GLfloat h = (GLfloat) (widget->allocation.height) / (GLfloat) (widget->allocation.width);
172
173         /*** OpenGL BEGIN ***/
174         if(!gdk_gl_drawable_gl_begin(gldrawable, glcontext)) {
175                 return FALSE;
176         }
177         
178         glViewport (0, 0, widget->allocation.width, widget->allocation.height);
179         glMatrixMode (GL_PROJECTION);
180         glLoadIdentity ();
181         glFrustum (-1.0, 1.0, -h, h, 5.0, 60.0);
182         glMatrixMode (GL_MODELVIEW);
183         glLoadIdentity ();
184         glTranslatef (0.0, 0.0, -40.0);
185         
186         gdk_gl_drawable_gl_end (gldrawable);
187         /*** OpenGL END ***/
188         return TRUE;
189 }
190 #endif
191
192 #endif  // GFX_LIBRARY == GTK