commit
05e19be0a3
@ -105,6 +105,7 @@ GEANY_CHECK_MINGW
|
||||
|
||||
GEANY_CHECK_SOCKET
|
||||
GEANY_CHECK_VTE
|
||||
GEANY_CHECK_MAC_INTEGRATION
|
||||
GEANY_CHECK_THE_FORCE dnl hehe
|
||||
|
||||
# i18n
|
||||
|
18
m4/geany-mac-integration.m4
Normal file
18
m4/geany-mac-integration.m4
Normal 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)])
|
||||
])
|
||||
])
|
@ -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;
|
||||
|
@ -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)"\" \
|
||||
|
@ -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);
|
||||
|
67
src/main.c
67
src/main.c
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
doc_path = utils_get_locale_from_utf8(doc->file_name);
|
||||
utils_start_new_geany_instance(doc_path);
|
||||
g_free(doc_path);
|
||||
g_free(geany_path);
|
||||
}
|
||||
else
|
||||
g_printerr("Unable to find 'geany'");
|
||||
}
|
||||
|
||||
|
||||
|
131
src/osx.c
Normal file
131
src/osx.c
Normal 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
36
src/osx.h
Normal 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 */
|
@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
@ -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,25 +314,17 @@ 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;
|
||||
}
|
||||
|
||||
populate_file_template_menu(new_with_template_menu);
|
||||
populate_file_template_menu(new_with_template_toolbar_menu);
|
||||
}
|
||||
|
||||
|
||||
/* indent is used to make some whitespace between comment char and real start of the line
|
||||
* e.g. indent = 8 prints " * here comes the text of the line"
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
92
src/utils.c
92
src/utils.c
@ -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'");
|
||||
}
|
||||
|
16
src/utils.h
16
src/utils.h
@ -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
11
wscript
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user