root / trunk / linux / glwindow.cpp

Revision 591, 7.2 kB (checked in by leo, 2 years ago)

Linux fixes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1//
2// OpenGL window
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
11typedef struct
12{
13  GtkWidget  *widget;
14  Display*   xdisplay;
15  GLXContext context;
16} GLWindowPrivate;
17
18// =============================================================================
19// static functions
20
21static gint realize_event (GtkWidget *widget, gpointer data)
22{
23  GLWindow *wnd = (GLWindow*)data;
24
25  wnd->OnInitialUpdate ();
26 
27  return TRUE;
28}
29
30static 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
42static 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
73static 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
93static 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
118static 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/*
127static void destroy_event (GtkWidget *widget, gpointer data)
128{
129  GLWindow *wnd = (GLWindow*)data;
130
131  wnd->DestroyContext ();
132}
133*/
134// =============================================================================
135// GLWindow class
136
137GLWindow::GLWindow (GLWindow *share)
138{
139  m_pShare = share;
140  m_pData = g_malloc (sizeof (GLWindowPrivate));
141}
142
143GLWindow::~GLWindow ()
144{
145  DestroyContext ();
146  g_free (m_pData);
147}
148
149bool 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  // choose visual
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  // Connect signal handlers
209  gtk_signal_connect (GTK_OBJECT (prv->widget), "expose_event",
210                      GTK_SIGNAL_FUNC (expose_event), this);
211  //  gtk_signal_connect (GTK_OBJECT (prv->widget), "destroy",
212  //                      GTK_SIGNAL_FUNC (destroy_event), this);
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
229void 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
242void GLWindow::OnInitialUpdate ()
243{
244  MakeCurrent ();
245  GL_InitializeExtensions ();
246}
247
248bool 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
259void 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
267void GLWindow::Redraw (bool ForceRedraw)
268{
269  GLWindowPrivate *prv = (GLWindowPrivate*)m_pData;
270
271  gtk_widget_draw (prv->widget, (GdkRectangle*)NULL);
272}
273
274void GLWindow::CaptureMouse()
275{
276}
277
278void GLWindow::ReleaseMouse()
279{
280}
Note: See TracBrowser for help on using the browser.