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