]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - radiant/mainframe.cpp
Fix GTK_CRITICAL errors
[xonotic/netradiant.git] / radiant / mainframe.cpp
index 4968123864ebeeecec72f2b30a77e8f183f36fa0..f39805bfd3bf09f0896abbf9cafad7415afbb59b 100644 (file)
 #include "referencecache.h"
 #include "texwindow.h"
 
+#if GDEF_OS_WINDOWS
+#include <process.h>
+#else
+#include <spawn.h>
+#endif
+
+#ifdef WORKAROUND_WINDOWS_GTK2_GLWIDGET
+/* workaround for gtk 2.24 issue: not displayed glwidget after toggle */
+#define WORKAROUND_GOBJECT_SET_GLWIDGET(window, widget) g_object_set_data( G_OBJECT( window ), "glwidget", G_OBJECT( widget ) )
+#else
+#define WORKAROUND_GOBJECT_SET_GLWIDGET(window, widget)
+#endif
 
 struct layout_globals_t
 {
@@ -187,7 +199,7 @@ void VFS_Destroy(){
 // Home Paths
 
 #if GDEF_OS_WINDOWS
-                                                                                                                       #include <shlobj.h>
+#include <shlobj.h>
 #include <objbase.h>
 const GUID qFOLDERID_SavedGames = {0x4C5C32FF, 0xBB9D, 0x43b0, {0xB5, 0xB4, 0x2D, 0x72, 0xE5, 0x4E, 0xAA, 0xA4}};
 #define qREFKNOWNFOLDERID GUID
@@ -213,9 +225,7 @@ void HomePaths_Realise(){
                        }
                        path.clear();
                        path << DirectoryCleaned( g_get_home_dir() ) << prefix << "/";
-#endif
-
-#if GDEF_OS_WINDOWS
+#elif GDEF_OS_WINDOWS
                        TCHAR mydocsdir[MAX_PATH + 1];
                        wchar_t *mydocsdirw;
                        HMODULE shfolder = LoadLibrary( "shfolder.dll" );
@@ -252,13 +262,19 @@ void HomePaths_Realise(){
                                        break;
                                }
                        }
-#endif
-
-#if GDEF_OS_POSIX
+#elif GDEF_OS_XDG
                        path.clear();
-                       path << DirectoryCleaned( g_get_home_dir() ) << prefix << "/";
-                       g_qeglobals.m_userEnginePath = path.c_str();
-                       break;
+                       path << DirectoryCleaned( g_get_user_data_dir() ) << ( prefix + 1 ) << "/";
+                       if ( file_exists( path.c_str() ) && file_is_directory( path.c_str() ) ) {
+                               g_qeglobals.m_userEnginePath = path.c_str();
+                               break;
+                       }
+                       else {
+                               path.clear();
+                               path << DirectoryCleaned( g_get_home_dir() ) << prefix << "/";
+                               g_qeglobals.m_userEnginePath = path.c_str();
+                               break;
+                       }
 #endif
                }
 
@@ -434,14 +450,32 @@ void setPakPath( int num, const char* path ){
 }
 
 
-// App Path
+// executable file path (full path)
+CopiedString g_strAppFilePath;
+
+// directory paths
+CopiedString g_strAppPath; 
+CopiedString g_strLibPath;
+CopiedString g_strDataPath;
 
-CopiedString g_strAppPath;                 ///< holds the full path of the executable
+const char* AppFilePath_get(){
+       return g_strAppFilePath.c_str();
+}
 
 const char* AppPath_get(){
        return g_strAppPath.c_str();
 }
 
+const char *LibPath_get()
+{
+    return g_strLibPath.c_str();
+}
+
+const char *DataPath_get()
+{
+    return g_strDataPath.c_str();
+}
+
 /// the path to the local rc-dir
 const char* LocalRcPath_get( void ){
        static CopiedString rc_path;
@@ -540,39 +574,28 @@ struct PakPath4 {
 bool g_disableEnginePath = false;
 bool g_disableHomePath = false;
 
-void Paths_constructPreferences( PreferencesPage& page ){
+void Paths_constructBasicPreferences(  PreferencesPage& page ) {
        page.appendPathEntry( "Engine Path", true, make_property<EnginePath>(g_strEnginePath) );
+}
 
-       page.appendCheckBox(
-               "", "Do not use Engine Path",
-               g_disableEnginePath
-               );
+void Paths_constructPreferences( PreferencesPage& page ){
+       Paths_constructBasicPreferences( page );
 
-       page.appendCheckBox(
-               "", "Do not use Home Path",
-               g_disableHomePath
-               );
+       page.appendSpacer( 4 );
+       page.appendLabel( "", "Advanced options" );
+       page.appendCheckBox( "", "Do not use Engine Path", g_disableEnginePath );
+       page.appendCheckBox( "", "Do not use Home Path", g_disableHomePath );
 
-       for ( int i = 0; i < g_pakPathCount; i++ ) {
-               std::string label = "Pak Path " + std::to_string(i);
-               switch (i) {
-                       case 0:
-                       page.appendPathEntry( label.c_str(), true, make_property<PakPath0>( g_strPakPath[i] ) );
-                       break;
-                       case 1:
-                       page.appendPathEntry( label.c_str(), true, make_property<PakPath1>( g_strPakPath[i] ) );
-                       break;
-                       case 2:
-                       page.appendPathEntry( label.c_str(), true, make_property<PakPath2>( g_strPakPath[i] ) );
-                       break;
-                       case 3:
-                       page.appendPathEntry( label.c_str(), true, make_property<PakPath3>( g_strPakPath[i] ) );
-                       break;
-                       case 4:
-                       page.appendPathEntry( label.c_str(), true, make_property<PakPath4>( g_strPakPath[i] ) );
-                       break;
-               }
-       }
+       page.appendSpacer( 4 );
+       page.appendLabel( "", "Only a very few games support Pak Paths," );
+       page.appendLabel( "", "if you don't know what it is, leave this blank." );
+
+       const char *label = "Pak Path ";
+       page.appendPathEntry( label, true, make_property<PakPath0>( g_strPakPath[0] ) );
+       page.appendPathEntry( label, true, make_property<PakPath1>( g_strPakPath[1] ) );
+       page.appendPathEntry( label, true, make_property<PakPath2>( g_strPakPath[2] ) );
+       page.appendPathEntry( label, true, make_property<PakPath3>( g_strPakPath[3] ) );
+       page.appendPathEntry( label, true, make_property<PakPath4>( g_strPakPath[4] ) );
 }
 
 void Paths_constructPage( PreferenceGroup& group ){
@@ -589,14 +612,14 @@ class PathsDialog : public Dialog
 {
 public:
 ui::Window BuildDialog(){
-       auto frame = create_dialog_frame( "Path settings", ui::Shadow::ETCHED_IN );
+       auto frame = create_dialog_frame( "Path Settings", ui::Shadow::ETCHED_IN );
 
        auto vbox2 = create_dialog_vbox( 0, 4 );
        frame.add(vbox2);
 
        {
-               PreferencesPage preferencesPage( *this, vbox2 );
-               Paths_constructPreferences( preferencesPage );
+               PreferencesPage page( *this, vbox2 );
+               Paths_constructBasicPreferences( page );
        }
 
        return ui::Window(create_simple_modal_dialog_window( "Engine Path Not Found", m_modal, frame ));
@@ -753,7 +776,7 @@ void Radiant_detachGameToolsPathObserver( ModuleObserver& observer ){
 void Radiant_Initialise(){
        GlobalModuleServer_Initialise();
 
-       Radiant_loadModulesFromRoot( AppPath_get() );
+       Radiant_loadModulesFromRoot( LibPath_get() );
 
        Preferences_Load();
 
@@ -782,7 +805,7 @@ void Radiant_Shutdown(){
 }
 
 void Exit(){
-       if ( ConfirmModified( "Exit Radiant" ) ) {
+       if ( ConfirmModified( "Exit " RADIANT_NAME ) ) {
                gtk_main_quit();
        }
 }
@@ -943,6 +966,53 @@ void ColorScheme_Ydnar(){
        XY_UpdateAllWindows();
 }
 
+/* color scheme to fit the GTK Adwaita Dark theme */
+void ColorScheme_AdwaitaDark()
+{
+       // SI_Colors0
+       // GlobalTextureBrowser().color_textureback
+       TextureBrowser_setBackgroundColour(GlobalTextureBrowser(), Vector3(0.25f, 0.25f, 0.25f));
+
+       // SI_Colors4
+       g_camwindow_globals.color_cameraback = Vector3(0.25f, 0.25f, 0.25f);
+       // SI_Colors12
+       g_camwindow_globals.color_selbrushes3d = Vector3(1.0f, 0.0f, 0.0f);
+       CamWnd_Update(*g_pParentWnd->GetCamWnd());
+
+       // SI_Colors1
+       g_xywindow_globals.color_gridback = Vector3(0.25f, 0.25f, 0.25f);
+       // SI_Colors2
+       g_xywindow_globals.color_gridminor = Vector3(0.21f, 0.23f, 0.23f);
+       // SI_Colors3
+       g_xywindow_globals.color_gridmajor = Vector3(0.14f, 0.15f, 0.15f);
+       // SI_Colors14
+       g_xywindow_globals.color_gridmajor_alt = Vector3(1.0f, 0.0f, 0.0f);
+       // SI_Colors6
+       g_xywindow_globals.color_gridblock = Vector3(1.0f, 1.0f, 1.0f);
+       // SI_Colors7
+       g_xywindow_globals.color_gridtext = Vector3(0.0f, 0.0f, 0.0f);
+       // ??
+       g_xywindow_globals.color_selbrushes = Vector3(1.0f, 0.0f, 0.0f);
+       // ??
+       g_xywindow_globals.color_clipper = Vector3(0.0f, 0.0f, 1.0f);
+       // SI_Colors8
+       g_xywindow_globals.color_brushes = Vector3(0.73f, 0.73f, 0.73f);
+
+       // SI_AxisColors0
+       g_xywindow_globals.AxisColorX = Vector3(1.0f, 0.0f, 0.0f);
+       // SI_AxisColors1
+       g_xywindow_globals.AxisColorY = Vector3(0.0f, 1.0f, 0.0f);
+       // SI_AxisColors2
+       g_xywindow_globals.AxisColorZ = Vector3(0.0f, 0.0f, 1.0f);
+       SetWorldspawnColour(g_xywindow_globals.color_brushes);
+       // ??
+       g_xywindow_globals.color_viewname = Vector3(0.5f, 0.0f, 0.75f);
+       XY_UpdateAllWindows();
+
+       // SI_Colors5
+       // g_entity_globals.color_entity = Vector3(0.0f, 0.0f, 0.0f);
+}
+
 typedef Callback<void(Vector3&)> GetColourCallback;
 typedef Callback<void(const Vector3&)> SetColourCallback;
 
@@ -1060,6 +1130,7 @@ ui::MenuItem create_colours_menu(){
        create_menu_item_with_mnemonic( menu_3, "Q3Radiant Original", "ColorSchemeQER" );
        create_menu_item_with_mnemonic( menu_3, "Black and Green", "ColorSchemeBlackAndGreen" );
        create_menu_item_with_mnemonic( menu_3, "Maya/Max/Lightwave Emulation", "ColorSchemeYdnar" );
+       create_menu_item_with_mnemonic(menu_3, "Adwaita Dark", "ColorSchemeAdwaitaDark");
 
        menu_separator( menu_in_menu );
 
@@ -1733,9 +1804,11 @@ void Selection_SnapToGrid(){
 
 
 static gint qe_every_second( gpointer data ){
-       GdkModifierType mask;
+       if (g_pParentWnd == nullptr)
+               return TRUE;
 
-       gdk_window_get_pointer( 0, 0, 0, &mask );
+       GdkModifierType mask;
+       gdk_window_get_pointer( gtk_widget_get_window(g_pParentWnd->m_window), nullptr, nullptr, &mask );
 
        if ( ( mask & ( GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK ) ) == 0 ) {
                QE_CheckAutoSave();
@@ -1847,15 +1920,18 @@ void ScreenUpdates_Disable( const char* message, const char* title ){
                bool isActiveApp = MainFrame_isActiveApp();
 
                g_wait = create_wait_dialog( title, message );
-               gtk_grab_add( g_wait.m_window  );
 
                if ( isActiveApp ) {
                        g_wait.m_window.show();
+                       gtk_grab_add( g_wait.m_window  );
                        ScreenUpdates_process();
                }
        }
        else if ( g_wait.m_window.visible() ) {
                g_wait.m_label.text(message);
+               if ( GTK_IS_WINDOW(g_wait.m_window) ) {
+                       gtk_grab_add(g_wait.m_window);
+               }
                ScreenUpdates_process();
        }
        g_wait_stack.push_back( message );
@@ -2314,7 +2390,7 @@ ui::MenuItem create_help_menu(){
 
        create_menu_item_with_mnemonic( menu, "Bug report", makeCallbackF(OpenBugReportURL) );
        create_menu_item_with_mnemonic( menu, "Shortcuts list", makeCallbackF(DoCommandListDlg) );
-       create_menu_item_with_mnemonic( menu, "_About", makeCallbackF(DoAbout) );
+       create_menu_item_with_mnemonic( menu, "_About...", makeCallbackF(DoAbout) );
 
        return help_menu_item;
 }
@@ -2693,10 +2769,14 @@ MainFrame::~MainFrame(){
 
        for ( std::vector<ui::Widget>::iterator i = g_floating_windows.begin(); i != g_floating_windows.end(); ++i )
        {
+#ifndef WORKAROUND_MACOS_GTK2_DESTROY
                i->destroy();
+#endif
        }
 
+#ifndef WORKAROUND_MACOS_GTK2_DESTROY
        m_window.destroy();
+#endif
 }
 
 void MainFrame::SetActiveXY( XYWnd* p ){
@@ -2853,7 +2933,7 @@ WindowPositionTracker g_posXZWnd;
 WindowPositionTracker g_posYZWnd;
 
 static gint mainframe_delete( ui::Widget widget, GdkEvent *event, gpointer data ){
-       if ( ConfirmModified( "Exit Radiant" ) ) {
+       if ( ConfirmModified( "Exit " RADIANT_NAME ) ) {
                gtk_main_quit();
        }
 
@@ -3027,6 +3107,8 @@ void MainFrame::Create(){
                        }
                        CamWnd_setParent( *m_pCamWnd, window );
 
+                       WORKAROUND_GOBJECT_SET_GLWIDGET( window, CamWnd_getWidget( *m_pCamWnd ) );
+
                        g_floating_windows.push_back( window );
                }
 
@@ -3046,6 +3128,8 @@ void MainFrame::Create(){
                        }
                        XY_Top_Shown_Construct( window );
 
+                       WORKAROUND_GOBJECT_SET_GLWIDGET( window, m_pXYWnd->GetWidget() );
+
                        g_floating_windows.push_back( window );
                }
 
@@ -3065,6 +3149,8 @@ void MainFrame::Create(){
 
                        XZ_Front_Shown_Construct( window );
 
+                       WORKAROUND_GOBJECT_SET_GLWIDGET( window, m_pXZWnd->GetWidget() );
+
                        g_floating_windows.push_back( window );
                }
 
@@ -3084,12 +3170,16 @@ void MainFrame::Create(){
 
                        YZ_Side_Shown_Construct( window );
 
+                       WORKAROUND_GOBJECT_SET_GLWIDGET( window, m_pYZWnd->GetWidget() );
+
                        g_floating_windows.push_back( window );
                }
 
                {
                        auto frame = create_framed_widget( TextureBrowser_constructWindow( GroupDialog_getWindow() ) );
                        g_page_textures = GroupDialog_addPage( "Textures", frame, TextureBrowserExportTitleCaller() );
+
+                       WORKAROUND_GOBJECT_SET_GLWIDGET( GroupDialog_getWindow(), TextureBrowser_getGLWidget() );
                }
 
                GroupDialog_show();
@@ -3123,6 +3213,8 @@ void MainFrame::Create(){
                {
             auto frame = create_framed_widget( TextureBrowser_constructWindow( window ) );
                        g_page_textures = GroupDialog_addPage( "Textures", frame, TextureBrowserExportTitleCaller() );
+
+                       WORKAROUND_GOBJECT_SET_GLWIDGET( window, TextureBrowser_getGLWidget() );
                }
        }
 
@@ -3212,7 +3304,7 @@ void MainFrame::SetStatusText( CopiedString& status_text, const char* pText ){
 }
 
 void Sys_Status( const char* status ){
-       if ( g_pParentWnd != 0 ) {
+       if ( g_pParentWnd != nullptr ) {
                g_pParentWnd->SetStatusText( g_pParentWnd->m_command_status, status );
        }
 }
@@ -3244,7 +3336,7 @@ void MainFrame::SetGridStatus(){
 }
 
 void GridStatus_onTextureLockEnabledChanged(){
-       if ( g_pParentWnd != 0 ) {
+       if ( g_pParentWnd != nullptr ) {
                g_pParentWnd->SetGridStatus();
        }
 }
@@ -3395,6 +3487,7 @@ void MainFrame_Construct(){
        GlobalCommands_insert( "ColorSchemeQER", makeCallbackF(ColorScheme_QER) );
        GlobalCommands_insert( "ColorSchemeBlackAndGreen", makeCallbackF(ColorScheme_Black) );
        GlobalCommands_insert( "ColorSchemeYdnar", makeCallbackF(ColorScheme_Ydnar) );
+       GlobalCommands_insert("ColorSchemeAdwaitaDark", makeCallbackF(ColorScheme_AdwaitaDark));
        GlobalCommands_insert( "ChooseTextureBackgroundColor", makeCallback( g_ColoursMenu.m_textureback ) );
        GlobalCommands_insert( "ChooseGridBackgroundColor", makeCallback( g_ColoursMenu.m_xyback ) );
        GlobalCommands_insert( "ChooseGridMajorColor", makeCallback( g_ColoursMenu.m_gridmajor ) );
@@ -3527,3 +3620,44 @@ void GLWindow_Construct(){
 
 void GLWindow_Destroy(){
 }
+
+void Radiant_Restart(){
+       // preferences are expected to be already saved in any way
+       // this is just to be sure and be future proof
+       Preferences_Save();
+
+       // this asks user for saving if map is modified
+       // user can chose to not save, it's ok
+       ConfirmModified( "Restart " RADIANT_NAME );
+
+       int status;
+
+       char *argv[ 3 ];
+       char exe_file[ 256 ];
+       char map_file[ 256 ];
+       bool with_map = false;
+
+       strncpy( exe_file, g_strAppFilePath.c_str(), 256 );
+
+       if ( !Map_Unnamed( g_map ) ) {
+               strncpy( map_file, Map_Name( g_map ), 256 );
+               with_map = true;
+       }
+
+       argv[ 0 ] = exe_file;
+       argv[ 1 ] = with_map ? map_file : NULL;
+       argv[ 2 ] = NULL;
+
+#if GDEF_OS_WINDOWS
+       status = !_spawnvpe( P_NOWAIT, exe_file, argv, environ );
+#else
+       pid_t pid;
+
+       status = posix_spawn( &pid, exe_file, NULL, NULL, argv, environ );
+#endif
+
+       // quit if radiant successfully started
+       if ( status == 0 ) {
+               gtk_main_quit();
+       }
+}