]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/glwindow.cpp
Merge pull request #21 from merlin1991/Q3-gamepack-fix
[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         GLWindow *wnd = (GLWindow*)data;
46
47         wnd->OnCreate();
48 }
49
50 static gint expose( GtkWidget *widget, GdkEventExpose *event, gpointer data ){
51         GLWindow *wnd = (GLWindow*)data;
52
53 #ifndef _WIN32
54         if ( event->count > 0 ) {
55                 return TRUE;
56         }
57 #endif
58
59         if ( !g_pParentWnd->IsSleeping() ) {
60                 wnd->OnExpose();
61         }
62
63         return TRUE;
64 }
65
66 static void button_press( GtkWidget *widget, GdkEventButton *event, gpointer data ){
67         GLWindow *wnd = (GLWindow*)data;
68         guint32 flags = 0;
69
70         gdk_pointer_grab( widget->window, FALSE,
71                                           (GdkEventMask)( GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK ),
72                                           NULL, NULL, GDK_CURRENT_TIME );
73
74         gtk_window_set_focus( GTK_WINDOW( g_pParentWnd->m_pWidget ), widget );
75
76         switch ( event->button )
77         {
78         case 1: flags |= MK_LBUTTON; break;
79         case 2: flags |= MK_MBUTTON; break;
80         case 3: flags |= MK_RBUTTON; break;
81 #if !GTK_CHECK_VERSION( 1,3,0 )
82         case 4: wnd->OnMouseWheel( true ); break;
83         case 5: wnd->OnMouseWheel( false ); break;
84 #endif
85         }
86
87         if ( ( event->state & GDK_CONTROL_MASK ) != 0 ) {
88                 flags |= MK_CONTROL;
89         }
90
91         if ( ( event->state & GDK_SHIFT_MASK ) != 0 ) {
92                 flags |= MK_SHIFT;
93         }
94
95         if ( event->type == GDK_BUTTON_PRESS ) {
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                 // do nothing
108         }
109 }
110
111 static void button_release( GtkWidget *widget, GdkEventButton *event, gpointer data ){
112         GLWindow *wnd = (GLWindow*)data;
113         guint32 flags = 0;
114
115         gdk_pointer_ungrab( GDK_CURRENT_TIME );
116
117         if ( ( event->state & GDK_CONTROL_MASK ) != 0 ) {
118                 flags |= MK_CONTROL;
119         }
120
121         if ( ( event->state & GDK_SHIFT_MASK ) != 0 ) {
122                 flags |= MK_SHIFT;
123         }
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         GLWindow *wnd = (GLWindow*)data;
138         guint32 flags = 0;
139
140         if ( ( event->state & GDK_BUTTON1_MASK ) != 0 ) {
141                 flags |= MK_LBUTTON;
142         }
143
144         if ( ( event->state & GDK_BUTTON2_MASK ) != 0 ) {
145                 flags |= MK_MBUTTON;
146         }
147
148         if ( ( event->state & GDK_BUTTON3_MASK ) != 0 ) {
149                 flags |= MK_RBUTTON;
150         }
151
152         if ( ( event->state & GDK_CONTROL_MASK ) != 0 ) {
153                 flags |= MK_CONTROL;
154         }
155
156         if ( ( event->state & GDK_SHIFT_MASK ) != 0 ) {
157                 flags |= MK_SHIFT;
158         }
159
160         wnd->OnMouseMove( flags, (int)event->x, (int)event->y );
161 }
162
163 static void resize( GtkWidget *widget, GtkAllocation *allocation, gpointer data ){
164         GLWindow *wnd = (GLWindow*)data;
165         wnd->OnSize( allocation->width, allocation->height );
166 }
167
168 static gint timer( gpointer data ){
169         GLWindow *wnd = (GLWindow*)data;
170         wnd->OnTimer();
171
172         return TRUE;
173 }
174
175 //! GtkGLExt port.
176 /*
177    static void create_context (GtkWidget *widget, gpointer data)
178    {
179    if (g_qeglobals_gui.d_glBase == NULL)
180     g_qeglobals_gui.d_glBase = widget;
181    }
182
183    static void destroy_context (GtkWidget *widget, gpointer data)
184    {
185    if (g_qeglobals_gui.d_glBase == widget)
186     g_qeglobals_gui.d_glBase = NULL;
187    }
188  */
189
190 #if GTK_CHECK_VERSION( 1,3,0 )
191 static gint scroll_event( GtkWidget *widget,
192                                                   GdkEventScroll *event,
193                                                   gpointer data ){
194         GLWindow *wnd = (GLWindow*)data;
195         wnd->OnMouseWheel( ( event->direction == GDK_SCROLL_UP ) ? true : false );
196         return TRUE;
197 }
198 #endif
199
200 // =============================================================================
201 // GLWindow class
202
203 #ifdef _DEBUG
204 //#define DBG_GLWINDOW
205 #endif
206
207 GLWindow::GLWindow ( bool zbuffer ){
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         }
224 //#endif
225
226 #if GTK_CHECK_VERSION( 1,3,0 )
227         gtk_widget_set_events( m_pWidget, GDK_DESTROY | GDK_EXPOSURE_MASK |
228                                                    GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK );
229 #else
230         gtk_widget_set_events( m_pWidget, GDK_DESTROY | GDK_EXPOSURE_MASK |
231                                                    GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK );
232 #endif
233
234         // Connect signal handlers
235         gtk_signal_connect( GTK_OBJECT( m_pWidget ), "realize", GTK_SIGNAL_FUNC( realize ), this );
236         gtk_signal_connect( GTK_OBJECT( m_pWidget ), "expose_event", GTK_SIGNAL_FUNC( expose ), this );
237         gtk_signal_connect( GTK_OBJECT( m_pWidget ), "motion_notify_event", GTK_SIGNAL_FUNC( motion ), this );
238         gtk_signal_connect( GTK_OBJECT( m_pWidget ), "button_press_event", GTK_SIGNAL_FUNC( button_press ), this );
239         gtk_signal_connect( GTK_OBJECT( m_pWidget ), "button_release_event",GTK_SIGNAL_FUNC( button_release ), this );
240         gtk_signal_connect( GTK_OBJECT( m_pWidget ), "size_allocate", GTK_SIGNAL_FUNC( resize ), this );
241 //! GtkGLExt port.
242 //  gtk_signal_connect (GTK_OBJECT (m_pWidget), "create_context", GTK_SIGNAL_FUNC (create_context), this);
243 //  gtk_signal_connect (GTK_OBJECT (m_pWidget), "destroy_context", GTK_SIGNAL_FUNC (destroy_context), this);
244 #if GTK_CHECK_VERSION( 1,3,0 )
245         gtk_signal_connect( GTK_OBJECT( m_pWidget ), "scroll_event", GTK_SIGNAL_FUNC( scroll_event ), this );
246 #endif
247 }
248
249 GLWindow::~GLWindow (){
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
259 void GLWindow::DestroyContext(){
260         gtk_glwidget_destroy_context( m_pWidget );
261 }
262
263 void GLWindow::CreateContext(){
264         gtk_glwidget_create_context( m_pWidget );
265 }
266
267 void GLWindow::SetTimer( guint millisec ){
268         m_nTimer = gtk_timeout_add( millisec, timer, this );
269 }
270
271 void GLWindow::KillTimer(){
272         gtk_timeout_remove( m_nTimer );
273         m_nTimer = 0;
274 }
275
276 bool GLWindow::MakeCurrent(){
277         return gtk_glwidget_make_current( m_pWidget );
278 }
279
280 void GLWindow::SwapBuffers(){
281         gtk_glwidget_swap_buffers( m_pWidget );
282 }