Branch: refs/heads/master Author: Colomban Wendling ban@herbesfolles.org Committer: Colomban Wendling ban@herbesfolles.org Date: Wed, 04 Mar 2015 13:08:11 UTC Commit: 05e19be0a3c83d169217ad6708e56eeed286e30c https://github.com/geany/geany/commit/05e19be0a3c83d169217ad6708e56eeed286e3...
Log Message: ----------- Merge pull request #419 from techee/osx-integration
OS X integration
Modified Paths: -------------- configure.ac m4/geany-mac-integration.m4 scintilla/gtk/ScintillaGTK.cxx src/Makefile.am src/keybindings.c src/main.c src/notebook.c src/osx.c src/osx.h src/plugins.c src/templates.c src/ui_utils.c src/utils.c src/utils.h wscript
Modified: configure.ac 1 lines changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -105,6 +105,7 @@ GEANY_CHECK_MINGW
GEANY_CHECK_SOCKET GEANY_CHECK_VTE +GEANY_CHECK_MAC_INTEGRATION GEANY_CHECK_THE_FORCE dnl hehe
# i18n
Modified: m4/geany-mac-integration.m4 18 lines changed, 18 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,18 @@ +dnl GEANY_CHECK_MAC_INTEGRATION +dnl Check for gtk-mac-integration to enable improved OS X integration +dnl +AC_DEFUN([GEANY_CHECK_MAC_INTEGRATION], +[ + AC_ARG_ENABLE([mac-integration], + [AS_HELP_STRING([--enable-mac-integration], + [use gtk-mac-integration to enable improved OS X integration [default=no]])], + [geany_enable_mac_integration="$enableval"], + [geany_enable_mac_integration="no"]) + + AS_IF([test "x$geany_enable_mac_integration" = "xyes"], + [ + AS_IF([test "x$enable_gtk3" = xyes], + [PKG_CHECK_MODULES(MAC_INTEGRATION, gtk-mac-integration-gtk3)], + [PKG_CHECK_MODULES(MAC_INTEGRATION, gtk-mac-integration-gtk2)]) + ]) +])
Modified: scintilla/gtk/ScintillaGTK.cxx 7 lines changed, 4 insertions(+), 3 deletions(-) =================================================================== @@ -1988,10 +1988,11 @@ gint ScintillaGTK::ScrollEvent(GtkWidget *widget, GdkEventScroll *event) { // Compute amount and direction to scroll (even tho on win32 there is // intensity of scrolling info in the native message, gtk doesn't // support this so we simulate similarly adaptive scrolling) - // Note that this is disabled on OS X (Darwin) where the X11 server already has - // and adaptive scrolling algorithm that fights with this one + // Note that this is disabled on OS X (Darwin) with the X11 backend + // where the X11 server already has an adaptive scrolling algorithm + // that fights with this one int cLineScroll; -#if defined(__MWERKS__) || defined(__APPLE_CPP__) || defined(__APPLE_CC__) +#if defined(__APPLE__) && !defined(GDK_WINDOWING_QUARTZ) cLineScroll = sciThis->linesPerScroll; if (cLineScroll == 0) cLineScroll = 4;
Modified: src/Makefile.am 4 lines changed, 3 insertions(+), 1 deletions(-) =================================================================== @@ -38,6 +38,7 @@ SRCS = \ msgwindow.c msgwindow.h \ navqueue.c navqueue.h \ notebook.c notebook.h \ + osx.c osx.h \ plugins.c plugins.h \ pluginutils.c pluginutils.h \ prefix.c prefix.h \ @@ -89,7 +90,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir) \ -I$(top_srcdir)/scintilla/include \ -I$(top_srcdir)/tagmanager/src \ - @GTK_CFLAGS@ @GTHREAD_CFLAGS@ + @GTK_CFLAGS@ @GTHREAD_CFLAGS@ $(MAC_INTEGRATION_CFLAGS)
# tell automake we have a C++ file so it uses the C++ linker we need for Scintilla nodist_EXTRA_geany_SOURCES = dummy.cxx @@ -142,6 +143,7 @@ geany_LDADD = \ $(top_builddir)/tagmanager/src/libtagmanager.a \ @GTK_LIBS@ \ @GTHREAD_LIBS@ \ + $(MAC_INTEGRATION_LIBS) \ $(INTLLIBS)
AM_CFLAGS = -DGEANY_DATADIR=""$(datadir)"" \
Modified: src/keybindings.c 28 lines changed, 1 insertions(+), 27 deletions(-) =================================================================== @@ -1101,23 +1101,6 @@ static gboolean check_menu_key(GeanyDocument *doc, guint keyval, guint state, gu
#ifdef HAVE_VTE -static gboolean on_menu_expose_event(GtkWidget *widget, GdkEventExpose *event, - gpointer user_data) -{ - if (!gtk_widget_get_sensitive(widget)) - gtk_widget_set_sensitive(GTK_WIDGET(widget), TRUE); - return FALSE; -} - - -#if GTK_CHECK_VERSION(3, 0, 0) -static gboolean on_menu_draw(GtkWidget *widget, cairo_t *cr, gpointer user_data) -{ - return on_menu_expose_event(widget, NULL, user_data); -} -#endif - - static gboolean set_sensitive(gpointer widget) { gtk_widget_set_sensitive(GTK_WIDGET(widget), TRUE); @@ -1158,16 +1141,7 @@ static gboolean check_vte(GdkModifierType state, guint keyval) * Note: maybe there's a better way of doing this ;-) */ widget = ui_lookup_widget(main_widgets.window, "menubar1"); gtk_widget_set_sensitive(widget, FALSE); - { - /* make the menubar sensitive before it is redrawn */ - static gboolean connected = FALSE; - if (!connected) -#if GTK_CHECK_VERSION(3, 0, 0) - g_signal_connect(widget, "draw", G_CALLBACK(on_menu_draw), NULL); -#else - g_signal_connect(widget, "expose-event", G_CALLBACK(on_menu_expose_event), NULL); -#endif - } + g_idle_add_full(G_PRIORITY_HIGH, set_sensitive, widget, NULL);
widget = main_widgets.editor_menu; gtk_widget_set_sensitive(widget, FALSE);
Modified: src/main.c 67 lines changed, 20 insertions(+), 47 deletions(-) =================================================================== @@ -62,6 +62,7 @@ #include "utils.h" #include "vte.h" #include "win32.h" +#include "osx.h"
#include "gtkcompat.h"
@@ -224,16 +225,7 @@ static void apply_settings(void) static void main_init(void) { /* add our icon path in case we aren't installed in the system prefix */ - gchar *path; -#ifdef G_OS_WIN32 - gchar *install_dir = win32_get_installation_dir(); - path = g_build_filename(install_dir, "share", "icons", NULL); - g_free(install_dir); -#else - path = g_build_filename(GEANY_DATADIR, "icons", NULL); -#endif - gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(), path); - g_free(path); + gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(), utils_resource_dir(RESOURCE_DIR_ICON));
/* inits */ ui_init_stock_items(); @@ -274,6 +266,9 @@ static void main_init(void)
ui_widgets.toolbar_menu = create_toolbar_popup_menu1(); ui_init(); +#ifdef MAC_INTEGRATION + osx_ui_init(); +#endif
/* set widget names for matching with .gtkrc-2.0 */ gtk_widget_set_name(main_widgets.window, "GeanyMainWindow"); @@ -400,30 +395,9 @@ static void change_working_directory_on_windows(void)
static void setup_paths(void) { - gchar *data_dir; - gchar *doc_dir; - - /* set paths */ -#ifdef G_OS_WIN32 - /* use the installation directory(the one where geany.exe is located) as the base for the - * documentation and data files */ - gchar *install_dir = win32_get_installation_dir(); - - data_dir = g_build_filename(install_dir, "data", NULL); /* e.g. C:\Program Files\geany\data */ - doc_dir = g_build_filename(install_dir, "doc", NULL); - - g_free(install_dir); -#else - data_dir = g_build_filename(GEANY_DATADIR, "geany", NULL); /* e.g. /usr/share/geany */ - doc_dir = g_build_filename(GEANY_DOCDIR, "html", NULL); -#endif - /* convert path names to locale encoding */ - app->datadir = utils_get_locale_from_utf8(data_dir); - app->docdir = utils_get_locale_from_utf8(doc_dir); - - g_free(data_dir); - g_free(doc_dir); + app->datadir = utils_get_locale_from_utf8(utils_resource_dir(RESOURCE_DIR_DATA)); + app->docdir = utils_get_locale_from_utf8(utils_resource_dir(RESOURCE_DIR_DOC)); }
@@ -473,26 +447,15 @@ gboolean main_is_realized(void) **/ void main_locale_init(const gchar *locale_dir, const gchar *package) { - gchar *l_locale_dir = NULL; - #ifdef HAVE_LOCALE_H setlocale(LC_ALL, ""); #endif
#ifdef G_OS_WIN32 - { - gchar *install_dir = win32_get_installation_dir(); - /* e.g. C:\Program Files\geany\lib\locale */ - l_locale_dir = g_build_filename(install_dir, "share", "locale", NULL); - g_free(install_dir); - } -#else - l_locale_dir = g_strdup(locale_dir); + locale_dir = utils_resource_dir(RESOURCE_DIR_LOCALE); #endif - - (void) bindtextdomain(package, l_locale_dir); + (void) bindtextdomain(package, locale_dir); (void) bind_textdomain_codeset(package, "UTF-8"); - g_free(l_locale_dir); }
@@ -647,6 +610,11 @@ static void parse_command_line_options(gint *argc, gchar ***argv) g_printerr("Geany: cannot open display\n"); exit(1); } + +#ifdef MAC_INTEGRATION + /* Create GtkosxApplication singleton - should be created shortly after gtk_init() */ + gtkosx_application_get(); +#endif }
@@ -1059,7 +1027,7 @@ gint main(gint argc, gchar **argv) setup_gtk2_styles(); #endif #ifdef ENABLE_NLS - main_locale_init(GEANY_LOCALEDIR, GETTEXT_PACKAGE); + main_locale_init(utils_resource_dir(RESOURCE_DIR_LOCALE), GETTEXT_PACKAGE); #endif parse_command_line_options(&argc, &argv);
@@ -1233,6 +1201,11 @@ gint main(gint argc, gchar **argv) * tell other components, mainly plugins, that startup is complete */ g_idle_add_full(G_PRIORITY_LOW, send_startup_complete, NULL, NULL);
+#ifdef MAC_INTEGRATION + /* OS X application ready - has to be called before entering main loop */ + gtkosx_application_ready(gtkosx_application_get()); +#endif + gtk_main(); return 0; }
Modified: src/notebook.c 23 lines changed, 4 insertions(+), 19 deletions(-) =================================================================== @@ -419,29 +419,14 @@ static void tab_bar_menu_activate_cb(GtkMenuItem *menuitem, gpointer data)
static void on_open_in_new_window_activate(GtkMenuItem *menuitem, gpointer user_data) { - gchar *geany_path; GeanyDocument *doc = user_data; + gchar *doc_path;
g_return_if_fail(doc->is_valid);
- geany_path = g_find_program_in_path("geany"); - - if (geany_path) - { - gchar *doc_path = utils_get_locale_from_utf8(doc->file_name); - gchar *argv[] = {geany_path, "-i", doc_path, NULL}; - GError *err = NULL; - - if (!utils_spawn_async(NULL, argv, NULL, 0, NULL, NULL, NULL, &err)) - { - g_printerr("Unable to open new window: %s", err->message); - g_error_free(err); - } - g_free(doc_path); - g_free(geany_path); - } - else - g_printerr("Unable to find 'geany'"); + doc_path = utils_get_locale_from_utf8(doc->file_name); + utils_start_new_geany_instance(doc_path); + g_free(doc_path); }
Modified: src/osx.c 131 lines changed, 131 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,131 @@ +/* + * osx.c - this file is part of Geany, a fast and lightweight IDE + * + * Copyright 2015 Jiri Techet <techet(at)gmail(dot)com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef MAC_INTEGRATION + +#include "osx.h" + +#include "utils.h" +#include "ui_utils.h" +#include "main.h" + + +static gboolean app_block_termination_cb(GtkosxApplication *app, gpointer data) +{ + return !main_quit(); +} + + +/* For some reason osx doesn't like when the NSApplicationOpenFile handler blocks for + * a long time which may be caused by the project_ask_close() below. Finish the + * NSApplicationOpenFile handler immediately and perform the potentially blocking + * code on idle in this function. */ +static gboolean open_project_idle(gchar *locale_path) +{ + gchar *utf8_path; + + utf8_path = utils_get_utf8_from_locale(locale_path); + if (app->project == NULL || + (g_strcmp0(utf8_path, app->project->file_name) != 0 && project_ask_close())) + project_load_file_with_session(locale_path); + g_free(utf8_path); + g_free(locale_path); + return FALSE; +} + + +static gboolean app_open_file_cb(GtkosxApplication *osx_app, gchar *path, gpointer user_data) +{ + gchar opened = FALSE; + gchar *locale_path; + + locale_path = utils_get_locale_from_utf8(path); + + if (!g_path_is_absolute(locale_path)) + { + gchar *cwd = g_get_current_dir(); + SETPTR(locale_path, g_build_filename(cwd, locale_path, NULL)); + g_free(cwd); + } + + if (g_str_has_suffix(path, ".geany")) + { + g_idle_add((GSourceFunc)open_project_idle, locale_path); + opened = TRUE; + } + else + { + opened = document_open_file(locale_path, FALSE, NULL, NULL) != NULL; + g_free(locale_path); + } + + return opened; +} + + +static void on_new_window(GtkMenuItem *menuitem, G_GNUC_UNUSED gpointer user_data) +{ + utils_start_new_geany_instance(NULL); +} + + +static void app_active_cb(GtkosxApplication* app, G_GNUC_UNUSED gpointer user_data) +{ + GeanyDocument *doc = document_get_current(); + if (doc) + document_check_disk_status(doc, TRUE); +} + + +void osx_ui_init(void) +{ + GtkWidget *item, *menu; + GtkosxApplication *osx_app = gtkosx_application_get(); + + item = ui_lookup_widget(main_widgets.window, "menubar1"); + gtk_widget_hide(item); + gtkosx_application_set_menu_bar(osx_app, GTK_MENU_SHELL(item)); + + item = ui_lookup_widget(main_widgets.window, "menu_quit1"); + gtk_widget_hide(item); + + item = ui_lookup_widget(main_widgets.window, "menu_info1"); + gtkosx_application_insert_app_menu_item(osx_app, item, 0); + + item = ui_lookup_widget(main_widgets.window, "menu_help1"); + gtkosx_application_set_help_menu(osx_app, GTK_MENU_ITEM(item)); + + gtkosx_application_set_use_quartz_accelerators(osx_app, FALSE); + + g_signal_connect(osx_app, "NSApplicationBlockTermination", + G_CALLBACK(app_block_termination_cb), NULL); + g_signal_connect(osx_app, "NSApplicationOpenFile", + G_CALLBACK(app_open_file_cb), NULL); + g_signal_connect(osx_app, "NSApplicationDidBecomeActive", + G_CALLBACK(app_active_cb), NULL); + + menu = gtk_menu_new(); + item = gtk_menu_item_new_with_label("New Window"); + g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(on_new_window), NULL); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + gtkosx_application_set_dock_menu(osx_app, GTK_MENU_SHELL(menu)); +} + +#endif /* MAC_INTEGRATION */
Modified: src/osx.h 36 lines changed, 36 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,36 @@ +/* + * osx.h - this file is part of Geany, a fast and lightweight IDE + * + * Copyright 2015 Jiri Techet <techet(at)gmail(dot)com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef GEANY_OSX_H +#define GEANY_OSX_H 1 + +#ifdef MAC_INTEGRATION + +#include <gtkosxapplication.h> + +G_BEGIN_DECLS + +void osx_ui_init(void); + +G_END_DECLS + +#endif /* MAC_INTEGRATION */ + +#endif /* GEANY_OSX_H */
Modified: src/plugins.c 12 lines changed, 1 insertions(+), 11 deletions(-) =================================================================== @@ -999,17 +999,7 @@ load_plugins_from_path(const gchar *path)
static gchar *get_plugin_path(void) { -#ifdef G_OS_WIN32 - gchar *path; - gchar *install_dir = win32_get_installation_dir(); - - path = g_build_filename(install_dir, "lib", NULL); - g_free(install_dir); - - return path; -#else - return g_build_filename(GEANY_LIBDIR, "geany", NULL); -#endif + return g_strdup(utils_resource_dir(RESOURCE_DIR_PLUGIN)); }
Modified: src/templates.c 81 lines changed, 27 insertions(+), 54 deletions(-) =================================================================== @@ -50,7 +50,8 @@
GeanyTemplatePrefs template_prefs;
-static GtkWidget *new_with_template_menu = NULL; /* submenu used for both file menu and toolbar */ +static GtkWidget *new_with_template_menu = NULL; +static GtkWidget *new_with_template_toolbar_menu = NULL;
/* TODO: implement custom insertion templates instead? */ static gchar *templates[GEANY_MAX_TEMPLATES]; @@ -257,7 +258,7 @@ static void add_file_item(const gchar *fname, GtkWidget *menu) }
-static gboolean add_custom_template_items(void) +static void populate_file_template_menu(GtkWidget *menu) { GSList *list = utils_get_config_files(GEANY_TEMPLATES_SUBDIR G_DIR_SEPARATOR_S "files"); GSList *node; @@ -266,40 +267,25 @@ static gboolean add_custom_template_items(void) { gchar *fname = node->data;
- add_file_item(fname, new_with_template_menu); + add_file_item(fname, menu); g_free(fname); } g_slist_free(list); - return list != NULL; }
static void create_file_template_menu(void) { - new_with_template_menu = gtk_menu_new(); - add_custom_template_items(); - - /* unless the file menu is showing, menu should be in the toolbar widget */ - geany_menu_button_action_set_menu(GEANY_MENU_BUTTON_ACTION( - toolbar_get_action_by_name("New")), new_with_template_menu); -} - + GtkWidget *item;
-static void on_file_menu_show(GtkWidget *item) -{ - geany_menu_button_action_set_menu( - GEANY_MENU_BUTTON_ACTION(toolbar_get_action_by_name("New")), NULL); + new_with_template_menu = gtk_menu_new(); item = ui_lookup_widget(main_widgets.window, "menu_new_with_template1"); gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), new_with_template_menu); -} -
-static void on_file_menu_hide(GtkWidget *item) -{ - item = ui_lookup_widget(main_widgets.window, "menu_new_with_template1"); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), NULL); - geany_menu_button_action_set_menu( - GEANY_MENU_BUTTON_ACTION(toolbar_get_action_by_name("New")), new_with_template_menu); + new_with_template_toolbar_menu = gtk_menu_new(); + g_object_ref(new_with_template_toolbar_menu); + geany_menu_button_action_set_menu(GEANY_MENU_BUTTON_ACTION(toolbar_get_action_by_name("New")), + new_with_template_toolbar_menu); }
@@ -328,23 +314,15 @@ void templates_init(void)
init_general_templates();
- create_file_template_menu(); - /* we hold our own ref for the menu as it has no parent whilst being moved */ - g_object_ref(new_with_template_menu); - - /* only connect signals to persistent objects once */ if (!init_done) { - GtkWidget *item; - /* reparent the template menu as needed */ - item = ui_lookup_widget(main_widgets.window, "file1"); - item = gtk_menu_item_get_submenu(GTK_MENU_ITEM(item)); - g_signal_connect(item, "show", G_CALLBACK(on_file_menu_show), NULL); - g_signal_connect(item, "hide", G_CALLBACK(on_file_menu_hide), NULL); - + create_file_template_menu(); g_signal_connect(geany_object, "document-save", G_CALLBACK(on_document_save), NULL); + init_done = TRUE; } - init_done = TRUE; + + populate_file_template_menu(new_with_template_menu); + populate_file_template_menu(new_with_template_toolbar_menu); }
@@ -527,30 +505,25 @@ gchar *templates_get_template_changelog(GeanyDocument *doc) }
-void templates_free_templates(void) +static void free_template_menu_items(GtkWidget *menu) { - gint i; GList *children, *item;
- /* disconnect the menu from the action widget, so destroying the items below doesn't - * trigger rebuilding of the menu on each item destroy */ - geany_menu_button_action_set_menu( - GEANY_MENU_BUTTON_ACTION(toolbar_get_action_by_name("New")), NULL); - - for (i = 0; i < GEANY_MAX_TEMPLATES; i++) - { - g_free(templates[i]); - } - /* destroy "New with template" sub menu items (in case we want to reload the templates) */ - children = gtk_container_get_children(GTK_CONTAINER(new_with_template_menu)); + children = gtk_container_get_children(GTK_CONTAINER(menu)); foreach_list(item, children) - { gtk_widget_destroy(GTK_WIDGET(item->data)); - } g_list_free(children); +}
- g_object_unref(new_with_template_menu); - new_with_template_menu = NULL; + +void templates_free_templates(void) +{ + gint i; + + for (i = 0; i < GEANY_MAX_TEMPLATES; i++) + g_free(templates[i]); + free_template_menu_items(new_with_template_menu); + free_template_menu_items(new_with_template_toolbar_menu); }
Modified: src/ui_utils.c 20 lines changed, 17 insertions(+), 3 deletions(-) =================================================================== @@ -50,6 +50,7 @@ #include "toolbar.h" #include "utils.h" #include "win32.h" +#include "osx.h"
#include "gtkcompat.h"
@@ -1307,6 +1308,19 @@ void ui_update_recent_project_menu(void) }
+/* Use instead of gtk_menu_reorder_child() to update the menubar properly on OS X */ +static void menu_reorder_child(GtkMenu *menu, GtkWidget *child, gint position) +{ + gtk_menu_reorder_child(menu, child, position); +#ifdef MAC_INTEGRATION + /* On OS X GtkMenuBar is kept in sync with the native OS X menubar using + * signals. Unfortunately gtk_menu_reorder_child() doesn't emit anything + * so we have to update the OS X menubar manually. */ + gtkosx_application_sync_menubar(gtkosx_application_get()); +#endif +} + + static void add_recent_file_menu_item(const gchar *utf8_filename, GeanyRecentFiles *grf, GtkWidget *menu) { GtkWidget *child = gtk_menu_item_new_with_label(utf8_filename); @@ -1320,7 +1334,7 @@ static void add_recent_file_menu_item(const gchar *utf8_filename, GeanyRecentFil * gtk_menu_shell_prepend() doesn't emit GtkContainer's "add" signal * which we need in GeanyMenubuttonAction */ gtk_container_add(GTK_CONTAINER(menu), child); - gtk_menu_reorder_child(GTK_MENU(menu), child, 0); + menu_reorder_child(GTK_MENU(menu), child, 0); } g_signal_connect(child, "activate", G_CALLBACK(grf->activate_cb), NULL); } @@ -1350,7 +1364,7 @@ static void recent_file_loaded(const gchar *utf8_filename, GeanyRecentFiles *grf item = g_list_find_custom(children, utf8_filename, (GCompareFunc) find_recent_file_item); /* either reorder or prepend a new one */ if (item) - gtk_menu_reorder_child(GTK_MENU(parents[i]), item->data, 0); + menu_reorder_child(GTK_MENU(parents[i]), item->data, 0); else add_recent_file_menu_item(utf8_filename, grf, parents[i]); g_list_free(children); @@ -2781,7 +2795,7 @@ void ui_menu_sort_by_label(GtkMenu *menu) pos = 0; foreach_list(node, list) { - gtk_menu_reorder_child(menu, node->data, pos); + menu_reorder_child(menu, node->data, pos); pos++; } g_list_free(list);
Modified: src/utils.c 92 lines changed, 92 insertions(+), 0 deletions(-) =================================================================== @@ -38,6 +38,7 @@ #include "templates.h" #include "ui_utils.h" #include "win32.h" +#include "osx.h"
#include <stdlib.h> #include <ctype.h> @@ -2088,3 +2089,94 @@ gchar *utils_get_user_config_dir(void) return g_build_filename(g_get_user_config_dir(), "geany", NULL); #endif } + + +static gboolean is_osx_bundle(void) +{ +#ifdef MAC_INTEGRATION + gchar *bundle_id = gtkosx_application_get_bundle_id(); + if (bundle_id) + { + g_free(bundle_id); + return TRUE; + } +#endif + return FALSE; +} + + +const gchar *utils_resource_dir(GeanyResourceDirType type) +{ + static const gchar *resdirs[RESOURCE_DIR_COUNT] = {NULL}; + + if (!resdirs[RESOURCE_DIR_DATA]) + { +#ifdef G_OS_WIN32 + gchar *prefix = win32_get_installation_dir(); + + resdirs[RESOURCE_DIR_DATA] = g_build_filename(prefix, "data", NULL); + resdirs[RESOURCE_DIR_ICON] = g_build_filename(prefix, "share", "icons", NULL); + resdirs[RESOURCE_DIR_DOC] = g_build_filename(prefix, "doc", NULL); + resdirs[RESOURCE_DIR_LOCALE] = g_build_filename(prefix, "share", "locale", NULL); + resdirs[RESOURCE_DIR_PLUGIN] = g_build_filename(prefix, "lib", NULL); + g_free(prefix); +#else + if (is_osx_bundle()) + { +# ifdef MAC_INTEGRATION + gchar *prefix = gtkosx_application_get_resource_path(); + + resdirs[RESOURCE_DIR_DATA] = g_build_filename(prefix, "share", "geany", NULL); + resdirs[RESOURCE_DIR_ICON] = g_build_filename(prefix, "share", "icons", NULL); + resdirs[RESOURCE_DIR_DOC] = g_build_filename(prefix, "share", "doc", "geany", "html", NULL); + resdirs[RESOURCE_DIR_LOCALE] = g_build_filename(prefix, "share", "locale", NULL); + resdirs[RESOURCE_DIR_PLUGIN] = g_build_filename(prefix, "lib", "geany", NULL); + g_free(prefix); +# endif + } + else + { + resdirs[RESOURCE_DIR_DATA] = g_build_filename(GEANY_DATADIR, "geany", NULL); + resdirs[RESOURCE_DIR_ICON] = g_build_filename(GEANY_DATADIR, "icons", NULL); + resdirs[RESOURCE_DIR_DOC] = g_build_filename(GEANY_DOCDIR, "html", NULL); + resdirs[RESOURCE_DIR_LOCALE] = g_build_filename(GEANY_LOCALEDIR, NULL); + resdirs[RESOURCE_DIR_PLUGIN] = g_build_filename(GEANY_LIBDIR, "geany", NULL); + } +#endif + } + + return resdirs[type]; +} + + +void utils_start_new_geany_instance(gchar *doc_path) +{ + gchar **argv; + const gchar *command = is_osx_bundle() ? "open" : "geany"; + gchar *exec_path = g_find_program_in_path(command); + + if (exec_path) + { + GError *err = NULL; + + if (is_osx_bundle()) + { + gchar *osx_argv[] = {exec_path, "-n", "-a", "Geany", doc_path, NULL}; + argv = osx_argv; + } + else + { + gchar *unix_argv[] = {exec_path, "-i", doc_path, NULL}; + argv = unix_argv; + } + + if (!utils_spawn_async(NULL, argv, NULL, 0, NULL, NULL, NULL, &err)) + { + g_printerr("Unable to open new window: %s", err->message); + g_error_free(err); + } + g_free(exec_path); + } + else + g_printerr("Unable to find 'geany'"); +}
Modified: src/utils.h 16 lines changed, 16 insertions(+), 0 deletions(-) =================================================================== @@ -200,6 +200,18 @@ const gchar *utils_find_open_xml_tag_pos(const gchar sel[], gint size);
#ifdef GEANY_PRIVATE
+typedef enum +{ + RESOURCE_DIR_DATA, + RESOURCE_DIR_ICON, + RESOURCE_DIR_DOC, + RESOURCE_DIR_LOCALE, + RESOURCE_DIR_PLUGIN, + + RESOURCE_DIR_COUNT +} GeanyResourceDirType; + + gint utils_get_line_endings(const gchar* buffer, gsize size);
gboolean utils_isbrace(gchar c, gboolean include_angles); @@ -294,6 +306,10 @@ gchar *utils_parse_and_format_build_date(const gchar *input);
gchar *utils_get_user_config_dir(void);
+const gchar *utils_resource_dir(GeanyResourceDirType type); + +void utils_start_new_geany_instance(gchar *doc_path); + #endif /* GEANY_PRIVATE */
G_END_DECLS
Modified: wscript 11 lines changed, 9 insertions(+), 2 deletions(-) =================================================================== @@ -131,7 +131,7 @@ geany_sources = set([ 'src/editor.c', 'src/encodings.c', 'src/filetypes.c', 'src/geanyentryaction.c', 'src/geanymenubuttonaction.c', 'src/geanyobject.c', 'src/geanywraplabel.c', 'src/highlighting.c', 'src/keybindings.c', - 'src/keyfile.c', 'src/log.c', 'src/main.c', 'src/msgwindow.c', 'src/navqueue.c', 'src/notebook.c', + 'src/keyfile.c', 'src/log.c', 'src/main.c', 'src/msgwindow.c', 'src/navqueue.c', 'src/notebook.c', 'src/osx.c', 'src/plugins.c', 'src/pluginutils.c', 'src/prefix.c', 'src/prefs.c', 'src/printing.c', 'src/project.c', 'src/sciwrappers.c', 'src/search.c', 'src/socket.c', 'src/stash.c', 'src/symbols.c', @@ -226,6 +226,10 @@ def configure(conf): conf.check_cfg(package='gio-2.0', uselib_store='GIO', args='--cflags --libs', mandatory=True) gtk_version = conf.check_cfg(modversion=gtk_package_name, uselib_store='GTK') or 'Unknown' conf.check_cfg(package='gthread-2.0', uselib_store='GTHREAD', args='--cflags --libs') + if conf.options.enable_mac_integration: + pkgname = 'gtk-mac-integration-gtk3' if conf.options.use_gtk3 else 'gtk-mac-integration-gtk2' + conf.check_cfg(package=pkgname, uselib_store='MAC_INTEGRATION', + mandatory=True, args='--cflags --libs') # remember GTK version for the build step conf.env['gtk_package_name'] = gtk_package_name conf.env['minimum_gtk_version'] = minimum_gtk_version @@ -347,6 +351,9 @@ def options(opt): opt.add_option('--enable-gtk3', action='store_true', default=False, help='compile with GTK3 support (experimental) [[default: No]', dest='use_gtk3') + opt.add_option('--enable-mac-integration', action='store_true', default=False, + help='use gtk-mac-integration to enable improved OS X integration [[default: No]', + dest='enable_mac_integration') opt.add_option('--disable-html-docs', action='store_true', default=False, help='do not generate HTML documentation using rst2html [[default: No]', dest='no_html_doc') @@ -441,7 +448,7 @@ def build(bld): source = geany_sources, includes = ['.', 'scintilla/include', 'tagmanager/src'], defines = ['G_LOG_DOMAIN="Geany"', 'GEANY_PRIVATE'], - uselib = ['GTK', 'GLIB', 'GMODULE', 'GIO', 'GTHREAD', 'WIN32', 'SUNOS_SOCKET', 'M'], + uselib = ['GTK', 'GLIB', 'GMODULE', 'GIO', 'GTHREAD', 'WIN32', 'MAC_INTEGRATION', 'SUNOS_SOCKET', 'M'], use = ['scintilla', 'ctags', 'tagmanager', 'mio'])
# geanyfunctions.h
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).