A few questions to GTK4 GtkDialog

Yesterday I read the GTK4 C API docs for GtkDialog

and wrote the draft about that topic for the Nim book:

Unfortunately there remained some open questions:

Let us start with the most unclear statement in the C API docs:

Under gtk_dialog_add_action_widget:

If you want to add a non-activatable widget, simply pack it into the action_area field of the GtkDialog struct.

That sentence is fully confusing for me.

What is the field of that struct. Should we directly access member fields of that widget? And there seems to be no field to be exposed. And for a non-activatable widget like a GtkLabel, which action would we expect then?

The next more general question: What is special for a GtkDialog compared to a GtkWindow? A GtkDialog seems to allow only restricted shapes of dialogs, because of the separated action- and message-area. Would a user be able to use a ordinary GtkWindow to create his own, more fancy shaped dialog? And I was surprised that the GtkFileChooserDialog is a child of GtkDialog, as it is much more complex and looks fully different. What important properties does it inherit from its parent?

Well there are some more open questions…

Sounds like it’s just an outdated piece of documentation.

gtk_dialog_get_action_area() is deprecated in GTK3 and removed in GTK4 so you shouldn’t really do anything like that.

Yes, a GtkDialog is just a bunch of convenience API for responses and such around a GtkWindow and you can of course just create your own dialogs.

1 Like

The next two questions a (Nim) GTK4 user may ask:

With use of setTransientFor() as done in the provided Nim example code the dialog box is located over the parent window and the parent window is frozen. But as you see from the provided snapshot the dialog is not exactly centered over the parent window. Is that a bug? And is there a way to influence the position of the dialog window in relation to the parent window?

And related: In the snapshot window the OK and Cancel buttons are both on the right side. What would be the best way to have the Cancel button totally on the left and the OK button on the right?

Next question users may ask:

We have gtk_window_set_modal(). That freezes the app. But how can we create system modal dialogs, which freezes the whole computer, like for the switch off dialog. And how can we create document modal dialogs, which may freeze only one window of an text processing tool?


And the other question I forgot: What is with Mnemonics for the buttons in the action are. Is there something like
newLabelWithMnemonic("_Ok") for the buttons in the action area?

[EDIT 2]

And one more question is about gtk_dialog_response(). In which situation would one call this? After some thinking I may have one idea: When we add a GTKEntry to the message area, we may connect that entry with a “activate” callback function and in the activate function call gtk_dialog_response()? Would that make any sense?

If you want detailed control over button placement, you are probably better off adding the buttons to your content. GtkDialogs action widget machinery is all about placing the buttons where the platform wants them (headerbar vs action area, left vs right, etc).

1 Like

We have gtk_window_set_modal(). That freezes the app. But how can we create system modal dialogs, which freezes the whole computer, like for the switch off dialog. And how can we create document modal dialogs, which may freeze only one window of an text processing tool?

This is confusing language. There is no ‘freezing’ happening here. A modal dialog makes the shadowed window(s) not respond to input until the dialog is dismissed, but the app continues to process input events (otherwise, you would not be able to dismiss the dialog).

‘System modal’ is a concept that needs to be enforced by the compositor; GTK does not provide api for this.

1 Like

Thanks for your reply. It is nice that you support Mr. Bassi with answering all the questions :slight_smile:

This is confusing language. There is no ‘freezing’ happening here.

I got the term freeze from the C API docs:

A “modal” dialog (that is, one which freezes the rest of the application from user input),

But of course you are right, only the rest of the app, not the dialog itself.

From the wikipedia article I got the info that at least Apple supports document modal dialogs?

And finally I found an issue:

proc dialogCb(b: Button; w: ApplicationWindow) =
  let dialog = newDialog()
  setProperty(dialog, "use-header-bar", toBoolVal(true))

results in

GLib-GObject-WARNING **: 19:24:20.786: g_object_set_is_valid_property: construct property "use-header-bar" for object 'GtkDialog' can't be set after construction

Yes, API docs tell us: “Construct Only”

But I had the hope that it would work when we apply it direct after calling the constructor, before we call show() on the dialog. Well good that I tested it. But as we do not have gtk_dialog_new_with_buttons() from gobject-introspection, we have no “use-header-bar” for our bindings. Well, we may create manually a gtk_dialog_new_with_buttons() called gtk_dialog_new_with_flags() which only accepts the flags…

And to answer the Mnemonics question:

dialog.addButton("_Yes", ResponseType.yes.ord)

works. When we press ALT the Y gets underlined, and when we additional press “y” we get a response signal emitted with yes id. This information is missing from C API docs.

That’s impossible. “construct-only” is a GObject concept, so there’s no notion of mapping a toplevel at that level.

1 Like

And maybe one more bug:

Using setTransientFor() seems to have no effect when we do not call setModal() additional. With only using setTransientFor() the dialog window pops up somewhere unrelated to the parent window. That is for Linux and Wayland, I assume that will work later when GTK4 is more mature.

GTK has nothing to do with positioning windows and dialogs: it’s up to the window manager to do that.

1 Like

@StefanSalewski thanks for this informative discussion.

  • Do you provide a similar mechanism to GObject construction in gintro nim binding? In Vala I use Object (param: value);?
  • do the binding generate a pointer to user_data as a last parameter in callbacks as in c?

For your first question I am not sure what you mean. Many examples are already provided in the GTK4 Nim book and in the README file of the gintro package. Vala was designed for Glib and Gobject, so it is clear that Vala has some advantages for GTK coding. For Nim we use currently proxy objects with the toggle_ref formalism for gobjects. So we do not work directly on the gobjects, Nim is currently not a real replacement for low level C for library development. I assume that Vala can fully replace C, for Rust I am not sure. Generally Nim can be used to create system libs which then behave like pure C libs, so generally Nim could be used to create new widgets from scratch and all that. But then we would have to make all the GTK C macros available first. That is possible, but I do not think that currently someone wants to use Nim for that low level development.

For the optional parameter in callbacks: That parameter is optional in Nim, we can just ignore it, or we can pass Nim value types or ref types. Ref types are Nim’s managed pointers. These optional arguments are indeed passed as pointers behind the scene, but for the user interface the parameters have a well defined type.

And is there a fix available for the Gnome Wayland GUI?

Because I an considering currently rewriting my old Ned Nim editor with GTK4 and the gintro bindings, so I wondered how a preferences dialog may look. So I launched GTK3 gedit and opened its preferences dialog: When the gedit main window is in the lower right corner, the preferences dialog opens somewhere close to the top left corner. For me not a real problem, but I think that is not optimal user experience. In think the window manager is called gdm on my gentoo linux box.

There’s no “fix”, because it’s not “a bug”: it’s a design choice of the Wayland protocol.

No, it’s GNOME Shell. GDM is the login manager.

The default layout of new windows in GNOME Shell is the classic “open each new window by applying an offset on box axes, starting from the top left corner until windows fit, then reset to (0, 0) and do the same” used by Windows and macOS.

Different window types can have different policies—for instance, modal dialogs are attached to the parent top level. Regardless, the policy is defined by the window manager, and the toolkit has not input in the matter.

1 Like

That is really funny. For the last 15 years I thought GDM is responsible for moving and resizing the windows, and that GNOME Shell is the terminal window where one can launch commands like cd, ls or less. Because GDM is the abbreviation of “Gnome Display Manager”, and terminal windows where called Shells on some OS.

So I learned something new today, thanks.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.