diff --git a/docs/reference/gtk/gtk3-sections.txt b/docs/reference/gtk/gtk3-sections.txt index 02a48afc09..d3e34c6dfa 100644 --- a/docs/reference/gtk/gtk3-sections.txt +++ b/docs/reference/gtk/gtk3-sections.txt @@ -7391,6 +7391,7 @@ gtk_application_uninhibit gtk_application_is_inhibited +gtk_application_prefers_app_menu gtk_application_get_app_menu gtk_application_set_app_menu gtk_application_get_menubar diff --git a/gtk/gtkapplication-dbus.c b/gtk/gtkapplication-dbus.c index 09afcfa015..60d4edddf0 100644 --- a/gtk/gtkapplication-dbus.c +++ b/gtk/gtkapplication-dbus.c @@ -23,6 +23,7 @@ #include "config.h" #include "gtkapplicationprivate.h" +#include "gtksettings.h" G_DEFINE_TYPE (GtkApplicationImplDBus, gtk_application_impl_dbus, GTK_TYPE_APPLICATION_IMPL) @@ -411,6 +412,38 @@ gtk_application_impl_dbus_is_inhibited (GtkApplicationImpl *impl, return inhibited; } +static gboolean +gtk_application_impl_dbus_prefers_app_menu (GtkApplicationImpl *impl) +{ + static gboolean decided; + static gboolean result; + + /* We do not support notifying if/when the result changes, so make + * sure that once we give an answer, we will always give the same one. + */ + if (!decided) + { + GtkSettings *gtk_settings; + gboolean show_app_menu; + gboolean show_menubar; + + gtk_settings = gtk_settings_get_default (); + g_object_get (G_OBJECT (gtk_settings), + "gtk-shell-shows-app-menu", &show_app_menu, + "gtk-shell-shows-menubar", &show_menubar, + NULL); + + /* We prefer traditional menus when we have a shell that doesn't + * show the appmenu or we have a shell that shows menubars + * (ie: Unity) + */ + result = show_app_menu && !show_menubar; + decided = TRUE; + } + + return result; +} + static void gtk_application_impl_dbus_init (GtkApplicationImplDBus *dbus) { @@ -446,6 +479,7 @@ gtk_application_impl_dbus_class_init (GtkApplicationImplDBusClass *class) impl_class->inhibit = gtk_application_impl_dbus_inhibit; impl_class->uninhibit = gtk_application_impl_dbus_uninhibit; impl_class->is_inhibited = gtk_application_impl_dbus_is_inhibited; + impl_class->prefers_app_menu = gtk_application_impl_dbus_prefers_app_menu; gobject_class->finalize = gtk_application_impl_dbus_finalize; } diff --git a/gtk/gtkapplication.c b/gtk/gtkapplication.c index a8b99811c2..662e501e44 100644 --- a/gtk/gtkapplication.c +++ b/gtk/gtkapplication.c @@ -1138,6 +1138,57 @@ gtk_application_remove_accelerator (GtkApplication *application, g_free (action_and_target); } +/** + * gtk_application_prefers_app_menu: + * @application: a #GtkApplication + * + * Determines if the desktop environment in which the application is + * running would prefer an application menu be shown. + * + * If this function returns %TRUE then the application should call + * gtk_application_set_app_menu() with the contents of an application + * menu, which will be shown by the desktop environment. If it returns + * %FALSE then you should consider using an alternate approach, such as + * a menubar. + * + * The value returned by this function is purely advisory and you are + * free to ignore it. If you call gtk_application_set_app_menu() even + * if the desktop environment doesn't support app menus, then a fallback + * will be provided. + * + * Applications are similarly free not to set an app menu even if the + * desktop environment wants to show one. In that case, a fallback will + * also be created by the desktop environment (GNOME, for example, uses + * a menu with only a "Quit" item in it). + * + * The value returned by this function never changes. Once it returns a + * particular value, it is guaranteed to always return the same value. + * + * You may only call this function after the application has been + * registered and after the base startup handler has run. You're most + * likely to want to use this from your own startup handler. It may + * also make sense to consult this function while constructing UI (in + * activate, open or an action activation handler) in order to determine + * if you should show a gear menu or not. + * + * This function will return %FALSE on Mac OS and a default app menu + * will be created automatically with the "usual" contents of that menu + * typical to most Mac OS applications. If you call + * gtk_application_set_app_menu() anyway, then this menu will be + * replaced with your own. + * + * Returns: %TRUE if you should set an app menu + * + * Since: 3.14 + **/ +gboolean +gtk_application_prefers_app_menu (GtkApplication *application) +{ + g_return_val_if_fail (application->priv->impl != NULL, FALSE); + + return gtk_application_impl_prefers_app_menu (application->priv->impl); +} + /** * gtk_application_set_app_menu: * @application: a #GtkApplication diff --git a/gtk/gtkapplication.h b/gtk/gtkapplication.h index 7ff13ad44b..9d1af95e10 100644 --- a/gtk/gtkapplication.h +++ b/gtk/gtkapplication.h @@ -151,6 +151,9 @@ void gtk_application_set_accels_for_action (GtkApplication const gchar *detailed_action_name, const gchar * const *accels); +GDK_AVAILABLE_IN_3_14 +gboolean gtk_application_prefers_app_menu (GtkApplication *application); + G_END_DECLS #endif /* __GTK_APPLICATION_H__ */ diff --git a/gtk/gtkapplicationimpl.c b/gtk/gtkapplicationimpl.c index 6cb899aad3..946284b19a 100644 --- a/gtk/gtkapplicationimpl.c +++ b/gtk/gtkapplicationimpl.c @@ -41,6 +41,7 @@ gtk_application_impl_init (GtkApplicationImpl *impl) } static guint do_nothing (void) { return 0; } +static gboolean return_false (void) { return FALSE; } static void gtk_application_impl_class_init (GtkApplicationImplClass *class) @@ -59,6 +60,7 @@ gtk_application_impl_class_init (GtkApplicationImplClass *class) class->inhibit = (gpointer) do_nothing; class->uninhibit = (gpointer) do_nothing; class->is_inhibited = (gpointer) do_nothing; + class->prefers_app_menu = (gpointer) return_false; } void @@ -153,6 +155,12 @@ gtk_application_impl_is_inhibited (GtkApplicationImpl *impl, return GTK_APPLICATION_IMPL_GET_CLASS (impl)->is_inhibited (impl, flags); } +gboolean +gtk_application_impl_prefers_app_menu (GtkApplicationImpl *impl) +{ + return GTK_APPLICATION_IMPL_GET_CLASS (impl)->prefers_app_menu (impl); +} + GtkApplicationImpl * gtk_application_impl_new (GtkApplication *application, GdkDisplay *display) diff --git a/gtk/gtkapplicationprivate.h b/gtk/gtkapplicationprivate.h index 5378c23b17..dbd711563b 100644 --- a/gtk/gtkapplicationprivate.h +++ b/gtk/gtkapplicationprivate.h @@ -103,6 +103,8 @@ typedef struct gboolean (* is_inhibited) (GtkApplicationImpl *impl, GtkApplicationInhibitFlags flags); + gboolean (* prefers_app_menu) (GtkApplicationImpl *impl); + } GtkApplicationImplClass; @@ -184,6 +186,8 @@ gboolean gtk_application_impl_is_inhibited (GtkAppl gchar * gtk_application_impl_dbus_get_window_path (GtkApplicationImplDBus *dbus, GtkWindow *window); +gboolean gtk_application_impl_prefers_app_menu (GtkApplicationImpl *impl); + void gtk_application_impl_quartz_setup_menu (GMenuModel *model, GtkActionMuxer *muxer);