Search code examples
gtkocamllablgtk

Capturing clicks in label_widget in expander (lablgtk)


In lablgtk, I have an Expander widget to which I added a button as part of its label, as in this picture:

GTK expander with a custom label_widget containing a button

However, I'm unable to capture clicks to this button, since all of them seem to be captured by the Expander object itself.

I even tried adding an event box between the expander and the button (similarly to what is recommended for clickable GLabels), but that did not help.

Is there a way to ensure the button receives the signal?

Here's a self-contained example to illustrate this: clicking on the button only prints expander activated!, but never button clicked!.

let main () =
  (* create expander, a label_widget, and a button *)
  let expander = GBin.expander () in
  let expander_label = GMisc.label ~text:"expander" () in
  let expander_label_widget = GPack.hbox () in
  let button = GButton.button ~stock:`OK () in

  (* add button to label_widget, and label_widget to expander *)
  expander_label_widget#add expander_label#coerce;
  expander_label_widget#add button#coerce;
  expander#set_label_widget expander_label_widget#coerce;

  (* add events for both the button and the expander *)
  ignore (button#connect#clicked
            ~callback:(fun () ->
                Format.printf "button clicked!@."));
  ignore (expander#connect#activate
            ~callback:(fun () ->
                Format.printf "expander activated!@."));

  (* create window and add expander *)
  let window = GWindow.window () in
  window#add expander#coerce;
  ignore (window#connect#destroy
            ~callback:(fun () -> GMain.Main.quit ()));
  (* show result *)
  window#show ();
  GMain.Main.main ()

let () =
  ignore (GtkMain.Main.init ());
  main ()

Solution

  • This seems to be a bug in GTK+. There's a workaround described here but it's in C. You have to add the following OCaml code to your main function. It worked for me.

      GMain.Idle.add (fun () ->
        let dummy = GButton.button ~stock:`OK () in
        expander#set_label_widget dummy#coerce ;
        expander#set_label_widget expander_label_widget#coerce ;
        false) ;