Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gtk_window_present does not move window to foreground

Tags:

macos

gtk3

I'm on macOS. Slightly modifying the first example snippet here by calling gtk_window_present repeatedly in a timeout, we get:

#include <gtk/gtk.h>

static gboolean timeout_callback (gpointer window) {
    printf("timeout\n");
    gtk_window_present (GTK_WINDOW (window));
    return TRUE;
}

static void activate (GtkApplication* app, gpointer user_data) {
    GtkWidget *window;

    window = gtk_application_window_new (app);
    gtk_window_set_title (GTK_WINDOW (window), "Window");
    gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
    gtk_widget_show_all (window);

    g_timeout_add(1000, timeout_callback, window);
    gtk_window_present (GTK_WINDOW (window));
}

int main (int argc, char **argv) {
    GtkApplication *app;
    int status;

    app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
    g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
    status = g_application_run (G_APPLICATION (app), argc, argv);
    g_object_unref (app);

    return status;
}

However, the window does not actually come to the foreground. How do I raise the main gtk+ window to the front in macOS / OS X?

like image 311
tomsmeding Avatar asked Sep 13 '25 12:09

tomsmeding


1 Answers

According to Paul Davis in this discussion:

OS X/MacOS has a concept for window layering that doesn't exist on X Window or in GTK (not explicitly, anyway).

Windows belong to a particular type layer. There is no way to make a window be above ALL other windows unless it is of the type that users the upper-most layer.

the current implementation of set_keep_above() (assuming it is like the one I originally worked on for GTK+2) only raises a window to the top of its layer group (just like the Cocoa equivalent).

If you want window to be "really on top", you have to ensure it will be on an upper layer, which in GTK terms means it needs to be a popup (for example).

The only thing that I have found to work is, sadly, an OS-specific fix, and one that cannot be done from C as far as I know.

The fix I propose is to add an Objective-C (e.g. foreground.m) file to the project with the following contents:

#import <AppKit/AppKit.h>

void macos_force_foreground_level() {
    [NSApp activateIgnoringOtherApps: YES];
}

You can then make this function available to the rest of your C program by also creating the following header file: (e.g. foreground.h)

#pragma once

#ifdef __cplusplus
extern "C" {
#endif

void macos_force_foreground_level();

#ifdef __cplusplus
}
#endif

(The __cplusplus stuff is for if you're actually also using this in a C++ program. If you're not, you can reduce the header file to just the #pragma once line and the void macos_force_foreground_level(); line.)

Include the header file where you want to be able to present the main application window on the foreground; there you can then call macos_force_foreground_level() to actually do it.

Of course, now you've added an Objective-C file to your project. On mac, you can compile this .m file to a .o file just using gcc (which on Mac really is Apple's own version of clang). (Make sure you're not passing flags like -std=c11 when compiling the .m, since that file is not even C ;) ). For linking, make sure to add -framework Foundation -framework AppKit to your linker flags.

If you have difficulties with making your build system work, you can ask in the comments, or ask another question.

like image 152
tomsmeding Avatar answered Sep 16 '25 12:09

tomsmeding