2626 * SPDX-License-Identifier: GPL-3.0-or-later
2727 */
2828
29- #include "bz-screenshots-carousel.h"
30- #include "bz-decorated-screenshot.h"
3129#include <adwaita.h>
3230
31+ #include "bz-decorated-screenshot.h"
32+ #include "bz-screenshots-carousel.h"
33+
34+ #define LIGHT_CLASS "screenshot-carousel-light"
35+ #define DARK_CLASS "screenshot-carousel-dark"
36+ #define LIGHT_MIX_PERCENTAGE 25
37+ #define DARK_MIX_PERCENTAGE 4
38+
3339struct _BzScreenshotsCarousel
3440{
3541 GtkWidget parent_instance ;
@@ -41,9 +47,12 @@ struct _BzScreenshotsCarousel
4147 GtkButton * next_button ;
4248 GtkWidget * next_button_revealer ;
4349
44- GListModel * model ;
45- gboolean compact ;
46- gulong items_changed_id ;
50+ GListModel * model ;
51+ gboolean compact ;
52+ char * light_accent_color ;
53+ char * dark_accent_color ;
54+ GtkCssProvider * css ;
55+ gulong items_changed_id ;
4756};
4857
4958G_DEFINE_FINAL_TYPE (BzScreenshotsCarousel , bz_screenshots_carousel , GTK_TYPE_WIDGET )
5362 PROP_0 ,
5463 PROP_MODEL ,
5564 PROP_COMPACT ,
65+ PROP_LIGHT_ACCENT_COLOR ,
66+ PROP_DARK_ACCENT_COLOR ,
5667 N_PROPS
5768};
5869
6677
6778static guint signals [N_SIGNALS ];
6879
80+ static void refresh_css (BzScreenshotsCarousel * self );
81+ static void clear_css (BzScreenshotsCarousel * self );
82+
6983static void
7084update_button_visibility (BzScreenshotsCarousel * self )
7185{
@@ -270,6 +284,24 @@ on_model_items_changed (GListModel *model,
270284 populate_carousel (self );
271285}
272286
287+ static void
288+ dark_changed (BzScreenshotsCarousel * self ,
289+ GParamSpec * pspec ,
290+ AdwStyleManager * mgr )
291+ {
292+ gboolean is_dark ;
293+
294+ if (self -> css == NULL )
295+ return ;
296+
297+ is_dark = adw_style_manager_get_dark (adw_style_manager_get_default ());
298+
299+ gtk_widget_remove_css_class (GTK_WIDGET (self ), LIGHT_CLASS );
300+ gtk_widget_remove_css_class (GTK_WIDGET (self ), DARK_CLASS );
301+
302+ gtk_widget_add_css_class (GTK_WIDGET (self ), is_dark ? DARK_CLASS : LIGHT_CLASS );
303+ }
304+
273305static void
274306bz_screenshots_carousel_dispose (GObject * object )
275307{
@@ -284,6 +316,11 @@ bz_screenshots_carousel_dispose (GObject *object)
284316
285317 g_clear_object (& self -> model );
286318
319+ clear_css (self );
320+
321+ g_clear_pointer (& self -> light_accent_color , g_free );
322+ g_clear_pointer (& self -> dark_accent_color , g_free );
323+
287324 if (root_child != NULL )
288325 gtk_widget_unparent (root_child );
289326
@@ -308,6 +345,12 @@ bz_screenshots_carousel_get_property (GObject *object,
308345 case PROP_COMPACT :
309346 g_value_set_boolean (value , self -> compact );
310347 break ;
348+ case PROP_LIGHT_ACCENT_COLOR :
349+ g_value_set_string (value , self -> light_accent_color );
350+ break ;
351+ case PROP_DARK_ACCENT_COLOR :
352+ g_value_set_string (value , self -> dark_accent_color );
353+ break ;
311354 default :
312355 G_OBJECT_WARN_INVALID_PROPERTY_ID (object , prop_id , pspec );
313356 }
@@ -329,6 +372,12 @@ bz_screenshots_carousel_set_property (GObject *object,
329372 case PROP_COMPACT :
330373 bz_screenshots_carousel_set_compact (self , g_value_get_boolean (value ));
331374 break ;
375+ case PROP_LIGHT_ACCENT_COLOR :
376+ bz_screenshots_carousel_set_light_accent_color (self , g_value_get_string (value ));
377+ break ;
378+ case PROP_DARK_ACCENT_COLOR :
379+ bz_screenshots_carousel_set_dark_accent_color (self , g_value_get_string (value ));
380+ break ;
332381 default :
333382 G_OBJECT_WARN_INVALID_PROPERTY_ID (object , prop_id , pspec );
334383 }
@@ -358,6 +407,20 @@ bz_screenshots_carousel_class_init (BzScreenshotsCarouselClass *klass)
358407 FALSE,
359408 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS );
360409
410+ properties [PROP_LIGHT_ACCENT_COLOR ] =
411+ g_param_spec_string ("light-accent-color" ,
412+ NULL ,
413+ NULL ,
414+ NULL ,
415+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS );
416+
417+ properties [PROP_DARK_ACCENT_COLOR ] =
418+ g_param_spec_string ("dark-accent-color" ,
419+ NULL ,
420+ NULL ,
421+ NULL ,
422+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS );
423+
361424 g_object_class_install_properties (object_class , N_PROPS , properties );
362425
363426 signals [SIGNAL_CLICKED ] =
@@ -396,6 +459,13 @@ bz_screenshots_carousel_init (BzScreenshotsCarousel *self)
396459
397460 if (self -> carousel )
398461 adw_carousel_set_allow_scroll_wheel (self -> carousel , FALSE);
462+
463+ g_signal_connect_object (
464+ adw_style_manager_get_default (),
465+ "notify::dark" ,
466+ G_CALLBACK (dark_changed ),
467+ self ,
468+ G_CONNECT_SWAPPED );
399469}
400470
401471GtkWidget *
@@ -455,3 +525,120 @@ bz_screenshots_carousel_get_compact (BzScreenshotsCarousel *self)
455525 g_return_val_if_fail (BZ_IS_SCREENSHOTS_CAROUSEL (self ), FALSE);
456526 return self -> compact ;
457527}
528+
529+ void
530+ bz_screenshots_carousel_set_light_accent_color (BzScreenshotsCarousel * self ,
531+ const char * color )
532+ {
533+ g_return_if_fail (BZ_IS_SCREENSHOTS_CAROUSEL (self ));
534+
535+ if (color == self -> light_accent_color ||
536+ (color != NULL &&
537+ g_strcmp0 (self -> light_accent_color , color ) == 0 ))
538+ return ;
539+
540+ g_clear_pointer (& self -> light_accent_color , g_free );
541+ if (color != NULL )
542+ self -> light_accent_color = g_strdup (color );
543+
544+ refresh_css (self );
545+
546+ g_object_notify_by_pspec (G_OBJECT (self ), properties [PROP_LIGHT_ACCENT_COLOR ]);
547+ }
548+
549+ const char *
550+ bz_screenshots_carousel_get_light_accent_color (BzScreenshotsCarousel * self )
551+ {
552+ g_return_val_if_fail (BZ_IS_SCREENSHOTS_CAROUSEL (self ), NULL );
553+ return self -> light_accent_color ;
554+ }
555+
556+ void
557+ bz_screenshots_carousel_set_dark_accent_color (BzScreenshotsCarousel * self ,
558+ const char * color )
559+ {
560+ g_return_if_fail (BZ_IS_SCREENSHOTS_CAROUSEL (self ));
561+
562+ if (color == self -> dark_accent_color ||
563+ (color != NULL &&
564+ g_strcmp0 (self -> dark_accent_color , color ) == 0 ))
565+ return ;
566+
567+ g_clear_pointer (& self -> dark_accent_color , g_free );
568+ if (color != NULL )
569+ self -> dark_accent_color = g_strdup (color );
570+
571+ refresh_css (self );
572+
573+ g_object_notify_by_pspec (G_OBJECT (self ), properties [PROP_DARK_ACCENT_COLOR ]);
574+ }
575+
576+ const char *
577+ bz_screenshots_carousel_get_dark_accent_color (BzScreenshotsCarousel * self )
578+ {
579+ g_return_val_if_fail (BZ_IS_SCREENSHOTS_CAROUSEL (self ), NULL );
580+ return self -> dark_accent_color ;
581+ }
582+
583+ static void
584+ refresh_css (BzScreenshotsCarousel * self )
585+ {
586+ g_autofree char * css_string = NULL ;
587+ g_autofree char * light_bg = NULL ;
588+ g_autofree char * dark_bg = NULL ;
589+ gboolean is_dark ;
590+
591+ clear_css (self );
592+
593+ if (self -> light_accent_color == NULL &&
594+ self -> dark_accent_color == NULL )
595+ return ;
596+
597+ if (self -> light_accent_color != NULL && self -> dark_accent_color != NULL )
598+ light_bg = g_strdup_printf ("color-mix(in srgb, %s %d%%, rgb(255,255,255))" ,
599+ self -> light_accent_color , LIGHT_MIX_PERCENTAGE );
600+ else if (self -> light_accent_color != NULL )
601+ light_bg = g_strdup (self -> light_accent_color );
602+ else if (self -> dark_accent_color != NULL )
603+ light_bg = g_strdup_printf ("color-mix(in srgb, %s %d%%, rgb(255,255,255))" ,
604+ self -> dark_accent_color , LIGHT_MIX_PERCENTAGE );
605+
606+ if (self -> light_accent_color != NULL && self -> dark_accent_color != NULL )
607+ dark_bg = g_strdup_printf ("color-mix(in srgb, %s %d%%, rgb(29,29,32))" ,
608+ self -> dark_accent_color , DARK_MIX_PERCENTAGE );
609+ else if (self -> dark_accent_color != NULL )
610+ dark_bg = g_strdup (self -> dark_accent_color );
611+ else if (self -> light_accent_color != NULL )
612+ dark_bg = g_strdup_printf ("color-mix(in srgb, %s %d%%, rgb(29,29,32))" ,
613+ self -> light_accent_color , DARK_MIX_PERCENTAGE );
614+
615+ css_string = g_strdup_printf (
616+ ".%s{background-color:%s;}\n"
617+ ".%s{background-color:%s;}" ,
618+ LIGHT_CLASS , light_bg ,
619+ DARK_CLASS , dark_bg );
620+
621+ self -> css = gtk_css_provider_new ();
622+ gtk_css_provider_load_from_string (self -> css , css_string );
623+ gtk_style_context_add_provider_for_display (
624+ gdk_display_get_default (),
625+ GTK_STYLE_PROVIDER (self -> css ),
626+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION );
627+
628+ is_dark = adw_style_manager_get_dark (adw_style_manager_get_default ());
629+
630+ gtk_widget_add_css_class (GTK_WIDGET (self ), is_dark ? DARK_CLASS : LIGHT_CLASS );
631+ }
632+
633+ static void
634+ clear_css (BzScreenshotsCarousel * self )
635+ {
636+ gtk_widget_remove_css_class (GTK_WIDGET (self ), LIGHT_CLASS );
637+ gtk_widget_remove_css_class (GTK_WIDGET (self ), DARK_CLASS );
638+
639+ if (self -> css != NULL )
640+ gtk_style_context_remove_provider_for_display (
641+ gdk_display_get_default (),
642+ GTK_STYLE_PROVIDER (self -> css ));
643+ g_clear_pointer (& self -> css , g_object_unref );
644+ }
0 commit comments