[libadwaita/wip/exalm/tab-overview] tab-view: Port away from GtkStack
- From: Alexander Mikhaylenko <alexm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libadwaita/wip/exalm/tab-overview] tab-view: Port away from GtkStack
- Date: Sun, 28 Aug 2022 17:02:43 +0000 (UTC)
commit 6ff6dbfb57a8b2628301d4b1834481105984b47e
Author: Alexander Mikhaylenko <alexm gnome org>
Date: Sat Aug 27 07:23:12 2022 +0400
tab-view: Port away from GtkStack
src/adw-tab-view.c | 128 +++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 104 insertions(+), 24 deletions(-)
---
diff --git a/src/adw-tab-view.c b/src/adw-tab-view.c
index e09db5ab..f2de2ff7 100644
--- a/src/adw-tab-view.c
+++ b/src/adw-tab-view.c
@@ -134,6 +134,8 @@ struct _AdwTabPage
float thumbnail_xalign;
float thumbnail_yalign;
+ GtkWidget *last_focus;
+
gboolean closing;
GdkPaintable *paintable;
};
@@ -166,7 +168,6 @@ struct _AdwTabView
{
GtkWidget parent_instance;
- GtkWidget *stack;
GListStore *children;
int n_pages;
@@ -314,6 +315,10 @@ adw_tab_page_finalize (GObject *object)
g_clear_pointer (&self->indicator_tooltip, g_free);
g_clear_pointer (&self->keyword, g_free);
+ if (self->last_focus)
+ g_object_remove_weak_pointer (G_OBJECT (self->last_focus),
+ (gpointer *) &self->last_focus);
+
G_OBJECT_CLASS (adw_tab_page_parent_class)->finalize (object);
}
@@ -1175,7 +1180,7 @@ page_belongs_to_this_view (AdwTabView *self,
if (!page)
return FALSE;
- return gtk_widget_get_parent (page->child) == self->stack;
+ return gtk_widget_get_parent (page->child) == GTK_WIDGET (self);
}
static inline gboolean
@@ -1198,7 +1203,9 @@ attach_page (AdwTabView *self,
g_list_store_insert (self->children, position, page);
- gtk_stack_add_child (GTK_STACK (self->stack), child);
+ gtk_widget_set_child_visible (child, FALSE);
+ gtk_widget_set_parent (child, GTK_WIDGET (self));
+ gtk_widget_queue_resize (GTK_WIDGET (self));
g_object_freeze_notify (G_OBJECT (self));
@@ -1224,14 +1231,36 @@ set_selected_page (AdwTabView *self,
{
guint old_position = GTK_INVALID_LIST_POSITION;
guint new_position = GTK_INVALID_LIST_POSITION;
+ gboolean contains_focus = FALSE;
if (self->selected_page == selected_page)
return;
if (self->selected_page) {
+ GtkRoot *root = gtk_widget_get_root (GTK_WIDGET (self));
+ GtkWidget *focus = root ? gtk_root_get_focus (root) : NULL;
+
if (notify_pages && self->pages)
old_position = adw_tab_view_get_page_position (self, self->selected_page);
+ if (!gtk_widget_in_destruction (GTK_WIDGET (self)) &&
+ focus &&
+ self->selected_page &&
+ self->selected_page->child &&
+ gtk_widget_is_ancestor (focus, self->selected_page->child)) {
+ contains_focus = TRUE;
+
+ if (self->selected_page->last_focus)
+ g_object_remove_weak_pointer (G_OBJECT (self->selected_page->last_focus),
+ (gpointer *) &self->selected_page->last_focus);
+ self->selected_page->last_focus = focus;
+ g_object_add_weak_pointer (G_OBJECT (self->selected_page->last_focus),
+ (gpointer *) &self->selected_page->last_focus);
+ }
+
+ if (self->selected_page->child)
+ gtk_widget_set_child_visible (self->selected_page->child, FALSE);
+
set_page_selected (self->selected_page, FALSE);
}
@@ -1241,8 +1270,19 @@ set_selected_page (AdwTabView *self,
if (notify_pages && self->pages)
new_position = adw_tab_view_get_page_position (self, self->selected_page);
- gtk_stack_set_visible_child (GTK_STACK (self->stack),
- adw_tab_page_get_child (selected_page));
+ if (!gtk_widget_in_destruction (GTK_WIDGET (self))) {
+ gtk_widget_set_child_visible (selected_page->child, TRUE);
+
+ if (contains_focus) {
+ if (selected_page->last_focus)
+ gtk_widget_grab_focus (selected_page->last_focus);
+ else
+ gtk_widget_child_focus (selected_page->child, GTK_DIR_TAB_FORWARD);
+ }
+
+ gtk_widget_queue_allocate (GTK_WIDGET (self));
+ }
+
set_page_selected (self->selected_page, TRUE);
}
@@ -1308,7 +1348,7 @@ select_previous_page (AdwTabView *self,
static void
detach_page (AdwTabView *self,
AdwTabPage *page,
- gboolean notify_pages)
+ gboolean in_dispose)
{
int pos = adw_tab_view_get_page_position (self, page);
GtkWidget *child;
@@ -1321,7 +1361,7 @@ detach_page (AdwTabView *self,
g_object_ref (child);
if (self->n_pages == 1)
- set_selected_page (self, NULL, notify_pages);
+ set_selected_page (self, NULL, !in_dispose);
g_list_store_remove (self->children, pos);
@@ -1334,11 +1374,14 @@ detach_page (AdwTabView *self,
g_object_thaw_notify (G_OBJECT (self));
- gtk_stack_remove (GTK_STACK (self->stack), child);
+ gtk_widget_unparent (child);
+
+ if (!in_dispose)
+ gtk_widget_queue_resize (GTK_WIDGET (self));
g_signal_emit (self, signals[SIGNAL_PAGE_DETACHED], 0, page, pos);
- if (notify_pages && self->pages)
+ if (!in_dispose && self->pages)
g_list_model_items_changed (G_LIST_MODEL (self->pages), pos, 1, 0);
g_object_unref (child);
@@ -1643,6 +1686,50 @@ init_shortcuts (AdwTabView *self,
(i + 9) % 10); /* Alt+0 means page 10, not 0 */
}
+static void
+adw_tab_view_measure (GtkWidget *widget,
+ GtkOrientation orientation,
+ int for_size,
+ int *minimum,
+ int *natural,
+ int *minimum_baseline,
+ int *natural_baseline)
+{
+ AdwTabView *self = ADW_TAB_VIEW (widget);
+ int i;
+
+ *minimum = 0;
+ *natural = 0;
+
+ for (i = 0; i < self->n_pages; i++) {
+ AdwTabPage *page = adw_tab_view_get_nth_page (self, i);
+
+ if (gtk_widget_get_visible (page->child)) {
+ int child_min, child_nat;
+
+ gtk_widget_measure (page->child, orientation, for_size,
+ &child_min, &child_nat, NULL, NULL);
+
+ *minimum = MAX (*minimum, child_min);
+ *natural = MAX (*natural, child_nat);
+ }
+ }
+}
+
+static void
+adw_tab_view_size_allocate (GtkWidget *widget,
+ int width,
+ int height,
+ int baseline)
+{
+ AdwTabView *self = ADW_TAB_VIEW (widget);
+
+ if (!self->selected_page)
+ return;
+
+ gtk_widget_allocate (self->selected_page->child, width, height, baseline, NULL);
+}
+
static void
adw_tab_view_dispose (GObject *object)
{
@@ -1654,13 +1741,11 @@ adw_tab_view_dispose (GObject *object)
while (self->n_pages) {
AdwTabPage *page = adw_tab_view_get_nth_page (self, 0);
- detach_page (self, page, FALSE);
+ detach_page (self, page, TRUE);
}
g_clear_object (&self->children);
- g_clear_pointer (&self->stack, gtk_widget_unparent);
-
G_OBJECT_CLASS (adw_tab_view_parent_class)->dispose (object);
}
@@ -1768,6 +1853,9 @@ adw_tab_view_class_init (AdwTabViewClass *klass)
object_class->get_property = adw_tab_view_get_property;
object_class->set_property = adw_tab_view_set_property;
+ widget_class->measure = adw_tab_view_measure;
+ widget_class->size_allocate = adw_tab_view_size_allocate;
+ widget_class->get_request_mode = adw_widget_get_request_mode;
widget_class->compute_expand = adw_widget_compute_expand;
/**
@@ -2093,7 +2181,7 @@ adw_tab_view_class_init (AdwTabViewClass *klass)
G_CALLBACK (close_page_cb));
gtk_widget_class_set_css_name (widget_class, "tabview");
- gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
+ gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_GROUP);
}
static void
@@ -2105,14 +2193,6 @@ adw_tab_view_init (AdwTabView *self)
self->default_icon = G_ICON (g_themed_icon_new ("adw-tab-icon-missing-symbolic"));
self->shortcuts = ADW_TAB_VIEW_SHORTCUT_ALL_SHORTCUTS;
- self->stack = gtk_stack_new ();
- gtk_widget_show (self->stack);
- gtk_widget_set_parent (self->stack, GTK_WIDGET (self));
-
- g_object_bind_property (self, "is-transferring-page",
- self->stack, "can-target",
- G_BINDING_INVERT_BOOLEAN);
-
tab_view_list = g_slist_prepend (tab_view_list, self);
controller = gtk_shortcut_controller_new ();
@@ -3280,7 +3360,7 @@ adw_tab_view_get_page (AdwTabView *self,
g_return_val_if_fail (ADW_IS_TAB_VIEW (self), NULL);
g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
- g_return_val_if_fail (gtk_widget_get_parent (child) == self->stack, NULL);
+ g_return_val_if_fail (gtk_widget_get_parent (child) == GTK_WIDGET (self), NULL);
for (i = 0; i < self->n_pages; i++) {
AdwTabPage *page = adw_tab_view_get_nth_page (self, i);
@@ -3625,7 +3705,7 @@ adw_tab_view_close_page_finish (AdwTabView *self,
adw_tab_paintable_freeze (ADW_TAB_PAINTABLE (page->paintable));
if (confirm)
- detach_page (self, page, TRUE);
+ detach_page (self, page, FALSE);
}
/**
@@ -3905,7 +3985,7 @@ adw_tab_view_detach_page (AdwTabView *self,
begin_transfer_for_group (self);
- detach_page (self, page, TRUE);
+ detach_page (self, page, FALSE);
}
void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]