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




commit 271ebd8e25952c84fbbd6285b3910f3e3e014001
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                     | 110 +++++++++++++++++++++++++++++++++-
 src/stylesheet/widgets/_tab-view.scss |  15 +++--
 2 files changed, 120 insertions(+), 5 deletions(-)
---
diff --git a/src/adw-tab-box.c b/src/adw-tab-box.c
index 37f6bdeb..607a1127 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,100 @@ adw_tab_box_size_allocate (GtkWidget *widget,
   update_visible (self);
 }
 
+static void
+snapshot_tab (AdwTabBox      *self,
+              GtkSnapshot    *snapshot,
+              TabInfo        *info,
+              cairo_region_t *clip_region)
+{
+  cairo_rectangle_int_t rect = { 0, 0, 0, 0 };
+  gboolean clip = FALSE;
+  int pos, width, scroll_pos;
+  int i, n;
+
+  if (gtk_widget_get_opacity (GTK_WIDGET (info->tab)) <= 0)
+    return;
+
+  rect.height = gtk_widget_get_height (GTK_WIDGET (self));
+  scroll_pos = (int) floor (gtk_adjustment_get_value (self->adjustment));
+
+  pos = get_tab_position (self, info);
+  width = info->width;
+
+  n = cairo_region_num_rectangles (clip_region);
+  for (i = 0; i < n; i++) {
+    cairo_rectangle_int_t clip_rect;
+    int x1, x2;
+
+    cairo_region_get_rectangle (clip_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, clip_rect.y, clip_rect.width, 
clip_rect.height));
+    gtk_widget_snapshot_child (GTK_WIDGET (self), GTK_WIDGET (info->tab), snapshot);
+    gtk_snapshot_pop (snapshot);
+    clip = TRUE;
+  }
+
+  if (!clip)
+    gtk_widget_snapshot_child (GTK_WIDGET (self), GTK_WIDGET (info->tab), snapshot);
+
+  rect.x = pos - scroll_pos;
+  rect.width = width;
+  cairo_region_subtract_rectangle (clip_region, &rect);
+}
+
+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 i, n;
+  GList *l;
+
+  rect.width = w;
+  rect.height = h;
+  region = cairo_region_create_rectangle (&rect);
+
+  if (self->reordered_tab)
+    snapshot_tab (self, snapshot, self->reordered_tab, region);
+
+  if (self->selected_tab)
+    snapshot_tab (self, snapshot, self->selected_tab, region);
+
+  for (l = self->tabs; l; l = l->next) {
+    TabInfo *info = l->data;
+
+    if (info == self->reordered_tab || info == self->selected_tab)
+      continue;
+
+    snapshot_tab (self, snapshot, info, region);
+  }
+
+  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 +3192,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 +3307,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 +3412,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]