Merge pull request #419 from techee/osx-integration

OS X integration
This commit is contained in:
Colomban Wendling 2015-03-04 14:08:11 +01:00
commit 05e19be0a3
15 changed files with 381 additions and 168 deletions

View File

@ -105,6 +105,7 @@ GEANY_CHECK_MINGW
GEANY_CHECK_SOCKET
GEANY_CHECK_VTE
GEANY_CHECK_MAC_INTEGRATION
GEANY_CHECK_THE_FORCE dnl hehe
# i18n

View File

@ -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)])
])
])

View File

@ -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;

View File

@ -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)"\" \

View File

@ -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);

View File

@ -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;
}

View File

@ -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);
}

131
src/osx.c Normal file
View File

@ -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 */

36
src/osx.h Normal file
View File

@ -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 */

View File

@ -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));
}

View File

@ -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)
{
GtkWidget *item;
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);
}
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);
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)
}
static void free_template_menu_items(GtkWidget *menu)
{
GList *children, *item;
children = gtk_container_get_children(GTK_CONTAINER(menu));
foreach_list(item, children)
gtk_widget_destroy(GTK_WIDGET(item->data));
g_list_free(children);
}
void templates_free_templates(void)
{
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));
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;
free_template_menu_items(new_with_template_menu);
free_template_menu_items(new_with_template_toolbar_menu);
}

View File

@ -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);

View File

@ -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'");
}

View File

@ -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

11
wscript
View File

@ -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