]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/ui.cpp
error check and bail if permission denied during gamepack install
[xonotic/netradiant.git] / radiant / ui.cpp
1 /*
2    Copyright (C) 1999-2007 id Software, Inc. and contributors.
3    For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 //-----------------------------------------------------------------------------
23 //
24 // DESCRIPTION:
25 // implementation of IMessaging specific interface
26 //
27
28 #include "stdafx.h"
29
30 CPtrArray l_Listeners[RADIANT_MSGCOUNT];
31 CPtrArray l_WindowListeners;
32 CXYWndWrapper l_XYWndWrapper;
33
34 // CGtkWindow implementation -------------------------------------
35
36 static void button_press( GtkWidget *widget, GdkEventButton *event, gpointer data ){
37         IWindowListener *pListen = static_cast<IWindowListener *>( data );
38         switch ( event->button )
39         {
40         case 1:
41                 pListen->OnLButtonDown( event->state, event->x, event->y ); break;
42         case 3:
43                 pListen->OnRButtonDown( event->state, event->x, event->y ); break;
44         }
45 }
46
47 static void button_release( GtkWidget *widget, GdkEventButton *event, gpointer data ){
48         IWindowListener *pListen = static_cast<IWindowListener *>( data );
49         switch ( event->button )
50         {
51         case 1:
52                 pListen->OnLButtonUp( event->state, event->x, event->y ); break;
53         case 3:
54                 pListen->OnRButtonUp( event->state, event->x, event->y ); break;
55         }
56 }
57
58 static void motion( GtkWidget *widget, GdkEventMotion *event, gpointer data ){
59         IWindowListener *pListen = static_cast<IWindowListener *>( data );
60         pListen->OnMouseMove( event->state, event->x, event->y );
61 }
62
63 static gint expose( GtkWidget *widget, GdkEventExpose *event, gpointer data ){
64         if ( event->count > 0 ) {
65                 return TRUE;
66         }
67
68         CGtkWindow *pWindow = static_cast<CGtkWindow *>( data );
69         pWindow->DoExpose();
70
71         return TRUE;
72 }
73
74 // we use the string versions of the keys for now..
75 static gint keypress( GtkWidget* widget, GdkEventKey* event, gpointer data ){
76         gint ret;
77
78         IWindowListener *pListen = static_cast<IWindowListener *>( data );
79         ret = pListen->OnKeyPressed( gdk_keyval_name( event->keyval ) );
80         if ( ret ) {
81                 gtk_signal_emit_stop_by_name( GTK_OBJECT( widget ), "key_press_event" );
82         }
83         return ret;
84 }
85
86 // close_widget is not hooked on the listener but on the CGtkWindow object to handle the closure
87 static gint close_widget( GtkWidget *widget, GdkEvent* event, gpointer data ){
88         CGtkWindow *pWindow = static_cast<CGtkWindow *>( data );
89         pWindow->Close();
90
91         return TRUE;
92 }
93
94 void CGtkWindow::DoExpose(){
95         gtk_glwidget_make_current( m_pGLWidget );
96         if ( m_pListen->Paint() ) {
97                 gtk_glwidget_swap_buffers( m_pGLWidget );
98         }
99 }
100
101 void CGtkWindow::Redraw(){
102         gtk_widget_queue_draw( m_pGLWidget );
103 }
104
105 void CGtkWindow::Close(){
106         // similar to a destructor, except we warn first
107         m_pListen->Close();
108         m_pListen->DecRef(); m_pListen = NULL;
109         gtk_widget_destroy( m_pWnd ); m_pWnd = NULL;
110 }
111
112 bool CGtkWindow::Show(){
113         // check we got everything and are reading to instanciate
114         if ( m_nWidthParam == 0 || m_nHeightParam == 0 ) {
115                 Sys_FPrintf( SYS_ERR, "Height and Width params not set in CGtkWindow::Show\n" );
116                 return false;
117         }
118         if ( !m_pListen ) {
119                 Sys_FPrintf( SYS_ERR, "No listener set in CGtkWindow::Show\n" );
120                 return false;
121         }
122
123         // seems all good, here we go
124         m_pWnd = gtk_window_new( GTK_WINDOW_TOPLEVEL );
125         gtk_window_set_title( GTK_WINDOW( m_pWnd ), m_Name.GetBuffer() );
126         gtk_window_set_default_size( GTK_WINDOW( m_pWnd ), m_nWidthParam, m_nHeightParam );
127         gtk_widget_show( m_pWnd );
128
129         // GL widget creation
130         m_pGLWidget = gtk_glwidget_new( FALSE, g_qeglobals_gui.d_glBase );
131
132         gtk_widget_set_events( m_pGLWidget, GDK_DESTROY | GDK_EXPOSURE_MASK | GDK_KEY_PRESS_MASK |
133                                                    GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK );
134
135         // Connect signal handlers
136         gtk_signal_connect( GTK_OBJECT( m_pGLWidget ), "expose_event", GTK_SIGNAL_FUNC( expose ), this );
137         gtk_signal_connect( GTK_OBJECT( m_pGLWidget ), "motion_notify_event",
138                                                 GTK_SIGNAL_FUNC( motion ), m_pListen );
139         gtk_signal_connect( GTK_OBJECT( m_pGLWidget ), "button_press_event",
140                                                 GTK_SIGNAL_FUNC( button_press ), m_pListen );
141         gtk_signal_connect( GTK_OBJECT( m_pGLWidget ), "button_release_event",
142                                                 GTK_SIGNAL_FUNC( button_release ), m_pListen );
143
144         gtk_signal_connect( GTK_OBJECT( m_pWnd ), "delete_event", GTK_SIGNAL_FUNC( close_widget ), this );
145         gtk_signal_connect( GTK_OBJECT( m_pWnd ), "key_press_event",
146                                                 GTK_SIGNAL_FUNC( keypress ), m_pListen );
147
148         gtk_widget_show( m_pGLWidget );
149         gtk_container_add( GTK_CONTAINER( m_pWnd ), m_pGLWidget );
150
151         return true;
152 }
153
154 IWindow* WINAPI QERApp_CreateGLWindow(){
155         return new CGtkWindow;
156 }
157
158 void WINAPI QERApp_HookWindow( IWindowListener* pListen ){
159         l_WindowListeners.Add( pListen );
160         pListen->IncRef();
161 }
162
163 void WINAPI QERApp_UnHookWindow( IWindowListener* pListen ){
164         for ( int i = 0; i < l_WindowListeners.GetSize(); i++ )
165         {
166                 if ( l_WindowListeners.GetAt( i ) == pListen ) {
167                         l_WindowListeners.RemoveAt( i );
168                         pListen->DecRef();
169                         return;
170                 }
171         }
172 #ifdef _DEBUG
173         Sys_Printf( "WARNING: IWindowListener not found in QERApp_UnHookWindow\n" );
174 #endif
175 }
176
177 void DispatchOnMouseMove( guint32 nFlags, int x, int y ){
178         for ( int i = 0; i < l_WindowListeners.GetSize(); i++ )
179                 static_cast<IWindowListener*>( l_WindowListeners.GetAt( i ) )->OnMouseMove( nFlags, x, y );
180 }
181
182 bool DispatchOnLButtonDown( guint32 nFlags, int x, int y ){
183         for ( int i = 0; i < l_WindowListeners.GetSize(); i++ )
184                 if ( static_cast<IWindowListener*>( l_WindowListeners.GetAt( i ) )->OnLButtonDown( nFlags, x, y ) ) {
185                         return true;
186                 }
187         return false;
188 }
189
190 bool DispatchOnLButtonUp( guint32 nFlags, int x, int y ){
191         for ( int i = 0; i < l_WindowListeners.GetSize(); i++ )
192                 if ( static_cast<IWindowListener*>( l_WindowListeners.GetAt( i ) )->OnLButtonUp( nFlags, x, y ) ) {
193                         return true;
194                 }
195         return false;
196 }
197
198 void WINAPI QERApp_HookListener( IListener* pListen, int Msg ){
199 #ifdef _DEBUG
200         if ( Msg >= RADIANT_MSGCOUNT ) {
201                 Sys_Printf( "ERROR: bad index in QERApp_HookListener\n" );
202                 return;
203         }
204 #endif
205         l_Listeners[Msg].Add( pListen );
206         pListen->IncRef();
207 }
208
209 int WINAPI QERApp_UnHookListener( IListener* pListen ){
210         int count = 0;
211         for ( int i = 0; i < RADIANT_MSGCOUNT; i++ )
212                 for ( int j = 0; j < l_Listeners[i].GetSize(); j++ )
213                         if ( l_Listeners[i].GetAt( j ) == pListen ) {
214                                 l_Listeners[i].RemoveAt( j );
215                                 pListen->DecRef();
216                                 count++;
217                         }
218         return count;
219 }
220
221 void DispatchRadiantMsg( int Msg ){
222 #ifdef _DEBUG
223         if ( Msg >= RADIANT_MSGCOUNT ) {
224                 Sys_Printf( "ERROR: bad index in DispatchRadiantMsg\n" );
225                 return;
226         }
227 #endif
228         for ( int i = 0; i < l_Listeners[Msg].GetSize(); i++ )
229                 static_cast<IListener *>( l_Listeners[Msg].GetAt( i ) )->DispatchRadiantMsg( Msg );
230 }
231
232 void CXYWndWrapper::SnapToGrid( int x1, int y1, vec3_t pt ){
233         int height = g_pParentWnd->ActiveXY()->GetWidget()->allocation.height;
234         g_pParentWnd->ActiveXY()->SnapToPoint( x1, height - 1 - y1, pt );
235 }
236
237 VIEWTYPE CXYWndWrapper::GetViewType( void ){
238         return (VIEWTYPE)g_pParentWnd->ActiveXY()->GetViewType();
239 }
240
241 IXYWndWrapper* WINAPI QERApp_GetXYWndWrapper(){
242         return &l_XYWndWrapper;
243 }