MODULE test_actions ; (* m2-GTK4 test - actions, action maps, menus and accelerators. Creates app-scoped GSimpleActions, activates one and checks the handler ran, round-trips a stateful boolean action's state through a GVariant, builds a GMenu/GMenuModel, and instantiates a GtkApplicationWindow + GtkPopoverMenuBar. Requires a display. *) FROM Gio IMPORT g_application_run, g_application_quit; FROM GtkApplication IMPORT gtk_application_new; FROM GtkApplicationWindow IMPORT gtk_application_window_new, gtk_application_window_get_show_menubar, gtk_application_window_set_show_menubar; FROM GSimpleAction IMPORT g_simple_action_new, g_simple_action_new_stateful, g_simple_action_set_state; FROM GActionMap IMPORT g_action_map_add_action, g_action_map_lookup_action; FROM GAction IMPORT g_action_activate, g_action_get_state; FROM GMenu IMPORT g_menu_new, g_menu_append, g_menu_append_submenu; FROM GMenuModel IMPORT g_menu_model_get_n_items; FROM GtkPopoverMenuBar IMPORT gtk_popover_menu_bar_new_from_model, gtk_popover_menu_bar_get_menu_model; FROM GVariant IMPORT g_variant_new_boolean, g_variant_get_boolean, g_variant_unref; FROM GtkUtils IMPORT Connect, SetAccel; FROM SYSTEM IMPORT ADDRESS, ADR; FROM libc IMPORT printf; CONST AppId = "org.example.m2gtk4.TestActions"; VAR app: ADDRESS; passed: BOOLEAN; activated: INTEGER; PROCEDURE OnHello (action: ADDRESS; param: ADDRESS; data: ADDRESS); BEGIN INC(activated) END OnHello; PROCEDURE OnActivate (application: ADDRESS; data: ADDRESS); VAR window, helloAction, flagAction, menu, submenu, bar: ADDRESS; state: ADDRESS; ok: BOOLEAN; n: INTEGER; BEGIN ok := TRUE; activated := 0; (* --- app-scoped parameterless action --- *) helloAction := g_simple_action_new("hello", NIL); Connect(helloAction, "activate", ADR(OnHello), NIL); g_action_map_add_action(application, helloAction); IF g_action_map_lookup_action(application, "hello") # helloAction THEN printf("lookup_action wrong\n"); ok := FALSE END; g_action_activate(helloAction, NIL); IF activated # 1 THEN printf("activate did not fire\n"); ok := FALSE END; (* --- stateful boolean action, GVariant round-trip --- *) flagAction := g_simple_action_new_stateful("flag", NIL, g_variant_new_boolean(0)); g_action_map_add_action(application, flagAction); state := g_action_get_state(flagAction); IF g_variant_get_boolean(state) # 0 THEN printf("initial state wrong\n"); ok := FALSE END; g_variant_unref(state); g_simple_action_set_state(flagAction, g_variant_new_boolean(1)); state := g_action_get_state(flagAction); IF g_variant_get_boolean(state) # 1 THEN printf("updated state wrong\n"); ok := FALSE END; g_variant_unref(state); (* --- GMenu / GMenuModel --- *) submenu := g_menu_new(); g_menu_append(submenu, "Hello", "app.hello"); g_menu_append(submenu, "Flag", "app.flag"); menu := g_menu_new(); g_menu_append_submenu(menu, "Test", submenu); n := g_menu_model_get_n_items(menu); IF n # 1 THEN printf("menubar item count wrong: %d\n", n); ok := FALSE END; IF g_menu_model_get_n_items(submenu) # 2 THEN printf("submenu item count wrong\n"); ok := FALSE END; bar := gtk_popover_menu_bar_new_from_model(menu); IF (bar = NIL) OR (gtk_popover_menu_bar_get_menu_model(bar) # menu) THEN printf("popover menu bar wrong\n"); ok := FALSE END; (* --- GtkApplicationWindow + accelerators --- *) window := gtk_application_window_new(application); gtk_application_window_set_show_menubar(window, 0); IF gtk_application_window_get_show_menubar(window) # 0 THEN printf("show_menubar round-trip wrong\n"); ok := FALSE END; SetAccel(application, "app.hello", "h"); SetAccel(application, "app.flag", "f"); passed := ok; g_application_quit(application) END OnActivate; VAR rc: INTEGER; BEGIN passed := FALSE; app := gtk_application_new(AppId, 0); IF app = NIL THEN printf("test_actions: FAIL (no app)\n"); HALT(1) END; Connect(app, "activate", ADR(OnActivate), NIL); rc := g_application_run(app, 0, NIL); IF passed THEN printf("test_actions: PASS\n"); HALT(0) ELSE printf("test_actions: FAIL\n"); HALT(1) END END test_actions.