Home > Back-end >  gtk3 on macos: window does not restore from the dock
gtk3 on macos: window does not restore from the dock

Time:07-29

Using GTK3 on MacOS, after minimizing the window, the dock icon does not restore the window. I have to use the "Show All Windows" selection from the dock icon menu.

Does anyone have a work-around or know something to make the dock icons work?

I would be happy with some simple objective-c code that would make the dock icons work.

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <getopt.h>
#include <unistd.h>

#include <gtk/gtk.h>

static void     testBuildUI (void);
gboolean        testMainLoop  (void);

int
main (int argc, char *argv[])
{
  gtk_init (&argc, NULL);
  testBuildUI ();
  testMainLoop ();
  return 0;
}

static void
testBuildUI (void)
{
  GtkWidget *window;

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  assert (window != NULL);
  gtk_widget_show_all (window);
}

int
testMainLoop (void)
{
  while (1) {
    gtk_main_iteration_do (FALSE);
    while (gtk_events_pending ()) {
      gtk_main_iteration_do (FALSE);
    }
    sleep (1);
  }
  return 0;
}

CodePudding user response:

There is no special code or Objective-C needed if you use gtk_application_new instead of gtk_init and start your main loop with g_application_run.

The documentation states the following:

Currently, GtkApplication handles GTK initialization, application uniqueness, session management, provides some basic scriptability and desktop shell integration by exporting actions and menus and manages a list of toplevel windows whose life-cycle is automatically tied to the life-cycle of your application.

see https://docs.gtk.org/gtk3/class.Application.html

Self contained test program

Your code slightly adapted to the above points might look like the following:

#include <gtk/gtk.h>
#include <assert.h>

static void testBuildUI(GApplication *app, gpointer data);

int main(int argc, char *argv[]) {
    printf("gtk version: %d.%d.%d\n", gtk_major_version, gtk_minor_version, gtk_micro_version);
    GtkApplication *app = gtk_application_new("com.example.MyApp",G_APPLICATION_FLAGS_NONE);
    g_signal_connect(app, "activate", G_CALLBACK(testBuildUI), NULL);
    g_application_run(G_APPLICATION(app), argc, argv);
    g_object_unref(app);
    return 0;
}

static void testBuildUI(GApplication *app, gpointer data) {
    GtkWidget *window;
    window = gtk_application_window_new(GTK_APPLICATION(app));
    assert (window != NULL);
    gtk_widget_show_all(GTK_WIDGET(window));
}

If you click on the dock icon of this test program, the window will restore as expected.

Alternative solution

If you want to avoid GApplication/GtkApplication, you could also use the gtk-mac-integration library instead, see https://github.com/jralls/gtk-mac-integration.

The library is rather small, only a few thousand lines of C code, so you can also easily take a look at how it works internally.

There is an important hint:

Older Gtk applications that aren't based around GApplication can be adapted to use the macOS menu bar and to integrate with the Dock using GtkOSXApplication. The Gtk API that GtkOSXApplication uses is deprecated in Gtk3 and has been removed from Gtk4. Since macOS integration is available directly in Gtk using GApplication GtkOSXIntegration will not be updated for the new menu API and is deprecated. Application maintainers are strongly encouraged to redesign their programs around GApplication, particularly before migrating to Gtk4.

see https://wiki.gnome.org/Projects/GTK/OSX/Integration

The integration is easy: after gtk_init create an application object. After setting up the window call gtkosx_application_ready with the application object.

As a side note, there is also a slightly more complex example in the src folder called test-integration.c under the Github link mentioned above that shows a more advanced menu and dock integration.

Finally, your program only minimally changed to work with the gtk-mac-integration lib:

#include <gtk/gtk.h>
#include <gtkosxapplication.h>
#include <assert.h>

static void testBuildUI(void);
static void testMainLoop(void);

static void
testBuildUI(void) {
    GtkWidget *window;

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    assert (window != NULL);
    gtk_widget_show_all(window);
}

void
testMainLoop(void) {
    while (1) {
        gtk_main_iteration_do(FALSE);
        while (gtk_events_pending()) {
            gtk_main_iteration_do(FALSE);
        }
        sleep(1);
    }
}

int
main(int argc, char *argv[]) {
    printf("gtk version: %d.%d.%d\n", gtk_major_version, gtk_minor_version, gtk_micro_version);
    gtk_init(&argc, &argv);
    GtkosxApplication *theApp = g_object_new(GTKOSX_TYPE_APPLICATION, NULL);
    testBuildUI();
    gtkosx_application_ready(theApp);
    testMainLoop();
    g_object_unref(theApp);
    return 0;
}

I installed the library using brew install gtk-mac-integration and linked the C program with libgtkmacintegration-gtk3.dylib. Also in this variant, the window is restored as expected. when you click on the dock icon of the program.

  • Related