[libhandy] tab: Make sure buttons don't interfere with scrolling



commit ec011ea80ec5901b13d760fa27b31385b7ade192
Author: Alexander Mikhaylenko <alexm gnome org>
Date:   Mon Feb 8 15:24:01 2021 +0500

    tab: Make sure buttons don't interfere with scrolling
    
    Don't show close buttons on hover unless the tab is fully visible, and
    don't make indicator clickable in that case.

 src/hdy-tab-box.c     | 22 +++++++++++++---------
 src/hdy-tab-private.h |  3 +++
 src/hdy-tab.c         | 31 ++++++++++++++++++++++++++-----
 3 files changed, 42 insertions(+), 14 deletions(-)
---
diff --git a/src/hdy-tab-box.c b/src/hdy-tab-box.c
index 07064a99..9d39cd7f 100644
--- a/src/hdy-tab-box.c
+++ b/src/hdy-tab-box.c
@@ -699,7 +699,7 @@ reorder_tab_cb (HdyTabBox        *self,
 /* Scrolling */
 
 static void
-update_needs_attention (HdyTabBox *self)
+update_visible (HdyTabBox *self)
 {
   gboolean left = FALSE, right = FALSE;
   GList *l;
@@ -721,11 +721,15 @@ update_needs_attention (HdyTabBox *self)
     if (!info->page)
       continue;
 
+    pos = get_tab_position (self, info);
+
+    hdy_tab_set_fully_visible (info->tab,
+                               pos + OVERLAP >= value &&
+                               pos + info->width - OVERLAP <= value + page_size);
+
     if (!hdy_tab_page_get_needs_attention (info->page))
       continue;
 
-    pos = get_tab_position (self, info);
-
     if (pos + info->width / 2.0 <= value)
       left = TRUE;
 
@@ -820,7 +824,7 @@ adjustment_value_changed_cb (HdyTabBox *self)
   self->hover_x += (value - self->adjustment_prev_value);
 
   update_hover (self);
-  update_needs_attention (self);
+  update_visible (self);
 
   if (self->drop_target_tab) {
     self->drop_target_x += (value - self->adjustment_prev_value);
@@ -1647,7 +1651,7 @@ page_attached_cb (HdyTabBox  *self,
   info->notify_needs_attention_id =
     g_signal_connect_object (page,
                              "notify::needs-attention",
-                             G_CALLBACK (update_needs_attention),
+                             G_CALLBACK (update_visible),
                              self,
                              G_CONNECT_SWAPPED);
 
@@ -2539,7 +2543,7 @@ hdy_tab_box_size_allocate (GtkWidget     *widget,
   self->allocated_width = allocation->width;
 
   if (!self->n_tabs)
-      return;
+    return;
 
   if (self->pinned) {
     for (l = self->tabs; l; l = l->next) {
@@ -2630,7 +2634,7 @@ hdy_tab_box_size_allocate (GtkWidget     *widget,
   }
 
   update_hover (self);
-  update_needs_attention (self);
+  update_visible (self);
 }
 
 static gboolean
@@ -3731,14 +3735,14 @@ hdy_tab_box_set_adjustment (HdyTabBox     *self,
 
   if (self->adjustment) {
     g_signal_handlers_disconnect_by_func (self->adjustment, adjustment_value_changed_cb, self);
-    g_signal_handlers_disconnect_by_func (self->adjustment, update_needs_attention, self);
+    g_signal_handlers_disconnect_by_func (self->adjustment, update_visible, self);
   }
 
   g_set_object (&self->adjustment, adjustment);
 
   if (self->adjustment) {
     g_signal_connect_object (self->adjustment, "value-changed", G_CALLBACK (adjustment_value_changed_cb), 
self, G_CONNECT_SWAPPED);
-    g_signal_connect_object (self->adjustment, "notify::page-size", G_CALLBACK (update_needs_attention), 
self, G_CONNECT_SWAPPED);
+    g_signal_connect_object (self->adjustment, "notify::page-size", G_CALLBACK (update_visible), self, 
G_CONNECT_SWAPPED);
   }
 
   g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ADJUSTMENT]);
diff --git a/src/hdy-tab-private.h b/src/hdy-tab-private.h
index 88e9aa0a..ab277ace 100644
--- a/src/hdy-tab-private.h
+++ b/src/hdy-tab-private.h
@@ -43,4 +43,7 @@ gboolean hdy_tab_get_inverted (HdyTab *self);
 void     hdy_tab_set_inverted (HdyTab   *self,
                                gboolean  inverted);
 
+void hdy_tab_set_fully_visible (HdyTab   *self,
+                                gboolean  fully_visible);
+
 G_END_DECLS
diff --git a/src/hdy-tab.c b/src/hdy-tab.c
index 42996b97..4e80b628 100644
--- a/src/hdy-tab.c
+++ b/src/hdy-tab.c
@@ -48,6 +48,7 @@ struct _HdyTab
   gboolean title_inverted;
   gboolean close_overlap;
   gboolean show_close;
+  gboolean fully_visible;
 
   HdyAnimation *close_btn_animation;
   cairo_pattern_t *gradient;
@@ -98,6 +99,7 @@ close_btn_animation_done_cb (HdyTab *self)
 {
   if (!self->show_close)
     gtk_widget_set_child_visible (self->close_btn, FALSE);
+  gtk_widget_set_opacity (self->close_btn, self->show_close ? 1 : 0);
 
   g_clear_pointer (&self->close_btn_animation, hdy_animation_unref);
 }
@@ -119,7 +121,7 @@ update_state (HdyTab *self)
 
   gtk_widget_set_state_flags (GTK_WIDGET (self), new_state, TRUE);
 
-  show_close = self->hovering || self->selected || self->dragging;
+  show_close = (self->hovering && self->fully_visible) || self->selected || self->dragging;
 
   if (self->show_close != show_close) {
     gdouble opacity = gtk_widget_get_opacity (self->close_btn);
@@ -129,11 +131,13 @@ update_state (HdyTab *self)
 
     self->show_close = show_close;
 
-    if (self->show_close)
+    /* gtk_widget_set_child_visible() does not no-op when it's already
+     * visible, avoid extra work */
+    if (show_close && !gtk_widget_get_child_visible (self->close_btn))
       gtk_widget_set_child_visible (self->close_btn, TRUE);
 
     self->close_btn_animation =
-      hdy_animation_new (self->close_btn,
+      hdy_animation_new (GTK_WIDGET (self),
                          opacity,
                          self->show_close ? 1 : 0,
                          CLOSE_BTN_ANIMATION_DURATION,
@@ -206,7 +210,7 @@ static void
 update_indicator (HdyTab *self)
 {
   gboolean activatable = self->page && hdy_tab_page_get_indicator_activatable (self->page);
-  gboolean clickable = activatable && (self->selected || !self->pinned);
+  gboolean clickable = activatable && (self->selected || (!self->pinned && self->fully_visible));
 
   set_style_class (self->indicator_btn, "clickable", clickable);
 }
@@ -267,7 +271,7 @@ indicator_clicked_cb (HdyTab *self)
     return;
 
   clickable = hdy_tab_page_get_indicator_activatable (self->page) &&
-              (self->selected || !self->pinned);
+              (self->selected || (!self->pinned && self->fully_visible));
 
   if (!clickable) {
     hdy_tab_view_set_selected_page (self->view, self->page);
@@ -1117,3 +1121,20 @@ hdy_tab_set_inverted (HdyTab   *self,
 
   g_object_notify_by_pspec (G_OBJECT (self), props[PROP_INVERTED]);
 }
+
+void
+hdy_tab_set_fully_visible (HdyTab   *self,
+                           gboolean  fully_visible)
+{
+  g_return_if_fail (HDY_IS_TAB (self));
+
+  fully_visible = !!fully_visible;
+
+  if (self->fully_visible == fully_visible)
+    return;
+
+  self->fully_visible = fully_visible;
+
+  update_state (self);
+  update_indicator (self);
+}


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