Compare commits

...

1 Commits

Author SHA1 Message Date
Matthias Clasen
e5fff06622 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.
2024-05-08 00:07:45 -04:00
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',