Add GtkIconProvider

This is a minimal interface to provide icon lookup by name.
It is implemented by GtkIconTheme, but platform libraries or
applications can provide their own implementation and pass it
to GTK.
This commit is contained in:
Matthias Clasen 2024-05-08 00:07:45 -04:00
parent cda1733fc7
commit e5fff06622
6 changed files with 268 additions and 13 deletions

View File

@ -163,6 +163,7 @@
#include <gtk/gtkgridview.h>
#include <gtk/gtkheaderbar.h>
#include <gtk/gtkicontheme.h>
#include <gtk/gtkiconprovider.h>
#include <gtk/deprecated/gtkiconview.h>
#include <gtk/gtkimage.h>
#include <gtk/gtkimcontext.h>

View File

@ -34,6 +34,7 @@
#include "gtkwidgetprivate.h"
#include "gdk/gdkprofilerprivate.h"
#include "gtksymbolicpaintable.h"
#include "gtkiconprovider.h"
struct _GtkIconHelper
{
@ -111,13 +112,25 @@ ensure_paintable_for_gicon (GtkIconHelper *self,
return GDK_PAINTABLE (icon);
}
static GdkPaintable *
ensure_paintable_for_icon_name (GtkIconHelper *self,
const char *name)
{
int size;
float scale;
size = gtk_icon_helper_get_size (self);
scale = gtk_widget_get_scale_factor (self->owner);
return gtk_lookup_icon (gtk_widget_get_display (self->owner), name, size, scale);
}
static GdkPaintable *
gtk_icon_helper_load_paintable (GtkIconHelper *self,
gboolean preload,
gboolean *out_symbolic)
{
GdkPaintable *paintable;
GIcon *gicon;
gboolean symbolic;
switch (gtk_image_definition_get_storage_type (self->def))
@ -128,18 +141,12 @@ gtk_icon_helper_load_paintable (GtkIconHelper *self,
break;
case GTK_IMAGE_ICON_NAME:
if (self->use_fallback)
gicon = g_themed_icon_new_with_default_fallbacks (gtk_image_definition_get_icon_name (self->def));
paintable = ensure_paintable_for_icon_name (self,
gtk_image_definition_get_icon_name (self->def));
if (GTK_IS_ICON_PAINTABLE (paintable))
symbolic = gtk_icon_paintable_is_symbolic (GTK_ICON_PAINTABLE (paintable));
else
gicon = g_themed_icon_new (gtk_image_definition_get_icon_name (self->def));
paintable = ensure_paintable_for_gicon (self,
gtk_css_node_get_style (self->node),
gtk_widget_get_scale_factor (self->owner),
gtk_widget_get_direction (self->owner),
preload,
gicon,
&symbolic);
g_object_unref (gicon);
symbolic = GTK_IS_SYMBOLIC_PAINTABLE (paintable);
break;
case GTK_IMAGE_GICON:

164
gtk/gtkiconprovider.c Normal file
View File

@ -0,0 +1,164 @@
/*
* Copyright © 2024 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen <mclasen@redhat.com>
*/
#include "config.h"
#include "gtkiconprovider.h"
#include "gtkicontheme.h"
#include "gtkenums.h"
#include "gtkwidgetprivate.h"
#include "gtkprivate.h"
G_DEFINE_INTERFACE (GtkIconProvider, gtk_icon_provider, G_TYPE_OBJECT)
static void
gtk_icon_provider_default_init (GtkIconProviderInterface *iface)
{
}
void
gtk_icon_provider_set_for_display (GdkDisplay *display,
GtkIconProvider *provider)
{
g_object_set_data_full (G_OBJECT (display), "--gtk-icon-provider",
g_object_ref (provider), g_object_unref);
gtk_system_setting_changed (display, GTK_SYSTEM_SETTING_ICON_THEME);
}
GtkIconProvider *
gtk_icon_provider_get_for_display (GdkDisplay *display)
{
GtkIconProvider *provider;
provider = g_object_get_data (G_OBJECT (display), "--gtk-icon-provider");
if (provider)
return provider;
return GTK_ICON_PROVIDER (gtk_icon_theme_get_for_display (display));
}
static GdkPaintable *gtk_lookup_builtin_icon (GdkDisplay *display,
const char *name,
int size,
float scale);
GdkPaintable *
gtk_lookup_icon (GdkDisplay *display,
const char *name,
int size,
float scale)
{
GtkIconProvider *provider;
GdkPaintable *icon;
provider = gtk_icon_provider_get_for_display (display);
icon = GTK_ICON_PROVIDER_GET_IFACE (provider)->lookup_icon (provider, name, size, scale);
if (!icon)
{
GTK_DISPLAY_DEBUG (display, ICONTHEME,
"%s: Looking up icon %s size %d@%f: not found",
G_OBJECT_TYPE_NAME (provider), name, size, scale);
icon = gtk_lookup_builtin_icon (display, name, size, scale);
}
return icon;
}
static GdkPaintable *
gtk_lookup_builtin_icon (GdkDisplay *display,
const char *name,
int size,
float scale)
{
int sizes[] = { 16, 32, 64 };
char pixel_size[24] = { 0, };
const char *contexts[] = {
"actions",
"categories",
"devices",
"emblems",
"emotes",
"mimetypes",
"places",
"status",
};
const char *extension;
GdkPaintable *icon = NULL;
for (int i = 0; i < G_N_ELEMENTS (sizes); i++)
{
if (sizes[i] >= size * scale)
{
size = sizes[i];
g_snprintf (pixel_size, sizeof (pixel_size), "%dx%d", size, size);
break;
}
}
if (pixel_size[0] == '\0')
{
g_snprintf (pixel_size, sizeof (pixel_size), "64x64");
size = 64;
}
if (g_str_has_suffix (name, "-symbolic"))
extension = ".symbolic.png";
else
extension = ".png";
for (int i = 0; i < G_N_ELEMENTS (contexts); i++)
{
char *uri;
GFile *file;
uri = g_strconcat ("resource:///org/gtk/libgtk/icons/", pixel_size, "/", contexts[i], "/", name, extension, NULL);
file = g_file_new_for_uri (uri);
if (g_file_query_exists (file, NULL))
{
GTK_DISPLAY_DEBUG (display, ICONTHEME,
"Looking up builtin icon %s size %d@%f: %s",
name, size, scale, uri);
icon = GDK_PAINTABLE (gtk_icon_paintable_new_for_file (file, size, 1));
}
g_object_unref (file);
g_free (uri);
if (icon)
break;
}
if (!icon)
{
GTK_DISPLAY_DEBUG (display, ICONTHEME,
"Looking up builtin icon %s size %d@%f: not found",
name, size, scale);
icon = GDK_PAINTABLE (gdk_texture_new_from_resource ("/org/gtk/libgtk/icons/16x16/status/image-missing.png"));
}
return icon;
}

62
gtk/gtkiconprovider.h Normal file
View File

@ -0,0 +1,62 @@
/*
* Copyright © 2024 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen <mclasen@redhat.com>
*/
#pragma once
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk.h> can be included directly."
#endif
#include <gtk/gtktypes.h>
#include <gdk/gdkpaintable.h>
#include <gdk/gdkdisplay.h>
G_BEGIN_DECLS
#define GTK_TYPE_ICON_PROVIDER (gtk_icon_provider_get_type ())
GDK_AVAILABLE_IN_4_16
G_DECLARE_INTERFACE (GtkIconProvider, gtk_icon_provider, GTK, ICON_PROVIDER, GObject)
struct _GtkIconProviderInterface
{
GTypeInterface g_iface;
GdkPaintable * (* lookup_icon) (GtkIconProvider *provider,
const char *icon_name,
int size,
float scale);
};
GDK_AVAILABLE_IN_4_16
void gtk_icon_provider_set_for_display (GdkDisplay *display,
GtkIconProvider *provider);
GDK_AVAILABLE_IN_4_16
GtkIconProvider * gtk_icon_provider_get_for_display (GdkDisplay *display);
GDK_AVAILABLE_IN_4_16
GdkPaintable * gtk_lookup_icon (GdkDisplay *display,
const char *icon_name,
int size,
float scale);
G_END_DECLS

View File

@ -54,6 +54,7 @@
#include "gdktextureutilsprivate.h"
#include "gdk/gdktextureprivate.h"
#include "gdk/gdkprofilerprivate.h"
#include "gtkiconprovider.h"
#define GDK_ARRAY_ELEMENT_TYPE char *
#define GDK_ARRAY_NULL_TERMINATED 1
@ -812,7 +813,25 @@ icon_cache_clear (GtkIconTheme *theme)
/****************** End of icon cache ***********************/
G_DEFINE_TYPE (GtkIconTheme, gtk_icon_theme, G_TYPE_OBJECT)
static GdkPaintable *
gtk_icon_theme_lookup_icon_as_provider (GtkIconProvider *provider,
const char *name,
int size,
float scale)
{
GtkIconTheme *self = GTK_ICON_THEME (provider);
return GDK_PAINTABLE (gtk_icon_theme_lookup_icon (self, name, NULL, size, (int) ceilf (scale), GTK_TEXT_DIR_LTR, 0));
}
static void
gtk_icon_provider_init (GtkIconProviderInterface *iface)
{
iface->lookup_icon = gtk_icon_theme_lookup_icon_as_provider;
}
G_DEFINE_TYPE_WITH_CODE (GtkIconTheme, gtk_icon_theme, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GTK_TYPE_ICON_PROVIDER, gtk_icon_provider_init))
/**
* gtk_icon_theme_new:

View File

@ -258,6 +258,7 @@ gtk_public_sources = files([
'gtkgridview.c',
'gtkheaderbar.c',
'gtkicontheme.c',
'gtkiconprovider.c',
'gtkimage.c',
'gtkimagedefinition.c',
'gtkimcontext.c',
@ -511,6 +512,7 @@ gtk_public_headers = files([
'gtkgridview.h',
'gtkheaderbar.h',
'gtkicontheme.h',
'gtkiconprovider.h',
'gtkimage.h',
'gtkimcontext.h',
'gtkimcontextsimple.h',