diff --git a/include/gui.hpp b/include/gui.hpp index 992493a..da7ee59 100644 --- a/include/gui.hpp +++ b/include/gui.hpp @@ -5,6 +5,7 @@ #include "config.hpp" #include "gdkmm/pixbuf.h" +#include "gdkmm/pixbufanimation.h" #include "gtkmm/alignment.h" #include "gtkmm/box.h" #include "gtkmm/container.h" @@ -28,28 +29,53 @@ class Window : public Gtk::Window Gtk::Alignment m_alignment; Gtk::Label m_label; Gtk::Image *m_img, m_bg_image; - Glib::RefPtr m_original_pixbuf; + Glib::RefPtr m_iter; + Glib::RefPtr m_bg_animation; + Glib::RefPtr m_bg_static_image; + int m_width, m_height; - void update_background_image(const int width, const int height) + void on_window_resize(Gtk::Allocation& allocation) { - if (m_original_pixbuf) - { - const Glib::RefPtr scaled_pixbuf = - m_original_pixbuf->scale_simple(width, height, Gdk::INTERP_BILINEAR); + m_width = allocation.get_width(); + m_height = allocation.get_height(); - m_bg_image.set(scaled_pixbuf); - } + if (m_bg_static_image) + // static image: Update to fit the new window size + update_static_image(); + else if (m_iter) + // animated image: Update the current frame + update_frame(); } - // Signal handler for window resize - void on_window_resized(Gtk::Allocation& allocation) + bool on_update_animation() { - const int new_width = allocation.get_width(); - const int new_height = allocation.get_height(); + if (!m_iter) + m_iter = m_bg_animation->get_iter(nullptr); + else + m_iter->advance(); + + update_frame(); + return true; // continue the timer + } - // Update the background image with the new dimensions - update_background_image(new_width, new_height); + void update_static_image() + { + // scale the static image to fit the window size + const Glib::RefPtr scaled_image = m_bg_static_image->scale_simple(m_width, m_height, Gdk::INTERP_BILINEAR); + m_bg_image.set(scaled_image); } + + void update_frame() + { + // scale the current frame of the animation to fit the window size + const Glib::RefPtr current_frame = m_iter->get_pixbuf(); + if (current_frame) + { + const Glib::RefPtr scaled_frame = current_frame->scale_simple(m_width, m_height, Gdk::INTERP_BILINEAR); + m_bg_image.set(scaled_frame); + } + } + }; } // namespace GUI diff --git a/src/gui.cpp b/src/gui.cpp index 4e199d1..59ffc30 100644 --- a/src/gui.cpp +++ b/src/gui.cpp @@ -12,6 +12,7 @@ #include "fmt/ranges.h" #include "gdkmm/pixbufanimation.h" #include "gtkmm/enums.h" +#include "glibmm/main.h" #include "pangomm/fontdescription.h" #include "parse.hpp" #include "query.hpp" @@ -110,8 +111,8 @@ Window::Window(const Config& config, const colors_t& colors, const std::string_v m_box.set_orientation(Gtk::ORIENTATION_HORIZONTAL); // https://stackoverflow.com/a/76372996 - auto context = m_label.get_pango_context(); - Pango::FontDescription font(config.font); + Glib::RefPtr context = m_label.get_pango_context(); + Pango::FontDescription font(config.font); debug("font family = {}", font.get_family().raw()); debug("font style = {}", fmt::underlying(font.get_style())); debug("font weight = {}", fmt::underlying(font.get_weight())); @@ -136,8 +137,19 @@ Window::Window(const Config& config, const colors_t& colors, const std::string_v if (!std::filesystem::exists(config.gui_bg_image)) die("Background image path '{}' doesn't exist", config.gui_bg_image); - m_original_pixbuf = Gdk::Pixbuf::create_from_file(config.gui_bg_image); - m_bg_image.set(m_original_pixbuf); + m_bg_animation = Gdk::PixbufAnimation::create_from_file(config.gui_bg_image); + if (m_bg_animation->is_static_image()) + { + // set it initially and resize only on window resize + m_bg_static_image = m_bg_animation->get_static_image(); + update_static_image(); + } + else + { + // animated image: use timer to update frames + const int duration = m_bg_animation->get_iter(nullptr)->get_delay_time(); + Glib::signal_timeout().connect(sigc::mem_fun(*this, &Window::on_update_animation), duration); + } m_overlay.add_overlay(m_bg_image); } @@ -147,7 +159,7 @@ Window::Window(const Config& config, const colors_t& colors, const std::string_v m_overlay.add_overlay(m_alignment); add(m_overlay); - signal_size_allocate().connect(sigc::mem_fun(*this, &Window::on_window_resized)); + signal_size_allocate().connect(sigc::mem_fun(*this, &Window::on_window_resize)); show_all_children(); }