Bug 1705877 - Add support for scaled cursors on GTK. r=stransky

I had overlooked the way to achieve this. This is possible using cairo
surfaces, but they only support integer scale factors, so we ceil and
potentially rasterize the image to a bigger size if needed.

Differential Revision: https://phabricator.services.mozilla.com/D112477
This commit is contained in:
Emilio Cobos Álvarez 2021-04-21 09:28:55 +00:00
Родитель cea51c8354
Коммит 6a5a33b978
2 изменённых файлов: 26 добавлений и 22 удалений

Просмотреть файл

@ -515,16 +515,8 @@ static void LoadWidgetIconPixbuf(GtkWidget* aWidgetIcon) {
gtk_icon_size_lookup(gtkIconSize, &iconWidth, &iconHeight);
/* Those are available since Gtk+ 3.10 as well as GtkHeaderBar */
static auto sGtkIconThemeLookupIconForScalePtr =
(GtkIconInfo *
(*)(GtkIconTheme*, const gchar*, gint, gint, GtkIconLookupFlags))
dlsym(RTLD_DEFAULT, "gtk_icon_theme_lookup_icon_for_scale");
static auto sGdkCairoSurfaceCreateFromPixbufPtr =
(cairo_surface_t * (*)(const GdkPixbuf*, int, GdkWindow*))
dlsym(RTLD_DEFAULT, "gdk_cairo_surface_create_from_pixbuf");
for (int scale = 1; scale < ICON_SCALE_VARIANTS + 1; scale++) {
GtkIconInfo* gtkIconInfo = sGtkIconThemeLookupIconForScalePtr(
GtkIconInfo* gtkIconInfo = gtk_icon_theme_lookup_icon_for_scale(
gtk_icon_theme_get_default(), iconName, iconWidth, scale,
(GtkIconLookupFlags)0);
@ -539,7 +531,7 @@ static void LoadWidgetIconPixbuf(GtkWidget* aWidgetIcon) {
g_object_unref(G_OBJECT(gtkIconInfo));
cairo_surface_t* iconSurface =
sGdkCairoSurfaceCreateFromPixbufPtr(iconPixbuf, scale, nullptr);
gdk_cairo_surface_create_from_pixbuf(iconPixbuf, scale, nullptr);
g_object_unref(iconPixbuf);
nsAutoCString surfaceName;

Просмотреть файл

@ -2388,18 +2388,11 @@ static GdkCursor* GetCursorForImage(const nsIWidget::Cursor& aCursor) {
if (!aCursor.IsCustom()) {
return nullptr;
}
// FIXME: GTK doesn't provide an API for custom cursors that have more than
// native resolution, so this will scale the image instead, which is slightly
// unfortunate.
nsIntSize size = nsIWidget::CustomCursorSize(aCursor);
GdkPixbuf* pixbuf =
nsImageToPixbuf::ImageToPixbuf(aCursor.mContainer, Some(size));
if (!pixbuf) {
return nullptr;
}
auto CleanupPixBuf =
mozilla::MakeScopeExit([&]() { g_object_unref(pixbuf); });
// NOTE: GTK only allows integer scale factors, so we ceil to the closest
// scale factor and then tell gtk to scale it down.
int32_t gtkScale = std::ceil(aCursor.mResolution);
// Reject cursors greater than 128 pixels in some direction, to prevent
// spoofing.
@ -2412,6 +2405,13 @@ static GdkCursor* GetCursorForImage(const nsIWidget::Cursor& aCursor) {
return nullptr;
}
nsIntSize rasterSize = size * gtkScale;
GdkPixbuf* pixbuf =
nsImageToPixbuf::ImageToPixbuf(aCursor.mContainer, Some(rasterSize));
if (!pixbuf) {
return nullptr;
}
// Looks like all cursors need an alpha channel (tested on Gtk 2.4.4). This
// is of course not documented anywhere...
// So add one if there isn't one yet
@ -2424,8 +2424,20 @@ static GdkCursor* GetCursorForImage(const nsIWidget::Cursor& aCursor) {
}
}
return gdk_cursor_new_from_pixbuf(gdk_display_get_default(), pixbuf,
aCursor.mHotspotX, aCursor.mHotspotY);
auto CleanupPixBuf =
mozilla::MakeScopeExit([&]() { g_object_unref(pixbuf); });
cairo_surface_t* surface =
gdk_cairo_surface_create_from_pixbuf(pixbuf, gtkScale, nullptr);
if (!surface) {
return nullptr;
}
auto CleanupSurface =
mozilla::MakeScopeExit([&]() { cairo_surface_destroy(surface); });
return gdk_cursor_new_from_surface(gdk_display_get_default(), surface,
aCursor.mHotspotX, aCursor.mHotspotY);
}
void nsWindow::SetCursor(const Cursor& aCursor) {