more eol-style
[xonotic/netradiant.git] / radiant / glwindow.cpp
1 /*
2 Copyright (c) 2001, Loki software, inc.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification, 
6 are permitted provided that the following conditions are met:
7
8 Redistributions of source code must retain the above copyright notice, this list 
9 of conditions and the following disclaimer.
10
11 Redistributions in binary form must reproduce the above copyright notice, this
12 list of conditions and the following disclaimer in the documentation and/or
13 other materials provided with the distribution.
14
15 Neither the name of Loki software nor the names of its contributors may be used 
16 to endorse or promote products derived from this software without specific prior 
17 written permission. 
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
22 DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
23 DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
24 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
26 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
29 */
30
31 //
32 // GLWindow - Base class for the small views used by Radiant
33 //
34 // Leonardo Zide (leo@lokigames.com
35 //
36
37 #include "stdafx.h"
38 #include "glwidget.h"
39 #include "glwindow.h"
40
41 // =============================================================================
42 // static functions
43
44 static void realize (GtkWidget *widget, gpointer data)
45 {
46   GLWindow *wnd = (GLWindow*)data;
47
48   wnd->OnCreate ();
49 }
50
51 static gint expose (GtkWidget *widget, GdkEventExpose *event, gpointer data)
52 {
53   GLWindow *wnd = (GLWindow*)data;
54
55 #ifndef _WIN32
56   if (event->count > 0)
57     return TRUE;
58 #endif
59
60   if (!g_pParentWnd->IsSleeping ())
61     wnd->OnExpose ();
62
63   return TRUE;
64 }
65
66 static void button_press (GtkWidget *widget, GdkEventButton *event, gpointer data)
67 {
68   GLWindow *wnd = (GLWindow*)data;
69   guint32 flags = 0;
70
71   gdk_pointer_grab (widget->window, FALSE,
72                     (GdkEventMask)(GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK),
73                     NULL, NULL, GDK_CURRENT_TIME);
74
75   gtk_window_set_focus (GTK_WINDOW (g_pParentWnd->m_pWidget), widget);
76
77   switch (event->button)
78   {
79   case 1: flags |= MK_LBUTTON; break;
80   case 2: flags |= MK_MBUTTON; break;
81   case 3: flags |= MK_RBUTTON; break;
82 #if !GTK_CHECK_VERSION (1,3,0)
83   case 4: wnd->OnMouseWheel(true); break;
84   case 5: wnd->OnMouseWheel(false); break;
85 #endif
86   }
87
88   if ((event->state & GDK_CONTROL_MASK) != 0)
89     flags |= MK_CONTROL;
90
91   if ((event->state & GDK_SHIFT_MASK) != 0)
92     flags |= MK_SHIFT;
93
94   if (event->type == GDK_BUTTON_PRESS)
95   {
96     switch (event->button)
97     {
98     case 1:
99       wnd->OnLButtonDown (flags, (int)event->x, (int)event->y); break;
100     case 2:
101       wnd->OnMButtonDown (flags, (int)event->x, (int)event->y); break;
102     case 3:
103       wnd->OnRButtonDown (flags, (int)event->x, (int)event->y); break;
104     }
105   }
106   else if (event->type == GDK_2BUTTON_PRESS)
107   {
108     // do nothing
109   }
110 }
111
112 static void button_release (GtkWidget *widget, GdkEventButton *event, gpointer data)
113 {
114   GLWindow *wnd = (GLWindow*)data;
115   guint32 flags = 0;
116
117   gdk_pointer_ungrab (GDK_CURRENT_TIME);
118
119   if ((event->state & GDK_CONTROL_MASK) != 0)
120     flags |= MK_CONTROL;
121
122   if ((event->state & GDK_SHIFT_MASK) != 0)
123     flags |= MK_SHIFT;
124
125   switch (event->button)
126   {
127   case 1:
128     wnd->OnLButtonUp (flags, (int)event->x, (int)event->y); break;
129   case 2:
130     wnd->OnMButtonUp (flags, (int)event->x, (int)event->y); break;
131   case 3:
132     wnd->OnRButtonUp (flags, (int)event->x, (int)event->y); break;
133   }
134 }
135
136 static void motion (GtkWidget *widget, GdkEventMotion *event, gpointer data)
137 {
138   GLWindow *wnd = (GLWindow*)data;
139   guint32 flags = 0;
140
141   if ((event->state & GDK_BUTTON1_MASK) != 0)
142     flags |= MK_LBUTTON;
143
144   if ((event->state & GDK_BUTTON2_MASK) != 0)
145     flags |= MK_MBUTTON;
146
147   if ((event->state & GDK_BUTTON3_MASK) != 0)
148     flags |= MK_RBUTTON;
149
150   if ((event->state & GDK_CONTROL_MASK) != 0)
151     flags |= MK_CONTROL;
152
153   if ((event->state & GDK_SHIFT_MASK) != 0)
154     flags |= MK_SHIFT;
155
156   wnd->OnMouseMove (flags, (int)event->x, (int)event->y);
157 }
158
159 static void resize (GtkWidget *widget, GtkAllocation *allocation, gpointer data)
160 {
161   GLWindow *wnd = (GLWindow*)data;
162   wnd->OnSize (allocation->width, allocation->height);
163 }
164
165 static gint timer (gpointer data)
166 {
167   GLWindow *wnd = (GLWindow*)data;
168   wnd->OnTimer ();
169
170   return TRUE;
171 }
172
173 //! GtkGLExt port.
174 /*
175 static void create_context (GtkWidget *widget, gpointer data)
176 {
177   if (g_qeglobals_gui.d_glBase == NULL)
178     g_qeglobals_gui.d_glBase = widget;
179 }
180
181 static void destroy_context (GtkWidget *widget, gpointer data)
182 {
183   if (g_qeglobals_gui.d_glBase == widget)
184     g_qeglobals_gui.d_glBase = NULL;
185 }
186 */
187
188 #if GTK_CHECK_VERSION (1,3,0)
189 static gint scroll_event( GtkWidget *widget,
190                     GdkEventScroll *event,
191                     gpointer   data )
192 {
193   GLWindow *wnd = (GLWindow*)data;
194   wnd->OnMouseWheel((event->direction == GDK_SCROLL_UP) ? true : false);
195   return TRUE;
196 }
197 #endif
198
199 // =============================================================================
200 // GLWindow class
201
202 #ifdef _DEBUG
203 //#define DBG_GLWINDOW
204 #endif
205
206 GLWindow::GLWindow (bool zbuffer)
207 {
208   m_nTimer = 0;
209   m_bMouseCapture = FALSE;
210   m_pParent = NULL;
211
212   m_pWidget = gtk_glwidget_new (zbuffer, g_qeglobals_gui.d_glBase);
213   GTK_WIDGET_SET_FLAGS (m_pWidget, GTK_CAN_FOCUS);
214
215 #ifdef DBG_GLWINDOW
216   Sys_Printf("GLWindow::GLWindow m_pWidget = %p\n", m_pWidget);
217 #endif
218
219 //! GtkGLExt port.
220 //#if defined (__linux__) || defined (__APPLE__)
221   if (g_qeglobals_gui.d_glBase == NULL)
222     g_qeglobals_gui.d_glBase = m_pWidget;
223 //#endif
224
225 #if GTK_CHECK_VERSION (1,3,0)
226   gtk_widget_set_events (m_pWidget, GDK_DESTROY | GDK_EXPOSURE_MASK |
227                          GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK);
228 #else
229   gtk_widget_set_events (m_pWidget, GDK_DESTROY | GDK_EXPOSURE_MASK |
230                          GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK);
231 #endif
232
233   // Connect signal handlers
234   gtk_signal_connect (GTK_OBJECT (m_pWidget), "realize", GTK_SIGNAL_FUNC (realize), this);
235   gtk_signal_connect (GTK_OBJECT (m_pWidget), "expose_event", GTK_SIGNAL_FUNC (expose), this);
236   gtk_signal_connect (GTK_OBJECT (m_pWidget), "motion_notify_event", GTK_SIGNAL_FUNC (motion), this);
237   gtk_signal_connect (GTK_OBJECT (m_pWidget), "button_press_event", GTK_SIGNAL_FUNC (button_press), this);
238   gtk_signal_connect (GTK_OBJECT (m_pWidget), "button_release_event",GTK_SIGNAL_FUNC (button_release), this);
239   gtk_signal_connect (GTK_OBJECT (m_pWidget), "size_allocate", GTK_SIGNAL_FUNC (resize), this);
240 //! GtkGLExt port.
241 //  gtk_signal_connect (GTK_OBJECT (m_pWidget), "create_context", GTK_SIGNAL_FUNC (create_context), this);
242 //  gtk_signal_connect (GTK_OBJECT (m_pWidget), "destroy_context", GTK_SIGNAL_FUNC (destroy_context), this);
243 #if GTK_CHECK_VERSION (1,3,0)
244   gtk_signal_connect (GTK_OBJECT (m_pWidget), "scroll_event", GTK_SIGNAL_FUNC (scroll_event), this);
245 #endif
246 }
247
248 GLWindow::~GLWindow ()
249 {
250 #ifdef DBG_GLWINDOW
251   Sys_Printf("GLWindow::~GLWindow m_pWidget = %p\n", m_pWidget);
252 #endif
253
254   if (m_pWidget && GTK_IS_WIDGET (m_pWidget))
255     gtk_widget_destroy (m_pWidget);
256 }
257
258 void GLWindow::DestroyContext ()
259 {
260   gtk_glwidget_destroy_context (m_pWidget);
261 }
262
263 void GLWindow::CreateContext ()
264 {
265   gtk_glwidget_create_context (m_pWidget);
266 }
267
268 void GLWindow::SetTimer (guint millisec)
269 {
270   m_nTimer = gtk_timeout_add (millisec, timer, this);
271 }
272
273 void GLWindow::KillTimer ()
274 {
275   gtk_timeout_remove (m_nTimer);
276   m_nTimer = 0;
277 }
278
279 bool GLWindow::MakeCurrent ()
280 {
281   return gtk_glwidget_make_current (m_pWidget);
282 }
283
284 void GLWindow::SwapBuffers ()
285 {
286   gtk_glwidget_swap_buffers (m_pWidget);
287 }