[libadwaita/wip/exalm/recoloring-fixes: 35/35] tab-box: Support recolorability better




commit fcc99b494994a6094e37cfbf6c7543fc79ffc208
Author: Alexander Mikhaylenko <alexm gnome org>
Date:   Mon Sep 13 18:02:15 2021 +0500

    tab-box: Support recolorability better
    
    Move background to a separate widget instead of tab box itself.
    
    Make tabs clip other tabs and the new background. This means that we can
    have half-transparent background and borders on both, and let the
    background of the tab bar be seen through.
    
    This doesn't adjust colors yet, that will be done later when refreshing
    colors in general. However, we can already get rid of the mix()ed border.

 src/adw-tab-box.c                     | 103 +++++++++++++++++++++++++++++++++-
 src/stylesheet/widgets/_tab-view.scss |  15 +++--
 2 files changed, 113 insertions(+), 5 deletions(-)
---
diff --git a/src/adw-tab-box.c b/src/adw-tab-box.c
index 37f6bdeb..37a01e13 100644
--- a/src/adw-tab-box.c
+++ b/src/adw-tab-box.c
@@ -11,6 +11,7 @@
 #include "adw-tab-box-private.h"
 #include "adw-animation-util-private.h"
 #include "adw-animation-private.h"
+#include "adw-gizmo-private.h"
 #include "adw-tab-private.h"
 #include "adw-tab-bar-private.h"
 #include "adw-tab-view-private.h"
@@ -93,6 +94,7 @@ struct _AdwTabBox
   int n_tabs;
 
   GtkPopover *context_menu;
+  GtkWidget *background;
 
   int allocated_width;
   int last_width;
@@ -2904,6 +2906,10 @@ adw_tab_box_size_allocate (GtkWidget *widget,
   int pos;
   double value;
 
+  gtk_widget_measure (self->background, GTK_ORIENTATION_HORIZONTAL, -1,
+                      NULL, NULL, NULL, NULL);
+  gtk_widget_allocate (self->background, width, height, baseline, NULL);
+
   adw_tab_box_measure (widget, GTK_ORIENTATION_HORIZONTAL, -1,
                        &self->allocated_width, NULL, NULL, NULL);
   self->allocated_width = MAX (self->allocated_width, width);
@@ -2983,7 +2989,7 @@ adw_tab_box_size_allocate (GtkWidget *widget,
     if (is_rtl)
       info->pos -= info->width;
 
-    child_allocation.x = ((info == self->reordered_tab) ? self->reorder_window_x : info->pos) - value;
+    child_allocation.x = ((info == self->reordered_tab) ? self->reorder_window_x : info->pos) - (int) floor 
(value);
     child_allocation.y = 0;
     child_allocation.width = info->width;
     child_allocation.height = height;
@@ -3018,6 +3024,93 @@ adw_tab_box_size_allocate (GtkWidget *widget,
   update_visible (self);
 }
 
+static void
+adw_tab_box_snapshot (GtkWidget   *widget,
+                      GtkSnapshot *snapshot)
+{
+  AdwTabBox *self = ADW_TAB_BOX (widget);
+  int w = gtk_widget_get_width (widget);
+  int h = gtk_widget_get_height (widget);
+  cairo_rectangle_int_t rect = { 0, 0, 0, 0 };
+  cairo_region_t *region;
+  int scroll_pos;
+  int i, n;
+  GList *l;
+
+  rect.width = w;
+  rect.height = h;
+  region = cairo_region_create_rectangle (&rect);
+  scroll_pos = (int) floor (gtk_adjustment_get_value (self->adjustment));
+
+  if (self->reordered_tab) {
+    TabInfo *info = self->reordered_tab;
+
+    if (gtk_widget_get_opacity (GTK_WIDGET (info->tab)) > 0) {
+      gtk_widget_snapshot_child (widget, GTK_WIDGET (info->tab), snapshot);
+
+      rect.x = get_tab_position (self, info) - scroll_pos;
+      rect.width = info->width;
+      cairo_region_subtract_rectangle (region, &rect);
+    }
+  }
+
+  for (l = self->tabs; l; l = l->next) {
+    TabInfo *info = l->data;
+    gboolean clip = FALSE;
+    int pos, width;
+
+    if (info == self->reordered_tab)
+      continue;
+
+    if (gtk_widget_get_opacity (GTK_WIDGET (info->tab)) <= 0)
+      continue;
+
+    pos = get_tab_position (self, info);
+    width = info->width;
+
+    n = cairo_region_num_rectangles (region);
+    for (i = 0; i < n; i++) {
+      cairo_rectangle_int_t clip_rect;
+      int x1, x2;
+
+      cairo_region_get_rectangle (region, i, &clip_rect);
+      x1 = clip_rect.x + scroll_pos;
+      x2 = x1 + clip_rect.width;
+
+      if (x1 < pos && x2 > pos + width) {
+        clip = FALSE;
+        break;
+      }
+
+      if (x2 < pos || x1 > pos + width)
+        continue;
+
+      gtk_snapshot_push_clip (snapshot, &GRAPHENE_RECT_INIT (clip_rect.x, 0, clip_rect.width, h));
+      gtk_widget_snapshot_child (widget, GTK_WIDGET (info->tab), snapshot);
+      gtk_snapshot_pop (snapshot);
+      clip = TRUE;
+    }
+
+    if (!clip)
+      gtk_widget_snapshot_child (widget, GTK_WIDGET (info->tab), snapshot);
+
+    rect.x = pos - scroll_pos;
+    rect.width = width;
+    cairo_region_subtract_rectangle (region, &rect);
+  }
+
+  n = cairo_region_num_rectangles (region);
+  for (i = 0; i < n; i++) {
+    cairo_region_get_rectangle (region, i, &rect);
+
+    gtk_snapshot_push_clip (snapshot, &GRAPHENE_RECT_INIT (rect.x, rect.y, rect.width, rect.height));
+    gtk_widget_snapshot_child (widget, self->background, snapshot);
+    gtk_snapshot_pop (snapshot);
+  }
+
+  cairo_region_destroy (region);
+}
+
 static gboolean
 adw_tab_box_focus (GtkWidget        *widget,
                    GtkDirectionType  direction)
@@ -3092,6 +3185,8 @@ adw_tab_box_dispose (GObject *object)
 
   g_clear_handle_id (&self->drop_switch_timeout_id, g_source_remove);
 
+  g_clear_pointer (&self->background, gtk_widget_unparent);
+
   self->drag_gesture = NULL;
   self->tab_bar = NULL;
   adw_tab_box_set_view (self, NULL);
@@ -3205,6 +3300,7 @@ adw_tab_box_class_init (AdwTabBoxClass *klass)
 
   widget_class->measure = adw_tab_box_measure;
   widget_class->size_allocate = adw_tab_box_size_allocate;
+  widget_class->snapshot = adw_tab_box_snapshot;
   widget_class->focus = adw_tab_box_focus;
   widget_class->unrealize = adw_tab_box_unrealize;
   widget_class->unmap = adw_tab_box_unmap;
@@ -3309,6 +3405,11 @@ adw_tab_box_init (AdwTabBox *self)
 
   gtk_widget_set_overflow (GTK_WIDGET (self), GTK_OVERFLOW_HIDDEN);
 
+  self->background = adw_gizmo_new ("background", NULL, NULL, NULL, NULL, NULL, NULL);
+  gtk_widget_set_can_target (self->background, FALSE);
+  gtk_widget_set_can_focus (self->background, FALSE);
+  gtk_widget_set_parent (self->background, GTK_WIDGET (self));
+
   controller = gtk_event_controller_motion_new ();
   g_signal_connect_swapped (controller, "motion", G_CALLBACK (motion_cb), self);
   g_signal_connect_swapped (controller, "leave", G_CALLBACK (leave_cb), self);
diff --git a/src/stylesheet/widgets/_tab-view.scss b/src/stylesheet/widgets/_tab-view.scss
index e8c03590..e7fb32a4 100644
--- a/src/stylesheet/widgets/_tab-view.scss
+++ b/src/stylesheet/widgets/_tab-view.scss
@@ -1,5 +1,5 @@
 $tab_bg: $headerbar_bg_color;
-$tab_border: gtkmix($headerbar_border_color, $headerbar_bg_color, 100% * $headerbar_border_opacity);
+$tab_border: gtkalpha($headerbar_border_color, $headerbar_border_opacity);
 
 @mixin undershoot-gradient($dir) {
   @if $variant == 'dark' {
@@ -24,7 +24,7 @@ $tab_border: gtkmix($headerbar_border_color, $headerbar_bg_color, 100% * $header
 tabbar {
   .box {
     min-height: 38px;
-    background: gtkshade($tab_bg, .97);
+    background: $headerbar_bg_color;
     color: $headerbar_fg_color;
     border-bottom: 1px solid $tab_border;
   }
@@ -42,7 +42,7 @@ tabbar {
       border-right-width: 1px;
     }
 
-    tabbox {
+    tabbox > background {
       &:dir(ltr) {
         box-shadow: inset -1px 0 $tab_border;
       }
@@ -73,12 +73,17 @@ tabbar {
     @include need-attention-gradient("left");
   }
 
+  tabbox > background {
+    background: gtkshade($tab_bg, .97);
+  }
+
   tab {
     border-style: solid;
     border-color: $tab_border;
     border-width: 0 1px 0 1px;
     transition: background 150ms ease-in-out, $focus_transition;
     background-color: $tab_bg;
+    background-clip: padding-box;
 
     @include focus-ring();
 
@@ -97,7 +102,8 @@ tabbar {
 
   .start-action,
   .end-action {
-    background: $tab_bg;
+    background-color: $tab_bg;
+    background-clip: padding-box;
     border-color: $tab_border;
     border-style: solid;
     transition: background 150ms ease-in-out;
@@ -122,6 +128,7 @@ tabbar {
 dnd tab {
   min-height: 26px;
   background-color: gtkshade($tab_bg, 1.09);
+  color: $headerbar_fg_color;
 
   $_wm_border: if($variant=='light', transparentize(black, 0.77), transparentize(black, 0.25));
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]