spk121 / guile-gi

Bindings for GObject Introspection and libgirepository for Guile
GNU General Public License v3.0
58 stars 7 forks source link

Using Gio Actions #119

Closed LordYuuma closed 2 years ago

LordYuuma commented 2 years ago

For context, old Gtk menus have been deprecated in favor of GMenuModel et al. In order to make these MenuModels work, some glue is needed in the form of GActions. However, Guile-GI seems to handle even relatively simple actions wrongly; the following MWE is perhaps overkill for a "Hello world", but aims to demonstrate that (at least string-typed) actions do not make the button clickable.

/* my-app.c */
#include <glib.h>
#include <gtk/gtk.h>

static void
on_hello_activate (GAction *action,
                  GVariant *param)
{
  g_print ("Hello %s\n", g_variant_get_string (param, NULL));
}

static void
on_app_activate (GApplication *app)
{
  /* Alternatively: GAction *action = g_simple_action_new ("hello", G_VARIANT_TYPE_STRING); */
  GAction *action = g_simple_action_new ("hello", g_variant_type_new ("s"));
  g_signal_connect (action, "activate", G_CALLBACK (on_hello_activate), NULL);
  g_action_map_add_action (G_ACTION_MAP (app), action);

  GtkWidget *window = gtk_application_window_new (GTK_APPLICATION (app));
  gtk_window_present (GTK_WINDOW (window));

  GtkWidget *button = gtk_button_new_with_label ("Hello");
  gtk_actionable_set_action_name (GTK_ACTIONABLE (button), "app.hello");
  gtk_actionable_set_action_target_value (GTK_ACTIONABLE (button),
                                          g_variant_new_string ("world"));
  gtk_window_set_child (GTK_WINDOW (window), button);
}

int
main (int argc, char *argv[])
{
  GtkApplication *app =
    gtk_application_new ("com.example.App", G_APPLICATION_FLAGS_NONE);
  g_signal_connect (app, "activate", G_CALLBACK (on_app_activate), NULL);
  return g_application_run (G_APPLICATION (app), argc, argv);
}
;; my-app.scm
(use-modules (gi) (gi util))
(push-duplicate-handler! 'merge-generics)
(use-typelibs ("GLib" "2.0")
              ("Gio" "2.0")
              ("GdkPixbuf" "2.0")
              ("Gtk" "4.0"))

(define (hello _action param)
  (format #t "Hello ~a~%" (get-string param)))

(define (on-app-activate app)
  (define action (make <GSimpleAction> #:name "hello"
                       #:parameter-type (variant-type:new "s")))
  (connect action activate hello)
  (define window (application-window:new app))
  (present window)

  (define button (make <GtkButton> #:label "Hello"))
  (set-action-name button "app.hello")
  (set-action-target-value button (variant:new-string "world"))
  (set-child window button))

(let ((app (make <GtkApplication> #:application-id "com.example.App")))
  (connect app activate on-app-activate)
  (run app))
spk121 commented 2 years ago

One of the differences between your C and Scheme examples is adding the action to the action map. By inserting

(add-action app action)

after your (connect action ... line, it seems to work as far as I can tell.

LordYuuma commented 2 years ago

Thanks, that indeed does the trick. Now for my personal use-case, I only need to find out how to make that string nullable, but that appears to be a problem with both the C and Scheme versions, so not a bug in Guile-GI afaict.