| 1 | |
|---|
| 2 | |
|---|
| 3 | |
|---|
| 4 | |
|---|
| 5 | #include <stdio.h> |
|---|
| 6 | #include <gtk/gtk.h> |
|---|
| 7 | #include <gdk/gdkx.h> |
|---|
| 8 | #include "opengl.h" |
|---|
| 9 | #include "glwindow.h" |
|---|
| 10 | |
|---|
| 11 | typedef struct |
|---|
| 12 | { |
|---|
| 13 | GtkWidget *widget; |
|---|
| 14 | Display* xdisplay; |
|---|
| 15 | GLXContext context; |
|---|
| 16 | } GLWindowPrivate; |
|---|
| 17 | |
|---|
| 18 | |
|---|
| 19 | |
|---|
| 20 | |
|---|
| 21 | static gint realize_event (GtkWidget *widget, gpointer data) |
|---|
| 22 | { |
|---|
| 23 | GLWindow *wnd = (GLWindow*)data; |
|---|
| 24 | |
|---|
| 25 | wnd->OnInitialUpdate (); |
|---|
| 26 | |
|---|
| 27 | return TRUE; |
|---|
| 28 | } |
|---|
| 29 | |
|---|
| 30 | static gint expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer data) |
|---|
| 31 | { |
|---|
| 32 | GLWindow *wnd = (GLWindow*)data; |
|---|
| 33 | |
|---|
| 34 | if (event->count > 0) |
|---|
| 35 | return TRUE; |
|---|
| 36 | |
|---|
| 37 | wnd->OnDraw (); |
|---|
| 38 | |
|---|
| 39 | return TRUE; |
|---|
| 40 | } |
|---|
| 41 | |
|---|
| 42 | static gint button_press_event (GtkWidget *widget, GdkEventButton *event, gpointer data) |
|---|
| 43 | { |
|---|
| 44 | GLWindow *wnd = (GLWindow*)data; |
|---|
| 45 | int x, y; |
|---|
| 46 | |
|---|
| 47 | x = (int)event->x; |
|---|
| 48 | y = widget->allocation.height - (int)event->y - 1; |
|---|
| 49 | |
|---|
| 50 | if (event->type == GDK_BUTTON_PRESS) |
|---|
| 51 | { |
|---|
| 52 | if (event->button == 1) |
|---|
| 53 | wnd->OnLeftButtonDown (x, y, (event->state & GDK_CONTROL_MASK) != 0, |
|---|
| 54 | (event->state & GDK_SHIFT_MASK) != 0); |
|---|
| 55 | else if (event->button == 3) |
|---|
| 56 | wnd->OnRightButtonDown (x, y, (event->state & GDK_CONTROL_MASK) != 0, |
|---|
| 57 | (event->state & GDK_SHIFT_MASK) != 0); |
|---|
| 58 | } |
|---|
| 59 | else if (event->type == GDK_2BUTTON_PRESS) |
|---|
| 60 | { |
|---|
| 61 | wnd->OnLeftButtonDoubleClick (x, y, (event->state & GDK_CONTROL_MASK) != 0, |
|---|
| 62 | (event->state & GDK_SHIFT_MASK) != 0); |
|---|
| 63 | } |
|---|
| 64 | |
|---|
| 65 | gtk_window_set_focus (GTK_WINDOW (gtk_widget_get_toplevel (widget)), widget); |
|---|
| 66 | gdk_pointer_grab (widget->window, FALSE, (GdkEventMask)(GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK| |
|---|
| 67 | GDK_POINTER_MOTION_MASK|GDK_POINTER_MOTION_HINT_MASK), |
|---|
| 68 | NULL, NULL, GDK_CURRENT_TIME); |
|---|
| 69 | |
|---|
| 70 | return TRUE; |
|---|
| 71 | } |
|---|
| 72 | |
|---|
| 73 | static gint button_release_event (GtkWidget *widget, GdkEventButton *event, gpointer data) |
|---|
| 74 | { |
|---|
| 75 | GLWindow *wnd = (GLWindow*)data; |
|---|
| 76 | int x, y; |
|---|
| 77 | |
|---|
| 78 | x = (int)event->x; |
|---|
| 79 | y = widget->allocation.height - (int)event->y - 1; |
|---|
| 80 | |
|---|
| 81 | gdk_pointer_ungrab (GDK_CURRENT_TIME); |
|---|
| 82 | |
|---|
| 83 | if (event->button == 1) |
|---|
| 84 | wnd->OnLeftButtonUp (x, y, (event->state & GDK_CONTROL_MASK) != 0, |
|---|
| 85 | (event->state & GDK_SHIFT_MASK) != 0); |
|---|
| 86 | else if (event->button == 3) |
|---|
| 87 | wnd->OnRightButtonUp (x, y, (event->state & GDK_CONTROL_MASK) != 0, |
|---|
| 88 | (event->state & GDK_SHIFT_MASK) != 0); |
|---|
| 89 | |
|---|
| 90 | return TRUE; |
|---|
| 91 | } |
|---|
| 92 | |
|---|
| 93 | static gint pointer_motion_event (GtkWidget *widget, GdkEventMotion *event, gpointer data) |
|---|
| 94 | { |
|---|
| 95 | GLWindow *wnd = (GLWindow*)data; |
|---|
| 96 | GdkModifierType state; |
|---|
| 97 | int x, y; |
|---|
| 98 | |
|---|
| 99 | if (event->is_hint) |
|---|
| 100 | { |
|---|
| 101 | gdk_window_get_pointer (event->window, &x, &y, &state); |
|---|
| 102 | state = (GdkModifierType)0; |
|---|
| 103 | } |
|---|
| 104 | else |
|---|
| 105 | { |
|---|
| 106 | x = (int)event->x; |
|---|
| 107 | y = (int)event->y; |
|---|
| 108 | state = (GdkModifierType)event->state; |
|---|
| 109 | } |
|---|
| 110 | |
|---|
| 111 | y = widget->allocation.height - y - 1; |
|---|
| 112 | |
|---|
| 113 | wnd->OnMouseMove (x, y, (event->state & GDK_CONTROL_MASK) != 0, (event->state & GDK_SHIFT_MASK) != 0); |
|---|
| 114 | |
|---|
| 115 | return TRUE; |
|---|
| 116 | } |
|---|
| 117 | |
|---|
| 118 | static gint size_allocate_event (GtkWidget *widget, GtkAllocation *allocation, gpointer data) |
|---|
| 119 | { |
|---|
| 120 | GLWindow *wnd = (GLWindow*)data; |
|---|
| 121 | |
|---|
| 122 | wnd->OnSize (allocation->width, allocation->height); |
|---|
| 123 | |
|---|
| 124 | return TRUE; |
|---|
| 125 | } |
|---|
| 126 | |
|---|
| 127 | |
|---|
| 128 | |
|---|
| 129 | |
|---|
| 130 | |
|---|
| 131 | |
|---|
| 132 | |
|---|
| 133 | |
|---|
| 134 | |
|---|
| 135 | |
|---|
| 136 | |
|---|
| 137 | GLWindow::GLWindow (GLWindow *share) |
|---|
| 138 | { |
|---|
| 139 | m_pShare = share; |
|---|
| 140 | m_pData = g_malloc (sizeof (GLWindowPrivate)); |
|---|
| 141 | } |
|---|
| 142 | |
|---|
| 143 | GLWindow::~GLWindow () |
|---|
| 144 | { |
|---|
| 145 | DestroyContext (); |
|---|
| 146 | g_free (m_pData); |
|---|
| 147 | } |
|---|
| 148 | |
|---|
| 149 | bool GLWindow::Create (void *data) |
|---|
| 150 | { |
|---|
| 151 | int attrlist[] = { GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 16, 0 }; |
|---|
| 152 | GLWindowPrivate *prv = (GLWindowPrivate*)m_pData; |
|---|
| 153 | Display *dpy = GDK_DISPLAY(); |
|---|
| 154 | GdkVisual *visual; |
|---|
| 155 | XVisualInfo *vi; |
|---|
| 156 | |
|---|
| 157 | |
|---|
| 158 | visual = gdk_visual_get_system (); |
|---|
| 159 | if (visual->depth < 16) |
|---|
| 160 | printf ("OpenGL fatal error: LeoCAD needs a display with at least 16 bit colors.\n"); |
|---|
| 161 | |
|---|
| 162 | if (dpy == NULL) |
|---|
| 163 | { |
|---|
| 164 | printf ("OpenGL fatal error: Cannot get display.\n"); |
|---|
| 165 | return false; |
|---|
| 166 | } |
|---|
| 167 | prv->xdisplay = dpy; |
|---|
| 168 | |
|---|
| 169 | vi = pfnglXChooseVisual (dpy, DefaultScreen (dpy), attrlist); |
|---|
| 170 | if (vi == NULL) |
|---|
| 171 | { |
|---|
| 172 | printf ("OpenGL fatal error: glXChooseVisual failed.\n"); |
|---|
| 173 | return false; |
|---|
| 174 | } |
|---|
| 175 | |
|---|
| 176 | visual = gdkx_visual_get (vi->visualid); |
|---|
| 177 | if (visual == NULL) |
|---|
| 178 | { |
|---|
| 179 | printf ("OpenGL fatal error: Cannot get visual.\n"); |
|---|
| 180 | return false; |
|---|
| 181 | } |
|---|
| 182 | |
|---|
| 183 | gtk_widget_push_colormap (gdk_colormap_new (visual, TRUE)); |
|---|
| 184 | gtk_widget_push_visual (visual); |
|---|
| 185 | |
|---|
| 186 | prv->widget = gtk_drawing_area_new (); |
|---|
| 187 | gtk_widget_set_double_buffered(GTK_WIDGET(prv->widget), FALSE); |
|---|
| 188 | |
|---|
| 189 | if (m_pShare == NULL) |
|---|
| 190 | prv->context = pfnglXCreateContext (dpy, vi, NULL, True); |
|---|
| 191 | else |
|---|
| 192 | { |
|---|
| 193 | GLWindowPrivate *share = (GLWindowPrivate*)m_pShare->m_pData; |
|---|
| 194 | |
|---|
| 195 | prv->context = pfnglXCreateContext (dpy, vi, share->context, True); |
|---|
| 196 | } |
|---|
| 197 | |
|---|
| 198 | gtk_widget_pop_visual (); |
|---|
| 199 | gtk_widget_pop_colormap (); |
|---|
| 200 | |
|---|
| 201 | XFree (vi); |
|---|
| 202 | |
|---|
| 203 | GTK_WIDGET_SET_FLAGS (prv->widget, GTK_CAN_FOCUS); |
|---|
| 204 | |
|---|
| 205 | gtk_widget_set_events (GTK_WIDGET (prv->widget), GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | |
|---|
| 206 | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK); |
|---|
| 207 | |
|---|
| 208 | |
|---|
| 209 | gtk_signal_connect (GTK_OBJECT (prv->widget), "expose_event", |
|---|
| 210 | GTK_SIGNAL_FUNC (expose_event), this); |
|---|
| 211 | |
|---|
| 212 | |
|---|
| 213 | gtk_signal_connect (GTK_OBJECT (prv->widget), "size_allocate", |
|---|
| 214 | GTK_SIGNAL_FUNC (size_allocate_event), this); |
|---|
| 215 | gtk_signal_connect (GTK_OBJECT (prv->widget), "motion_notify_event", |
|---|
| 216 | GTK_SIGNAL_FUNC (pointer_motion_event), this); |
|---|
| 217 | gtk_signal_connect (GTK_OBJECT (prv->widget), "button_press_event", |
|---|
| 218 | GTK_SIGNAL_FUNC (button_press_event), this); |
|---|
| 219 | gtk_signal_connect (GTK_OBJECT (prv->widget), "button_release_event", |
|---|
| 220 | GTK_SIGNAL_FUNC (button_release_event), this); |
|---|
| 221 | gtk_signal_connect (GTK_OBJECT (prv->widget), "realize", |
|---|
| 222 | GTK_SIGNAL_FUNC (realize_event), this); |
|---|
| 223 | |
|---|
| 224 | *((GtkWidget**)data) = prv->widget; |
|---|
| 225 | |
|---|
| 226 | return true; |
|---|
| 227 | } |
|---|
| 228 | |
|---|
| 229 | void GLWindow::DestroyContext () |
|---|
| 230 | { |
|---|
| 231 | GLWindowPrivate *prv = (GLWindowPrivate*)m_pData; |
|---|
| 232 | |
|---|
| 233 | if (prv->context == pfnglXGetCurrentContext ()) |
|---|
| 234 | pfnglXMakeCurrent (prv->xdisplay, None, NULL); |
|---|
| 235 | |
|---|
| 236 | if (prv->context) |
|---|
| 237 | pfnglXDestroyContext (prv->xdisplay, prv->context); |
|---|
| 238 | |
|---|
| 239 | prv->context = NULL; |
|---|
| 240 | } |
|---|
| 241 | |
|---|
| 242 | void GLWindow::OnInitialUpdate () |
|---|
| 243 | { |
|---|
| 244 | MakeCurrent (); |
|---|
| 245 | GL_InitializeExtensions (); |
|---|
| 246 | } |
|---|
| 247 | |
|---|
| 248 | bool GLWindow::MakeCurrent () |
|---|
| 249 | { |
|---|
| 250 | GLWindowPrivate *prv = (GLWindowPrivate*)m_pData; |
|---|
| 251 | gboolean ret = false; |
|---|
| 252 | |
|---|
| 253 | if (prv->context) |
|---|
| 254 | ret = pfnglXMakeCurrent (prv->xdisplay, GDK_WINDOW_XWINDOW (prv->widget->window), prv->context); |
|---|
| 255 | |
|---|
| 256 | return ret; |
|---|
| 257 | } |
|---|
| 258 | |
|---|
| 259 | void GLWindow::SwapBuffers () |
|---|
| 260 | { |
|---|
| 261 | GLWindowPrivate *prv = (GLWindowPrivate*)m_pData; |
|---|
| 262 | |
|---|
| 263 | if (prv->context) |
|---|
| 264 | pfnglXSwapBuffers (GDK_WINDOW_XDISPLAY (prv->widget->window), GDK_WINDOW_XWINDOW (prv->widget->window)); |
|---|
| 265 | } |
|---|
| 266 | |
|---|
| 267 | void GLWindow::Redraw (bool ForceRedraw) |
|---|
| 268 | { |
|---|
| 269 | GLWindowPrivate *prv = (GLWindowPrivate*)m_pData; |
|---|
| 270 | |
|---|
| 271 | gtk_widget_draw (prv->widget, (GdkRectangle*)NULL); |
|---|
| 272 | } |
|---|
| 273 | |
|---|
| 274 | void GLWindow::CaptureMouse() |
|---|
| 275 | { |
|---|
| 276 | } |
|---|
| 277 | |
|---|
| 278 | void GLWindow::ReleaseMouse() |
|---|
| 279 | { |
|---|
| 280 | } |
|---|