From dfb9ea645c300aab2a32cbd3728ca31284b6df10 Mon Sep 17 00:00:00 2001 From: Hari Rana Date: Tue, 5 May 2026 09:27:12 -0400 Subject: [PATCH] common/date-chooser: Use GcalGizmo GcalGizmo allows us to handle focus within child widgets much more cleanly, as it no longer requires us to override the ancestor and re-iterating through children. Part-of: --- src/gui/common/gcal-date-chooser.blp | 10 ++- src/gui/common/gcal-date-chooser.c | 112 ++++++++++++--------------- 2 files changed, 58 insertions(+), 64 deletions(-) diff --git a/src/gui/common/gcal-date-chooser.blp b/src/gui/common/gcal-date-chooser.blp index 9cc3f2a4..b179f497 100644 --- a/src/gui/common/gcal-date-chooser.blp +++ b/src/gui/common/gcal-date-chooser.blp @@ -64,15 +64,19 @@ template $GcalDateChooser: Adw.Bin { } } - Grid grid { - row-homogeneous: true; - column-homogeneous: true; + $GcalGizmo gizmo { + layout-manager: BinLayout {}; layout { column: 0; column-span: 2; row: 1; } + + Grid grid { + row-homogeneous: true; + column-homogeneous: true; + } } } } diff --git a/src/gui/common/gcal-date-chooser.c b/src/gui/common/gcal-date-chooser.c index f8700390..0ce86bec 100644 --- a/src/gui/common/gcal-date-chooser.c +++ b/src/gui/common/gcal-date-chooser.c @@ -22,6 +22,7 @@ #include "gcal-utils.h" #include "gcal-date-chooser.h" +#include "gcal-gizmo.h" #include "gcal-date-chooser-day.h" #include "gcal-multi-choice.h" #include "gcal-range-tree.h" @@ -44,6 +45,8 @@ struct _GcalDateChooser GtkWidget *popover_month_choice; GtkWidget *year_choice; GtkWidget *combined_choice; + + GcalGizmo *gizmo; GtkWidget *grid; GtkWidget *day_grid; @@ -671,6 +674,50 @@ gcal_view_interface_init (GcalViewInterface *iface) } +/* + * GcalGizmo overrides + */ + +static gboolean +gcal_gizmo_focus (GcalGizmo *gizmo, + GtkDirectionType direction, + gpointer user_data) +{ + GtkWidget *focus_widget, *new_focus; + GTypeClass *gizmo_parent_class; + gboolean is_tab, is_rtl; + GtkRoot *root; + + is_tab = direction == GTK_DIR_TAB_FORWARD || direction == GTK_DIR_TAB_BACKWARD; + + if (gtk_widget_get_focus_child (GTK_WIDGET (gizmo)) && is_tab) + return FALSE; + + if (direction == GTK_DIR_LEFT || direction == GTK_DIR_RIGHT) + { + is_rtl = gtk_widget_get_direction (GTK_WIDGET (gizmo)) == GTK_TEXT_DIR_RTL; + root = gtk_widget_get_root (GTK_WIDGET (gizmo)); + focus_widget = gtk_root_get_focus (root); + + g_assert (GCAL_IS_DATE_CHOOSER_DAY (focus_widget)); + + if (direction == (is_rtl ? GTK_DIR_LEFT : GTK_DIR_RIGHT)) + new_focus = gtk_widget_get_next_sibling (focus_widget); + else + new_focus = gtk_widget_get_prev_sibling (focus_widget); + + if (new_focus) + return gtk_widget_grab_focus (new_focus); + } + + gizmo_parent_class = g_type_class_peek_parent (G_OBJECT_GET_CLASS (gizmo)); + if (!GTK_WIDGET_CLASS (gizmo_parent_class)->focus (GTK_WIDGET (gizmo), direction)) + return gtk_widget_keynav_failed (GTK_WIDGET (gizmo), direction); + + return TRUE; +} + + /* * GcalTimelineSubscriber implementation */ @@ -885,65 +932,6 @@ gcal_date_chooser_finalize (GObject *object) G_OBJECT_CLASS (gcal_date_chooser_parent_class)->finalize (object); } -static gboolean -gcal_date_chooser_child_focus (GtkWidget *widget, - GtkDirectionType direction) -{ - GcalDateChooser *self = GCAL_DATE_CHOOSER (widget); - GtkRoot *root; - GtkWidget *focus_widget, *new_focus; - gboolean is_tab, is_rtl, left_or_right; - - is_tab = direction == GTK_DIR_TAB_FORWARD || direction == GTK_DIR_TAB_BACKWARD; - - if (gtk_widget_get_focus_child (self->grid)) - { - if (is_tab) - { - root = gtk_widget_get_root (self->grid); - - while (gtk_widget_get_focus_child (self->grid)) - { - GtkWidget *previous_widget = gtk_root_get_focus (root); - - GTK_WIDGET_CLASS (gcal_date_chooser_parent_class)->focus (widget, direction); - - if (previous_widget == gtk_root_get_focus (root)) - return FALSE; - } - - return TRUE; - } - - if (gtk_widget_child_focus (self->grid, direction)) - return TRUE; - - left_or_right = direction == GTK_DIR_LEFT || direction == GTK_DIR_RIGHT; - - if (left_or_right) - { - is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL; - root = gtk_widget_get_root (self->grid); - focus_widget = gtk_root_get_focus (root); - - g_assert (GCAL_IS_DATE_CHOOSER_DAY (focus_widget)); - - if (direction == (is_rtl ? GTK_DIR_LEFT : GTK_DIR_RIGHT)) - new_focus = gtk_widget_get_next_sibling (focus_widget); - else - new_focus = gtk_widget_get_prev_sibling (focus_widget); - - if (new_focus) - return gtk_widget_grab_focus (new_focus); - } - - gtk_widget_error_bell (self->grid); - return TRUE; - } - - return GTK_WIDGET_CLASS (gcal_date_chooser_parent_class)->focus (widget, direction); -} - static void gcal_date_chooser_dispose (GObject *object) { @@ -957,14 +945,13 @@ gcal_date_chooser_class_init (GcalDateChooserClass *class) GObjectClass *object_class = G_OBJECT_CLASS (class); g_type_ensure (GCAL_TYPE_MULTI_CHOICE); + g_type_ensure (GCAL_TYPE_GIZMO); object_class->dispose = gcal_date_chooser_dispose; object_class->finalize = gcal_date_chooser_finalize; object_class->set_property = calendar_set_property; object_class->get_property = calendar_get_property; - widget_class->focus = gcal_date_chooser_child_focus; - properties[PROP_SHOW_HEADING] = g_param_spec_boolean ("show-heading", "Show Heading", "If TRUE, a heading is displayed", @@ -1026,6 +1013,7 @@ gcal_date_chooser_class_init (GcalDateChooserClass *class) gtk_widget_class_bind_template_child (widget_class, GcalDateChooser, popover_month_choice); gtk_widget_class_bind_template_child (widget_class, GcalDateChooser, year_choice); gtk_widget_class_bind_template_child (widget_class, GcalDateChooser, grid); + gtk_widget_class_bind_template_child (widget_class, GcalDateChooser, gizmo); gtk_widget_class_bind_template_callback (widget_class, combined_multi_choice_changed); gtk_widget_class_bind_template_callback (widget_class, get_combined_choice_visible); @@ -1099,6 +1087,8 @@ gcal_date_chooser_init (GcalDateChooser *self) gtk_widget_init_template (GTK_WIDGET (self)); + gcal_gizmo_set_focus_func (self->gizmo, gcal_gizmo_focus, NULL); + for (col = 0; col < N_WEEKDAYS; col++) { self->cols[col] = gtk_label_new ("");