From 1d64d5211fc7c660d9facbc5c927bbce32029863 Mon Sep 17 00:00:00 2001 From: Matthew Brush Date: Sun, 19 Oct 2014 13:49:58 -0700 Subject: [PATCH] Replace dynamic exports with codegen for GtkBuilder callbacks This prevents having to export those callbacks and put them in the global namespace. Also, use inline shell script in Makefile.am instead of a Python script which should be more portable (by default) and gets rid of the helper script. --- m4/geany-lib.m4 | 23 ++----- scripts/dynamicsymbols.py | 73 --------------------- src/Makefile.am | 24 +++++-- src/callbacks.c | 2 + src/callbacks.h | 3 + src/dynamicsymbols.list | 161 ---------------------------------------------- src/signalconn.c.in | 32 +++++++++ src/ui_utils.c | 2 +- 8 files changed, 61 insertions(+), 259 deletions(-) delete mode 100755 scripts/dynamicsymbols.py delete mode 100644 src/dynamicsymbols.list create mode 100644 src/signalconn.c.in diff --git a/m4/geany-lib.m4 b/m4/geany-lib.m4 index 90323342d..3e63b09b5 100644 --- a/m4/geany-lib.m4 +++ b/m4/geany-lib.m4 @@ -24,25 +24,14 @@ dnl `__attribute__((visibility(...)))` extension and use it if so. ]) CFLAGS="${libgeany_backup_cflags}" -dnl Try and see if we can use our list of dynamically exported symbols with -dnl the linker and use it if so. - AC_MSG_CHECKING([whether linker supports --dynamic-list]) - libgeany_backup_ldflags=$LDFLAGS - LDFLAGS=-Wl,--dynamic-list="${srcdir}/src/dynamicsymbols.list" - AC_LINK_IFELSE([ - AC_LANG_PROGRAM([], []) - ], [ - LIBGEANY_LIBS="-Wl,--dynamic-list=\"\$(top_srcdir)/src/dynamicsymbols.list\"" - AC_MSG_RESULT([yes]) - ], [ - LIBGEANY_LIBS="" - AC_MSG_RESULT([no]) - ]) - LDFLAGS="${libgeany_backup_ldflags}" - - LIBGEANY_LIBS="${LIBGEANY_LIBS} -version-info ${libgeany_current}:${libgeany_revision}:${libgeany_age}" + LIBGEANY_LIBS="-version-info ${libgeany_current}:${libgeany_revision}:${libgeany_age}" AC_SUBST([LIBGEANY_CFLAGS]) AC_SUBST([LIBGEANY_LIBS]) +dnl Check for utilities needed to do codegen + AC_PATH_PROG([SORT], [sort], [ + AC_MSG_ERROR([The 'sort' utility is required, is it installed?])]) + AC_PATH_PROG([UNIQ], [uniq], [ + AC_MSG_ERROR([The 'uniq' utility is required, is it installed?])]) ]) diff --git a/scripts/dynamicsymbols.py b/scripts/dynamicsymbols.py deleted file mode 100755 index 6a8b4fd99..000000000 --- a/scripts/dynamicsymbols.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env python - -""" -Script to parse GtkBuilder XML file for signal handler references and list -them in a linker file for which symbols to dynamically export. -""" - -import optparse -import os -import re -import sys -from xml.etree import ElementTree as ET - -def find_handlers(xml_filename, excludes=[]): - def is_excluded(name, excludes): - for exclude in excludes: - m = re.match(exclude, name) - if m: - return True - return False - - tree = ET.parse(xml_filename) - root = tree.getroot() - handlers = [] - signals = root.findall(".//signal") - - for signal in signals: - handler = signal.attrib["handler"] - if not is_excluded(handler, excludes): - handlers.append(handler) - - return sorted(handlers) - -def write_dynamic_list(handlers, output_file): - output_file.write("""\ -/* This file was auto-generated by the `%s' script, do not edit. */ -{ -""" % os.path.basename(__file__)) - for handler in handlers: - output_file.write("\t%s;\n" % handler) - output_file.write("};\n") - -def main(args): - p = optparse.OptionParser(usage="%prog [-o FILE] XMLFILE") - p.add_option("-o", "--output", metavar="FILE", dest="output_file", - default="-", help="write the output to this file (default `-' for stdin)") - - opts, args = p.parse_args(args) - - output_file = None - try: - if opts.output_file == "-": - output_file = sys.stdout - else: - output_file = open(opts.output_file, 'w') - - args = args[1:] - if len(args) == 0: - p.error("invalid XMLFILE argument, expecting a filename, got none") - elif len(args) > 1: - p.error("too many XMLFILE arguments, expecting a single filename") - - handlers = find_handlers(args[0], ["gtk_.+"]) - write_dynamic_list(handlers, output_file) - - finally: - if output_file is not None and output_file is not sys.stdout: - output_file.close() - - return 0 - -if __name__ == "__main__": - sys.exit(main(sys.argv)) diff --git a/src/Makefile.am b/src/Makefile.am index 636e636b8..78c5436ca 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,7 +11,7 @@ EXTRA_DIST = \ pluginprivate.h \ projectprivate.h \ makefile.win32 \ - $(top_srcdir)/src/dynamicsymbols.list + $(srcdir)/signalconn.c.in bin_PROGRAMS = geany lib_LTLIBRARIES = libgeany.la @@ -173,10 +173,20 @@ AM_CFLAGS = -DGEANY_DATADIR=\""$(datadir)"\" \ clean-local: -# Helper rule to rebuild the dynamicsymbols.list file when handlers are -# added to data/geany.glade. Run `make dynamic-symbols' from the src builddir. -$(top_srcdir)/src/dynamicsymbols.list: $(top_srcdir)/data/geany.glade - -python $(top_srcdir)/scripts/dynamicsymbols.py -o $@ $(top_srcdir)/data/geany.glade -dynamic-symbols: $(top_srcdir)/src/dynamicsymbols.list - endif + +callbacks.c: signalconn.c + +glade_file=$(top_srcdir)/data/geany.glade +template_file=$(srcdir)/signalconn.c.in + +signalconn.c: $(glade_file) $(template_file) + $(AM_V_GEN)( \ + echo '/* This file is auto-generated, do not edit. */' && \ + $(SED) -n '/@callback_map@/q;p' "$(template_file)" && \ + $(SED) -n 's/^.*handler="\([^"]\+\)".*$$/\tg_hash_table_insert(hash, "\1", G_CALLBACK(\1));/p' "$(glade_file)" \ + | $(SORT) | $(UNIQ) && \ + $(SED) -n '/@callback_map@/{:l;n;p;b l}' "$(template_file)" \ + ) > $@ || { $(RM) $@ && exit 1; } + +CLEANFILES = signalconn.c diff --git a/src/callbacks.c b/src/callbacks.c index 039f90305..4923050f2 100644 --- a/src/callbacks.c +++ b/src/callbacks.c @@ -1988,3 +1988,5 @@ GEANY_EXPORT_SYMBOL void on_detect_width_from_file_activate(GtkMenuItem *menuite ui_document_show_hide(doc); } } + +#include "signalconn.c" diff --git a/src/callbacks.h b/src/callbacks.h index de1879586..6017b1ed8 100644 --- a/src/callbacks.h +++ b/src/callbacks.h @@ -26,6 +26,9 @@ G_BEGIN_DECLS +/* Defined in auto-generated code in signalconn.c */ +void callbacks_connect(GtkBuilder *builder); + extern gboolean ignore_callback; void on_new1_activate(GtkMenuItem *menuitem, gpointer user_data); diff --git a/src/dynamicsymbols.list b/src/dynamicsymbols.list deleted file mode 100644 index d3117f0fd..000000000 --- a/src/dynamicsymbols.list +++ /dev/null @@ -1,161 +0,0 @@ -/* This file was auto-generated by the `dynamicsymbols.py' script, do not edit. */ -{ - on_button_customize_toolbar_clicked; - on_change_font1_activate; - on_clone1_activate; - on_close1_activate; - on_close_all1_activate; - on_close_other_documents1_activate; - on_comments_bsd_activate; - on_comments_changelog_activate; - on_comments_changelog_activate; - on_comments_fileheader_activate; - on_comments_fileheader_activate; - on_comments_function_activate; - on_comments_function_activate; - on_comments_gpl_activate; - on_comments_multiline_activate; - on_context_action1_activate; - on_copy1_activate; - on_copy1_activate; - on_copy_current_lines1_activate; - on_count_words1_activate; - on_cr_activate; - on_crlf_activate; - on_customize_toolbar1_activate; - on_cut1_activate; - on_cut1_activate; - on_cut_current_lines1_activate; - on_debug_messages1_activate; - on_delete1_activate; - on_delete1_activate; - on_delete_current_lines1_activate; - on_detect_type_from_file_activate; - on_detect_width_from_file_activate; - on_duplicate_line_or_selection1_activate; - on_edit1_activate; - on_escape_key_press_event; - on_file1_activate; - on_file_properties_activate; - on_find1_activate; - on_find_document_usage1_activate; - on_find_document_usage1_activate; - on_find_in_files1_activate; - on_find_next1_activate; - on_find_nextsel1_activate; - on_find_previous1_activate; - on_find_prevsel1_activate; - on_find_usage1_activate; - on_find_usage1_activate; - on_fullscreen1_toggled; - on_go_to_line_activate; - on_go_to_next_marker1_activate; - on_go_to_previous_marker1_activate; - on_goto_tag_declaration1; - on_goto_tag_definition1; - on_goto_tag_definition1; - on_help1_activate; - on_help_menu_item_bug_report_activate; - on_help_menu_item_donate_activate; - on_help_menu_item_wiki_activate; - on_help_shortcuts1_activate; - on_hide_toolbar1_activate; - on_indent_width_activate; - on_indent_width_activate; - on_indent_width_activate; - on_indent_width_activate; - on_indent_width_activate; - on_indent_width_activate; - on_indent_width_activate; - on_indent_width_activate; - on_info1_activate; - on_insert_alternative_white_space1_activate; - on_insert_alternative_white_space1_activate; - on_lf_activate; - on_line_breaking1_activate; - on_line_wrapping1_toggled; - on_load_tags1_activate; - on_mark_all1_activate; - on_markers_margin1_toggled; - on_menu_color_schemes_activate; - on_menu_comment_line1_activate; - on_menu_comments_bsd_activate; - on_menu_comments_gpl_activate; - on_menu_comments_multiline_activate; - on_menu_decrease_indent1_activate; - on_menu_fold_all1_activate; - on_menu_increase_indent1_activate; - on_menu_open_selected_file1_activate; - on_menu_open_selected_file1_activate; - on_menu_project1_activate; - on_menu_reload_configuration1_activate; - on_menu_remove_indicators1_activate; - on_menu_select_all1_activate; - on_menu_select_all1_activate; - on_menu_show_indentation_guides1_toggled; - on_menu_show_line_endings1_toggled; - on_menu_show_sidebar1_toggled; - on_menu_show_white_space1_toggled; - on_menu_toggle_all_additional_widgets1_activate; - on_menu_toggle_line_commentation1_activate; - on_menu_uncomment_line1_activate; - on_menu_unfold_all1_activate; - on_menu_write_unicode_bom1_toggled; - on_motion_event; - on_move_lines_down1_activate; - on_move_lines_up1_activate; - on_new1_activate; - on_next_message1_activate; - on_normal_size1_activate; - on_notebook1_switch_page_after; - on_open1_activate; - on_page_setup1_activate; - on_paste1_activate; - on_paste1_activate; - on_plugin_preferences1_activate; - on_preferences1_activate; - on_previous_message1_activate; - on_print1_activate; - on_project_close1_activate; - on_project_new1_activate; - on_project_open1_activate; - on_project_properties1_activate; - on_quit1_activate; - on_redo1_activate; - on_redo1_activate; - on_reflow_lines_block1_activate; - on_remove_markers1_activate; - on_replace1_activate; - on_replace_spaces_activate; - on_replace_tabs_activate; - on_reset_indentation1_activate; - on_save1_activate; - on_save_all1_activate; - on_save_as1_activate; - on_search1_activate; - on_select_current_lines1_activate; - on_select_current_paragraph1_activate; - on_send_selection_to_vte1_activate; - on_set_file_readonly1_toggled; - on_show_color_chooser1_activate; - on_show_line_numbers1_toggled; - on_show_messages_window1_toggled; - on_show_toolbar1_toggled; - on_smart_line_indent1_activate; - on_spaces1_activate; - on_strip_trailing_spaces1_activate; - on_tabs1_activate; - on_tabs_and_spaces1_activate; - on_toggle_case1_activate; - on_toolbutton_reload_clicked; - on_tv_notebook_switch_page; - on_tv_notebook_switch_page_after; - on_undo1_activate; - on_undo1_activate; - on_use_auto_indentation1_toggled; - on_website1_activate; - on_window_delete_event; - on_window_state_event; - on_zoom_in1_activate; - on_zoom_out1_activate; -}; diff --git a/src/signalconn.c.in b/src/signalconn.c.in new file mode 100644 index 000000000..d5983f0a4 --- /dev/null +++ b/src/signalconn.c.in @@ -0,0 +1,32 @@ + + +static void builder_connect_func(GtkBuilder *builder, GObject *object, + const gchar *signal_name, const gchar *handler_name, GObject *connect_obj, + GConnectFlags flags, gpointer user_data) +{ + GHashTable *hash = user_data; + GCallback callback; + + callback = g_hash_table_lookup(hash, handler_name); + g_return_if_fail(callback); + + if (connect_obj == NULL) + g_signal_connect_data(object, signal_name, callback, NULL, NULL, flags); + else + g_signal_connect_object(object, signal_name, callback, connect_obj, flags); +} + + +void callbacks_connect(GtkBuilder *builder) +{ + GHashTable *hash; + + g_return_if_fail(GTK_IS_BUILDER(builder)); + + hash = g_hash_table_new(g_str_hash, g_str_equal); + +@callback_map@ + + gtk_builder_connect_signals_full(builder, builder_connect_func, hash); + g_hash_table_destroy(hash); +} diff --git a/src/ui_utils.c b/src/ui_utils.c index 4f049451e..e9f548a06 100644 --- a/src/ui_utils.c +++ b/src/ui_utils.c @@ -2448,7 +2448,7 @@ void ui_init_builder(void) } g_free(interface_file); - gtk_builder_connect_signals(builder, NULL); + callbacks_connect(builder); edit_menu1 = GTK_WIDGET(gtk_builder_get_object(builder, "edit_menu1")); prefs_dialog = GTK_WIDGET(gtk_builder_get_object(builder, "prefs_dialog")); -- 2.11.4.GIT