diff --git a/CMakeLists.txt b/CMakeLists.txt index 883cf3991..22b44ae90 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,7 +46,6 @@ option(PROJECT_FOLDERS "Put source files into subfolders in project file" ON) CMAKE_DEPENDENT_OPTION(USE_COCOA "Use Apple Cocoa widgets." ON "APPLE" OFF) CMAKE_DEPENDENT_OPTION(USE_WIN32_WINDOWS "Use Microsoft Desktop App User Interface widgets." ON "WIN32" OFF) CMAKE_DEPENDENT_OPTION(USE_SDL_MAINLOOP "Use SDL to create windows etc. Qt editor." ON "NOT USE_COCOA AND NOT USE_WIN32_WINDOWS" OFF) -CMAKE_DEPENDENT_OPTION(USE_GTK "Use GTK+ widgets." ON "NOT USE_COCOA AND NOT USE_WIN32_WINDOWS AND NOT USE_SDL_MAINLOOP" OFF) option(WITH_AUTOMATIC_UPDATE "Automatic updates are downloaded from the project website." OFF) set_property(GLOBAL PROPERTY USE_FOLDERS ${PROJECT_FOLDERS}) @@ -298,9 +297,6 @@ CHECK_CXX_SOURCE_COMPILES("#include \nvoid GLAPIENTRY OpenGLDebugProc if(UNIX AND NOT APPLE) FINDLIB(X11_LIBRARIES X11) - if(USE_GTK) - FINDLIB(XRANDR_LIBRARIES Xrandr) - endif() endif() if (WIN32) @@ -323,13 +319,6 @@ endif() SET(HAVE_LIBREADLINE ${READLINE_FOUND} CACHE INTERNAL "libreadline available") find_package(GTK3 COMPONENTS gthread gio gobject glib OPTIONAL_COMPONENTS gtksourceview) -if(USE_GTK) - SET(WITH_GLIB ${GTK3_FOUND}) - include_directories(SYSTEM ${GTK3_INCLUDE_DIRS}) - # Set GTK link directory. This needs to be done before add_executable, - # otherwise the path is not used for linking clonk - link_directories(${GTK3_LIBRARY_DIRS}) -endif() # Select an audio library find_package("Audio") @@ -384,31 +373,6 @@ add_custom_command( VERBATIM ) -add_custom_command( - OUTPUT engine-resource.c - COMMAND - ${GLIB_COMPILE_RESOURCES} "--internal" "--generate" - "--target" "engine-resource.c" - "--sourcedir" ${CMAKE_CURRENT_SOURCE_DIR}/src/res - "${CMAKE_CURRENT_SOURCE_DIR}/src/res/engine.xml" - MAIN_DEPENDENCY src/res/engine.xml - DEPENDS - ${CMAKE_CURRENT_SOURCE_DIR}/src/res/Brush_Trans.png - ${CMAKE_CURRENT_SOURCE_DIR}/src/res/Halt_Trans.png - ${CMAKE_CURRENT_SOURCE_DIR}/src/res/Picker_Trans.png - ${CMAKE_CURRENT_SOURCE_DIR}/src/res/Cursor_Trans.png - ${CMAKE_CURRENT_SOURCE_DIR}/src/res/Play_Trans.png - ${CMAKE_CURRENT_SOURCE_DIR}/src/res/Dynamic_Trans.png - ${CMAKE_CURRENT_SOURCE_DIR}/src/res/Line_Trans.png - ${CMAKE_CURRENT_SOURCE_DIR}/src/res/Rect_Trans.png - ${CMAKE_CURRENT_SOURCE_DIR}/src/res/Exact_Trans.png - ${CMAKE_CURRENT_SOURCE_DIR}/src/res/Mouse_Trans.png - ${CMAKE_CURRENT_SOURCE_DIR}/src/res/Static_Trans.png - ${CMAKE_CURRENT_SOURCE_DIR}/src/res/Fill_Trans.png - ${CMAKE_CURRENT_SOURCE_DIR}/src/res/oc.ico - VERBATIM -) - ############################################################################ # Mac OS bundle setup ############################################################################ @@ -966,16 +930,7 @@ elseif(UPNP_STYLE STREQUAL "miniupnpc") endif() # source files specific to a GUI library -if(USE_GTK) - list(APPEND OC_GUI_SOURCES - src/editor/C4ConsoleGTK.cpp - src/editor/C4ConsoleGTKDlg.cpp - src/editor/C4ConsoleGTKDlg.h - src/platform/C4AppGTK.cpp - src/platform/C4WindowGTK.cpp - engine-resource.c - ) -elseif(USE_SDL_MAINLOOP) +if(USE_SDL_MAINLOOP) list(APPEND OC_GUI_SOURCES src/platform/C4AppSDL.cpp src/platform/C4WindowSDL.cpp @@ -1188,9 +1143,6 @@ target_link_libraries(openclonk libc4script libmisc ) -if(USE_GTK) - target_link_libraries(openclonk ${GTK3_LIBRARIES}) -endif() if(USE_COCOA) target_link_libraries(openclonk "-framework Cocoa -framework AppKit -framework Quartz -framework OpenAL -framework AudioToolbox") endif() @@ -1217,7 +1169,6 @@ target_link_libraries(openclonk-server ${READLINE_LIBRARIES} ${Audio_LIBRARIES} ${GETOPT_LIBRARIES} - ${GTK3_glib_LIBRARIES} ${TinyXML_LIBRARIES} ${DBGHELP_LIBRARIES} ${UPNP_LIBRARIES} diff --git a/src/editor/C4Console.cpp b/src/editor/C4Console.cpp index d2030c11e..a074092d6 100644 --- a/src/editor/C4Console.cpp +++ b/src/editor/C4Console.cpp @@ -583,7 +583,7 @@ void C4Console::RegisterRecentInput(const char *input, RecentScriptInputLists se mru.erase(mru.begin()); } -#if !(defined(USE_WIN32_WINDOWS) || defined(USE_COCOA) || defined(USE_GTK) || defined(WITH_QT_EDITOR)) +#if !(defined(USE_WIN32_WINDOWS) || defined(USE_COCOA) || defined(WITH_QT_EDITOR)) class C4ConsoleGUI::State: public C4ConsoleGUI::InternalState { public: State(C4ConsoleGUI *console): Super(console) {} diff --git a/src/editor/C4ConsoleGTK.cpp b/src/editor/C4ConsoleGTK.cpp deleted file mode 100644 index daa9f5ec4..000000000 --- a/src/editor/C4ConsoleGTK.cpp +++ /dev/null @@ -1,1680 +0,0 @@ -/* - * OpenClonk, http://www.openclonk.org - * - * Copyright (c) 1998-2000, Matthes Bender - * Copyright (c) 2002, 2005, Sven Eberhardt - * Copyright (c) 2006-2007, Armin Burgmeier - * Copyright (c) 2007, Günther Brammer - * Copyright (c) 2009-2016, The OpenClonk Team and contributors - * - * Distributed under the terms of the ISC license; see accompanying file - * "COPYING" for details. - * - * "Clonk" is a registered trademark of Matthes Bender, used with permission. - * See accompanying file "TRADEMARK" for details. - * - * To redistribute this file separately, substitute the full license texts - * for the above references. - */ - -#include "C4Include.h" -#include "editor/C4Console.h" - -#include "editor/C4ConsoleGTKDlg.h" -#include "c4group/C4Language.h" -#include "script/C4Aul.h" -#include "game/C4Application.h" -#include "control/C4GameSave.h" -#include "game/C4Game.h" -#include "gui/C4MessageInput.h" -#include "C4Version.h" -#include "c4group/C4Language.h" -#include "object/C4Object.h" -#include "player/C4Player.h" -#include "landscape/C4Landscape.h" -#include "landscape/C4Sky.h" -#include "game/C4GraphicsSystem.h" -#include "player/C4PlayerList.h" -#include "control/C4GameControl.h" -#include "landscape/C4Texture.h" -#include "game/C4Viewport.h" - -#include "platform/StdFile.h" -#include "platform/StdRegistry.h" - -#include -#ifdef GDK_WINDOWING_X11 -#include -#endif - -using namespace OpenFileFlags; - -namespace -{ - void SelectComboBoxText(GtkComboBox* combobox, const char* text) - { - GtkTreeModel* model = gtk_combo_box_get_model(combobox); - - GtkTreeIter iter; - for (gboolean ret = gtk_tree_model_get_iter_first(model, &iter); ret; ret = gtk_tree_model_iter_next(model, &iter)) - { - gchar* col_text; - gtk_tree_model_get(model, &iter, 0, &col_text, -1); - - if (SEqualNoCase(text, col_text)) - { - g_free(col_text); - gtk_combo_box_set_active_iter(combobox, &iter); - return; - } - - g_free(col_text); - } - } - - gboolean RowSeparatorFunc(GtkTreeModel* model, GtkTreeIter* iter, void* user_data) - { - gchar* text; - gtk_tree_model_get(model, iter, 0, &text, -1); - - if (SEqual(text, "------")) { g_free(text); return true; } - g_free(text); - return false; - } -} - -class C4ConsoleGUI::State: public C4ConsoleGUI::InternalState -{ -public: - - GtkWidget* txtLog; - GtkWidget* txtScript; - GtkWidget* btnPlay; - GtkWidget* btnHalt; - GtkWidget* btnModePlay; - GtkWidget* btnModeEdit; - GtkWidget* btnModeDraw; - - GtkWidget* menuBar; - GtkWidget* itemNet; - GtkWidget* menuNet; - - GtkWidget* menuViewport; - GtkWidget* menuPlayer; - - GtkWidget* fileOpen; - GtkWidget* fileOpenWithPlayers; - GtkWidget* fileSave; - GtkWidget* fileSaveAs; - GtkWidget* fileSaveGameAs; - GtkWidget* fileRecord; - GtkWidget* fileClose; - GtkWidget* fileQuit; - - GtkWidget* compObjects; - - GtkWidget* plrJoin; - - GtkWidget* viewNew; - - GtkWidget* helpAbout; - - GtkWidget* statusBar; - GtkWidget* lblFrame; - GtkWidget* lblTime; - - GtkWidget* propertydlg; - GtkWidget* propertydlg_textview; - GtkAdjustment* propertydlg_vadj; - double propertydlg_vadj_pos; - GtkWidget* propertydlg_entry; - - gulong handlerDestroy; - gulong handlerPlay; - gulong handlerHalt; - gulong handlerModePlay; - gulong handlerModeEdit; - gulong handlerModeDraw; - guint handlerPropertyDlgRescrollIdle; - - State(C4ConsoleGUI *console): Super(console) - { - Clear(); - } - - ~State() - { - // This is just to be sure, it should not be necessary since - // the widgets will be removed anyway as soon as the state is. - if(handlerDestroy) - g_signal_handler_disconnect(GetOwner()->window, handlerDestroy); - if(handlerPlay) - g_signal_handler_disconnect(btnPlay, handlerPlay); - if(handlerHalt) - g_signal_handler_disconnect(btnHalt, handlerHalt); - if(handlerModePlay) - g_signal_handler_disconnect(btnModePlay, handlerModePlay); - if(handlerModeEdit) - g_signal_handler_disconnect(btnModeEdit, handlerModeEdit); - if(handlerModeDraw) - g_signal_handler_disconnect(btnModeDraw, handlerModeDraw); - if (handlerPropertyDlgRescrollIdle) - g_source_remove(handlerPropertyDlgRescrollIdle); - if (propertydlg) - { - C4DevmodeDlg::RemovePage(propertydlg); - propertydlg = NULL; - } - } - - void InitGUI(); - void Clear(); - - void DoEnableControls(bool fEnable); - - static void OnDestroy(GtkWidget* window, gpointer data); - - static void OnScriptEntry(GtkWidget* entry, gpointer data); - static void OnPlay(GtkWidget* button, gpointer data); - static void OnHalt(GtkWidget* button, gpointer data); - static void OnModePlay(GtkWidget* button, gpointer data); - static void OnModeEdit(GtkWidget* button, gpointer data); - static void OnModeDraw(GtkWidget* button, gpointer data); - - static void OnFileOpen(GtkWidget* item, gpointer data); - static void OnFileOpenWPlrs(GtkWidget* item, gpointer data); - static void OnFileSave(GtkWidget* item, gpointer data); - static void OnFileSaveAs(GtkWidget* item, gpointer data); - static void OnFileSaveGameAs(GtkWidget* item, gpointer data); - static void OnFileRecord(GtkWidget* item, gpointer data); - static void OnFileClose(GtkWidget* item, gpointer data); - static void OnFileQuit(GtkWidget* item, gpointer data); - - static void OnCompObjects(GtkWidget* item, gpointer data); - - static void OnPlrJoin(GtkWidget* item, gpointer data); - static void OnPlrQuit(GtkWidget* item, gpointer data); - static void OnViewNew(GtkWidget* item, gpointer data); - static void OnViewNewPlr(GtkWidget* item, gpointer data); - static void OnHelpAbout(GtkWidget* item, gpointer data); - - static void OnNetClient(GtkWidget* item, gpointer data); - - static void OnScriptActivate(GtkWidget* widget, gpointer data); - - static void OnPropertyVadjustmentChanged(GtkAdjustment* adj, gpointer data); - static gboolean OnPropertyDlgRescrollIdle(gpointer data); -}; - -class C4ToolsDlg::State: public C4ConsoleGUI::InternalState -{ -public: - GtkWidget* hbox; - - GtkWidget* brush; - GtkWidget* line; - GtkWidget* rect; - GtkWidget* fill; - GtkWidget* picker; - - GtkWidget* landscape_dynamic; - GtkWidget* landscape_static; - GtkWidget* landscape_exact; - - GtkWidget* preview; - GtkWidget* scale; - - GtkWidget* fg_materials; - GtkWidget* fg_textures; - GtkWidget* bg_materials; - GtkWidget* bg_textures; - - gulong handlerBrush; - gulong handlerLine; - gulong handlerRect; - gulong handlerFill; - gulong handlerPicker; - - gulong handlerDynamic; - gulong handlerStatic; - gulong handlerExact; - - gulong handlerIft; - gulong handlerNoIft; - - gulong handlerFgMaterials; - gulong handlerFgTextures; - gulong handlerBgMaterials; - gulong handlerBgTextures; - gulong handlerScale; - - gulong handlerHide; - - //static void OnDestroy(GtkWidget* widget, gpointer data); - static void OnButtonModeDynamic(GtkWidget* widget, gpointer data); - static void OnButtonModeStatic(GtkWidget* widget, gpointer data); - static void OnButtonModeExact(GtkWidget* widget, gpointer data); - static void OnButtonBrush(GtkWidget* widget, gpointer data); - static void OnButtonLine(GtkWidget* widget, gpointer data); - static void OnButtonRect(GtkWidget* widget, gpointer data); - static void OnButtonFill(GtkWidget* widget, gpointer data); - static void OnButtonPicker(GtkWidget* widget, gpointer data); - static void OnButtonIft(GtkWidget* widget, gpointer data); - static void OnButtonNoIft(GtkWidget* widget, gpointer data); - static void OnComboMaterial(GtkWidget* widget, gpointer data); - static void OnComboTexture(GtkWidget* widget, gpointer data); - static void OnComboBgMaterial(GtkWidget* widget, gpointer data); - static void OnComboBgTexture(GtkWidget* widget, gpointer data); - static void OnGrade(GtkWidget* widget, gpointer data); - static void OnWindowHide(GtkWidget* widget, gpointer data); - - State(C4ToolsDlg* dlg): Super(dlg), hbox(NULL) { } - bool Open(); - void UpdateToolCtrls(); - void InitMaterialCtrls(); - void UpdatePreview(); - void UpdateLandscapeModeCtrls(); - void UpdateIFTControls(); - - ~State() - { - if (hbox != NULL) - { - g_signal_handler_disconnect(G_OBJECT(C4DevmodeDlg::GetWindow()), handlerHide); - C4DevmodeDlg::RemovePage(hbox); - hbox = NULL; - } - } - - void Clear() {} - void Default() { GetOwner()->ModeBack = true; } -}; - -void C4ConsoleGUI::State::OnScriptActivate(GtkWidget* widget, gpointer data) -{ - const gchar* text = gtk_entry_get_text(GTK_ENTRY(widget)); - if (text && text[0]) - Console.EditCursor.In(text); -} - -void C4ConsoleGUI::State::OnPropertyVadjustmentChanged(GtkAdjustment* adj, gpointer data) -{ - C4ConsoleGUI* gui = static_cast(data); - State* state = gui->state; - - if (state->propertydlg_vadj_pos != -1.0) - gtk_adjustment_set_value(adj, state->propertydlg_vadj_pos); -} - -gboolean C4ConsoleGUI::State::OnPropertyDlgRescrollIdle(gpointer data) -{ - C4ConsoleGUI* gui = static_cast(data); - State* state = gui->state; - - state->propertydlg_vadj_pos = -1.0; - state->handlerPropertyDlgRescrollIdle = 0; - return FALSE; -} - -C4Window* C4ConsoleGUI::CreateConsoleWindow(C4AbstractApp* pApp) -{ - C4Rect r(0, 0, 400, 350); - C4Window* retval = C4Window::Init(C4Window::W_Console, pApp, LoadResStr("IDS_CNS_CONSOLE"), &r); - state->InitGUI(); - UpdateHaltCtrls(true); - EnableControls(fGameOpen); - ClearViewportMenu(); - return retval; -} - -void C4ConsoleGUI::State::InitGUI() -{ - // ------------ Play/Pause and Mode --------------------- - GtkWidget* image_play = gtk_image_new_from_resource("/org/openclonk/engine/Play_Trans.png"); - GtkWidget* image_pause = gtk_image_new_from_resource("/org/openclonk/engine/Halt_Trans.png"); - - GtkWidget* image_mode_play = gtk_image_new_from_resource("/org/openclonk/engine/Mouse_Trans.png"); - GtkWidget* image_mode_edit = gtk_image_new_from_resource("/org/openclonk/engine/Cursor_Trans.png"); - GtkWidget* image_mode_draw = gtk_image_new_from_resource("/org/openclonk/engine/Brush_Trans.png"); - - btnPlay = GTK_WIDGET(gtk_toggle_tool_button_new()); - btnHalt = GTK_WIDGET(gtk_toggle_tool_button_new()); - btnModePlay = GTK_WIDGET(gtk_toggle_tool_button_new()); - btnModeEdit = GTK_WIDGET(gtk_toggle_tool_button_new()); - btnModeDraw = GTK_WIDGET(gtk_toggle_tool_button_new()); - - gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(btnPlay), image_play); - gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(btnHalt), image_pause); - gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(btnModePlay), image_mode_play); - gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(btnModeEdit), image_mode_edit); - gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(btnModeDraw), image_mode_draw); - - GtkWidget* top_hbox = gtk_toolbar_new(); - - gtk_toolbar_insert(GTK_TOOLBAR(top_hbox), GTK_TOOL_ITEM(btnPlay), -1); - gtk_toolbar_insert(GTK_TOOLBAR(top_hbox), GTK_TOOL_ITEM(btnHalt), -1); - gtk_toolbar_insert(GTK_TOOLBAR(top_hbox), gtk_separator_tool_item_new(), -1); - gtk_toolbar_insert(GTK_TOOLBAR(top_hbox), GTK_TOOL_ITEM(btnModePlay), -1); - gtk_toolbar_insert(GTK_TOOLBAR(top_hbox), GTK_TOOL_ITEM(btnModeEdit), -1); - gtk_toolbar_insert(GTK_TOOLBAR(top_hbox), GTK_TOOL_ITEM(btnModeDraw), -1); - - GtkToolItem * itm = gtk_tool_item_new(); - gtk_tool_item_set_expand(itm, TRUE); - lblTime = gtk_label_new("00:00:00 (0 FPS)"); - gtk_container_add(GTK_CONTAINER(itm), lblTime); - gtk_toolbar_insert(GTK_TOOLBAR(top_hbox), itm, -1); - - itm = gtk_tool_item_new(); - gtk_tool_item_set_expand(itm, TRUE); - lblFrame = gtk_label_new("Frame: 0"); - gtk_container_add(GTK_CONTAINER(itm), lblFrame); - gtk_toolbar_insert(GTK_TOOLBAR(top_hbox), itm, -1); - - // ------------ Statusbar --------------------- - statusBar = gtk_statusbar_new(); - - // ------------ Log view and script entry --------------------- - GtkWidget* scroll = gtk_scrolled_window_new(NULL, NULL); - - txtLog = gtk_text_view_new(); - txtScript = gtk_entry_new(); - - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll), GTK_SHADOW_IN); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); - gtk_text_view_set_editable(GTK_TEXT_VIEW(txtLog), false); - gtk_text_view_set_left_margin(GTK_TEXT_VIEW(txtLog), 2); - gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(txtLog), GTK_WRAP_CHAR); - - gtk_container_add(GTK_CONTAINER(scroll), txtLog); - - // ------------ Menu ------------------- - menuBar = gtk_menu_bar_new(); - - GtkWidget* itemFile = gtk_menu_item_new_with_label(LoadResStr("IDS_MNU_FILE")); - GtkWidget* itemComponents = gtk_menu_item_new_with_label(LoadResStr("IDS_MNU_COMPONENTS")); - GtkWidget* itemPlayer = gtk_menu_item_new_with_label(LoadResStr("IDS_MNU_PLAYER")); - GtkWidget* itemViewport = gtk_menu_item_new_with_label(LoadResStr("IDS_MNU_VIEWPORT")); - GtkWidget* itemHelp = gtk_menu_item_new_with_label("?"); - - gtk_menu_shell_append(GTK_MENU_SHELL(menuBar), itemFile); - gtk_menu_shell_append(GTK_MENU_SHELL(menuBar), itemComponents); - gtk_menu_shell_append(GTK_MENU_SHELL(menuBar), itemPlayer); - gtk_menu_shell_append(GTK_MENU_SHELL(menuBar), itemViewport); - gtk_menu_shell_append(GTK_MENU_SHELL(menuBar), itemHelp); - - GtkWidget* menuFile = gtk_menu_new(); - GtkWidget* menuComponents = gtk_menu_new(); - GtkWidget* menuHelp = gtk_menu_new(); - - menuPlayer = gtk_menu_new(); - menuViewport = gtk_menu_new(); - - gtk_menu_item_set_submenu(GTK_MENU_ITEM(itemFile), menuFile); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(itemComponents), menuComponents); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(itemPlayer), menuPlayer); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(itemViewport), menuViewport); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(itemHelp), menuHelp); - - fileOpen = gtk_menu_item_new_with_label(LoadResStr("IDS_MNU_OPEN")); - gtk_menu_shell_append(GTK_MENU_SHELL(menuFile), fileOpen); - - fileOpenWithPlayers = gtk_menu_item_new_with_label(LoadResStr("IDS_MNU_OPENWPLRS")); - gtk_menu_shell_append(GTK_MENU_SHELL(menuFile), fileOpenWithPlayers); - - gtk_menu_shell_append(GTK_MENU_SHELL(menuFile), GTK_WIDGET(gtk_separator_menu_item_new())); - - fileSave = gtk_menu_item_new_with_label(LoadResStr("IDS_MNU_SAVESCENARIO")); - gtk_menu_shell_append(GTK_MENU_SHELL(menuFile), fileSave); - - fileSaveAs = gtk_menu_item_new_with_label(LoadResStr("IDS_MNU_SAVESCENARIOAS")); - gtk_menu_shell_append(GTK_MENU_SHELL(menuFile), fileSaveAs); - - fileSaveGameAs = gtk_menu_item_new_with_label(LoadResStr("IDS_MNU_SAVEGAMEAS")); - gtk_menu_shell_append(GTK_MENU_SHELL(menuFile), fileSaveGameAs); - - fileRecord = gtk_menu_item_new_with_label(LoadResStr("IDS_MNU_RECORD")); - gtk_menu_shell_append(GTK_MENU_SHELL(menuFile), fileRecord); - - gtk_menu_shell_append(GTK_MENU_SHELL(menuFile), GTK_WIDGET(gtk_separator_menu_item_new())); - - fileClose = gtk_menu_item_new_with_label(LoadResStr("IDS_MNU_CLOSE")); - gtk_menu_shell_append(GTK_MENU_SHELL(menuFile), fileClose); - - gtk_menu_shell_append(GTK_MENU_SHELL(menuFile), GTK_WIDGET(gtk_separator_menu_item_new())); - - fileQuit = gtk_menu_item_new_with_label(LoadResStr("IDS_MNU_QUIT")); - gtk_menu_shell_append(GTK_MENU_SHELL(menuFile), fileQuit); - - compObjects = gtk_menu_item_new_with_label(LoadResStr("IDS_BTN_OBJECTS")); - gtk_menu_shell_append(GTK_MENU_SHELL(menuComponents), compObjects); - - plrJoin = gtk_menu_item_new_with_label(LoadResStr("IDS_MNU_JOIN")); - gtk_menu_shell_append(GTK_MENU_SHELL(menuPlayer), plrJoin); - - viewNew = gtk_menu_item_new_with_label(LoadResStr("IDS_MNU_NEW")); - gtk_menu_shell_append(GTK_MENU_SHELL(menuViewport), viewNew); - - helpAbout = gtk_menu_item_new_with_label(LoadResStr("IDS_MENU_ABOUT")); - gtk_menu_shell_append(GTK_MENU_SHELL(menuHelp), helpAbout); - - // ------------ Window --------------------- - GtkWidget* box = gtk_grid_new(); - gtk_orientable_set_orientation (GTK_ORIENTABLE(box), GTK_ORIENTATION_VERTICAL); - - gtk_container_add(GTK_CONTAINER(box), menuBar); - gtk_container_add(GTK_CONTAINER(box), top_hbox); - gtk_widget_set_vexpand(scroll, true); - gtk_widget_set_hexpand(scroll, true); - gtk_container_add(GTK_CONTAINER(box), scroll); - gtk_widget_set_margin_top(txtScript, 3); - gtk_widget_set_margin_bottom(txtScript, 3); - gtk_container_add(GTK_CONTAINER(box), txtScript); - gtk_container_add(GTK_CONTAINER(box), statusBar); - - gtk_container_add(GTK_CONTAINER(GetOwner()->window), box); - gtk_widget_show_all(GTK_WIDGET(GetOwner()->window)); - - // ------------ Signals --------------------- - handlerDestroy = g_signal_connect(G_OBJECT(GetOwner()->window), "destroy", G_CALLBACK(OnDestroy), this); - handlerPlay = g_signal_connect(G_OBJECT(btnPlay), "toggled", G_CALLBACK(OnPlay), this); - handlerHalt = g_signal_connect(G_OBJECT(btnHalt), "toggled", G_CALLBACK(OnHalt), this); - handlerModePlay = g_signal_connect(G_OBJECT(btnModePlay), "toggled", G_CALLBACK(OnModePlay), this); - handlerModeEdit = g_signal_connect(G_OBJECT(btnModeEdit), "toggled", G_CALLBACK(OnModeEdit), this); - handlerModeDraw = g_signal_connect(G_OBJECT(btnModeDraw), "toggled", G_CALLBACK(OnModeDraw), this); - g_signal_connect(G_OBJECT(txtScript), "activate", G_CALLBACK(OnScriptEntry), this); - g_signal_connect(G_OBJECT(fileOpen), "activate", G_CALLBACK(OnFileOpen), this); - g_signal_connect(G_OBJECT(fileOpenWithPlayers), "activate", G_CALLBACK(OnFileOpenWPlrs), this); - g_signal_connect(G_OBJECT(fileSave), "activate", G_CALLBACK(OnFileSave), this); - g_signal_connect(G_OBJECT(fileSaveAs), "activate", G_CALLBACK(OnFileSaveAs), this); - g_signal_connect(G_OBJECT(fileSaveGameAs), "activate", G_CALLBACK(OnFileSaveGameAs), this); - g_signal_connect(G_OBJECT(fileRecord), "activate", G_CALLBACK(OnFileRecord), this); - g_signal_connect(G_OBJECT(fileClose), "activate", G_CALLBACK(OnFileClose), this); - g_signal_connect(G_OBJECT(fileQuit), "activate", G_CALLBACK(OnFileQuit), this); - g_signal_connect(G_OBJECT(compObjects), "activate", G_CALLBACK(OnCompObjects), this); - g_signal_connect(G_OBJECT(plrJoin), "activate", G_CALLBACK(OnPlrJoin), this); - g_signal_connect(G_OBJECT(viewNew), "activate", G_CALLBACK(OnViewNew), this); - g_signal_connect(G_OBJECT(helpAbout), "activate", G_CALLBACK(OnHelpAbout), this); -} - -void C4ConsoleGUI::State::Clear() -{ - // Clear widget pointers - txtLog = NULL; - txtScript = NULL; - btnPlay = NULL; - btnHalt = NULL; - btnModePlay = NULL; - btnModeEdit = NULL; - btnModeDraw = NULL; - - menuBar = NULL; - itemNet = NULL; - menuNet = NULL; - - menuViewport = NULL; - menuPlayer = NULL; - - fileOpen = NULL; - fileOpenWithPlayers = NULL; - fileSave = NULL; - fileSaveAs = NULL; - fileSaveGameAs = NULL; - fileRecord = NULL; - fileClose = NULL; - fileQuit = NULL; - - compObjects = NULL; - - plrJoin = NULL; - - viewNew = NULL; - - helpAbout = NULL; - - statusBar = NULL; - lblFrame = NULL; - lblTime = NULL; - - handlerDestroy = 0; - handlerPlay = 0; - handlerHalt = 0; - handlerModePlay = 0; - handlerModeEdit = 0; - handlerModeDraw = 0; - handlerPropertyDlgRescrollIdle = 0; - - propertydlg = 0; -} - -void C4ConsoleGUI::DisplayInfoText(InfoTextType type, StdStrBuf& text) -{ - if (!Active) - return; - GtkWidget* label; - switch (type) - { - case CONSOLE_Cursor: - gtk_statusbar_pop(GTK_STATUSBAR(state->statusBar), 0); - if (text.getData()) gtk_statusbar_push(GTK_STATUSBAR(state->statusBar), 0, text.getData()); - return; - case CONSOLE_FrameCounter: - label = state->lblFrame; - break; - case CONSOLE_TimeFPS: - label = state->lblTime; - } - gtk_label_set_label(GTK_LABEL(label), text.getData()); -} - -void C4ConsoleGUI::AddMenuItemForPlayer(C4Player *player, StdStrBuf &player_text) -{ - GtkWidget* menuItem = gtk_menu_item_new_with_label(player_text.getData()); - gtk_menu_shell_append(GTK_MENU_SHELL(state->menuViewport), menuItem); - g_signal_connect(G_OBJECT(menuItem), "activate", G_CALLBACK(State::OnViewNewPlr), GINT_TO_POINTER(player->Number)); - gtk_widget_show(menuItem); -} - -void C4ConsoleGUI::SetCursor(Cursor cursor) -{ - // Seems not to work. Don't know why... - GdkDisplay * display = gtk_widget_get_display(GTK_WIDGET(window)); - GdkCursor * gdkcursor; - - if (cursor == CURSOR_Wait) - gdkcursor = gdk_cursor_new_for_display(display, GDK_WATCH); - else - gdkcursor = NULL; - - GdkWindow* window_wnd = gtk_widget_get_window(GTK_WIDGET(window)); - - gdk_window_set_cursor(window_wnd, gdkcursor); - gdk_display_flush(display); - if (cursor) - g_object_unref (gdkcursor); -} - -void C4ConsoleGUI::ClearViewportMenu() -{ - // Don't need to do anything if the GUI is not created - if(state->menuViewport == NULL) return; - - GList* children = gtk_container_get_children(GTK_CONTAINER(state->menuViewport)); - for (GList* item = children; item != NULL; item = item->next) - { - if (item->data != state->viewNew) - gtk_container_remove(GTK_CONTAINER(state->menuViewport), GTK_WIDGET(item->data)); - } - g_list_free(children); -} - -void C4ConsoleGUI::RecordingEnabled() -{ - gtk_widget_set_sensitive(state->fileRecord, false); -} - -void C4ConsoleGUI::ShowAboutWithCopyright(StdStrBuf ©right) -{ - gtk_show_about_dialog(GTK_WINDOW(window), "name", C4ENGINECAPTION, "version", C4VERSION, "copyright", copyright.getData(), NULL); -} - -bool C4ConsoleGUI::UpdateModeCtrls(int iMode) -{ - if (!Active) - return false; - - // Prevents recursion - g_signal_handler_block(state->btnModePlay, state->handlerModePlay); - g_signal_handler_block(state->btnModeEdit, state->handlerModeEdit); - g_signal_handler_block(state->btnModeDraw, state->handlerModeDraw); - - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(state->btnModePlay), iMode == C4CNS_ModePlay); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(state->btnModeEdit), iMode == C4CNS_ModeEdit); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(state->btnModeDraw), iMode == C4CNS_ModeDraw); - - g_signal_handler_unblock(state->btnModePlay, state->handlerModePlay); - g_signal_handler_unblock(state->btnModeEdit, state->handlerModeEdit); - g_signal_handler_unblock(state->btnModeDraw, state->handlerModeDraw); - return true; -} - -bool C4ConsoleGUI::FileSelect(StdStrBuf *sFilename, const char * szFilter, DWORD dwFlags, bool fSave) -{ - GtkWidget* dialog = gtk_file_chooser_dialog_new(fSave ? "Save file..." : "Load file...", GTK_WINDOW(window), fSave ? GTK_FILE_CHOOSER_ACTION_SAVE : GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, fSave ? GTK_STOCK_SAVE : GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); - - // TODO: Set dialog modal? - - if (g_path_is_absolute(sFilename->getData()) ) - gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), sFilename->getData()); - else if (fSave) - gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), sFilename->getData()); - - // Install file filter - while (*szFilter) - { - char pattern[16 + 1]; - - GtkFileFilter* filter = gtk_file_filter_new(); - gtk_file_filter_set_name(filter, szFilter); - szFilter+=SLen(szFilter)+1; - - while (true) - { - SCopyUntil(szFilter, pattern, ';', 16); - - int len = SLen(pattern); - char last_c = szFilter[len]; - - szFilter += (len + 1); - - // Got not all of the filter, try again. - if (last_c != ';' && last_c != '\0') - continue; - - gtk_file_filter_add_pattern(filter, pattern); - if (last_c == '\0') break; - } - - gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter); - } - - gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), (dwFlags & OFN_OVERWRITEPROMPT) != 0); - - // TODO: Not in GTK+ 2.4, we could check GTK+ version at runtime and rely on lazy binding -// gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(dialog), (dwFlags & OFN_HIDEREADONLY) == 0); - - gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), (dwFlags & OFN_ALLOWMULTISELECT) != 0); - gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dialog), true); - - int response; - while (true) - { - response = gtk_dialog_run(GTK_DIALOG(dialog)); - if (response == GTK_RESPONSE_CANCEL || response == GTK_RESPONSE_DELETE_EVENT) break; - - bool error = false; - - // Check for OFN_FILEMUSTEXIST - if ((dwFlags & OFN_ALLOWMULTISELECT) == 0) - { - char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - - if ((dwFlags & OFN_FILEMUSTEXIST) && !g_file_test(filename, G_FILE_TEST_IS_REGULAR)) - { - Message(FormatString("File \"%s\" does not exist", filename).getData(), false); - error = true; - } - - g_free(filename); - } - - if (!error) break; - } - - if (response != GTK_RESPONSE_ACCEPT) - { - gtk_widget_destroy(dialog); - return false; - } - - // Build result string - if ((dwFlags & OFN_ALLOWMULTISELECT) == 0) - { - // Just the file name without multiselect - char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - sFilename->Copy(filename); - g_free(filename); - } - else - { - // Otherwise its the folder followed by the file names, - // separated by '\0'-bytes - char* folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(dialog)); - - sFilename->Copy(folder); - g_free(folder); - - GSList* files = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); - for (GSList* item = files; item != NULL; item = item->next) - { - const char* file = static_cast(item->data); - char* basefile = g_path_get_basename(file); - - sFilename->AppendChar('\0'); - sFilename->Append(basefile); - - g_free(basefile); - g_free(item->data); - } - - // End of list - g_slist_free(files); - } - - gtk_widget_destroy(dialog); - return true; -} - -bool C4ConsoleGUI::Message(const char *message, bool query) -{ - if (!Active) return false; - GtkWidget* dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, query ? (GTK_BUTTONS_OK_CANCEL) : (GTK_BUTTONS_OK), "%s", message); - int response = gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); - return response == GTK_RESPONSE_OK; -} - -void C4ConsoleGUI::Out(const char *message) -{ - // Append text to log - if (!window) return; - - GtkTextIter end; - GtkTextBuffer* buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(state->txtLog)); - gtk_text_buffer_get_end_iter(buffer, &end); - - gtk_text_buffer_insert(buffer, &end, message, -1); - gtk_text_buffer_insert(buffer, &end, "\n", 1); - - gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(state->txtLog), gtk_text_buffer_get_insert(buffer), 0.0, false, 0.0, 0.0); -} - -void C4ConsoleGUI::AddNetMenu() -{ - state->itemNet = gtk_menu_item_new_with_label(LoadResStr("IDS_MNU_NET")); - state->menuNet = gtk_menu_new(); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(state->itemNet), state->menuNet); - gtk_menu_shell_insert(GTK_MENU_SHELL(state->menuBar), state->itemNet, 4 /*MenuIndexHelp*/); - gtk_widget_show_all(state->itemNet); -} - -void C4ConsoleGUI::AddNetMenuItemForPlayer(int32_t index, StdStrBuf &text) -{ - GtkWidget* item = gtk_menu_item_new_with_label(text.getData()); - gtk_menu_shell_append(GTK_MENU_SHELL(state->menuNet), item); - g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(State::OnNetClient), GINT_TO_POINTER(Game.Clients.getLocalID())); - gtk_widget_show_all(item); -} - -void C4ConsoleGUI::ClearNetMenu() -{ - // Don't need to do anything if the GUI is not created - if(state->menuBar == NULL || state->itemNet == NULL) return; - - gtk_container_remove(GTK_CONTAINER(state->menuBar), state->itemNet); - state->itemNet = NULL; -} - -void C4ConsoleGUI::SetInputFunctions(std::list& functions) -{ - // Don't need to do anything if the GUI is not created - if(state->txtScript == NULL) return; - - GtkEntryCompletion* completion = gtk_entry_get_completion(GTK_ENTRY(state->txtScript)); - if (!completion) - { - completion = gtk_entry_completion_new(); - GtkListStore* store = gtk_list_store_new(1, G_TYPE_STRING); - gtk_entry_completion_set_model(completion, GTK_TREE_MODEL(store)); - g_object_unref(G_OBJECT(store)); - gtk_entry_completion_set_text_column(completion, 0); - gtk_entry_set_completion(GTK_ENTRY(state->txtScript), completion); - g_object_unref(G_OBJECT(completion)); - } - - GtkListStore* store = GTK_LIST_STORE(gtk_entry_completion_get_model(completion)); - g_assert(store); - gtk_list_store_clear(store); - - GtkTreeIter iter; - for (std::list::iterator it(functions.begin()); it != functions.end(); ++it) - { - const char* fn = *it; - if (!fn) continue; - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, 0, fn, -1); - } -} - -void C4ConsoleGUI::ClearPlayerMenu() -{ - // Don't need to do anything if the GUI is not created - if(state->menuPlayer == NULL) return; - - GList* children = gtk_container_get_children(GTK_CONTAINER(state->menuPlayer)); - for (GList* item = children; item != NULL; item = item->next) - { - if (item->data != state->plrJoin) - gtk_container_remove(GTK_CONTAINER(state->menuPlayer), GTK_WIDGET(item->data)); - } - g_list_free(children); -} - -void C4ConsoleGUI::AddKickPlayerMenuItem(C4Player *player, StdStrBuf& player_text, bool enabled) -{ - // TODO: Implement AddMenuItem... - GtkWidget* menuItem = gtk_menu_item_new_with_label(player_text.getData()); - gtk_menu_shell_append(GTK_MENU_SHELL(state->menuPlayer), menuItem); - g_signal_connect(G_OBJECT(menuItem), "activate", G_CALLBACK(State::OnPlrQuit), GINT_TO_POINTER(player->Number)); - gtk_widget_show(menuItem); - - gtk_widget_set_sensitive(menuItem, (!::Network.isEnabled() || ::Network.isHost()) && Editing); -} - -bool C4ConsoleGUI::ClearLog() -{ - if(state->txtLog == NULL) return false; - - gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(state->txtLog)), "", 0); - return true; -} - -bool C4ConsoleGUI::DoUpdateHaltCtrls(bool fHalt) -{ - // Prevents recursion - g_signal_handler_block(state->btnPlay, state->handlerPlay); - g_signal_handler_block(state->btnHalt, state->handlerHalt); - - //gtk_widget_set_sensitive(btnPlay, fHalt); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(state->btnPlay), !fHalt); - //gtk_widget_set_sensitive(btnHalt, !fHalt); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(state->btnHalt), fHalt); - - g_signal_handler_unblock(state->btnPlay, state->handlerPlay); - g_signal_handler_unblock(state->btnHalt, state->handlerHalt); - return true; -} - -void C4ConsoleGUI::ToolsDlgSelectTexture(C4ToolsDlg *dlg, const char *texture) -{ - C4ToolsDlg::State* state = dlg->state; - g_signal_handler_block(state->fg_textures, state->handlerFgTextures); - SelectComboBoxText(GTK_COMBO_BOX(state->fg_textures), texture); - g_signal_handler_unblock(state->fg_textures, state->handlerFgTextures); -} - -void C4ConsoleGUI::ToolsDlgSelectMaterial(C4ToolsDlg *dlg, const char *material) -{ - C4ToolsDlg::State* state = dlg->state; - g_signal_handler_block(state->fg_materials, state->handlerFgMaterials); - SelectComboBoxText(GTK_COMBO_BOX(state->fg_materials), material); - g_signal_handler_unblock(state->fg_materials, state->handlerFgMaterials); -} - -void C4ConsoleGUI::ToolsDlgSelectBackTexture(C4ToolsDlg *dlg, const char *texture) -{ - C4ToolsDlg::State* state = dlg->state; - g_signal_handler_block(state->bg_textures, state->handlerBgTextures); - SelectComboBoxText(GTK_COMBO_BOX(state->bg_textures), texture); - g_signal_handler_unblock(state->bg_textures, state->handlerBgTextures); -} - -void C4ConsoleGUI::ToolsDlgSelectBackMaterial(C4ToolsDlg *dlg, const char *material) -{ - C4ToolsDlg::State* state = dlg->state; - g_signal_handler_block(state->bg_materials, state->handlerBgMaterials); - SelectComboBoxText(GTK_COMBO_BOX(state->bg_materials), material); - g_signal_handler_unblock(state->bg_materials, state->handlerBgMaterials); -} - -void C4ConsoleGUI::DoEnableControls(bool fEnable) -{ - state->DoEnableControls(fEnable); -} - -void C4ConsoleGUI::State::DoEnableControls(bool fEnable) -{ - // Halt controls - gtk_widget_set_sensitive(btnPlay, ::Network.isLobbyActive() || fEnable); - gtk_widget_set_sensitive(btnHalt, ::Network.isLobbyActive() || fEnable); - - // Edit modes - gtk_widget_set_sensitive(btnModePlay, ::Network.isLobbyActive() || fEnable); - gtk_widget_set_sensitive(btnModeEdit, ::Network.isLobbyActive() || fEnable); - gtk_widget_set_sensitive(btnModeDraw, ::Network.isLobbyActive() || fEnable); - - // Console input - gtk_widget_set_sensitive(txtScript, ::Network.isLobbyActive() || fEnable); - - // File menu - // C4Network2 will have to handle that cases somehow (TODO: test) - gtk_widget_set_sensitive(fileRecord, Game.IsRunning && ::Control.IsRuntimeRecordPossible()); - gtk_widget_set_sensitive(fileSaveGameAs, fEnable && ::Players.GetCount()); - gtk_widget_set_sensitive(fileSave, fEnable); - gtk_widget_set_sensitive(fileSaveAs, fEnable); - gtk_widget_set_sensitive(fileClose, fEnable); - - // Components menu - gtk_widget_set_sensitive(compObjects, fEnable && GetOwner()->Editing); - // Player & viewport menu - gtk_widget_set_sensitive(plrJoin, fEnable && GetOwner()->Editing); - gtk_widget_set_sensitive(viewNew, fEnable); -} - -bool C4ConsoleGUI::PropertyDlgOpen() -{ - if (state->propertydlg == NULL) - { - GtkWidget * vbox = state->propertydlg = gtk_grid_new(); - gtk_orientable_set_orientation(GTK_ORIENTABLE(vbox), GTK_ORIENTATION_VERTICAL); - - GtkWidget* scrolled_wnd = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_wnd), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_wnd), GTK_SHADOW_IN); - GtkAdjustment* adj = state->propertydlg_vadj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(scrolled_wnd)); - state->propertydlg_vadj_pos = -1.0; - - g_signal_connect(G_OBJECT(adj), "changed", G_CALLBACK(State::OnPropertyVadjustmentChanged), this); - - GtkWidget * textview = state->propertydlg_textview = gtk_text_view_new(); - GtkWidget * entry = state->propertydlg_entry = gtk_entry_new(); - - gtk_container_add(GTK_CONTAINER(scrolled_wnd), textview); - gtk_widget_set_vexpand(scrolled_wnd, true); - gtk_widget_set_hexpand(scrolled_wnd, true); - gtk_container_add(GTK_CONTAINER(vbox), scrolled_wnd); - gtk_widget_set_margin_top(entry, 3); - gtk_container_add(GTK_CONTAINER(vbox), entry); - - gtk_text_view_set_editable(GTK_TEXT_VIEW(textview), false); - gtk_text_view_set_left_margin(GTK_TEXT_VIEW(textview), 2); - gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(textview), GTK_WRAP_CHAR); - gtk_widget_set_sensitive(entry, Console.Editing); - - gtk_widget_show_all(vbox); - - C4DevmodeDlg::AddPage(vbox, GTK_WINDOW(Console.window), LoadResStr("IDS_DLG_PROPERTIES")); - - g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(State::OnScriptActivate), this); - } - - C4DevmodeDlg::SwitchPage(state->propertydlg); - return true; -} - -void C4ConsoleGUI::PropertyDlgClose() -{ -} - -void C4ConsoleGUI::PropertyDlgUpdate(C4EditCursorSelection &rSelection, bool force_function_update) -{ - if (!state->propertydlg) return; - if (!C4DevmodeDlg::GetWindow()) return; - if (!gtk_widget_get_visible(GTK_WIDGET(C4DevmodeDlg::GetWindow()))) return; - - // Remember current scroll position - if (PropertyDlgObject == rSelection.GetObject()) - { - state->propertydlg_vadj_pos = gtk_adjustment_get_value(state->propertydlg_vadj); - state->handlerPropertyDlgRescrollIdle = g_idle_add_full(GTK_TEXT_VIEW_PRIORITY_VALIDATE + 1, State::OnPropertyDlgRescrollIdle, this, NULL); - } - else - { - state->propertydlg_vadj_pos = -1.0; - // TODO: Reset idle handler? - } - - GtkTextBuffer* buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(state->propertydlg_textview)); - gtk_text_buffer_set_text(buffer, rSelection.GetDataString().getData(), -1); - - if (PropertyDlgObject == rSelection.GetObject() && !force_function_update) return; - PropertyDlgObject = rSelection.GetObject(); - - std::list functions = ::Console.GetScriptSuggestions(PropertyDlgObject, C4Console::MRU_Object); - GtkEntryCompletion* completion = gtk_entry_get_completion(GTK_ENTRY(state->propertydlg_entry)); - GtkListStore* store; - - // Uncouple list store from completion so that the completion is not - // notified for every row we are going to insert. This enhances - // performance significantly. - if (!completion) - { - completion = gtk_entry_completion_new(); - store = gtk_list_store_new(1, G_TYPE_STRING); - - gtk_entry_completion_set_text_column(completion, 0); - gtk_entry_set_completion(GTK_ENTRY(state->propertydlg_entry), completion); - g_object_unref(G_OBJECT(completion)); - } - else - { - store = GTK_LIST_STORE(gtk_entry_completion_get_model(completion)); - g_object_ref(G_OBJECT(store)); - gtk_entry_completion_set_model(completion, NULL); - } - - GtkTreeIter iter; - gtk_list_store_clear(store); - - for (std::list::iterator it(functions.begin()); it != functions.end(); it++) - { - const char* fn = *it; - if (fn) - { - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, 0, fn, -1); - } - } - - // Reassociate list store with completion - gtk_entry_completion_set_model(completion, GTK_TREE_MODEL(store)); -} - -bool C4ConsoleGUI::ToolsDlgOpen(C4ToolsDlg *dlg) -{ - return dlg->state->Open(); -} - -bool C4ToolsDlg::State::Open() -{ - if (hbox == NULL) - { - hbox = gtk_grid_new(); - GtkWidget * toolbar = gtk_toolbar_new(); - - GtkWidget* image_brush = gtk_image_new_from_resource("/org/openclonk/engine/Brush_Trans.png"); - GtkWidget* image_line = gtk_image_new_from_resource("/org/openclonk/engine/Line_Trans.png"); - GtkWidget* image_rect = gtk_image_new_from_resource("/org/openclonk/engine/Rect_Trans.png"); - GtkWidget* image_fill = gtk_image_new_from_resource("/org/openclonk/engine/Fill_Trans.png"); - GtkWidget* image_picker = gtk_image_new_from_resource("/org/openclonk/engine/Picker_Trans.png"); - GtkWidget* image_dynamic = gtk_image_new_from_resource("/org/openclonk/engine/Dynamic_Trans.png"); - GtkWidget* image_static = gtk_image_new_from_resource("/org/openclonk/engine/Static_Trans.png"); - GtkWidget* image_exact = gtk_image_new_from_resource("/org/openclonk/engine/Exact_Trans.png"); - - brush = GTK_WIDGET(gtk_toggle_tool_button_new()); - line = GTK_WIDGET(gtk_toggle_tool_button_new()); - rect = GTK_WIDGET(gtk_toggle_tool_button_new()); - fill = GTK_WIDGET(gtk_toggle_tool_button_new()); - picker = GTK_WIDGET(gtk_toggle_tool_button_new()); - landscape_dynamic = GTK_WIDGET(gtk_toggle_tool_button_new()); - landscape_static = GTK_WIDGET(gtk_toggle_tool_button_new()); - landscape_exact = GTK_WIDGET(gtk_toggle_tool_button_new()); - - gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(landscape_dynamic), image_dynamic); - gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(landscape_static), image_static); - gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(landscape_exact), image_exact); - gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(brush), image_brush); - gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(line), image_line); - gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(rect), image_rect); - gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(fill), image_fill); - gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(picker), image_picker); - - gtk_container_add(GTK_CONTAINER(toolbar), landscape_dynamic); - gtk_container_add(GTK_CONTAINER(toolbar), landscape_static); - gtk_container_add(GTK_CONTAINER(toolbar), landscape_exact); - gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(gtk_separator_tool_item_new())); - gtk_container_add(GTK_CONTAINER(toolbar), brush); - gtk_container_add(GTK_CONTAINER(toolbar), line); - gtk_container_add(GTK_CONTAINER(toolbar), rect); - gtk_container_add(GTK_CONTAINER(toolbar), fill); - gtk_container_add(GTK_CONTAINER(toolbar), picker); - - gtk_grid_attach(GTK_GRID(hbox), toolbar, 0, 0, 5, 1); - - preview = gtk_image_new(); - gtk_widget_set_vexpand(preview, true); - gtk_widget_set_hexpand(preview, true); - gtk_grid_attach(GTK_GRID(hbox), preview, 0, 1, 1, 1); - - scale = gtk_scale_new(GTK_ORIENTATION_VERTICAL, NULL); - gtk_widget_set_vexpand(scale, true); - gtk_grid_attach(GTK_GRID(hbox), scale, 1, 1, 1, 1); - - GtkWidget * grid = gtk_grid_new(); - fg_materials = gtk_combo_box_text_new(); - g_object_set(fg_materials, "margin", 3, NULL); - fg_textures = gtk_combo_box_text_new(); - g_object_set(fg_textures, "margin", 3, NULL); - bg_materials = gtk_combo_box_text_new(); - g_object_set(bg_materials, "margin", 3, NULL); - bg_textures = gtk_combo_box_text_new(); - g_object_set(bg_textures, "margin", 3, NULL); - - // Link the material combo boxes together, but not the texture combo boxes, - // so that we can sort the texture combo box differently. - gtk_combo_box_set_model(GTK_COMBO_BOX(bg_materials), gtk_combo_box_get_model(GTK_COMBO_BOX(fg_materials))); - - gtk_combo_box_set_row_separator_func(GTK_COMBO_BOX(fg_materials), RowSeparatorFunc, NULL, NULL); - gtk_combo_box_set_row_separator_func(GTK_COMBO_BOX(fg_textures), RowSeparatorFunc, NULL, NULL); - gtk_combo_box_set_row_separator_func(GTK_COMBO_BOX(bg_materials), RowSeparatorFunc, NULL, NULL); - gtk_combo_box_set_row_separator_func(GTK_COMBO_BOX(bg_textures), RowSeparatorFunc, NULL, NULL); - - gtk_grid_attach(GTK_GRID(grid), gtk_label_new(LoadResStr("IDS_CTL_MATERIAL")), 1, 0, 1, 1); - gtk_grid_attach(GTK_GRID(grid), gtk_label_new(LoadResStr("IDS_CTL_TEXTURE")), 2, 0, 1, 1); - - GtkWidget* fg_lbl = gtk_label_new(LoadResStr("IDS_CTL_FOREGROUND")); - gtk_widget_set_halign(fg_lbl, GTK_ALIGN_END); -#if GTK_CHECK_VERSION(3,12,0) - gtk_widget_set_margin_start(fg_lbl, 3); -#else - gtk_widget_set_margin_left(fg_lbl, 3); -#endif - gtk_grid_attach(GTK_GRID(grid), fg_lbl, 0, 1, 1, 1); - gtk_grid_attach(GTK_GRID(grid), fg_materials, 1, 1, 1, 1); - gtk_grid_attach(GTK_GRID(grid), fg_textures, 2, 1, 1, 1); - - GtkWidget* bg_lbl = gtk_label_new(LoadResStr("IDS_CTL_BACKGROUND")); - gtk_widget_set_halign(bg_lbl, GTK_ALIGN_END); -#if GTK_CHECK_VERSION(3,12,0) - gtk_widget_set_margin_start(bg_lbl, 3); -#else - gtk_widget_set_margin_left(bg_lbl, 3); -#endif - gtk_grid_attach(GTK_GRID(grid), bg_lbl, 0, 2, 1, 1); - gtk_grid_attach(GTK_GRID(grid), bg_materials, 1, 2, 1, 1); - gtk_grid_attach(GTK_GRID(grid), bg_textures, 2, 2, 1, 1); - - gtk_grid_attach(GTK_GRID(hbox), grid, 2, 1, 1, 1); - - gtk_widget_show_all(hbox); - - C4DevmodeDlg::AddPage(hbox, GTK_WINDOW(Console.window), LoadResStr("IDS_DLG_TOOLS")); - - //g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(OnDestroy), this); - handlerDynamic = g_signal_connect(G_OBJECT(landscape_dynamic), "toggled", G_CALLBACK(OnButtonModeDynamic), this); - handlerStatic = g_signal_connect(G_OBJECT(landscape_static), "toggled", G_CALLBACK(OnButtonModeStatic), this); - handlerExact = g_signal_connect(G_OBJECT(landscape_exact), "toggled", G_CALLBACK(OnButtonModeExact), this); - handlerBrush = g_signal_connect(G_OBJECT(brush), "toggled", G_CALLBACK(OnButtonBrush), this); - handlerLine = g_signal_connect(G_OBJECT(line), "toggled", G_CALLBACK(OnButtonLine), this); - handlerRect = g_signal_connect(G_OBJECT(rect), "toggled", G_CALLBACK(OnButtonRect), this); - handlerFill = g_signal_connect(G_OBJECT(fill), "toggled", G_CALLBACK(OnButtonFill), this); - handlerPicker = g_signal_connect(G_OBJECT(picker), "toggled", G_CALLBACK(OnButtonPicker), this); - handlerFgMaterials = g_signal_connect(G_OBJECT(fg_materials), "changed", G_CALLBACK(OnComboMaterial), this); - handlerFgTextures = g_signal_connect(G_OBJECT(fg_textures), "changed", G_CALLBACK(OnComboTexture), this); - handlerBgMaterials = g_signal_connect(G_OBJECT(bg_materials), "changed", G_CALLBACK(OnComboBgMaterial), this); - handlerBgTextures = g_signal_connect(G_OBJECT(bg_textures), "changed", G_CALLBACK(OnComboBgTexture), this); - handlerScale = g_signal_connect(G_OBJECT(scale), "value-changed", G_CALLBACK(OnGrade), this); - - handlerHide = g_signal_connect(G_OBJECT(C4DevmodeDlg::GetWindow()), "hide", G_CALLBACK(OnWindowHide), this); - } - - C4DevmodeDlg::SwitchPage(hbox); - return true; -} - -void C4ConsoleGUI::ToolsDlgInitMaterialCtrls(C4ToolsDlg *dlg) -{ - dlg->state->InitMaterialCtrls(); -} - -void C4ToolsDlg::State::InitMaterialCtrls() -{ - GtkListStore* list = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(fg_materials))); - - g_signal_handler_block(fg_materials, handlerFgMaterials); - g_signal_handler_block(bg_materials, handlerBgMaterials); - gtk_list_store_clear(list); - - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(fg_materials), C4TLS_MatSky); - - for (int32_t cnt = 0; cnt < ::MaterialMap.Num; cnt++) - { - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(fg_materials), ::MaterialMap.Map[cnt].Name); - } - - g_signal_handler_unblock(fg_materials, handlerFgMaterials); - g_signal_handler_unblock(bg_materials, handlerBgMaterials); - - SelectComboBoxText(GTK_COMBO_BOX(fg_materials), GetOwner()->Material); - SelectComboBoxText(GTK_COMBO_BOX(bg_materials), GetOwner()->BackMaterial); -} - -void C4ToolsDlg::UpdateToolCtrls() -{ - state->UpdateToolCtrls(); -} - -void C4ToolsDlg::State::UpdateToolCtrls() -{ - C4ToolsDlg* dlg = GetOwner(); - g_signal_handler_block(brush, handlerBrush); - g_signal_handler_block(line, handlerLine); - g_signal_handler_block(rect, handlerRect); - g_signal_handler_block(fill, handlerFill); - g_signal_handler_block(picker, handlerPicker); - - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(brush), dlg->Tool == C4TLS_Brush); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(line), dlg->Tool == C4TLS_Line); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(rect), dlg->Tool == C4TLS_Rect); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(fill), dlg->Tool == C4TLS_Fill); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(picker), dlg->Tool == C4TLS_Picker); - - g_signal_handler_unblock(brush, handlerBrush); - g_signal_handler_unblock(line, handlerLine); - g_signal_handler_unblock(rect, handlerRect); - g_signal_handler_unblock(fill, handlerFill); - g_signal_handler_unblock(picker, handlerPicker); -} - -void C4ToolsDlg::UpdateTextures() -{ - GtkComboBox* boxes[2] = { - GTK_COMBO_BOX(state->fg_textures), - GTK_COMBO_BOX(state->bg_textures) - }; - - const char* materials[2] = { - Material, BackMaterial - }; - - for (int i = 0; i < 2; ++i) - { - // Refill dlg - GtkComboBox* box = boxes[i]; - const char* material = materials[i]; - - GtkListStore* list = GTK_LIST_STORE(gtk_combo_box_get_model(box)); - gtk_list_store_clear(list); - - // bottom-most: any invalid textures - bool fAnyEntry = false; int32_t cnt; const char *szTexture; - if (::Landscape.GetMode()!=LandscapeMode::Exact) - for (cnt=0; (szTexture=::TextureMap.GetTexture(cnt)); cnt++) - { - if (!::TextureMap.GetIndex(material, szTexture, false)) - { - fAnyEntry = true; - gtk_combo_box_text_prepend_text(GTK_COMBO_BOX_TEXT(box), szTexture); - } - } - // separator - if (fAnyEntry) - { - gtk_combo_box_text_prepend_text(GTK_COMBO_BOX_TEXT(box), "-------"); - } - - // atop: valid textures - for (cnt=0; (szTexture=::TextureMap.GetTexture(cnt)); cnt++) - { - // Current material-texture valid? Always valid for exact mode - if (::TextureMap.GetIndex(material,szTexture,false) || ::Landscape.GetMode()==LandscapeMode::Exact) - { - gtk_combo_box_text_prepend_text(GTK_COMBO_BOX_TEXT(box), szTexture); - } - } - } - - // reselect current - g_signal_handler_block(state->fg_textures, state->handlerFgTextures); - SelectComboBoxText(GTK_COMBO_BOX(state->fg_textures), Texture); - g_signal_handler_unblock(state->fg_textures, state->handlerFgTextures); - - g_signal_handler_block(state->bg_textures, state->handlerBgTextures); - SelectComboBoxText(GTK_COMBO_BOX(state->bg_textures), BackTexture); - g_signal_handler_unblock(state->bg_textures, state->handlerBgTextures); -} - -void C4ToolsDlg::NeedPreviewUpdate() -{ - state->UpdatePreview(); -} - -void C4ToolsDlg::State::UpdatePreview() -{ - if (!hbox) return; - if (!gtk_widget_is_sensitive(preview)) return; - - C4ToolsDlg* dlg = GetOwner(); - - int width = gtk_widget_get_allocated_width(preview); - int height = gtk_widget_get_allocated_height(preview); - width = std::min(width, dlg->Grade * 2); - height = std::min(height, dlg->Grade * 2); - - // fill bg - C4Pattern Pattern; - // Sky material: sky as pattern only - if (SEqual(dlg->Material,C4TLS_MatSky)) - { - Pattern.Set(::Landscape.GetSky().Surface, 0); - } - // Material-Texture - else - { - // Get/Create TexMap entry - BYTE iTex = ::TextureMap.GetIndex(dlg->Material, dlg->Texture, true); - if (iTex) - { - // Define texture pattern - const C4TexMapEntry *pTex = ::TextureMap.GetEntry(iTex); - // Security - if (pTex) - { - // Set drawing pattern - Pattern = pTex->GetPattern(); - } - } - } - - // Copy the texture into a circle in a cairo surface - // TODO: Apply zoom factor to the circle size - cairo_surface_t * surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); - cairo_surface_flush(surface); - unsigned char * data = cairo_image_surface_get_data(surface); - int stride = cairo_image_surface_get_stride(surface); - - int x = width/2, y = height/2, r = dlg->Grade; - for (int ycnt = -std::min(r, height); ycnt < std::min(r, height - y); ycnt++) - { - int lwdt = (int)sqrt(float(r * r - ycnt * ycnt)); - for (int xcnt = std::max(x - lwdt, 0); xcnt < std::min(x + lwdt, width); ++xcnt) - { - DWORD * pix = reinterpret_cast(data + xcnt * 4 + (y + ycnt) * stride); - *pix = Pattern.PatternClr(xcnt, y + ycnt); - } - } - cairo_surface_mark_dirty(surface); - gtk_image_set_from_surface(GTK_IMAGE(preview), surface); - cairo_surface_destroy(surface); -} - -void C4ToolsDlg::UpdateLandscapeModeCtrls() -{ - state->UpdateLandscapeModeCtrls(); -} - -void C4ToolsDlg::State::UpdateLandscapeModeCtrls() -{ - LandscapeMode iMode = ::Landscape.GetMode(); - g_signal_handler_block(landscape_dynamic, handlerDynamic); - g_signal_handler_block(landscape_static, handlerStatic); - g_signal_handler_block(landscape_exact, handlerExact); - - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(landscape_dynamic), iMode==LandscapeMode::Dynamic); - gtk_widget_set_sensitive(landscape_dynamic, iMode==LandscapeMode::Dynamic); - - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(landscape_static), iMode==LandscapeMode::Static); - gtk_widget_set_sensitive(landscape_static, ::Landscape.HasMap()); - - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(landscape_exact), iMode==LandscapeMode::Exact); - - g_signal_handler_unblock(landscape_dynamic, handlerDynamic); - g_signal_handler_unblock(landscape_static, handlerStatic); - g_signal_handler_unblock(landscape_exact, handlerExact); - - C4DevmodeDlg::SetTitle(hbox, LoadResStr(iMode==LandscapeMode::Dynamic ? "IDS_DLG_DYNAMIC" : iMode==LandscapeMode::Static ? "IDS_DLG_STATIC" : "IDS_DLG_EXACT")); -} - -void C4ToolsDlg::UpdateIFTControls() -{ - state->UpdateIFTControls(); -} - -void C4ToolsDlg::State::UpdateIFTControls() -{ - // No-op since we have background material controls -} - -void C4ToolsDlg::InitGradeCtrl() -{ - if (!state->hbox) return; - g_signal_handler_block(state->scale, state->handlerScale); - gtk_range_set_increments(GTK_RANGE(state->scale), 1, 5); - gtk_range_set_range(GTK_RANGE(state->scale), C4TLS_GradeMin, C4TLS_GradeMax); - gtk_scale_set_draw_value(GTK_SCALE(state->scale), false); - gtk_range_set_value(GTK_RANGE(state->scale), C4TLS_GradeMax-Grade); - g_signal_handler_unblock(state->scale, state->handlerScale); -} - -bool C4ToolsDlg::PopMaterial() -{ - if (!state->hbox) return false; - gtk_widget_grab_focus(state->fg_materials); - gtk_combo_box_popup(GTK_COMBO_BOX(state->fg_materials)); - return true; -} - -bool C4ToolsDlg::PopTextures() -{ - if (!state->hbox) return false; - gtk_widget_grab_focus(state->fg_textures); - gtk_combo_box_popup(GTK_COMBO_BOX(state->fg_textures)); - return true; -} - -void C4ConsoleGUI::ToolsDlgClose() -{ - // nope -} - -void C4ConsoleGUI::SetCaptionToFileName(const char* file_name) -{ -} - -void C4ToolsDlg::EnableControls() -{ - LandscapeMode iLandscapeMode=::Landscape.GetMode(); - gtk_widget_set_sensitive(state->brush, iLandscapeMode>=LandscapeMode::Static); - gtk_widget_set_sensitive(state->line, iLandscapeMode>=LandscapeMode::Static); - gtk_widget_set_sensitive(state->rect, iLandscapeMode>=LandscapeMode::Static); - gtk_widget_set_sensitive(state->fill, iLandscapeMode>=LandscapeMode::Exact); - gtk_widget_set_sensitive(state->picker, iLandscapeMode>=LandscapeMode::Static); - gtk_widget_set_sensitive(state->fg_materials, iLandscapeMode>=LandscapeMode::Static); - gtk_widget_set_sensitive(state->fg_textures, iLandscapeMode >= LandscapeMode::Static && !SEqual(Material,C4TLS_MatSky)); - gtk_widget_set_sensitive(state->bg_materials, iLandscapeMode>=LandscapeMode::Static && !SEqual(Material,C4TLS_MatSky)); - gtk_widget_set_sensitive(state->bg_textures, iLandscapeMode >= LandscapeMode::Static && !SEqual(Material,C4TLS_MatSky) && !SEqual(BackMaterial, C4TLS_MatSky)); - gtk_widget_set_sensitive(state->scale, iLandscapeMode>=LandscapeMode::Static); - gtk_widget_set_sensitive(state->preview, iLandscapeMode>=LandscapeMode::Static); - NeedPreviewUpdate(); -} - -// GTK+ Callbacks - -void C4ConsoleGUI::State::OnDestroy(GtkWidget* window, gpointer data) -{ - // The main window was destroyed, so clear all widget pointers in our - // state, so that we don't try to use it anymore. - static_cast(data)->Clear(); -} - -void C4ConsoleGUI::State::OnScriptEntry(GtkWidget* entry, gpointer data) -{ - C4ConsoleGUI::State* state = static_cast(data); - const char * text = gtk_entry_get_text(GTK_ENTRY(state->txtScript)); - ::Console.RegisterRecentInput(text, C4Console::MRU_Scenario); - ::Console.In(text); - ::Console.UpdateInputCtrl(); - gtk_editable_select_region(GTK_EDITABLE(state->txtScript), 0, -1); -} - -void C4ConsoleGUI::State::OnPlay(GtkWidget* button, gpointer data) -{ - Console.DoPlay(); - - // Must update haltctrls even if DoPlay did noting to restore - // previous settings since GTK may have released this toggle button - static_cast(data)->GetOwner()->UpdateHaltCtrls(!!Game.HaltCount); -} - -void C4ConsoleGUI::State::OnHalt(GtkWidget* button, gpointer data) -{ - Console.DoHalt(); - - // Must update haltctrls even if DoPlay did noting to restore - // previous settings since GTK may have released this toggle button - static_cast(data)->GetOwner()->UpdateHaltCtrls(!!Game.HaltCount); -} - -void C4ConsoleGUI::State::OnModePlay(GtkWidget* button, gpointer data) -{ - Console.EditCursor.SetMode(C4CNS_ModePlay); -} - -void C4ConsoleGUI::State::OnModeEdit(GtkWidget* button, gpointer data) -{ - Console.EditCursor.SetMode(C4CNS_ModeEdit); -} - -void C4ConsoleGUI::State::OnModeDraw(GtkWidget* button, gpointer data) -{ - Console.EditCursor.SetMode(C4CNS_ModeDraw); -} - -void C4ConsoleGUI::State::OnFileOpen(GtkWidget* item, gpointer data) -{ - Console.FileOpen(); -} - -void C4ConsoleGUI::State::OnFileOpenWPlrs(GtkWidget* item, gpointer data) -{ - Console.FileOpenWPlrs(); -} - -void C4ConsoleGUI::State::OnFileSave(GtkWidget* item, gpointer data) -{ - Console.FileSave(); -} - -void C4ConsoleGUI::State::OnFileSaveAs(GtkWidget* item, gpointer data) -{ - Console.FileSaveAs(false); -} - -void C4ConsoleGUI::State::OnFileSaveGameAs(GtkWidget* item, gpointer data) -{ - Console.FileSaveAs(true); -} - -void C4ConsoleGUI::State::OnFileRecord(GtkWidget* item, gpointer data) -{ - Console.FileRecord(); -} - -void C4ConsoleGUI::State::OnFileClose(GtkWidget* item, gpointer data) -{ - Console.FileClose(); -} - -void C4ConsoleGUI::State::OnFileQuit(GtkWidget* item, gpointer data) -{ - Console.FileQuit(); -} - -void C4ConsoleGUI::State::OnCompObjects(GtkWidget* item, gpointer data) -{ - Console.ObjectListDlg.Open(); -} - -void C4ConsoleGUI::State::OnPlrJoin(GtkWidget* item, gpointer data) -{ - Console.PlayerJoin(); -} - -void C4ConsoleGUI::State::OnPlrQuit(GtkWidget* item, gpointer data) -{ - C4Player *plr = ::Players.Get(GPOINTER_TO_INT(data)); - if (!plr) return; - ::Control.Input.Add(CID_PlrAction, C4ControlPlayerAction::Eliminate(plr)); -} - -void C4ConsoleGUI::State::OnViewNew(GtkWidget* item, gpointer data) -{ - Console.ViewportNew(); -} - -void C4ConsoleGUI::State::OnViewNewPlr(GtkWidget* item, gpointer data) -{ - ::Viewports.CreateViewport(GPOINTER_TO_INT(data)); -} - -void C4ConsoleGUI::State::OnHelpAbout(GtkWidget* item, gpointer data) -{ - Console.HelpAbout(); -} - -void C4ConsoleGUI::State::OnNetClient(GtkWidget* item, gpointer data) -{ - if (!::Control.isCtrlHost()) return; - Game.Clients.CtrlRemove(Game.Clients.getClientByID(GPOINTER_TO_INT(data)), LoadResStr("IDS_MSG_KICKBYMENU")); -} - -void C4ToolsDlg::State::OnButtonModeDynamic(GtkWidget* widget, gpointer data) -{ - static_cast(data)->GetOwner()->SetLandscapeMode(LandscapeMode::Dynamic, false); -} - -void C4ToolsDlg::State::OnButtonModeStatic(GtkWidget* widget, gpointer data) -{ - static_cast(data)->GetOwner()->SetLandscapeMode(LandscapeMode::Static, false); -} - -void C4ToolsDlg::State::OnButtonModeExact(GtkWidget* widget, gpointer data) -{ - static_cast(data)->GetOwner()->SetLandscapeMode(LandscapeMode::Exact, false); -} - -void C4ToolsDlg::State::OnButtonBrush(GtkWidget* widget, gpointer data) -{ - static_cast(data)->GetOwner()->SetTool(C4TLS_Brush, false); -} - -void C4ToolsDlg::State::OnButtonLine(GtkWidget* widget, gpointer data) -{ - static_cast(data)->GetOwner()->SetTool(C4TLS_Line, false); -} - -void C4ToolsDlg::State::OnButtonRect(GtkWidget* widget, gpointer data) -{ - static_cast(data)->GetOwner()->SetTool(C4TLS_Rect, false); -} - -void C4ToolsDlg::State::OnButtonFill(GtkWidget* widget, gpointer data) -{ - static_cast(data)->GetOwner()->SetTool(C4TLS_Fill, false); -} - -void C4ToolsDlg::State::OnButtonPicker(GtkWidget* widget, gpointer data) -{ - static_cast(data)->GetOwner()->SetTool(C4TLS_Picker, false); -} - -void C4ToolsDlg::State::OnButtonIft(GtkWidget* widget, gpointer data) -{ - static_cast(data)->GetOwner()->SetIFT(true); -} - -void C4ToolsDlg::State::OnButtonNoIft(GtkWidget* widget, gpointer data) -{ - static_cast(data)->GetOwner()->SetIFT(false); -} - -void C4ToolsDlg::State::OnComboMaterial(GtkWidget* widget, gpointer data) -{ - gchar* text = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(widget)); - static_cast(data)->GetOwner()->SetMaterial(text); - g_free(text); -} - -void C4ToolsDlg::State::OnComboTexture(GtkWidget* widget, gpointer data) -{ - gchar* text = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(widget)); - static_cast(data)->GetOwner()->SetTexture(text); - g_free(text); -} - -void C4ToolsDlg::State::OnComboBgMaterial(GtkWidget* widget, gpointer data) -{ - gchar* text = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(widget)); - static_cast(data)->GetOwner()->SetBackMaterial(text); - g_free(text); -} - -void C4ToolsDlg::State::OnComboBgTexture(GtkWidget* widget, gpointer data) -{ - gchar* text = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(widget)); - static_cast(data)->GetOwner()->SetBackTexture(text); - g_free(text); -} - -void C4ToolsDlg::State::OnGrade(GtkWidget* widget, gpointer data) -{ - C4ToolsDlg::State* state = static_cast(data); - int value = static_cast(gtk_range_get_value(GTK_RANGE(state->scale)) + 0.5); - state->GetOwner()->SetGrade(C4TLS_GradeMax-value); -} - -void C4ToolsDlg::State::OnWindowHide(GtkWidget* widget, gpointer data) -{ - static_cast(data)->GetOwner()->Active = false; -} - -#include "editor/C4ConsoleGUICommon.h" diff --git a/src/editor/C4ConsoleGTKDlg.cpp b/src/editor/C4ConsoleGTKDlg.cpp deleted file mode 100644 index c915cb299..000000000 --- a/src/editor/C4ConsoleGTKDlg.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - * OpenClonk, http://www.openclonk.org - * - * Copyright (c) 2007-2009, RedWolf Design GmbH, http://www.clonk.de/ - * Copyright (c) 2010-2016, The OpenClonk Team and contributors - * - * Distributed under the terms of the ISC license; see accompanying file - * "COPYING" for details. - * - * "Clonk" is a registered trademark of Matthes Bender, used with permission. - * See accompanying file "TRADEMARK" for details. - * - * To redistribute this file separately, substitute the full license texts - * for the above references. - */ - -/* Common window for drawing and property tool dialogs in console mode */ - -#include "C4Include.h" -#include "editor/C4ConsoleGTKDlg.h" - -#include - -GtkWidget* C4DevmodeDlg::window = NULL; -GtkWidget* C4DevmodeDlg::notebook = NULL; - -int C4DevmodeDlg::x = -1; -int C4DevmodeDlg::y = -1; - -namespace -{ - gboolean OnDeleteEvent(GtkWidget* widget, gpointer user_data) - { - // Just hide the window, don't destroy it - C4DevmodeDlg::SwitchPage(NULL); - return true; - } -} - -void C4DevmodeDlg::OnDestroy(GtkWidget* window, gpointer user_data) -{ - C4DevmodeDlg::window = NULL; - C4DevmodeDlg::notebook = NULL; -} - -void C4DevmodeDlg::AddPage(GtkWidget* widget, GtkWindow* parent, const char* title) -{ - // Create Window if necessary - if (window == NULL) - { - notebook = gtk_notebook_new(); - gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), false); - gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook), false); - gtk_widget_show(GTK_WIDGET(notebook)); - - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_container_add(GTK_CONTAINER(window), notebook); - - gtk_window_set_resizable(GTK_WINDOW(window), true); - gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_UTILITY); - gtk_window_set_default_size(GTK_WINDOW(window), 320, 320); - gtk_window_set_role(GTK_WINDOW(window), "toolbox"); - - gtk_window_set_transient_for(GTK_WINDOW(window), parent); - gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER_ON_PARENT); - - g_signal_connect(G_OBJECT(window), "delete-event", G_CALLBACK(OnDeleteEvent), NULL); - g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(OnDestroy), NULL); - } - - // Add page to notebook - GtkWidget* label = gtk_label_new(title); - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), widget, label); -} - -void C4DevmodeDlg::RemovePage(GtkWidget* widget) -{ - int page_num = gtk_notebook_page_num(GTK_NOTEBOOK(notebook), widget); - assert(page_num != -1); // Make sure it is contained - - gtk_notebook_remove_page(GTK_NOTEBOOK(notebook), page_num); - - if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook)) == 0) - gtk_widget_destroy(window); -} - -void C4DevmodeDlg::SwitchPage(GtkWidget* widget) -{ - bool is_visible = gtk_widget_get_visible(GTK_WIDGET(window)); - - // Remember window position - if (window != NULL && is_visible) - gtk_window_get_position(GTK_WINDOW(window), &x, &y); - - if (widget != NULL) - { - assert(window != NULL); - - // Show required page - int page_num = gtk_notebook_page_num(GTK_NOTEBOOK(notebook), widget); - assert(page_num != -1); // Make sure it is contained - - gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), page_num); - gtk_window_set_title(GTK_WINDOW(window), gtk_notebook_get_tab_label_text(GTK_NOTEBOOK(notebook), widget)); - - // Show window if not visible - if (!is_visible) - { - gtk_widget_show(window); - if (x != -1 || y != -1) - gtk_window_move(GTK_WINDOW(window), x, y); - } - } - else - { - if (window != NULL && is_visible) - gtk_widget_hide(window); - } -} - -void C4DevmodeDlg::SetTitle(GtkWidget* widget, const char* title) -{ - gtk_notebook_set_tab_label_text(GTK_NOTEBOOK(notebook), widget, title); - int page_num = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)); - if (gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page_num) == widget) - gtk_window_set_title(GTK_WINDOW(window), title); -} diff --git a/src/editor/C4ConsoleGTKDlg.h b/src/editor/C4ConsoleGTKDlg.h deleted file mode 100644 index a5b48ed67..000000000 --- a/src/editor/C4ConsoleGTKDlg.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * OpenClonk, http://www.openclonk.org - * - * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/ - * Copyright (c) 2013-2016, The OpenClonk Team and contributors - * - * Distributed under the terms of the ISC license; see accompanying file - * "COPYING" for details. - * - * "Clonk" is a registered trademark of Matthes Bender, used with permission. - * See accompanying file "TRADEMARK" for details. - * - * To redistribute this file separately, substitute the full license texts - * for the above references. - */ - -/* Common window for drawing and property tool dialogs in console mode */ - -#ifndef INC_C4DevmodeDlg -#define INC_C4DevmodeDlg - -#ifdef USE_GTK -#include -#endif // USE_GTK - -// TODO: Threadsafety? -class C4DevmodeDlg -{ - // Make sure all developer tools are held in the same window -#ifdef USE_GTK -private: - static GtkWidget* window; - static GtkWidget* notebook; - - static int x, y; - - static void OnDestroy(GtkWidget* widget, gpointer user_data); - -public: - static GtkWidget* GetWindow() { return window; } - static void AddPage(GtkWidget* widget, GtkWindow* parent, const char* title); - static void RemovePage(GtkWidget* widget); - static void SwitchPage(GtkWidget* widget); - - static void SetTitle(GtkWidget* widget, const char* title); -#endif // USE_GTK -}; - -#endif //INC_C4DevmodeDlg diff --git a/src/editor/C4EditCursor.cpp b/src/editor/C4EditCursor.cpp index 46ecb7a58..06b5e68ea 100644 --- a/src/editor/C4EditCursor.cpp +++ b/src/editor/C4EditCursor.cpp @@ -41,9 +41,6 @@ #include "res/resource.h" #endif -#ifdef USE_GTK -#include -#endif StdStrBuf C4EditCursorSelection::GetDataString() const { @@ -176,22 +173,6 @@ bool C4EditCursor::Init() #ifdef USE_WIN32_WINDOWS if (!(hMenu = LoadMenu(Application.GetInstance(),MAKEINTRESOURCE(IDR_CONTEXTMENUS)))) return false; -#elif defined(USE_GTK) - menuContext = gtk_menu_new(); - - itemDelete = gtk_menu_item_new_with_label(LoadResStr("IDS_MNU_DELETE")); - itemDuplicate = gtk_menu_item_new_with_label(LoadResStr("IDS_MNU_DUPLICATE")); - itemGrabContents = gtk_menu_item_new_with_label(LoadResStr("IDS_MNU_CONTENTS")); - - gtk_menu_shell_append(GTK_MENU_SHELL(menuContext), itemDelete); - gtk_menu_shell_append(GTK_MENU_SHELL(menuContext), itemDuplicate); - gtk_menu_shell_append(GTK_MENU_SHELL(menuContext), itemGrabContents); - - g_signal_connect(G_OBJECT(itemDelete), "activate", G_CALLBACK(OnDelete), this); - g_signal_connect(G_OBJECT(itemDuplicate), "activate", G_CALLBACK(OnDuplicate), this); - g_signal_connect(G_OBJECT(itemGrabContents), "activate", G_CALLBACK(OnGrabContents), this); - - gtk_widget_show_all(menuContext); #endif Console.UpdateModeCtrls(Mode); @@ -1142,16 +1123,6 @@ void C4EditCursor::AppendMenuItem(int num, const StdStrBuf & label) AppendMenu(GetSubMenu(hMenu,0), MF_STRING, IDM_VPORTDYN_FIRST + num, label.GetWideChar()); else AppendMenu(GetSubMenu(hMenu,0), MF_SEPARATOR, IDM_VPORTDYN_FIRST, NULL); -#elif defined(USE_GTK) - GtkWidget * wdg; - if (num) - wdg = gtk_menu_item_new_with_label(label.getData()); - else - wdg = gtk_separator_menu_item_new(); - itemsObjselect[num].MenuItem = wdg; - gtk_menu_shell_append(GTK_MENU_SHELL(menuContext), wdg); - if (num) - g_signal_connect(G_OBJECT(wdg), "activate", G_CALLBACK(OnObjselect), &itemsObjselect[num]); #endif } @@ -1167,10 +1138,6 @@ bool C4EditCursor::DoContextMenu(DWORD dwKeyState) SetMenuItemText(hContext,IDM_VIEWPORT_DELETE,LoadResStr("IDS_MNU_DELETE")); SetMenuItemText(hContext,IDM_VIEWPORT_DUPLICATE,LoadResStr("IDS_MNU_DUPLICATE")); SetMenuItemText(hContext,IDM_VIEWPORT_CONTENTS,LoadResStr("IDS_MNU_CONTENTS")); -#elif defined(USE_GTK) - gtk_widget_set_sensitive(itemDelete, fObjectSelected && Console.Editing); - gtk_widget_set_sensitive(itemDuplicate, fObjectSelected && Console.Editing); - gtk_widget_set_sensitive(itemGrabContents, fObjectSelected && Selection.GetObject()->Contents.ObjectCount() && Console.Editing); #endif // Add selection and custom command entries for any objects at the cursor @@ -1274,9 +1241,6 @@ bool C4EditCursor::DoContextMenu(DWORD dwKeyState) break; } ObjselectDelItems(); -#elif defined(USE_GTK) - gtk_widget_show_all(menuContext); - gtk_menu_popup(GTK_MENU(menuContext), NULL, NULL, NULL, NULL, 3, gtk_get_current_event_time()); #endif return true; } @@ -1439,53 +1403,12 @@ void C4EditCursor::EMControl(C4PacketType eCtrlType, C4ControlPacket *pCtrl) ::Control.DoInput(eCtrlType, pCtrl, CDT_Decide); } -#ifdef USE_GTK -// GTK+ callbacks -void C4EditCursor::OnDelete(GtkWidget* widget, gpointer data) -{ - static_cast(data)->Delete(); -} - -void C4EditCursor::OnDuplicate(GtkWidget* widget, gpointer data) -{ - static_cast(data)->Duplicate(); -} - -void C4EditCursor::OnGrabContents(GtkWidget* widget, gpointer data) -{ - static_cast(data)->GrabContents(); -} - -void C4EditCursor::OnObjselect(GtkWidget* widget, gpointer data) -{ - bool IsShiftDown = false; - GdkEvent* event = gtk_get_current_event(); - if(event) - { - if(event->type == GDK_BUTTON_PRESS) - IsShiftDown = ( ((GdkEventButton*)event)->state & MK_SHIFT) != 0; - else if(event->type == GDK_KEY_PRESS) - IsShiftDown = ( ((GdkEventKey*)event)->state & MK_SHIFT) != 0; - - gdk_event_free(event); - } - ObjselItemDt* it = static_cast(data); - if (it->Command.getLength()) - it->EditCursor->DoContextObjCommand(it->Object, it->Command.getData()); - else - it->EditCursor->DoContextObjsel(it->Object, !IsShiftDown); - it->EditCursor->ObjselectDelItems(); -} - -#endif void C4EditCursor::ObjselectDelItems() { if(!itemsObjselect.size()) return; std::vector::iterator it = itemsObjselect.begin(); while(it != itemsObjselect.end()) { - #if defined(USE_GTK) - gtk_widget_destroy(it->MenuItem); - #elif defined(USE_WIN32_WINDOWS) + #if defined(USE_WIN32_WINDOWS) if(!it->ItemId) { ++it; continue; } HMENU hContext = GetSubMenu(hMenu,0); DeleteMenu(hContext, it->ItemId, MF_BYCOMMAND); diff --git a/src/editor/C4EditCursor.h b/src/editor/C4EditCursor.h index 69843a6ca..e3409e8cb 100644 --- a/src/editor/C4EditCursor.h +++ b/src/editor/C4EditCursor.h @@ -27,9 +27,6 @@ #include #include "object/C4DefGraphics.h" -#ifdef USE_GTK -#include -#endif // Currently selected elements in editcursor. May be objects and other prop lists. class C4EditCursorSelection : public std::list @@ -69,19 +66,11 @@ protected: StdCopyStrBuf Command; #if defined(USE_WIN32_WINDOWS) UINT_PTR ItemId; -#elif defined(USE_GTK) - GtkWidget* MenuItem; #endif }; std::vector itemsObjselect; #ifdef USE_WIN32_WINDOWS HMENU hMenu; -#elif defined(USE_GTK) - GtkWidget* menuContext; - GtkWidget* itemDelete; - GtkWidget* itemDuplicate; - GtkWidget* itemGrabContents; - GtkWidget* itemProperties; #endif // Selection may either be any number of objects or a single non-object prop list C4EditCursorSelection selection; @@ -151,12 +140,6 @@ public: void PerformDuplicationLegacy(int32_t *pObjects, int32_t iObjectNum, bool fLocalCall); protected: -#ifdef USE_GTK - static void OnDelete(GtkWidget* widget, gpointer data); - static void OnDuplicate(GtkWidget* widget, gpointer data); - static void OnGrabContents(GtkWidget* widget, gpointer data); - static void OnObjselect(GtkWidget* widget, gpointer data); -#endif public: void AddToSelection(C4PropList *add_obj); // add object to selection and do script callback. Doesn't do OnSelectionChanged(). bool RemoveFromSelection(C4PropList *remove_obj); // remove object from selection and do script callback. return true if object was in selection before. Doesn't do OnSelectionChanged(). diff --git a/src/editor/C4ObjectListDlg.cpp b/src/editor/C4ObjectListDlg.cpp index 12dbd2afe..38c57c29a 100644 --- a/src/editor/C4ObjectListDlg.cpp +++ b/src/editor/C4ObjectListDlg.cpp @@ -23,819 +23,6 @@ #include "object/C4GameObjects.h" #include "script/C4Effect.h" -#ifdef USE_GTK -#include - - -/* Some boilerplate GObject defines. 'klass' is used instead of 'class', because 'class' is a C++ keyword */ - -#define C4_TYPE_LIST (c4_list_get_type ()) -#define C4_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), C4_TYPE_LIST, C4List)) -#define C4_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), C4_TYPE_LIST, C4ListClass)) -#define C4_IS_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), C4_TYPE_LIST)) -#define C4_IS_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), C4_TYPE_LIST)) -#define C4_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), C4_TYPE_LIST, C4ListClass)) - -/* The data columns that we export via the tree model interface */ - -enum -{ - C4_LIST_COL_OBJECT, - C4_LIST_N_COLUMNS -}; - -typedef struct _C4List C4List; -typedef struct _C4ListClass C4ListClass; - -struct _C4List -{ - GObject parent; /* this MUST be the first member */ - - C4ObjectList * data; - - gint stamp; /* A random integer to check if an iter belongs to this model */ -}; - - - -/* more boilerplate GObject stuff */ - -struct _C4ListClass -{ - GObjectClass parent_class; -}; - -static GObjectClass *parent_class = NULL; - -GType c4_list_get_type (void); - -// Initialise an instance -static void -c4_list_init (C4List *c4_list) -{ - c4_list->data = &::Objects; - - c4_list->stamp = g_random_int(); /* Random int to check whether iters belong to this model */ -} - -// destructor -static void -c4_list_finalize (GObject *object) -{ - /* must chain up - finalize parent */ - (* parent_class->finalize) (object); -} - - -static GtkTreeModelFlags -c4_list_get_flags (GtkTreeModel *tree_model) -{ - g_return_val_if_fail (C4_IS_LIST(tree_model), (GtkTreeModelFlags)0); - - // neither is this a flat list nor do the iters persist changes in the model - //return GtkTreeModelFlags(GTK_TREE_MODEL_ITERS_PERSIST); - return GtkTreeModelFlags(0); -} - -// converts 'path' into an iterator and stores that in 'iter' -static gboolean -c4_list_get_iter (GtkTreeModel * tree_model, GtkTreeIter * iter, GtkTreePath * path) -{ - gint *indices, depth; - - g_assert(C4_IS_LIST(tree_model)); - g_assert(path!=NULL); - - C4List * c4_list = C4_LIST(tree_model); - - indices = gtk_tree_path_get_indices(path); - depth = gtk_tree_path_get_depth(path); - - iter->stamp = c4_list->stamp; - - - C4ObjectLink * pLnk = C4_LIST(tree_model)->data->First; - // Skip Contained Objects in the main list - while (pLnk && pLnk->Obj->Contained) pLnk = pLnk->Next; - for (int i = 0; i < depth; ++i) - { - if (!pLnk) - return false; - if (indices[i] < 0) - return false; - for (int j = 0; j < indices[i]; ++j) - { - pLnk = pLnk->Next; - // Skip Contained Objects in the main list - while (i == 0 && pLnk && pLnk->Obj->Contained) pLnk = pLnk->Next; - if (!pLnk) - return false; - } - iter->user_data = pLnk; - iter->user_data2 = pLnk->Obj->Contained; - pLnk = pLnk->Obj->Contents.First; - } - - return true; -} - -// converts 'iter' into a new tree path and returns that. -// Note: This is called by OnObjectRemove with an iter which is not in the -// list anymore, but with the object and prev still usable. -static GtkTreePath * -c4_list_get_path (GtkTreeModel * tree_model, GtkTreeIter * iter) -{ - g_return_val_if_fail (C4_IS_LIST(tree_model), NULL); - g_return_val_if_fail (iter != NULL, NULL); - g_return_val_if_fail (iter->user_data != NULL, NULL); - - GtkTreePath *path = gtk_tree_path_new(); - - C4List * c4_list = C4_LIST(tree_model); - - C4Object * pObj = ((C4ObjectLink *) iter->user_data)->Obj; - - int i = 0; - for (C4ObjectLink * pLnk = ((C4ObjectLink *) iter->user_data)->Prev; pLnk; pLnk = pLnk->Prev) - { - // Skip Contained Objects in the main list - if (pObj->Contained != pLnk->Obj->Contained) continue; - ++i; - } - gtk_tree_path_prepend_index(path, i); - - pObj = (C4Object *) iter->user_data2; - while (pObj) - { - i = 0; - C4ObjectList * pList = c4_list->data; - if (pObj->Contained) - pList = &pObj->Contained->Contents; - for (C4ObjectLink * pLnk = pList->First; pLnk && pLnk->Obj != pObj; pLnk = pLnk->Next) - { - // Skip Contained Objects in the main list - if (pObj->Contained != pLnk->Obj->Contained) continue; - ++i; - } - gtk_tree_path_prepend_index(path, i); - pObj = pObj->Contained; - } - - return path; -} - -// ++iter -static gboolean -c4_list_iter_next (GtkTreeModel * tree_model, GtkTreeIter * iter) -{ - g_return_val_if_fail (C4_IS_LIST (tree_model), false); - - if (iter == NULL || iter->user_data == NULL) - return false; - - C4ObjectLink * pLnk = (C4ObjectLink *) iter->user_data; - - pLnk = pLnk->Next; - - // Skip Contained Objects in the main list - if (!(C4Object *)iter->user_data2) - while (pLnk && pLnk->Obj->Contained) - pLnk = pLnk->Next; - if (!pLnk) - return false; - - iter->user_data = pLnk; - iter->user_data2 = pLnk->Obj->Contained; - - return true; -} - -// Set 'iter' to the first child of 'parent', or the first top-level row if -// 'parent' is 0, or return false if there aren't any children. -static gboolean -c4_list_iter_children (GtkTreeModel * tree_model, GtkTreeIter * iter, GtkTreeIter * parent) -{ - g_return_val_if_fail (parent == NULL || parent->user_data != NULL, false); - g_return_val_if_fail (C4_IS_LIST (tree_model), false); - - C4List *c4_list = C4_LIST(tree_model); - - C4ObjectLink * pLnk; - if (parent) - { - C4ObjectList * pList = &((C4ObjectLink *)parent->user_data)->Obj->Contents; - pLnk = pList->First; - } - else - { - pLnk = c4_list->data->First; - // Skip... - while (pLnk && pLnk->Obj->Contained) pLnk = pLnk->Next; - } - if (!pLnk) - return false; - - /* Set iter to first item in list */ - iter->stamp = c4_list->stamp; - iter->user_data = pLnk; - iter->user_data2 = pLnk->Obj->Contained; - - return true; -} - -// Return true if 'parent' has children. -static gboolean -c4_list_iter_has_child (GtkTreeModel *tree_model, - GtkTreeIter *parent) -{ - g_return_val_if_fail (parent == NULL || parent->user_data != NULL, false); - g_return_val_if_fail (C4_IS_LIST (tree_model), false); - - C4List *c4_list = C4_LIST(tree_model); - - C4ObjectList * pList = c4_list->data; - if (parent) - pList = &((C4ObjectLink *)parent->user_data)->Obj->Contents; - return pList->First != 0; -} - -// Counts the children 'parent' has. -static gint -c4_list_iter_n_children (GtkTreeModel *tree_model, GtkTreeIter *parent) -{ - g_return_val_if_fail (C4_IS_LIST (tree_model), -1); - g_return_val_if_fail (parent == NULL || parent->user_data != NULL, -1); - - C4List *c4_list = C4_LIST(tree_model); - - int i = 0; - if (parent) - { - C4ObjectList * pList = &((C4ObjectLink *)parent->user_data)->Obj->Contents; - C4ObjectLink * pLnk = pList->First; - while (pLnk) - { - ++i; - pLnk = pLnk->Next; - } - } - else - { - C4ObjectLink * pLnk = c4_list->data->First; - while (pLnk) - { - if (!pLnk->Obj->Contained) - ++i; - pLnk = pLnk->Next; - } - } - return i; -} - -// Sets 'iter' to the 'n'-th child of 'parent'. -static gboolean -c4_list_iter_nth_child (GtkTreeModel * tree_model, GtkTreeIter * iter, GtkTreeIter * parent, gint n) -{ - g_return_val_if_fail (C4_IS_LIST (tree_model), false); - g_return_val_if_fail (parent == NULL || parent->user_data != NULL, false); - - C4List *c4_list = C4_LIST(tree_model); - - C4ObjectLink * pLnk; - if (parent) - { - C4ObjectList * pList = &((C4ObjectLink *)parent->user_data)->Obj->Contents; - pLnk = pList->First; - for (int i = 0; i < n; ++i) - { - if (!pLnk) - return false; - pLnk = pLnk->Next; - } - } - else - { - pLnk = c4_list->data->First; - for (int i = 0; i < n; ++i) - { - if (!pLnk) - return false; - pLnk = pLnk->Next; - // Skip... - while (pLnk && pLnk->Obj->Contained) pLnk = pLnk->Next; - } - } - if (!pLnk) - return false; - - iter->stamp = c4_list->stamp; - iter->user_data = pLnk; - iter->user_data2 = pLnk->Obj->Contained; - - return true; -} - -// Helper function. -static gboolean c4_list_iter_for_C4Object (GtkTreeModel * tree_model, GtkTreeIter * iter, C4ObjectList * pList, C4Object * pObj) -{ - if (!pObj) - return false; - - C4List * c4_list = C4_LIST(tree_model); - - for (C4ObjectLink * pLnk = pList->First; pLnk; pLnk = pLnk->Next) - { - if (pLnk->Obj == pObj) - { - iter->stamp = c4_list->stamp; - iter->user_data = pLnk; - iter->user_data2 = pLnk->Obj->Contained; - - return true; - } - } - - g_return_val_if_reached(false); -} - -// Sets 'iter' to the parent row of 'child'. -static gboolean -c4_list_iter_parent (GtkTreeModel * tree_model, GtkTreeIter * iter, GtkTreeIter * child) -{ - g_return_val_if_fail (C4_IS_LIST (tree_model), false); - g_return_val_if_fail (child == NULL || child->user_data != NULL, false); - - C4List * c4_list = C4_LIST(tree_model); - - C4Object * pObj = (C4Object *) child->user_data2; - - C4ObjectList * pList = c4_list->data; - if (pObj->Contained) - pList = &pObj->Contained->Contents; - return c4_list_iter_for_C4Object(tree_model, iter, pList, pObj); -} - -static C4Object * -c4_list_iter_get_C4Object(GtkTreeModel * tree_model, GtkTreeIter * iter) -{ - g_return_val_if_fail (C4_IS_LIST (tree_model), NULL); - g_return_val_if_fail (iter != NULL && iter->user_data != NULL, NULL); - - return ((C4ObjectLink *) iter->user_data)->Obj; -} - -// How many columns does this model have? -static gint -c4_list_get_n_columns (GtkTreeModel * tree_model) -{ - g_return_val_if_fail (C4_IS_LIST(tree_model), 0); - - return 1; -} - -// What sort of data is in the column? -static GType -c4_list_get_column_type (GtkTreeModel * tree_model, gint index) -{ - g_return_val_if_fail (C4_IS_LIST(tree_model), G_TYPE_INVALID); - g_return_val_if_fail (index < 1 && index >= 0, G_TYPE_INVALID); - - return G_TYPE_POINTER; -} - -// gets the data for the 'column' in the row at 'iter' and stores that in 'value'. -static void -c4_list_get_value (GtkTreeModel * tree_model, GtkTreeIter * iter, gint column, GValue * value) -{ - g_return_if_fail (C4_IS_LIST (tree_model)); - g_return_if_fail (iter != NULL); - g_return_if_fail (column == 0); - - C4Object * pObj = ((C4ObjectLink *) iter->user_data)->Obj; - g_return_if_fail (pObj != NULL); - - g_value_init (value, G_TYPE_POINTER); - g_value_set_pointer(value, pObj); - -// g_value_set_string(value, pObj->GetName()); -} - -// Wrapper around g_object_new. -static C4List * -c4_list_new (void) -{ - C4List * list; - - list = (C4List *) g_object_new (C4_TYPE_LIST, NULL); - - g_assert(list != NULL); - - return list; -} - -// Called once for the class. -static void -c4_list_class_init (C4ListClass * klass) -{ - GObjectClass * object_class; - - parent_class = (GObjectClass*) g_type_class_peek_parent (klass); - object_class = (GObjectClass*) klass; - - object_class->finalize = c4_list_finalize; -} - -// fill in the GtkTreeModel interface with the functions above. -static void -c4_list_tree_model_init (GtkTreeModelIface *iface) -{ - iface->get_flags = c4_list_get_flags; - iface->get_n_columns = c4_list_get_n_columns; - iface->get_column_type = c4_list_get_column_type; - iface->get_iter = c4_list_get_iter; - iface->get_path = c4_list_get_path; - iface->get_value = c4_list_get_value; - iface->iter_next = c4_list_iter_next; - iface->iter_children = c4_list_iter_children; - iface->iter_has_child = c4_list_iter_has_child; - iface->iter_n_children = c4_list_iter_n_children; - iface->iter_nth_child = c4_list_iter_nth_child; - iface->iter_parent = c4_list_iter_parent; -} - -// Return the type, registering it on first call. -GType -c4_list_get_type (void) -{ - static GType c4_list_type = 0; - - if (c4_list_type == 0) - { - // Some boilerplate type registration stuff - static const GTypeInfo c4_list_info = - { - sizeof (C4ListClass), /* class_size */ - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) c4_list_class_init, /* class_init */ - NULL, /* class finalize */ - NULL, /* class_data */ - sizeof (C4List), /* instance_size */ - 0, /* n_preallocs */ - (GInstanceInitFunc) c4_list_init, /* instance_init */ - NULL /* value_table */ - }; - - c4_list_type = g_type_register_static (G_TYPE_OBJECT, "C4List", - &c4_list_info, (GTypeFlags)0); - - /* register the GtkTreeModel interface with the type system */ - static const GInterfaceInfo tree_model_info = - { - (GInterfaceInitFunc) c4_list_tree_model_init, - NULL, - NULL - }; - - g_type_add_interface_static (c4_list_type, GTK_TYPE_TREE_MODEL, &tree_model_info); - } - - return c4_list_type; -} - -void C4ObjectListDlg::OnObjectRemove(C4ObjectList * pList, C4ObjectLink * pLnk) -{ - if (!model) return; - - C4List * c4_list = C4_LIST(model); - C4Object * Contained = pLnk->Obj->Contained; - GtkTreeIter iter; - iter.stamp = c4_list->stamp; - iter.user_data = pLnk; - iter.user_data2 = Contained; - - // While pLnk is not in the list anymore, with pLnk->Prev and Contained a path can still be made - GtkTreePath * path = c4_list_get_path(GTK_TREE_MODEL(model), &iter); - - gtk_tree_model_row_deleted(GTK_TREE_MODEL(model), path); - gtk_tree_path_free(path); - - // Removed from a now empty container? - if (Contained && !Contained->Contents.First) - { - printf("Removed from a now empty container\n"); - GtkTreeIter parent; - C4ObjectList * pList = c4_list->data; - if (Contained->Contained) - pList = &Contained->Contained->Contents; - c4_list_iter_for_C4Object(GTK_TREE_MODEL(model), &parent, pList, Contained); - - GtkTreePath * path = c4_list_get_path(GTK_TREE_MODEL(model), &parent); - - gtk_tree_model_row_has_child_toggled(GTK_TREE_MODEL(model), path, &parent); - gtk_tree_path_free(path); - } - - - // Cheat: For the signals it must look as if the object had it's parent removed already - pLnk->Obj->Contained = 0; - // if removed from contents, it get's added to main list - if (pList != c4_list->data) - { - printf("Removed from a container\n"); - GtkTreeIter iter; - C4ObjectList * pList = c4_list->data; - c4_list_iter_for_C4Object(GTK_TREE_MODEL(model), &iter, pList, pLnk->Obj); - - GtkTreePath * path = c4_list_get_path(GTK_TREE_MODEL(model), &iter); - - gtk_tree_model_row_inserted(GTK_TREE_MODEL(model), path, &iter); - gtk_tree_path_free(path); - } - - // End-of-cheat - pLnk->Obj->Contained = Contained; -} - -void C4ObjectListDlg::OnObjectAdded(C4ObjectList * pList, C4ObjectLink * pLnk) -{ - if (!model) return; - - C4List * c4_list = C4_LIST(model); - - // Inserted into a container? Remove from main list - if (pList != c4_list->data) - { - printf("Inserted into a container\n"); - GtkTreePath *path = gtk_tree_path_new(); - int i = 0; - C4ObjectList * pList = c4_list->data; - C4Object * pObj = pLnk->Obj; - for (C4ObjectLink * pLnk2 = pList->First; pLnk2 && pLnk2->Obj != pObj; pLnk2 = pLnk2->Next) - { - // Skip Contained Objects in the main list - if (pLnk2->Obj->Contained) continue; - ++i; - } - gtk_tree_path_prepend_index(path, i); - - gtk_tree_model_row_deleted(GTK_TREE_MODEL(model), path); - gtk_tree_path_free(path); - } - - GtkTreeIter iter; - iter.stamp = c4_list->stamp; - iter.user_data = pLnk; - iter.user_data2 = pLnk->Obj->Contained; - - GtkTreePath * path = c4_list_get_path(GTK_TREE_MODEL(model), &iter); - - gtk_tree_model_row_inserted(GTK_TREE_MODEL(model), path, &iter); - gtk_tree_path_free(path); - - // Inserted into a previously empty container? - if (pLnk->Obj->Contained && - pLnk->Obj->Contained->Contents.First == pLnk->Obj->Contained->Contents.Last) - { - printf("Inserted into a previously empty container\n"); - GtkTreeIter parent; - c4_list_iter_parent(GTK_TREE_MODEL(model), &parent, &iter); - - GtkTreePath * path = c4_list_get_path(GTK_TREE_MODEL(model), &parent); - - gtk_tree_model_row_has_child_toggled(GTK_TREE_MODEL(model), path, &parent); - gtk_tree_path_free(path); - } -} - -void C4ObjectListDlg::OnObjectRename(C4ObjectList * pList, C4ObjectLink * pLnk) -{ -} - -void C4ObjectListDlg::OnDestroy(GtkWidget* widget, C4ObjectListDlg* dlg) -{ - dlg->window = 0; - dlg->model = 0; - dlg->treeview = 0; -} - -void C4ObjectListDlg::OnRowActivated(GtkTreeView * tree_view, GtkTreePath * path, GtkTreeViewColumn * column, C4ObjectListDlg * dlg) -{ - Console.EditCursor.SetMode(C4CNS_ModeEdit); - Console.EditCursor.OpenPropTools(); -} - -void C4ObjectListDlg::OnSelectionChanged(GtkTreeSelection* selection, C4ObjectListDlg* dlg) -{ - if (dlg->updating_selection) return; - dlg->updating_selection = true; - - GList* list = gtk_tree_selection_get_selected_rows(selection, NULL); - - Console.EditCursor.GetSelection().Clear(); - for (GList * i = list; i; i = i->next) - { - GtkTreePath * path = (GtkTreePath *)i->data; - GtkTreeIter iter; - c4_list_get_iter(GTK_TREE_MODEL(dlg->model), &iter, path); - Console.EditCursor.GetSelection().Add(((C4ObjectLink *)iter.user_data)->Obj, C4ObjectList::stNone); - } - - g_list_foreach (list, (GFunc)gtk_tree_path_free, NULL); - g_list_free (list); - - Console.EditCursor.OnSelectionChanged(); - dlg->updating_selection = false; -} - -void C4ObjectListDlg::Update(C4EditCursorSelection &rSelection) -{ - if (updating_selection) return; - if (!window) return; - updating_selection = true; - - GtkTreeSelection *selection; - - selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); - - gtk_tree_selection_unselect_all(selection); - - for (auto val : rSelection) - { - C4Object *obj = val.getObj(); - if (!obj) continue; // it's a non-object proplist or deleted object - GtkTreeIter iter; - C4List * c4_list = C4_LIST(model); - C4ObjectList * pList = c4_list->data; - if (obj->Contained) - pList = &obj->Contained->Contents; - c4_list_iter_for_C4Object(GTK_TREE_MODEL(model), &iter, pList, obj); - gtk_tree_selection_select_iter(selection, &iter); - } - - updating_selection = false; -} - -C4ObjectListDlg::C4ObjectListDlg(): - window(0), - treeview(0), - model(0), - updating_selection(false) -{ -} - -C4ObjectListDlg::~C4ObjectListDlg() -{ -} - -void C4ObjectListDlg::Execute() -{ -} - -static void name_cell_data_func(GtkTreeViewColumn* column, GtkCellRenderer* renderer, GtkTreeModel* model, GtkTreeIter* iter, gpointer data) -{ - C4Object* object = c4_list_iter_get_C4Object(model, iter); - - g_object_set(G_OBJECT(renderer), "text", object->GetName(), (gpointer)NULL); -} - -enum { ICON_SIZE = 24 }; - -#ifdef _UNUSED_ -static void icon_cell_data_func(GtkTreeViewColumn* column, GtkCellRenderer* renderer, GtkTreeModel* model, GtkTreeIter* iter, gpointer data) -{ - C4Object* object = c4_list_iter_get_C4Object(model, iter); - - // Icons for objects with ColorByOwner are cached by object, others by Def - // FIXME: Invalidate cache when objects change color, and redraw. - gpointer key = object->Def; - if (object->Def->ColorByOwner) key = object; - - GHashTable* table = static_cast(data); - GdkPixbuf* pixbuf = GDK_PIXBUF(g_hash_table_lookup(table, key)); - - if (pixbuf == NULL) - { - /* Not yet cached, create from Graphics */ - C4Surface* surface = object->Def->Graphics.Bmp.Bitmap; - if (object->Def->Graphics.Bmp.BitmapClr) surface = object->Def->Graphics.Bmp.BitmapClr; - - const C4Rect& picture = object->Def->PictureRect; - pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, picture.Wdt, picture.Hgt); - guchar* pixels = gdk_pixbuf_get_pixels(pixbuf); - surface->Lock(); - for (int y = 0; y < picture.Hgt; ++ y) for (int x = 0; x < picture.Wdt; ++ x) - { - DWORD dw = surface->GetPixDw(picture.x + x, picture.y + y, true); - *pixels = (dw >> 16) & 0xff; ++ pixels; - *pixels = (dw >> 8 ) & 0xff; ++ pixels; - *pixels = (dw ) & 0xff; ++ pixels; - *pixels = 0xff - ((dw >> 24) & 0xff); ++ pixels; - } - surface->Unlock(); - - // Scale down to ICON_SIZE, keeping aspect ratio - guint dest_width, dest_height; - if (picture.Wdt >= picture.Hgt) - { - double factor = static_cast(picture.Hgt) / static_cast(picture.Wdt); - dest_width = ICON_SIZE; - dest_height = dest_width * factor; - } - else - { - double factor = static_cast(picture.Wdt) / static_cast(picture.Hgt); - dest_height = ICON_SIZE; - dest_width = dest_height * factor; - } - - GdkPixbuf* scaled = gdk_pixbuf_scale_simple(pixbuf, dest_width, dest_height, GDK_INTERP_HYPER); - g_object_unref(G_OBJECT(pixbuf)); - pixbuf = scaled; - - g_hash_table_insert(table, key, pixbuf); - } - - g_object_set(G_OBJECT(renderer), "pixbuf", pixbuf, NULL); -} -#endif // _UNUSED_ - -void C4ObjectListDlg::Open() -{ - // Create Window if necessary - if (window == NULL) - { - // The Windows - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - - gtk_window_set_resizable(GTK_WINDOW(window), true); - gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_UTILITY); - gtk_window_set_role(GTK_WINDOW(window), "objectlist"); - gtk_window_set_title(GTK_WINDOW(window), "Objects"); - gtk_window_set_default_size(GTK_WINDOW(window), 180, 300); - - gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(Console.window)); - - g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(OnDestroy), this); - - // The Tree - GtkWidget* scrolled_wnd = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_wnd), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_wnd), GTK_SHADOW_IN); - - model = G_OBJECT(c4_list_new()); - - treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model)); - - g_object_unref(model); /* destroy store automatically with view */ - - g_signal_connect(G_OBJECT(treeview), "row-activated", G_CALLBACK(OnRowActivated), this); - - GtkTreeViewColumn * col = gtk_tree_view_column_new(); - GtkCellRenderer * renderer = gtk_cell_renderer_text_new(); - gtk_tree_view_column_pack_start(col, renderer, true); - gtk_tree_view_column_set_cell_data_func(col, renderer, name_cell_data_func, NULL, NULL); - - gtk_tree_view_column_set_title(col, "Name"); - gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED); - gtk_tree_view_append_column(GTK_TREE_VIEW(treeview),col); - - gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), false); - gtk_tree_view_set_fixed_height_mode(GTK_TREE_VIEW(treeview), true); - - GtkTreeSelection * selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); - gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); - - g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(OnSelectionChanged), this); - - gtk_container_add(GTK_CONTAINER(scrolled_wnd), treeview); - gtk_widget_set_vexpand(scrolled_wnd, true); - gtk_widget_set_hexpand(scrolled_wnd, true); - - gtk_container_add(GTK_CONTAINER(window), scrolled_wnd); - - gtk_widget_show_all(window); - } - else - { - gtk_window_present_with_time(GTK_WINDOW(window), gtk_get_current_event_time()); - } -} - -void C4ObjectListDlg::OnObjectContainerChanged(C4Object *obj, C4Object *old_container, C4Object *new_container) -{ -} - -void C4ObjectListDlg::OnEffectAdded(C4Effect *fx) -{ -} - -void C4ObjectListDlg::OnEffectRemoved(C4Effect *fx) -{ -} - - -#else C4ObjectListDlg::C4ObjectListDlg() { @@ -928,6 +115,5 @@ void C4ObjectListDlg::OnEffectRemoved(C4Effect *fx) #endif WITH_QT_EDITOR -#endif C4ObjectListChangeListener & ObjectListChangeListener = Console.ObjectListDlg; diff --git a/src/editor/C4ObjectListDlg.h b/src/editor/C4ObjectListDlg.h index c97087632..2621b9552 100644 --- a/src/editor/C4ObjectListDlg.h +++ b/src/editor/C4ObjectListDlg.h @@ -19,9 +19,6 @@ #ifndef INC_C4ObjectListDlg #define INC_C4ObjectListDlg -#ifdef USE_GTK -#include -#endif // USE_GTK #include "object/C4ObjectList.h" @@ -48,17 +45,6 @@ public: virtual void OnEffectAdded(class C4Effect *fx) override; virtual void OnEffectRemoved(class C4Effect *fx) override; -#ifdef USE_GTK -private: - GtkWidget * window; - GtkWidget * treeview; - GObject * model; - bool updating_selection; - - static void OnDestroy(GtkWidget * widget, C4ObjectListDlg * dlg); - static void OnRowActivated(GtkTreeView * tree_view, GtkTreePath * path, GtkTreeViewColumn * column, C4ObjectListDlg * dlg); - static void OnSelectionChanged(GtkTreeSelection * selection, C4ObjectListDlg * dlg); -#endif // USE_GTK }; #endif //INC_C4ObjectListDlg diff --git a/src/editor/C4ToolsDlg.h b/src/editor/C4ToolsDlg.h index 971983fa8..62f5d52b5 100644 --- a/src/editor/C4ToolsDlg.h +++ b/src/editor/C4ToolsDlg.h @@ -20,9 +20,6 @@ #ifndef INC_C4ToolsDlg #define INC_C4ToolsDlg -#ifdef USE_GTK -#include -#endif #include "config/C4Constants.h" #include "landscape/C4Landscape.h" diff --git a/src/editor/C4ViewportWindow.cpp b/src/editor/C4ViewportWindow.cpp index e1b00fd52..1e1d0f0f6 100644 --- a/src/editor/C4ViewportWindow.cpp +++ b/src/editor/C4ViewportWindow.cpp @@ -25,9 +25,6 @@ #include "landscape/C4Landscape.h" #include "player/C4PlayerList.h" -#ifdef USE_GTK -#include -#endif #ifdef WITH_QT_EDITOR #include "editor/C4ConsoleQtViewport.h" @@ -117,70 +114,7 @@ bool C4Viewport::ScrollBarsByViewPosition() return true; } -#elif defined(USE_GTK) -bool C4Viewport::TogglePlayerLock() -{ - if (PlayerLock) - { - PlayerLock = false; - gtk_widget_show(pWindow->h_scrollbar); - gtk_widget_show(pWindow->v_scrollbar); - ScrollBarsByViewPosition(); - } - else - { - PlayerLock = true; - gtk_widget_hide(pWindow->h_scrollbar); - gtk_widget_hide(pWindow->v_scrollbar); - } - - return true; -} - -bool C4Viewport::ScrollBarsByViewPosition() -{ - if (PlayerLock) return false; - - GtkAllocation allocation; - gtk_widget_get_allocation(GTK_WIDGET(pWindow->render_widget), &allocation); - - GtkAdjustment* adjustment = gtk_range_get_adjustment(GTK_RANGE(pWindow->h_scrollbar)); - - gtk_adjustment_configure(adjustment, - GetViewX(), // value - 0, // lower - ::Landscape.GetWidth(), // upper - ViewportScrollSpeed, // step_increment - allocation.width / Zoom, // page_increment - allocation.width / Zoom // page_size - ); - - adjustment = gtk_range_get_adjustment(GTK_RANGE(pWindow->v_scrollbar)); - gtk_adjustment_configure(adjustment, - GetViewY(), // value - 0, // lower - ::Landscape.GetHeight(), // upper - ViewportScrollSpeed, // step_increment - allocation.height / Zoom, // page_increment - allocation.height / Zoom // page_size - ); - return true; -} - -bool C4Viewport::ViewPositionByScrollBars() -{ - if (PlayerLock) return false; - - GtkAdjustment* adjustment = gtk_range_get_adjustment(GTK_RANGE(pWindow->h_scrollbar)); - SetViewX(gtk_adjustment_get_value(adjustment)); - - adjustment = gtk_range_get_adjustment(GTK_RANGE(pWindow->v_scrollbar)); - SetViewY(gtk_adjustment_get_value(adjustment)); - - return true; -} - -#endif // USE_GTK +#endif void C4ViewportWindow::PerformUpdate() { diff --git a/src/editor/C4ViewportWindow.h b/src/editor/C4ViewportWindow.h index 42732c898..57ae0ca54 100644 --- a/src/editor/C4ViewportWindow.h +++ b/src/editor/C4ViewportWindow.h @@ -22,9 +22,6 @@ #include "platform/C4Window.h" -#ifdef USE_GTK -#include -#endif #ifdef WITH_QT_EDITOR #define C4ViewportWindowStyle (WS_VISIBLE) #else @@ -37,10 +34,6 @@ class C4ViewportWindow: public C4Window public: C4Viewport * cvp; C4ViewportWindow(C4Viewport * cvp): cvp(cvp) { } -#if defined(USE_GTK) - GtkWidget* h_scrollbar; - GtkWidget* v_scrollbar; -#endif void EditCursorMove(int X, int Y, uint32_t); using C4Window::Init; C4Window * Init(int32_t iPlayer); diff --git a/src/game/C4Game.cpp b/src/game/C4Game.cpp index cedfd2080..da9bbcdc3 100644 --- a/src/game/C4Game.cpp +++ b/src/game/C4Game.cpp @@ -1855,19 +1855,6 @@ bool C4Game::SaveGameTitle(C4Group &hGroup) bool C4Game::DoKeyboardInput(C4KeyCode vk_code, C4KeyEventType eEventType, bool fAlt, bool fCtrl, bool fShift, bool fRepeated, class C4GUI::Dialog *pForDialog, bool fPlrCtrlOnly, int32_t iStrength) { -#ifdef USE_GTK - static std::map PressedKeys; - // Keyrepeats are send as down, down, ..., down, up, where all downs are not distinguishable from the first. - if (eEventType == KEYEV_Down) - { - if (PressedKeys[vk_code]) fRepeated = true; - else PressedKeys[vk_code] = true; - } - else if (eEventType == KEYEV_Up) - { - PressedKeys[vk_code] = false; - } -#endif // compose key C4KeyCodeEx Key(vk_code, C4KeyShiftState(fAlt*KEYS_Alt + fCtrl*KEYS_Control + fShift*KEYS_Shift), fRepeated); return DoKeyboardInput(Key, eEventType, pForDialog, fPlrCtrlOnly, iStrength); diff --git a/src/game/C4Viewport.cpp b/src/game/C4Viewport.cpp index 5dbc48a33..64b19e8bc 100644 --- a/src/game/C4Viewport.cpp +++ b/src/game/C4Viewport.cpp @@ -60,16 +60,7 @@ bool C4Viewport::UpdateOutputSize(int32_t new_width, int32_t new_height) } else { -#ifdef USE_GTK - GtkAllocation allocation; - gtk_widget_get_allocation(GTK_WIDGET(pWindow->render_widget), &allocation); - - // Use only size of drawing area without scrollbars - rect.x = allocation.x; - rect.y = allocation.y; - rect.Wdt = allocation.width; - rect.Hgt = allocation.height; -#elif defined(WITH_QT_EDITOR) +#if defined(WITH_QT_EDITOR) // Never query the window - size is always passed from Qt. return false; #else diff --git a/src/graphics/C4DrawGL.h b/src/graphics/C4DrawGL.h index 09f7306a9..3a44a0d22 100644 --- a/src/graphics/C4DrawGL.h +++ b/src/graphics/C4DrawGL.h @@ -127,8 +127,6 @@ protected: C4Window * pWindow; // window to draw in #ifdef USE_WGL HDC hDC; // device context handle -#elif defined(USE_GTK) - /*GLXContext*/void * ctx; #elif defined(USE_SDL_MAINLOOP) void * ctx; #endif diff --git a/src/graphics/C4DrawGLCtx.cpp b/src/graphics/C4DrawGLCtx.cpp index 9c90e660e..c8c1d126c 100644 --- a/src/graphics/C4DrawGLCtx.cpp +++ b/src/graphics/C4DrawGLCtx.cpp @@ -438,153 +438,6 @@ bool CStdGLCtx::PageFlip() return true; } -#elif defined(USE_GTK) -#include -#include -#include -#include - -namespace { -void InitGLXPointers() -{ - glXGetVisualFromFBConfig = (PFNGLXGETVISUALFROMFBCONFIGPROC)(glXGetProcAddress((const GLubyte*)"glXGetVisualFromFBConfig")); - glXChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC)(glXGetProcAddress((const GLubyte*)"glXChooseFBConfig")); - glXCreateNewContext = (PFNGLXCREATENEWCONTEXTPROC)(glXGetProcAddress((const GLubyte*)"glXCreateNewContext")); -} -} - -CStdGLCtx::CStdGLCtx(): pWindow(0), ctx(0), this_context(contexts.end()) { } - -void CStdGLCtx::Clear(bool multisample_change) -{ - Deselect(); - if (ctx) - { - Display * const dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default()); - glXDestroyContext(dpy, (GLXContext)ctx); - ctx = 0; - } - pWindow = 0; - - if (this_context != contexts.end()) - { - contexts.erase(this_context); - this_context = contexts.end(); - } -} - -bool CStdGLCtx::Init(C4Window * pWindow, C4AbstractApp *) -{ - // safety - if (!pGL) return false; - // store window - this->pWindow = pWindow; - Display * const dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default()); - InitGLXPointers(); - if (!glXGetVisualFromFBConfig || !glXChooseFBConfig || !glXCreateNewContext) - { - return pGL->Error(" gl: Unable to retrieve GLX 1.4 entry points"); - } - XVisualInfo *vis_info = glXGetVisualFromFBConfig(dpy, pWindow->Info); - // Create base context so we can initialize GLEW - GLXContext dummy_ctx = glXCreateContext(dpy, vis_info, 0, True); - XFree(vis_info); - glXMakeCurrent(dpy, pWindow->renderwnd, dummy_ctx); - glewExperimental = GL_TRUE; - GLenum err = glewInit(); - if (err != GLEW_OK) - { - return pGL->Error((const char*)glewGetErrorString(err)); - } - - // Create Context with sharing (if this is the main context, our ctx will be 0, so no sharing) - const int attribs[] = { - GLX_CONTEXT_MAJOR_VERSION_ARB, REQUESTED_GL_CTX_MAJOR, - GLX_CONTEXT_MINOR_VERSION_ARB, REQUESTED_GL_CTX_MINOR, - GLX_CONTEXT_FLAGS_ARB, (Config.Graphics.DebugOpenGL ? GLX_CONTEXT_DEBUG_BIT_ARB : 0), - GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, - None - }; - GLXContext share_context = (pGL->pMainCtx != this) ? static_cast(pGL->pMainCtx->ctx) : 0; - - if (glXCreateContextAttribsARB) - { - gdk_x11_display_error_trap_push(gdk_display_get_default()); - ctx = glXCreateContextAttribsARB(dpy, pWindow->Info, share_context, True, attribs); - gdk_x11_display_error_trap_pop_ignored(gdk_display_get_default()); - } - if(!ctx) { - Log(" gl: falling back to attribute-less context creation."); - ctx = glXCreateNewContext(dpy, pWindow->Info, GLX_RGBA_TYPE, share_context, True); - } - - glXMakeCurrent(dpy, None, NULL); - glXDestroyContext(dpy, dummy_ctx); - - // No luck? - if (!ctx) return pGL->Error(" gl: Unable to create context"); - if (!Select(true)) return pGL->Error(" gl: Unable to select context"); - // init extensions - glewExperimental = GL_TRUE; - err = glewInit(); - if (GLEW_OK != err) - { - // Problem: glewInit failed, something is seriously wrong. - return pGL->Error(reinterpret_cast(glewGetErrorString(err))); - } - - this_context = contexts.insert(contexts.end(), this); - return true; -} - -bool CStdGLCtx::Select(bool verbose) -{ - // safety - if (!pGL || !ctx) - { - if (verbose) pGL->Error(" gl: pGL is zero"); - return false; - } - Display * const dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default()); - // make context current - if (!pWindow->renderwnd || !glXMakeCurrent(dpy, pWindow->renderwnd, (GLXContext)ctx)) - { - if (verbose) pGL->Error(" gl: glXMakeCurrent failed"); - return false; - } - SelectCommon(); - // update clipper - might have been done by UpdateSize - // however, the wrong size might have been assumed - if (!pGL->UpdateClipper()) - { - if (verbose) pGL->Error(" gl: UpdateClipper failed"); - return false; - } - // success - return true; -} - -void CStdGLCtx::Deselect() -{ - if (pGL && pGL->pCurrCtx == this) - { - Display * const dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default()); - glXMakeCurrent(dpy, None, NULL); - pGL->pCurrCtx = 0; - pGL->RenderTarget = 0; - } -} - -bool CStdGLCtx::PageFlip() -{ - // flush GL buffer - glFlush(); - if (!pWindow || !pWindow->renderwnd) return false; - Display * const dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default()); - glXSwapBuffers(dpy, pWindow->renderwnd); - return true; -} - #elif defined(USE_SDL_MAINLOOP) CStdGLCtx::CStdGLCtx(): pWindow(0), this_context(contexts.end()) { ctx = NULL; } @@ -663,7 +516,7 @@ bool CStdGLCtx::PageFlip() return true; } -#endif //USE_GTK/USE_SDL_MAINLOOP +#endif // USE_* #ifdef WITH_QT_EDITOR #undef LineFeed // conflicts with Qt diff --git a/src/gui/C4KeyboardInput.cpp b/src/gui/C4KeyboardInput.cpp index 5e134e465..509b6f4ce 100644 --- a/src/gui/C4KeyboardInput.cpp +++ b/src/gui/C4KeyboardInput.cpp @@ -22,13 +22,6 @@ #include "game/C4Game.h" #include "platform/C4Window.h" -#ifdef USE_GTK -#include -#ifdef GDK_WINDOWING_X11 -#include -#include -#endif -#endif #include #include @@ -412,7 +405,7 @@ StdStrBuf C4KeyCodeEx::KeyCode2String(C4KeyCode wCode, bool fHumanReadable, bool // for config files and such: dump scancode return FormatString("$%x", static_cast(wCode)); } -#if defined(USE_WIN32_WINDOWS) || (defined(_WIN32) && defined(USE_GTK)) +#if defined(USE_WIN32_WINDOWS) // Query map const C4KeyCodeMapEntry *pCheck = KeyCodeMap; @@ -442,20 +435,6 @@ StdStrBuf C4KeyCodeEx::KeyCode2String(C4KeyCode wCode, bool fHumanReadable, bool if (wCode == pCheck->wCode) return StdStrBuf((pCheck->szShortName && fShort) ? pCheck->szShortName : pCheck->szName); else ++pCheck; // not found: Compose as direct code return FormatString("\\x%x", static_cast(wCode)); -#elif defined(USE_GTK) - Display * const dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default()); - KeySym keysym = (KeySym)XkbKeycodeToKeysym(dpy,wCode+8,0,0); - char* name = NULL; - if (keysym != NoSymbol) { // is the keycode without shift modifiers mapped to a symbol? - name = gtk_accelerator_get_label_with_keycode(gdk_display_get_default(), keysym, wCode+8, (GdkModifierType)0); - } - if (name) { // is there a string representation of the keysym? - // prevent memleak - StdStrBuf buf; - buf.Copy(name); - g_free(name); - return buf; - } #elif defined(USE_SDL_MAINLOOP) StdStrBuf buf; buf.Copy(SDL_GetScancodeName(static_cast(wCode))); diff --git a/src/platform/C4App.h b/src/platform/C4App.h index 0a063d164..7042a63f6 100644 --- a/src/platform/C4App.h +++ b/src/platform/C4App.h @@ -122,11 +122,7 @@ public: pthread_t MainThread; #endif -#if defined(USE_GTK) -protected: - class C4X11AppImpl * Priv; - -#elif defined(USE_SDL_MAINLOOP) +#if defined(USE_SDL_MAINLOOP) public: void HandleSDLEvent(SDL_Event& event); diff --git a/src/platform/C4AppGTK.cpp b/src/platform/C4AppGTK.cpp deleted file mode 100644 index 9fa18968c..000000000 --- a/src/platform/C4AppGTK.cpp +++ /dev/null @@ -1,378 +0,0 @@ -/* - * OpenClonk, http://www.openclonk.org - * - * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/ - * Copyright (c) 2009-2016, The OpenClonk Team and contributors - * - * Distributed under the terms of the ISC license; see accompanying file - * "COPYING" for details. - * - * "Clonk" is a registered trademark of Matthes Bender, used with permission. - * See accompanying file "TRADEMARK" for details. - * - * To redistribute this file separately, substitute the full license texts - * for the above references. - */ - -/* A wrapper class to OS dependent event and window interfaces, X11 version */ - -#include "C4Include.h" -#include "platform/C4App.h" - -#include "platform/C4Window.h" -#include "graphics/C4DrawGL.h" -#include "graphics/C4Draw.h" -#include "platform/StdFile.h" -#include "lib/StdBuf.h" - -#include -#include - -#ifdef GDK_WINDOWING_X11 -#include -#include -#include -#endif - -class C4GLibProc: public StdSchedulerProc -{ -public: - C4GLibProc(GMainContext *context): context(context), query_time(C4TimeMilliseconds::NegativeInfinity) { fds.resize(1); g_main_context_ref(context); } - ~C4GLibProc() - { - g_main_context_unref(context); - } - - GMainContext *context; -#ifdef STDSCHEDULER_USE_EVENTS - std::vector fds; -#else - std::vector fds; -#endif - C4TimeMilliseconds query_time; - int timeout; - int max_priority; - -private: - // Obtain the timeout and FDs from the glib mainloop. We then pass them - // to the StdScheduler in GetFDs() and GetNextTick() so that it can - // poll the file descriptors, along with the file descriptors from - // other sources that it might have. - void query(C4TimeMilliseconds Now) - { - // If Execute() has not yet been called, then finish the current iteration first. - // Note that we cannot simply ignore the query() call, as new - // FDs or Timeouts may have been added to the Glib loop in the meanwhile - if (!query_time.IsInfinite()) - { - //g_main_context_check(context, max_priority, fds.empty() ? NULL : (GPollFD*) &fds[0], fds.size()); - Execute(); - } - - g_main_context_prepare (context, &max_priority); - unsigned int fd_count; - if (fds.empty()) fds.resize(1); - while ((fd_count = g_main_context_query(context, max_priority, &timeout, (GPollFD*) &fds[0], fds.size())) > fds.size()) - { - fds.resize(fd_count); - } - // Make sure we don't report more FDs than there are available - fds.resize(fd_count); - query_time = Now; - } - -public: - // Iterate the Glib main loop until all pending events have been - // processed. Don't use g_main_context_pending() directly as the - // C4GLibProc might have initiated a loop iteration already. - // This is mainly used to update the log in the editor window while - // a scenario is being loaded. - void IteratePendingEvents() - { - // TODO: I think we can also iterate the context manually, - // without g_main_context_iteration. This might be less hacky. - - // Finish current iteration first - C4TimeMilliseconds old_query_time = C4TimeMilliseconds::NegativeInfinity; - if (!query_time.IsInfinite()) - { - old_query_time = query_time; - //g_main_context_check(context, max_priority, fds.empty() ? NULL : (GPollFD*) &fds[0], fds.size()); - //query_time = C4TimeMilliseconds::NegativeInfinity; - Execute(); - } - - // Run the loop - while (g_main_context_pending(context)) - g_main_context_iteration(context, false); - - // Return to original state - if (!old_query_time.IsInfinite()) - query(old_query_time); - } - - // StdSchedulerProc override -#ifdef STDSCHEDULER_USE_EVENTS - virtual HANDLE GetEvent() - { - return reinterpret_cast(fds[0].fd); - } -#else - virtual void GetFDs(std::vector & rfds) - { - if (query_time.IsInfinite()) query(C4TimeMilliseconds::Now()); - rfds.insert(rfds.end(), fds.begin(), fds.end()); - } -#endif - virtual C4TimeMilliseconds GetNextTick(C4TimeMilliseconds Now) - { - query(Now); - if (timeout < 0) return C4TimeMilliseconds::PositiveInfinity; - return query_time + timeout; - } - virtual bool Execute(int iTimeout = -1, pollfd * readyfds = 0) - { - if (query_time.IsInfinite()) return true; - g_main_context_check(context, max_priority, fds.empty() ? NULL : readyfds ? (GPollFD*) readyfds : (GPollFD*) &fds[0], fds.size()); - - // g_main_context_dispatch makes callbacks from the main loop. - // We allow the callback to iterate the mainloop via - // IteratePendingEvents so reset query_time before to not call - // g_main_context_check() twice for the current iteration. - // This would otherwise lead to a freeze since - // g_main_context_check() seems to block when called twice. - query_time = C4TimeMilliseconds::NegativeInfinity; - g_main_context_dispatch(context); - return true; - } -}; - -class C4X11AppImpl -{ -public: - C4GLibProc GLibProc; - C4X11AppImpl(C4AbstractApp *pApp): - GLibProc(g_main_context_default()), - xrandr_major_version(-1), xrandr_minor_version(-1), - xrandr_oldmode(-1), - xrandr_rot(0), - xrandr_event(-1), - argc(0), argv(0) - { - } - - int xrandr_major_version, xrandr_minor_version; - int xrandr_oldmode; - unsigned short xrandr_rot; - int xrandr_event; - - int argc; char ** argv; -}; - -C4AbstractApp::C4AbstractApp(): Active(false), fQuitMsgReceived(false), - // main thread -#ifdef _WIN32 - hInstance(NULL), - idMainThread(::GetCurrentThreadId()), -#elif defined(HAVE_PTHREAD) - MainThread (pthread_self()), -#endif - Priv(new C4X11AppImpl(this)), fDspModeSet(false) -{ - Add(&Priv->GLibProc); -} - -C4AbstractApp::~C4AbstractApp() -{ - Remove(&Priv->GLibProc); - delete Priv; -} - -bool C4AbstractApp::Init(int argc, char * argv[]) -{ - // Set locale - setlocale(LC_ALL,""); - gtk_init(&argc, &argv); - - GdkPixbuf* icon = gdk_pixbuf_new_from_resource("/org/openclonk/engine/oc.ico", NULL); - gtk_window_set_default_icon(icon); - g_object_unref(icon); - // Try to figure out the location of the executable - Priv->argc=argc; Priv->argv=argv; - -#ifdef GDK_WINDOWING_X11 - Display * const dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default()); - int xrandr_error_base; - if (!XRRQueryExtension(dpy, &Priv->xrandr_event, &xrandr_error_base) - || !XRRQueryVersion(dpy, &Priv->xrandr_major_version, &Priv->xrandr_minor_version)) - { - Priv->xrandr_major_version = -1; - Priv->xrandr_minor_version = 0; - } - if (Priv->xrandr_major_version >= 0) - { - XRRSelectInput(dpy, DefaultRootWindow(dpy), RRScreenChangeNotifyMask); - } - else - Log("The Xrandr extension is missing. Resolution switching will not work."); -#endif - - // Custom initialization - return DoInit (argc, argv); -} - -static void -gtk_clipboard_store_all (void) -{ - GtkClipboard *clipboard; - GSList *displays, *list; - - displays = gdk_display_manager_list_displays (gdk_display_manager_get ()); - - list = displays; - while (list) - { - GdkDisplay *display = static_cast(list->data); - - clipboard = gtk_clipboard_get_for_display (display, GDK_SELECTION_CLIPBOARD); - - if (clipboard) - gtk_clipboard_store (clipboard); - - list = list->next; - } - g_slist_free (displays); - -} - -void C4AbstractApp::Clear() -{ - gtk_clipboard_store_all(); -} - -void C4AbstractApp::Quit() -{ - fQuitMsgReceived = true; -} - -bool C4AbstractApp::FlushMessages() -{ - // Always fail after quit message - if (fQuitMsgReceived) - return false; - - Priv->GLibProc.IteratePendingEvents(); - return true; -} - -bool C4AbstractApp::SetVideoMode(int iXRes, int iYRes, unsigned int iRefreshRate, unsigned int iMonitor, bool fFullScreen) -{ - if (!fFullScreen) - { - RestoreVideoMode(); - if (iXRes != -1) - pWindow->SetSize(iXRes, iYRes); - return true; - } - -#ifdef GDK_WINDOWING_X11 - Display * const dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default()); - if (Priv->xrandr_major_version >= 0 && !(iXRes == -1 && iYRes == -1)) - { - // randr spec says to always get fresh info, so don't cache. - XRRScreenConfiguration * conf = XRRGetScreenInfo (dpy, pWindow->renderwnd); - if (Priv->xrandr_oldmode == -1) - Priv->xrandr_oldmode = XRRConfigCurrentConfiguration (conf, &Priv->xrandr_rot); - int n; - XRRScreenSize * sizes = XRRConfigSizes(conf, &n); - for (int i = 0; i < n; ++i) - { - if (int(sizes[i].width) == iXRes && int(sizes[i].height) == iYRes) - { -#ifdef _DEBUG - LogF("XRRSetScreenConfig %d", i); -#endif - fDspModeSet = XRRSetScreenConfig(dpy, conf, pWindow->renderwnd, i, Priv->xrandr_rot, CurrentTime) == RRSetConfigSuccess; - break; - } - } - XRRFreeScreenConfigInfo(conf); - } -#endif - gtk_window_fullscreen(GTK_WINDOW(pWindow->window)); - return fDspModeSet || (iXRes == -1 && iYRes == -1); -} - -void C4AbstractApp::RestoreVideoMode() -{ -#ifdef GDK_WINDOWING_X11 - // Restore resolution - Display * const dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default()); - if (fDspModeSet && Priv->xrandr_major_version >= 0 && Priv->xrandr_oldmode != -1) - { - XRRScreenConfiguration * conf = XRRGetScreenInfo (dpy, pWindow->renderwnd); -#ifdef _DEBUG - LogF("XRRSetScreenConfig %d (back)", Priv->xrandr_oldmode); -#endif - XRRSetScreenConfig (dpy, conf, pWindow->renderwnd, Priv->xrandr_oldmode, Priv->xrandr_rot, CurrentTime); - Priv->xrandr_oldmode = -1; - XRRFreeScreenConfigInfo(conf); - fDspModeSet = false; - } -#endif - // pWindow may be unset when C4AbstractApp gets destroyed during the - // initialization code, before a window has been created - if (pWindow) - gtk_window_unfullscreen(GTK_WINDOW(pWindow->window)); -} - -bool C4AbstractApp::GetIndexedDisplayMode(int32_t iIndex, int32_t *piXRes, int32_t *piYRes, int32_t *piBitDepth, int32_t *piRefreshRate, uint32_t iMonitor) -{ -#ifdef GDK_WINDOWING_X11 - Display * const dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default()); - int n; - XRRScreenSize * sizes = XRRSizes(dpy, XDefaultScreen(dpy), &n); - if (iIndex < n && iIndex >= 0) - { - *piXRes = sizes[iIndex].width; - *piYRes = sizes[iIndex].height; - *piBitDepth = 32; - return true; - } - return false; -#endif -} - -// Copy the text to the clipboard or the primary selection -bool C4AbstractApp::Copy(const StdStrBuf & text, bool fClipboard) -{ - gtk_clipboard_set_text(gtk_clipboard_get(fClipboard ? GDK_SELECTION_CLIPBOARD : GDK_SELECTION_PRIMARY), - text.getData(), text.getLength()); - return true; -} - -// Paste the text from the clipboard or the primary selection -StdStrBuf C4AbstractApp::Paste(bool fClipboard) -{ - char * r = gtk_clipboard_wait_for_text(gtk_clipboard_get(fClipboard ? GDK_SELECTION_CLIPBOARD : GDK_SELECTION_PRIMARY)); -// gtk_clipboard_request_text(gtk_clipboard_get(fClipboard ? GDK_SELECTION_CLIPBOARD : GDK_SELECTION_PRIMARY), -// GtkClipboardTextReceivedFunc callback, gpointer user_data); - StdStrBuf rbuf; - rbuf.Copy(r); - g_free(r); - return rbuf; -} - -// Is there something in the clipboard? -bool C4AbstractApp::IsClipboardFull(bool fClipboard) -{ - return gtk_clipboard_wait_is_text_available(gtk_clipboard_get(fClipboard ? GDK_SELECTION_CLIPBOARD : GDK_SELECTION_PRIMARY)); -} - -void C4AbstractApp::MessageDialog(const char * message) -{ - GtkWidget * dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", message); - gtk_window_set_title(GTK_WINDOW(dialog), "OpenClonk Error"); - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); -} diff --git a/src/platform/C4Window.h b/src/platform/C4Window.h index 5252f729a..38a8404ab 100644 --- a/src/platform/C4Window.h +++ b/src/platform/C4Window.h @@ -21,18 +21,7 @@ #include "lib/StdBuf.h" -#if defined(USE_GTK) -#ifdef _WIN32 -#undef MK_CONTROL -#undef MK_SHIFT -#endif -// from X.h: -//#define ShiftMask (1<<0) -//#define ControlMask (1<<2) -#define MK_CONTROL (1<<2) -#define MK_SHIFT (1<<0) -#define MK_ALT (1<<3) -#elif defined(USE_SDL_MAINLOOP) +#if defined(USE_SDL_MAINLOOP) #include #define MK_SHIFT (KMOD_LSHIFT | KMOD_RSHIFT) #define MK_CONTROL (KMOD_LCTRL | KMOD_RCTRL) @@ -59,7 +48,7 @@ extern int MK_ALT; #include #endif -#if defined(USE_WIN32_WINDOWS) || defined(USE_GTK) || defined(USE_CONSOLE) || defined(USE_SDL_MAINLOOP) +#if defined(USE_WIN32_WINDOWS) || defined(USE_CONSOLE) || defined(USE_SDL_MAINLOOP) #define K_ESCAPE 1 #define K_1 2 #define K_2 3 @@ -267,10 +256,6 @@ extern C4KeyCode K_PRINT; extern C4KeyCode K_CENTER; #endif -#ifdef USE_GTK -// Forward declaration because xlib.h is evil -typedef struct __GLXFBConfigRec *GLXFBConfig; -#endif class C4Window #ifdef USE_COCOA @@ -325,33 +310,17 @@ public: #if defined(USE_WIN32_WINDOWS) HWND hWindow; virtual bool Win32DialogMessageHandling(MSG * msg) { return false; }; -#elif defined(USE_GTK) - /*GtkWidget*/void * window; - // Set by Init to the widget which is used as a - // render target, which can be the whole window. - /*GtkWidget*/void * render_widget; - // Mouse grabbing has to be restored when the window gains focus. - bool mouse_was_grabbed = false; #elif defined(USE_SDL_MAINLOOP) SDL_Window * window; void HandleSDLEvent(SDL_WindowEvent &e); #endif #ifdef USE_WGL HWND renderwnd; -#elif defined(USE_GTK) - unsigned long renderwnd; #endif #ifdef WITH_QT_EDITOR class QOpenGLWidget *glwidget; #endif protected: -#if defined(USE_GTK) - bool FindFBConfig(int samples, GLXFBConfig *info); - - // The GLXFBConfig the window was created with - GLXFBConfig Info; - unsigned long handlerDestroy; -#endif virtual C4Window * Init(WindowKind windowKind, C4AbstractApp * pApp, const char * Title, const C4Rect * size); friend class C4Draw; friend class CStdGL; diff --git a/src/platform/C4WindowGTK.cpp b/src/platform/C4WindowGTK.cpp deleted file mode 100644 index f9a4ef271..000000000 --- a/src/platform/C4WindowGTK.cpp +++ /dev/null @@ -1,949 +0,0 @@ -/* - * OpenClonk, http://www.openclonk.org - * - * Copyright (c) 2005-2009, RedWolf Design GmbH, http://www.clonk.de/ - * Copyright (c) 2009-2016, The OpenClonk Team and contributors - * - * Distributed under the terms of the ISC license; see accompanying file - * "COPYING" for details. - * - * "Clonk" is a registered trademark of Matthes Bender, used with permission. - * See accompanying file "TRADEMARK" for details. - * - * To redistribute this file separately, substitute the full license texts - * for the above references. - */ - -/* A wrapper class to OS dependent event and window interfaces, GTK+ version */ - -#include "C4Include.h" -#include "platform/C4Window.h" - -#include "platform/C4App.h" -#include "C4Version.h" -#include "config/C4Config.h" - -#include "graphics/C4DrawGL.h" -#include "graphics/C4Draw.h" -#include "platform/StdFile.h" -#include "lib/StdBuf.h" - -#include "lib/C4Rect.h" - -#include "editor/C4Console.h" -#include "editor/C4ViewportWindow.h" -#include "game/C4Viewport.h" -#include "gui/C4MouseControl.h" - -#include -#include -#include - -#ifdef GDK_WINDOWING_X11 -#include -#include -#include - -// Some helper functions for choosing a proper visual - -namespace { -static const std::map base_attrib_map { - {GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT}, - {GLX_X_RENDERABLE, True}, - {GLX_RED_SIZE, 4}, - {GLX_GREEN_SIZE, 4}, - {GLX_BLUE_SIZE, 4}, - {GLX_DEPTH_SIZE, 8} -}; - -// Turns an int->int map into an attribute list suitable for any GLX calls. -std::unique_ptr MakeGLXAttribList(const std::map &map) -{ - // We need two ints for every attribute, plus one as a sentinel - auto list = std::make_unique(map.size() * 2 + 1); - int *cursor = list.get(); - for(const auto &attrib : map) - { - *cursor++ = attrib.first; - *cursor++ = attrib.second; - } - *cursor = None; - return list; -} - -// This function picks an acceptable GLXFBConfig. To do this, we first -// request a list of framebuffer configs with no less than 4 bits per color; -// no less than 8 bits of depth buffer; if multisampling is not -1, -// with at least the requested number of samples; and with double buffering. -// If that returns no suitable configs, we retry with only a single buffer. -GLXFBConfig PickGLXFBConfig(Display* dpy, int multisampling) -{ - std::map attrib_map = base_attrib_map; - - if (multisampling >= 0) - { - attrib_map[GLX_SAMPLE_BUFFERS] = multisampling > 0 ? 1 : 0; - attrib_map[GLX_SAMPLES] = multisampling; - } - - GLXFBConfig *configs = NULL; - int config_count; - // Find a double-buffered FB config - attrib_map[GLX_DOUBLEBUFFER] = True; - std::unique_ptr attribs = MakeGLXAttribList(attrib_map); - configs = glXChooseFBConfig(dpy, DefaultScreen(dpy), attribs.get(), &config_count); - if (config_count == 0) - { - // If none exists, try to find a single-buffered one - if (configs != NULL) - XFree(configs); - attrib_map[GLX_DOUBLEBUFFER] = False; - attribs = MakeGLXAttribList(attrib_map); - configs = glXChooseFBConfig(dpy, DefaultScreen(dpy), attribs.get(), &config_count); - } - - GLXFBConfig config = NULL; - if (config_count > 0) - { - config = configs[0]; - } - - XFree(configs); - return config; -} -} -#elif defined(GDK_WINDOWING_WIN32) -#include "platform/C4windowswrapper.h" -#include -#endif // GDK_WINDOWING_X11 - -static void OnDestroyStatic(GtkWidget* widget, gpointer data) -{ - C4Window* wnd = static_cast(data); - wnd->Clear(); -} - -static gboolean OnDelete(GtkWidget* widget, GdkEvent* event, gpointer data) -{ - C4Window* wnd = static_cast(data); - wnd->Close(); - return true; -} - -#ifdef GDK_WINDOWING_X11 -static constexpr int x11scancodeoffset = 8; -#else -static constexpr int x11scancodeoffset = 0; -#endif - -static gboolean OnKeyPress(GtkWidget* widget, GdkEventKey* event, gpointer data) -{ - C4Window* wnd = static_cast(data); - if (event->hardware_keycode <= x11scancodeoffset) return false; - Game.DoKeyboardInput(event->hardware_keycode - x11scancodeoffset, KEYEV_Down, - !!(event->state & GDK_MOD1_MASK), - !!(event->state & GDK_CONTROL_MASK), - !!(event->state & GDK_SHIFT_MASK), false, NULL); - wnd->CharIn(event->string); // FIXME: Use GtkIMContext somehow - return true; -} - -static gboolean OnKeyRelease(GtkWidget* widget, GdkEventKey* event, gpointer user_data) -{ - if (event->hardware_keycode <= x11scancodeoffset) return false; - Game.DoKeyboardInput(event->hardware_keycode - x11scancodeoffset, KEYEV_Up, - !!(event->state & GDK_MOD1_MASK), - !!(event->state & GDK_CONTROL_MASK), - !!(event->state & GDK_SHIFT_MASK), false, NULL); - return true; -} - -static void OnDragDataReceivedStatic(GtkWidget* widget, GdkDragContext* context, gint x, gint y, GtkSelectionData* data, guint info, guint time, gpointer user_data) -{ - if (!Console.Editing) { Console.Message(LoadResStr("IDS_CNS_NONETEDIT")); return; } - C4ViewportWindow* window = static_cast(user_data); - - gchar** uris = gtk_selection_data_get_uris(data); - if (!uris) return; - - for (gchar** uri = uris; *uri != NULL; ++ uri) - { - gchar* file = g_filename_from_uri(*uri, NULL, NULL); - if (!file) continue; - - window->cvp->DropFile(file, x, y); - g_free(file); - } - - g_strfreev(uris); -} - -static gboolean OnExposeStatic(GtkWidget* widget, void *, gpointer user_data) -{ - C4Viewport* cvp = static_cast(user_data)->cvp; - cvp->Execute(); - return true; -} - -static void OnRealizeStatic(GtkWidget* widget, gpointer user_data) -{ - // Initial PlayerLock - if (static_cast(user_data)->cvp->GetPlayerLock()) - { - gtk_widget_hide(static_cast(user_data)->h_scrollbar); - gtk_widget_hide(static_cast(user_data)->v_scrollbar); - } -} - -static gboolean OnKeyPressStatic(GtkWidget* widget, GdkEventKey* event, gpointer user_data) -{ - if (event->keyval == GDK_KEY_Scroll_Lock) - { - static_cast(user_data)->cvp->TogglePlayerLock(); - return true; - } - if (event->hardware_keycode <= x11scancodeoffset) return false; - Console.EditCursor.KeyDown(event->hardware_keycode - x11scancodeoffset, event->state); - return false; -} - -static gboolean OnKeyReleaseStatic(GtkWidget* widget, GdkEventKey* event, gpointer user_data) -{ - if (event->hardware_keycode <= x11scancodeoffset) return false; - Console.EditCursor.KeyUp(event->hardware_keycode - x11scancodeoffset, event->state); - return false; -} - -static gboolean OnScrollVW(GtkWidget* widget, GdkEventScroll* event, gpointer user_data) -{ - C4ViewportWindow* window = static_cast(user_data); - - if (::MouseControl.IsViewport(window->cvp) && (Console.EditCursor.GetMode()==C4CNS_ModePlay)) - { - switch (event->direction) - { - case GDK_SCROLL_UP: - C4GUI::MouseMove(C4MC_Button_Wheel, (int32_t)event->x, (int32_t)event->y, event->state + (short(1) << 16), window->cvp); - break; - case GDK_SCROLL_DOWN: - C4GUI::MouseMove(C4MC_Button_Wheel, (int32_t)event->x, (int32_t)event->y, event->state + (short(-1) << 16), window->cvp); - break; - default: - return false; - } - } - return true; -} - -static gboolean OnButtonPressStatic(GtkWidget* widget, GdkEventButton* event, gpointer user_data) -{ - C4ViewportWindow* window = static_cast(user_data); - - if (::MouseControl.IsViewport(window->cvp) && (Console.EditCursor.GetMode()==C4CNS_ModePlay)) - { - switch (event->button) - { - case 1: - if (event->type == GDK_BUTTON_PRESS) - C4GUI::MouseMove(C4MC_Button_LeftDown, (int32_t)event->x, (int32_t)event->y, event->state, window->cvp); - else if (event->type == GDK_2BUTTON_PRESS) - C4GUI::MouseMove(C4MC_Button_LeftDouble, (int32_t)event->x, (int32_t)event->y, event->state, window->cvp); - break; - case 2: - C4GUI::MouseMove(C4MC_Button_MiddleDown, (int32_t)event->x, (int32_t)event->y, event->state, window->cvp); - break; - case 3: - if (event->type == GDK_BUTTON_PRESS) - C4GUI::MouseMove(C4MC_Button_RightDown, (int32_t)event->x, (int32_t)event->y, event->state, window->cvp); - else if (event->type == GDK_2BUTTON_PRESS) - C4GUI::MouseMove(C4MC_Button_RightDouble, (int32_t)event->x, (int32_t)event->y, event->state, window->cvp); - break; - } - } - else - { - switch (event->button) - { - case 1: - Console.EditCursor.LeftButtonDown(event->state); - break; - case 3: - Console.EditCursor.RightButtonDown(event->state); - break; - } - } - - return true; -} - -static gboolean OnButtonReleaseStatic(GtkWidget* widget, GdkEventButton* event, gpointer user_data) -{ - C4ViewportWindow* window = static_cast(user_data); - - if (::MouseControl.IsViewport(window->cvp) && (Console.EditCursor.GetMode()==C4CNS_ModePlay)) - { - switch (event->button) - { - case 1: - C4GUI::MouseMove(C4MC_Button_LeftUp, (int32_t)event->x, (int32_t)event->y, event->state, window->cvp); - break; - case 2: - C4GUI::MouseMove(C4MC_Button_MiddleUp, (int32_t)event->x, (int32_t)event->y, event->state, window->cvp); - break; - case 3: - C4GUI::MouseMove(C4MC_Button_RightUp, (int32_t)event->x, (int32_t)event->y, event->state, window->cvp); - break; - } - } - else - { - switch (event->button) - { - case 1: - Console.EditCursor.LeftButtonUp(event->state); - break; - case 3: - Console.EditCursor.RightButtonUp(event->state); - break; - } - } - - return true; -} - -static gboolean OnMotionNotifyStatic(GtkWidget* widget, GdkEventMotion* event, gpointer user_data) -{ - C4ViewportWindow* window = static_cast(user_data); - - if (::MouseControl.IsViewport(window->cvp) && (Console.EditCursor.GetMode()==C4CNS_ModePlay)) - { - C4GUI::MouseMove(C4MC_Button_None, (int32_t)event->x, (int32_t)event->y, event->state, window->cvp); - } - else - { - window->EditCursorMove(event->x, event->y, event->state); - } - - return true; -} - -static gboolean OnConfigureStatic(GtkWidget* widget, GdkEventConfigure* event, gpointer user_data) -{ - C4ViewportWindow* window = static_cast(user_data); - C4Viewport* cvp = window->cvp; - - //cvp->UpdateOutputSize(); - cvp->ScrollBarsByViewPosition(); - - return false; -} - -static gboolean OnConfigureDareaStatic(GtkWidget* widget, GdkEventConfigure* event, gpointer user_data) -{ - C4ViewportWindow* window = static_cast(user_data); - C4Viewport* cvp = window->cvp; - - cvp->UpdateOutputSize(); - - return false; -} - -static void OnVScrollStatic(GtkAdjustment* adjustment, gpointer user_data) -{ - static_cast(user_data)->cvp->ViewPositionByScrollBars(); -} - -static void OnHScrollStatic(GtkAdjustment* adjustment, gpointer user_data) -{ - static_cast(user_data)->cvp->ViewPositionByScrollBars(); -} - -static GtkTargetEntry drag_drop_entries[] = -{ - { const_cast("text/uri-list"), 0, 0 } -}; - -static gboolean OnConfigureNotify(GtkWidget *widget, GdkEvent *event, gpointer user_data) -{ - Application.OnResolutionChanged(event->configure.width, event->configure.height); - return false; -} - -static bool fullscreen_needs_restore = false; -static gboolean fullscreen_restore(gpointer data) -{ - if (fullscreen_needs_restore) - Application.SetVideoMode(Application.GetConfigWidth(), Application.GetConfigHeight(), Config.Graphics.RefreshRate, Config.Graphics.Monitor, Application.FullScreenMode()); - fullscreen_needs_restore = false; - return FALSE; -} - -static bool grab_mouse(GtkWidget *widget) -{ - // This should be possible with pure GTK code as well, using - // gdk_device_grab(). However, while gdk_device_grab() will prevent clicks - // outside of the game window, the mouse gets stuck near the edge of the - // window when trying to move outside. -#ifdef GDK_WINDOWING_X11 - Display * const dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default()); - Window xwindow = gdk_x11_window_get_xid(gtk_widget_get_window(widget)); - int result = XGrabPointer(dpy, xwindow, true, 0, GrabModeAsync, GrabModeAsync, xwindow, None, CurrentTime); - return result == GrabSuccess; -#endif - return true; -} - -static void ungrab_mouse() -{ -#ifdef GDK_WINDOWING_X11 - Display * const dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default()); - XUngrabPointer(dpy, CurrentTime); -#endif -} - -static gboolean grab_mouse_fn(gpointer user_data) -{ - // Grabbing may not be possible immediately after focusing the window, so - // try again if we don't succeed. - return !grab_mouse((GtkWidget*) user_data); -} - -static gboolean OnFocusInFS(GtkWidget *widget, GdkEvent *event, gpointer user_data) -{ - Application.Active = true; - if (Application.FullScreenMode()) - { - fullscreen_needs_restore = true; - gdk_threads_add_idle(fullscreen_restore, NULL); - } - C4Window *window = (C4Window*) user_data; - if (window->mouse_was_grabbed) - gdk_threads_add_timeout(50, grab_mouse_fn, widget); - // Reset urgency hint (does nothing if unset) - assert(widget == window->window && "OnFocusInFS callback used for something other than the main window."); - gtk_window_set_urgency_hint(GTK_WINDOW(window->window), false); - return false; -} -static gboolean OnFocusOutFS(GtkWidget *widget, GdkEvent *event, gpointer user_data) -{ - Application.Active = false; - if (Application.FullScreenMode() && Application.GetConfigWidth() != -1) - { - Application.RestoreVideoMode(); - gtk_window_iconify(GTK_WINDOW(widget)); - fullscreen_needs_restore = false; - } - ungrab_mouse(); - return false; -} - -static gboolean OnButtonPressFS(GtkWidget* widget, GdkEventButton* event, gpointer user_data) -{ - switch (event->button) - { - case 1: - if (event->type == GDK_BUTTON_PRESS) - C4GUI::MouseMove(C4MC_Button_LeftDown, (int32_t)event->x, (int32_t)event->y, event->state, NULL); - else if (event->type == GDK_2BUTTON_PRESS) - C4GUI::MouseMove(C4MC_Button_LeftDouble, (int32_t)event->x, (int32_t)event->y, event->state, NULL); - break; - case 2: - C4GUI::MouseMove(C4MC_Button_MiddleDown, (int32_t)event->x, (int32_t)event->y, event->state, NULL); - break; - case 3: - if (event->type == GDK_BUTTON_PRESS) - C4GUI::MouseMove(C4MC_Button_RightDown, (int32_t)event->x, (int32_t)event->y, event->state, NULL); - else if (event->type == GDK_2BUTTON_PRESS) - C4GUI::MouseMove(C4MC_Button_RightDouble, (int32_t)event->x, (int32_t)event->y, event->state, NULL); - break; - default: - return false; - } - return true; -} - -gboolean OnButtonRelease(GtkWidget* widget, GdkEventButton* event, gpointer user_data) -{ - int b; - switch (event->button) - { - case 1: b = C4MC_Button_LeftUp; break; - case 2: b = C4MC_Button_MiddleUp; break; - case 3: b = C4MC_Button_RightUp; break; - default: return false; - } - C4GUI::MouseMove(b, (int32_t)event->x, (int32_t)event->y, event->state, NULL); - return true; -} - -static gboolean OnMotionNotify(GtkWidget* widget, GdkEventMotion* event, gpointer user_data) -{ - C4GUI::MouseMove(C4MC_Button_None, (int32_t)event->x, (int32_t)event->y, event->state, NULL); - return true; -} - -static gboolean OnScroll(GtkWidget* widget, GdkEventScroll* event, gpointer user_data) -{ - C4GUI::DialogWindow * window = static_cast(user_data); - C4GUI::Dialog *pDlg = ::pGUI->GetDialog(window); - int idy; - switch (event->direction) - { - case GDK_SCROLL_UP: idy = 32; break; - case GDK_SCROLL_DOWN: idy = -32; break; - default: return false; - } - - // FIXME: make the GUI api less insane here - if (pDlg) - ::pGUI->MouseInput(C4MC_Button_Wheel, event->x, event->y, event->state + (idy << 16), pDlg, NULL); - else - C4GUI::MouseMove(C4MC_Button_Wheel, event->x, event->y, event->state + (idy << 16), NULL); - return true; -} - -static gboolean OnButtonPressGD(GtkWidget* widget, GdkEventButton* event, gpointer user_data) -{ - C4GUI::DialogWindow * window = static_cast(user_data); - C4GUI::Dialog *pDlg = ::pGUI->GetDialog(window); - - switch (event->button) - { - case 1: - if (event->type == GDK_2BUTTON_PRESS) - { - ::pGUI->MouseInput(C4MC_Button_LeftDouble, event->x, event->y, event->state, pDlg, NULL); - } - else if (event->type == GDK_BUTTON_PRESS) - { - ::pGUI->MouseInput(C4MC_Button_LeftDown,event->x, event->y, event->state, pDlg, NULL); - } - break; - case 2: - if (event->type == GDK_BUTTON_PRESS) - ::pGUI->MouseInput(C4MC_Button_MiddleDown, event->x, event->y, event->state, pDlg, NULL); - break; - case 3: - if (event->type == GDK_2BUTTON_PRESS) - { - ::pGUI->MouseInput(C4MC_Button_RightDouble, event->x, event->y, event->state, pDlg, NULL); - } - else if (event->type == GDK_BUTTON_PRESS) - { - ::pGUI->MouseInput(C4MC_Button_RightDown, event->x, event->y, event->state, pDlg, NULL); - } - break; - } - - return true; -} - -static gboolean OnButtonReleaseGD(GtkWidget* widget, GdkEventButton* event, gpointer user_data) -{ - C4GUI::DialogWindow * window = static_cast(user_data); - C4GUI::Dialog *pDlg = ::pGUI->GetDialog(window); - - switch (event->button) - { - case 1: - ::pGUI->MouseInput(C4MC_Button_LeftUp, event->x, event->y, event->state, pDlg, NULL); - break; - case 2: - ::pGUI->MouseInput(C4MC_Button_MiddleUp, event->x, event->y, event->state, pDlg, NULL); - break; - case 3: - ::pGUI->MouseInput(C4MC_Button_RightUp, event->x, event->y, event->state, pDlg, NULL); - break; - } - return true; -} - -static gboolean OnMotionNotifyGD(GtkWidget* widget, GdkEventMotion* event, gpointer user_data) -{ - C4GUI::DialogWindow * window = static_cast(user_data); - C4GUI::Dialog *pDlg = ::pGUI->GetDialog(window); - - ::pGUI->MouseInput(C4MC_Button_None, event->x, event->y, event->state, pDlg, NULL); - - return true; -} - -static gboolean OnConfigureGD(GtkWidget* widget, GdkEventConfigure* event, gpointer user_data) -{ - C4GUI::DialogWindow * window = static_cast(user_data); - - window->pSurface->UpdateSize(event->width, event->height); - - return false; -} - -C4Window::C4Window (): - Active(false), pSurface(0), - renderwnd(0), Info(0), window(NULL) -{ -} - -C4Window::~C4Window () -{ - Clear(); -} - -#ifdef GDK_WINDOWING_X11 -bool C4Window::FindFBConfig(int samples, GLXFBConfig *info) -{ - Display * const dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default()); - GLXFBConfig config = PickGLXFBConfig(dpy, samples); - if (info) - { - *info = config; - } - return config != NULL; - - return false; -} -#endif - -void C4Window::EnumerateMultiSamples(std::vector& samples) const -{ -#ifdef GDK_WINDOWING_X11 - Display * const dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default()); - std::map attribs = base_attrib_map; - attribs[GLX_SAMPLE_BUFFERS_ARB] = 1; - - int config_count = 0; - GLXFBConfig *configs = glXChooseFBConfig(dpy, DefaultScreen(dpy), MakeGLXAttribList(attribs).get(), &config_count); - - std::set multisamples; - for(int i = 0; i < config_count; ++i) - { - int v_samples; - glXGetFBConfigAttrib(dpy, configs[i], GLX_SAMPLES, &v_samples); - multisamples.insert(v_samples); - } - - XFree(configs); - samples.assign(multisamples.cbegin(), multisamples.cend()); -#else - if(pGL && pGL->pMainCtx) - samples = pGL->pMainCtx->EnumerateMultiSamples(); -#endif -} - -bool C4Window::StorePosition(const char *, const char *, bool) { return true; } - -bool C4Window::RestorePosition(const char *, const char *, bool) -{ - // The Windowmanager is responsible for window placement. - return true; -} - -void C4Window::FlashWindow() -{ - gtk_window_set_urgency_hint(GTK_WINDOW(window), true); -} - -void C4Window::GrabMouse(bool grab) -{ - if (grab) - { - // Don't grab the mouse while the game window isn't focused. - if (Application.Active) - grab_mouse(GTK_WIDGET(window)); - mouse_was_grabbed = true; - } - else - { - ungrab_mouse(); - mouse_was_grabbed = false; - } -} - -C4Window* C4Window::Init(WindowKind windowKind, C4AbstractApp * pApp, const char * Title, const C4Rect * size) -{ - Active = true; -#ifdef GDK_WINDOWING_X11 - if(!FindFBConfig(Config.Graphics.MultiSampling, &Info)) - { - // Disable multisampling if we don't find a visual which - // supports the currently configured setting. - if(!FindFBConfig(0, &Info)) return NULL; - Config.Graphics.MultiSampling = 0; - } -#endif - - assert(!window); - - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - if (windowKind == W_Viewport) - { - C4ViewportWindow * vw = static_cast(this); - - // Cannot just use ScrolledWindow because this would just move - // the GdkWindow of the DrawingArea. - GtkWidget* table = gtk_grid_new(); - render_widget = gtk_drawing_area_new(); - gtk_widget_set_hexpand(GTK_WIDGET(render_widget), true); - gtk_widget_set_vexpand(GTK_WIDGET(render_widget), true); - gtk_grid_attach(GTK_GRID(table), GTK_WIDGET(render_widget), 0, 0, 1, 1); - vw->h_scrollbar = gtk_scrollbar_new(GTK_ORIENTATION_HORIZONTAL, NULL); - gtk_grid_attach(GTK_GRID(table), vw->h_scrollbar, 0, 1, 1, 1); - vw->v_scrollbar = gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL, NULL); - gtk_grid_attach(GTK_GRID(table), vw->v_scrollbar, 1, 0, 1, 1); - - GtkAdjustment* adjustment = gtk_range_get_adjustment(GTK_RANGE(vw->h_scrollbar)); - - g_signal_connect( - G_OBJECT(adjustment), - "value-changed", - G_CALLBACK(OnHScrollStatic), - this - ); - - adjustment = gtk_range_get_adjustment(GTK_RANGE(vw->v_scrollbar)); - - g_signal_connect( - G_OBJECT(adjustment), - "value-changed", - G_CALLBACK(OnVScrollStatic), - this - ); - - gtk_container_add(GTK_CONTAINER(window), table); - - gtk_widget_add_events(GTK_WIDGET(window), GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK | GDK_POINTER_MOTION_MASK); - - gtk_drag_dest_set(GTK_WIDGET(render_widget), GTK_DEST_DEFAULT_ALL, drag_drop_entries, 1, GDK_ACTION_COPY); - g_signal_connect(G_OBJECT(render_widget), "drag-data-received", G_CALLBACK(OnDragDataReceivedStatic), this); - g_signal_connect(G_OBJECT(render_widget), "draw", G_CALLBACK(OnExposeStatic), this); - g_signal_connect(G_OBJECT(window), "key-press-event", G_CALLBACK(OnKeyPressStatic), this); - g_signal_connect(G_OBJECT(window), "key-release-event", G_CALLBACK(OnKeyReleaseStatic), this); - g_signal_connect(G_OBJECT(window), "scroll-event", G_CALLBACK(OnScrollVW), this); - g_signal_connect(G_OBJECT(window), "button-press-event", G_CALLBACK(OnButtonPressStatic), this); - g_signal_connect(G_OBJECT(window), "button-release-event", G_CALLBACK(OnButtonReleaseStatic), this); - g_signal_connect(G_OBJECT(window), "motion-notify-event", G_CALLBACK(OnMotionNotifyStatic), this); - g_signal_connect(G_OBJECT(window), "key-press-event", G_CALLBACK(OnKeyPress), this); - g_signal_connect(G_OBJECT(window), "key-release-event", G_CALLBACK(OnKeyRelease), this); - g_signal_connect(G_OBJECT(window), "configure-event", G_CALLBACK(OnConfigureStatic), this); - g_signal_connect(G_OBJECT(window), "realize", G_CALLBACK(OnRealizeStatic), this); - - g_signal_connect_after(G_OBJECT(render_widget), "configure-event", G_CALLBACK(OnConfigureDareaStatic), this); - -#if !GTK_CHECK_VERSION(3,10,0) - // do not draw the default background - gtk_widget_set_double_buffered (GTK_WIDGET(render_widget), false); -#endif - - gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(Console.window)); -#if !GTK_CHECK_VERSION(3,14,0) - gtk_window_set_has_resize_grip(GTK_WINDOW(window), false); -#endif - } - else if (windowKind == W_Fullscreen) - { - render_widget = gtk_drawing_area_new(); - gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(render_widget)); - - g_signal_connect(G_OBJECT(window), "configure-event", G_CALLBACK(OnConfigureNotify), this); - g_signal_connect(G_OBJECT(window), "focus-in-event", G_CALLBACK(OnFocusInFS), this); - g_signal_connect(G_OBJECT(window), "focus-out-event", G_CALLBACK(OnFocusOutFS), this); - g_signal_connect(G_OBJECT(window), "unmap-event", G_CALLBACK(OnFocusOutFS), this); - g_signal_connect(G_OBJECT(window), "button-press-event", G_CALLBACK(OnButtonPressFS), this); - g_signal_connect(G_OBJECT(window), "button-release-event", G_CALLBACK(OnButtonRelease), this); - g_signal_connect(G_OBJECT(window), "motion-notify-event", G_CALLBACK(OnMotionNotify), this); - g_signal_connect(G_OBJECT(window), "key-press-event", G_CALLBACK(OnKeyPress), this); - g_signal_connect(G_OBJECT(window), "key-release-event", G_CALLBACK(OnKeyRelease), this); - g_signal_connect(G_OBJECT(window), "scroll-event", G_CALLBACK(OnScroll), this); - gtk_widget_add_events(GTK_WIDGET(window), GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); -#if !GTK_CHECK_VERSION(3,10,0) - gtk_widget_set_double_buffered (GTK_WIDGET(render_widget), false); -#endif - - GValue val = {0,{{0}}}; - g_value_init (&val, G_TYPE_BOOLEAN); - g_value_set_boolean (&val, true); - g_object_set_property (G_OBJECT (render_widget), "can-focus", &val); - g_object_set_property (G_OBJECT (window), "can-focus", &val); - g_value_unset (&val); -#if !GTK_CHECK_VERSION(3,14,0) - gtk_window_set_has_resize_grip(GTK_WINDOW(window), false); -#endif - } - else if (windowKind == W_GuiWindow) - { - render_widget = window; - g_signal_connect(G_OBJECT(window), "button-press-event", G_CALLBACK(OnButtonPressGD), this); - g_signal_connect(G_OBJECT(window), "button-release-event", G_CALLBACK(OnButtonReleaseGD), this); - g_signal_connect(G_OBJECT(window), "motion-notify-event", G_CALLBACK(OnMotionNotifyGD), this); - g_signal_connect(G_OBJECT(window), "configure-event", G_CALLBACK(OnConfigureGD), this); - g_signal_connect(G_OBJECT(window), "scroll-event", G_CALLBACK(OnScroll), this); - - gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(Console.window)); -#if !GTK_CHECK_VERSION(3,14,0) - gtk_window_set_has_resize_grip(GTK_WINDOW(window), false); -#endif - } - else if (windowKind == W_Console) - { - render_widget = window; - } - assert(window); - assert(render_widget); - // Override gtk's default to match name/class of the XLib windows - gtk_window_set_wmclass(GTK_WINDOW(window), C4ENGINENAME, C4ENGINENAME); - gtk_window_set_default_size(GTK_WINDOW(window), size->Wdt, size->Hgt); - - g_signal_connect(G_OBJECT(window), "delete-event", G_CALLBACK(OnDelete), this); - handlerDestroy = g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(OnDestroyStatic), this); - gtk_widget_add_events(GTK_WIDGET(window), GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_SCROLL_MASK); - - // TODO: It would be nice to support GDK_SCROLL_SMOOTH_MASK and - // smooth scrolling for scrolling in menus, however that should not - // change the scroll wheel behaviour ingame for zooming or - // inventory change. Note that when both GDK_SCROLL_MASK and - // GDK_SMOOTH_SCROLL_MASK are enabled, both type of scroll events - // are reported, so one needs to make sure to not double-process them. - // It would be nice to have smooth scrolling also e.g. for zooming - // ingame, but it probably requires the notion of smooth scrolling - // other parts of the engine as well. -#ifdef GDK_WINDOWING_X11 - GdkScreen * scr = gtk_widget_get_screen(GTK_WIDGET(render_widget)); - Display * const dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default()); - XVisualInfo *vis_info = glXGetVisualFromFBConfig(dpy, Info); - assert(vis_info); - GdkVisual * vis = gdk_x11_screen_lookup_visual(scr, vis_info->visualid); - XFree(vis_info); - gtk_widget_set_visual(GTK_WIDGET(render_widget),vis); -#endif - gtk_widget_show_all(GTK_WIDGET(window)); - -// XVisualInfo vitmpl; int blub; -// vitmpl.visual = gdk_x11_visual_get_xvisual(gtk_widget_get_visual(window)); -// vitmpl.visualid = XVisualIDFromVisual(vitmpl.visual); -// Info = XGetVisualInfo(dpy, VisualIDMask, &vitmpl, &blub); - -// printf("%p\n", gtk_widget_get_visual(render_widget)); -// Info = gdk_x11_visual_get_xvisual(gtk_widget_get_visual(render_widget)); - - // Default icon has been set right after gtk_init(), - // so we don't need to take care about setting the icon here. - - SetTitle(Title); - - // Wait until window is mapped to get the window's XID - gtk_widget_show_now(GTK_WIDGET(window)); - GdkWindow* render_gdk_wnd; - if (GTK_IS_LAYOUT(render_widget)) - render_gdk_wnd = gtk_layout_get_bin_window(GTK_LAYOUT(render_widget)); - else - render_gdk_wnd = gtk_widget_get_window(GTK_WIDGET(render_widget)); - -#ifdef GDK_WINDOWING_X11 - renderwnd = GDK_WINDOW_XID(render_gdk_wnd); -#elif defined(GDK_WINDOWING_WIN32) - renderwnd = reinterpret_cast(gdk_win32_window_get_handle(render_gdk_wnd)); -#endif - // Make sure the window is shown and ready to be rendered into, - // this avoids an async X error. - gdk_flush(); - - if (windowKind == W_Fullscreen) - gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(render_widget)), - gdk_cursor_new_for_display(gdk_display_get_default(), GDK_BLANK_CURSOR)); - return this; -} - -bool C4Window::ReInit(C4AbstractApp* pApp) -{ - // Check whether multisampling settings was changed. If not then we - // don't need to ReInit anything. -#ifdef GDK_WINDOWING_X11 - int value; - Display * const dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default()); - glXGetFBConfigAttrib(dpy, Info, GLX_SAMPLES, &value); - if(value == Config.Graphics.MultiSampling) return true; - - // Check whether we have a visual with the requested number of samples - GLXFBConfig new_info; - if(!FindFBConfig(Config.Graphics.MultiSampling, &new_info)) return false; - - GdkScreen * scr = gtk_widget_get_screen(GTK_WIDGET(render_widget)); - XVisualInfo *vis_info = glXGetVisualFromFBConfig(dpy, new_info); - assert(vis_info); - GdkVisual * vis = gdk_x11_screen_lookup_visual(scr, vis_info->visualid); - XFree(vis_info); - - // Un- and re-realizing the render_widget does not work, the window - // remains hidden afterwards. So we re-create it from scratch. - gtk_widget_destroy(GTK_WIDGET(render_widget)); - render_widget = gtk_drawing_area_new(); -#if !GTK_CHECK_VERSION(3,10,0) - gtk_widget_set_double_buffered (GTK_WIDGET(render_widget), false); -#endif - g_object_set(G_OBJECT(render_widget), "can-focus", TRUE, NULL); - - gtk_widget_set_visual(GTK_WIDGET(render_widget),vis); - - Info = new_info; - - // Wait until window is mapped to get the window's XID - gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(render_widget)); - gtk_widget_show_now(GTK_WIDGET(render_widget)); - - if (GTK_IS_LAYOUT(render_widget)) - { - GdkWindow* bin_wnd = gtk_layout_get_bin_window(GTK_LAYOUT(render_widget)); - renderwnd = GDK_WINDOW_XID(bin_wnd); - } - else - { - GdkWindow* render_wnd = gtk_widget_get_window(GTK_WIDGET(render_widget)); - renderwnd = GDK_WINDOW_XID(render_wnd); - } - - gdk_flush(); - gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(render_widget)), - gdk_cursor_new_for_display(gdk_display_get_default(), GDK_BLANK_CURSOR)); - return true; -#endif -} - -void C4Window::Clear() -{ - if (window != NULL) - { - g_signal_handler_disconnect(window, handlerDestroy); - gtk_widget_destroy(GTK_WIDGET(window)); - handlerDestroy = 0; - } - - // Avoid that the base class tries to free these - renderwnd = 0; - - window = NULL; - Active = false; - - Info = 0; -} - -void C4Window::SetSize(unsigned int width, unsigned int height) -{ - gtk_window_resize(GTK_WINDOW(window), width, height); -} - -bool C4Window::GetSize(C4Rect * r) -{ - r->x = 0; r->y = 0; - gtk_window_get_size(GTK_WINDOW(window), &r->Wdt, &r->Hgt); - return true; -} - -void C4Window::SetTitle(char const * Title) -{ - gtk_window_set_title(GTK_WINDOW(window), Title); -} - -void C4Window::RequestUpdate() -{ - // just invoke directly - PerformUpdate(); -} diff --git a/src/platform/PlatformAbstraction.cpp b/src/platform/PlatformAbstraction.cpp index de5bbfa4b..7078ae8e3 100644 --- a/src/platform/PlatformAbstraction.cpp +++ b/src/platform/PlatformAbstraction.cpp @@ -62,42 +62,7 @@ bool EraseItemSafe(const char *szFilename) return false; } -#ifdef USE_GTK -#include -bool OpenURL(const char *szURL) -{ - GError *error = 0; - if (gtk_show_uri(NULL, szURL, GDK_CURRENT_TIME, &error)) - return true; - if (error != NULL) - { - fprintf (stderr, "Unable to open URL: %s\n", error->message); - g_error_free (error); - } - const char * argv[][3] = - { - { "xdg-open", szURL, 0 }, - { "sensible-browser", szURL, 0 }, - { "firefox", szURL, 0 }, - { "mozilla", szURL, 0 }, - { "konqueror", szURL, 0 }, - { "epiphany", szURL, 0 }, - { 0, 0, 0 } - }; - for (int i = 0; argv[i][0]; ++i) - { - error = 0; - if (g_spawn_async (g_get_home_dir(), const_cast(argv[i]), 0, G_SPAWN_SEARCH_PATH, 0, 0, 0, &error)) - return true; - else - { - fprintf(stderr, "%s\n", error->message); - g_error_free (error); - } - } - return false; -} -#elif defined(WITH_QT_EDITOR) +#if defined(WITH_QT_EDITOR) #undef LineFeed #include #include diff --git a/src/platform/PlatformAbstraction.h b/src/platform/PlatformAbstraction.h index 1ec175ced..0479f20ef 100644 --- a/src/platform/PlatformAbstraction.h +++ b/src/platform/PlatformAbstraction.h @@ -24,7 +24,7 @@ #include #endif // HAVE_CONFIG_H -#if defined(USE_WIN32_WINDOWS) || (defined(_WIN32) && defined(USE_GTK)) +#if defined(USE_WIN32_WINDOWS) #define USE_WGL #endif