diff --git a/CHANGELOG.md b/CHANGELOG.md index 3710363e..1c791ca7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ All notable changes to eww will be listed here, starting at changes since versio - Fix values in the `EWW_NET` variable (By: mario-kr) - Fix the gtk `expander` widget (By: ovalkonia) - Fix wayland monitor names support (By: dragonnn) +- Render image widget at full resolution when display scaling is enabled (By: zane-weissman) ### Features - Update rust toolchain to 1.81.0 (By: w-lfchen) diff --git a/crates/eww/src/widgets/widget_definitions.rs b/crates/eww/src/widgets/widget_definitions.rs index 29c14a08..40c56be0 100644 --- a/crates/eww/src/widgets/widget_definitions.rs +++ b/crates/eww/src/widgets/widget_definitions.rs @@ -12,6 +12,7 @@ use eww_shared_util::Spanned; use gdk::{ModifierType, NotifyType}; use glib::translate::FromGlib; use gtk::{self, glib, prelude::*, DestDefaults, TargetEntry, TargetList}; +use gtk::{cairo, gdk::ffi::gdk_cairo_surface_create_from_pixbuf}; use gtk::{gdk, pango}; use itertools::Itertools; use once_cell::sync::Lazy; @@ -591,6 +592,7 @@ fn build_gtk_image(bargs: &mut BuilderArgs) -> Result { // @prop preserve-aspect-ratio - whether to keep the aspect ratio when resizing an image. Default: true, false doesn't work for all image types // @prop fill-svg - sets the color of svg images prop(path: as_string, image_width: as_i32 = -1, image_height: as_i32 = -1, preserve_aspect_ratio: as_bool = true, fill_svg: as_string = "") { + if !path.ends_with(".svg") && !fill_svg.is_empty() { log::warn!("Fill attribute ignored, file is not an svg image"); } @@ -599,9 +601,11 @@ fn build_gtk_image(bargs: &mut BuilderArgs) -> Result { let pixbuf_animation = gtk::gdk_pixbuf::PixbufAnimation::from_file(std::path::PathBuf::from(path))?; gtk_widget.set_from_animation(&pixbuf_animation); } else { - let pixbuf; + let scale = gtk_widget.scale_factor(); + let pixbuf: gtk::gdk_pixbuf::Pixbuf; + // populate the pixel buffer - if path.ends_with(".svg") && !fill_svg.is_empty() { + if path.ends_with(".svg") && !fill_svg.is_empty() { // render with fill let svg_data = std::fs::read_to_string(std::path::PathBuf::from(path.clone()))?; // The fastest way to add/change fill color let svg_data = if svg_data.contains("fill=") { @@ -612,12 +616,25 @@ fn build_gtk_image(bargs: &mut BuilderArgs) -> Result { reg.replace(&svg_data, &format!(")?; + pixbuf = gtk::gdk_pixbuf::Pixbuf::from_stream_at_scale(&stream, image_width * scale, image_height * scale, preserve_aspect_ratio, None::<>k::gio::Cancellable>)?; stream.close(None::<>k::gio::Cancellable>)?; } else { - pixbuf = gtk::gdk_pixbuf::Pixbuf::from_file_at_scale(std::path::PathBuf::from(path), image_width, image_height, preserve_aspect_ratio)?; + pixbuf = gtk::gdk_pixbuf::Pixbuf::from_file_at_scale(std::path::PathBuf::from(path), image_width * scale, image_height * scale, preserve_aspect_ratio)?; + //gtk_widget.set_from_pixbuf(Some(&pixbuf)); } - gtk_widget.set_from_pixbuf(Some(&pixbuf)); + + // render to surface + let surface = unsafe { + // gtk::cairo::Surface will destroy the underlying surface on drop + let ptr = gdk_cairo_surface_create_from_pixbuf( + pixbuf.as_ptr(), + scale, + std::ptr::null_mut(), + ); + cairo::Surface::from_raw_full(ptr)? + }; + + gtk_widget.set_from_surface(Some(surface.as_ref())); } }, // @prop icon - name of a theme icon