[geany/geany] 05e19b: Merge pull request #419 from techee/osx-integration
Colomban Wendling
git-noreply at xxxxx
Wed Mar 4 13:08:11 UTC 2015
Branch: refs/heads/master
Author: Colomban Wendling <ban at herbesfolles.org>
Committer: Colomban Wendling <ban at herbesfolles.org>
Date: Wed, 04 Mar 2015 13:08:11 UTC
Commit: 05e19be0a3c83d169217ad6708e56eeed286e30c
https://github.com/geany/geany/commit/05e19be0a3c83d169217ad6708e56eeed286e30c
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).
More information about the Commits
mailing list