From ce7c6d58c230bb1d03481b097fd10fddb3d79265 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 23 Mar 2013 00:16:24 -0400 Subject: [PATCH] Add gdk_set_allowed_backends This new function allows programmatic control over the GDK backends that will be used at runtime. --- docs/reference/gdk/gdk3-sections.txt | 1 + docs/reference/gtk/running.sgml | 3 + gdk/gdk.symbols | 1 + gdk/gdkdisplaymanager.c | 142 ++++++++++++++++++++++----- gdk/gdkmain.h | 3 + 5 files changed, 128 insertions(+), 22 deletions(-) diff --git a/docs/reference/gdk/gdk3-sections.txt b/docs/reference/gdk/gdk3-sections.txt index 3b052218c9..e409bbc0eb 100644 --- a/docs/reference/gdk/gdk3-sections.txt +++ b/docs/reference/gdk/gdk3-sections.txt @@ -10,6 +10,7 @@ gdk_parse_args gdk_get_display_arg_name gdk_notify_startup_complete gdk_notify_startup_complete_with_id +gdk_set_allowed_backends gdk_get_program_class diff --git a/docs/reference/gtk/running.sgml b/docs/reference/gtk/running.sgml index 576f83f25f..71fb7b364b 100644 --- a/docs/reference/gtk/running.sgml +++ b/docs/reference/gtk/running.sgml @@ -461,6 +461,9 @@ nevertheless. + Since 3.10, this environment variable can contain a comma-separated list + of backend names, which are tried in order. The list may also contain + a *, which means: try all remaining backends. For more information about selecting backends, see the gdk_display_manager_get() function. diff --git a/gdk/gdk.symbols b/gdk/gdk.symbols index 1f99c6406c..6e30e9a203 100644 --- a/gdk/gdk.symbols +++ b/gdk/gdk.symbols @@ -335,6 +335,7 @@ gdk_set_program_class gdk_set_show_events gdk_setting_action_get_type gdk_setting_get +gdk_set_allowed_backends gdk_status_get_type gdk_synthesize_window_state gdk_test_render_sync diff --git a/gdk/gdkdisplaymanager.c b/gdk/gdkdisplaymanager.c index 70b6a62a9d..e29fa511b5 100644 --- a/gdk/gdkdisplaymanager.c +++ b/gdk/gdkdisplaymanager.c @@ -225,6 +225,48 @@ gdk_display_manager_get_property (GObject *object, } } +static const gchar *allowed_backends; + +/** + * gdk_set_allowed_backends: + * @backends: a comma-separated list of backends + * + * Sets a list of backends that GDK should try to use. + * + * This can be be useful if your application does not + * work with certain GDK backends. + * + * By default, GDK tries all included backends. + * + * For example, + * + * gdk_set_allowed_backends ("wayland,quartz,*"); + * + * instructs GDK to try the Wayland backend first, + * followed by the Quartz backend, and then all + * others. + * + * If the GDK_BACKEND environment variable + * is set, it determines what backends are tried in what + * order, while still respecting the set of allowed backends + * that are specified by this function. + * + * The possible backend names are x11, win32, quartz, + * broadway, wayland. You can also include a * in the + * list to try all remaining backends. + * + * This call must happen prior to gdk_display_open(), + * gtk_init(), gtk_init_with_args() or gtk_init_check() + * in order to take effect. + * + * Since: 3.10 + */ +void +gdk_set_allowed_backends (const gchar *backends) +{ + allowed_backends = g_strdup (backends); +} + /** * gdk_display_manager_get: * @@ -233,7 +275,8 @@ gdk_display_manager_get_property (GObject *object, * When called for the first time, this function consults the * GDK_BACKEND environment variable to find out which * of the supported GDK backends to use (in case GDK has been compiled - * with multiple backends). + * with multiple backends). Applications can use gdk_set_allowed_backends() + * to limit what backends can be used. * * Returns: (transfer none): The global #GdkDisplayManager singleton; * gdk_parse_args(), gdk_init(), or gdk_init_check() must have @@ -246,38 +289,93 @@ gdk_display_manager_get (void) { static GdkDisplayManager *manager = NULL; - if (!manager) + if (manager == NULL) { - const gchar *backend; + const gchar *backend_list; + gchar **backends; + gint i; + gboolean allow_any; + + if (allowed_backends == NULL) + allowed_backends = "*"; + allow_any = strstr (allowed_backends, "*") != NULL; + + backend_list = g_getenv ("GDK_BACKEND"); + if (backend_list == NULL) + backend_list = allowed_backends; + backends = g_strsplit (backend_list, ",", 0); + + for (i = 0; manager == NULL && backends[i] != NULL; i++) + { + const gchar *backend = backends[i]; + gboolean any = g_str_equal (backend, "*"); + + if (!allow_any && !any && !strstr (allowed_backends, backend)) + continue; - backend = g_getenv ("GDK_BACKEND"); #ifdef GDK_WINDOWING_QUARTZ - if (backend == NULL || strcmp (backend, "quartz") == 0) - manager = g_initable_new (gdk_quartz_display_manager_get_type (), NULL, NULL, NULL); + if ((any && allow_any) || + (any && strstr (allowed_backends, "quartz")) || + g_str_equal (backend, "quartz")) + { + GDK_NOTE (MISC, g_message ("Trying quartz backend")); + manager = g_initable_new (gdk_quartz_display_manager_get_type (), NULL, NULL, NULL); + if (manager) + break; + } #endif #ifdef GDK_WINDOWING_WIN32 - if (!manager && (backend == NULL || strcmp (backend, "win32") == 0)) - manager = g_initable_new (gdk_win32_display_manager_get_type (), NULL, NULL, NULL); -#endif -#ifdef GDK_WINDOWING_WAYLAND - if (!manager && (backend == NULL || strcmp (backend, "wayland") == 0)) - manager = g_initable_new (gdk_wayland_display_manager_get_type (), NULL, NULL, NULL); + if ((any && allow_any) || + (any && strstr (allowed_backends, "win32")) || + g_str_equal (backend, "win32")) + { + GDK_NOTE (MISC, g_message ("Trying win32 backend")); + manager = g_initable_new (gdk_win32_display_manager_get_type (), NULL, NULL, NULL); + if (manager) + break; + } #endif #ifdef GDK_WINDOWING_X11 - if (!manager && (backend == NULL || strcmp (backend, "x11") == 0)) - manager = g_initable_new (gdk_x11_display_manager_get_type (), NULL, NULL, NULL); + if ((any && allow_any) || + (any && strstr (allowed_backends, "x11")) || + g_str_equal (backend, "x11")) + { + GDK_NOTE (MISC, g_message ("Trying x11 backend")); + manager = g_initable_new (gdk_x11_display_manager_get_type (), NULL, NULL, NULL); + if (manager) + break; + } +#endif +#ifdef GDK_WINDOWING_WAYLAND + if ((any && allow_any) || + (any && strstr (allowed_backends, "wayland")) || + g_str_equal (backend, "wayland")) + { + GDK_NOTE (MISC, g_message ("Trying wayland backend")); + manager = g_initable_new (gdk_wayland_display_manager_get_type (), NULL, NULL, NULL); + if (manager) + break; + } #endif #ifdef GDK_WINDOWING_BROADWAY - if (!manager && (backend == NULL || strcmp (backend, "broadway") == 0)) - manager = g_initable_new (gdk_broadway_display_manager_get_type (), NULL, NULL, NULL); + if ((any && allow_any) || + (any && strstr (allowed_backends, "broadway")) || + g_str_equal (backend, "broadway")) + { + GDK_NOTE (MISC, g_message ("Trying broadway backend")); + manager = g_initable_new (gdk_broadway_display_manager_get_type (), NULL, NULL, NULL); + if (manager) + break; + } #endif - if (!manager) - { - if (backend != NULL) - g_error ("Unsupported GDK backend: %s", backend); - else - g_error ("No GDK backend found"); } + + g_strfreev (backends); + + if (manager == NULL) + g_error ("No GDK backend found (%s)", allowed_backends); + + GDK_NOTE (MISC, if (manager) g_message ("Using %s", G_OBJECT_TYPE_NAME (manager))); } return manager; diff --git a/gdk/gdkmain.h b/gdk/gdkmain.h index 27788dd2da..05b15b9928 100644 --- a/gdk/gdkmain.h +++ b/gdk/gdkmain.h @@ -117,6 +117,9 @@ void gdk_flush (void); void gdk_disable_multidevice (void); +GDK_AVAILABLE_IN_3_10 +void gdk_set_allowed_backends (const gchar *backends); + G_END_DECLS #endif /* __GDK_MAIN_H__ */