views/month-view-row: Implement keyboard navigation for event widgets vertically

This commit is contained in:
Hari Rana
2026-02-24 21:22:26 -03:00
parent 4901709e63
commit e1c139782f
+64 -1
View File
@@ -243,6 +243,66 @@ find_last_event_widget (GcalMonthViewRow *self)
GCAL_RETURN (nearest ? g_steal_pointer (&nearest->widget) : NULL);
}
static GtkWidget *
find_nearest_vertical_event_widget (GcalMonthViewRow *self,
FocusEventData *focused,
GtkDirectionType direction)
{
g_autoptr (FocusEventData) candidate = NULL;
g_autoptr (FocusEventData) nearest = NULL;
GtkWidget *child;
gboolean downward, forward_or_backward;
gboolean is_rtl;
GCAL_ENTRY;
downward = direction == GTK_DIR_DOWN || direction == GTK_DIR_TAB_FORWARD;
is_rtl = gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL;
forward_or_backward = direction == GTK_DIR_TAB_FORWARD || direction == GTK_DIR_TAB_BACKWARD;
for (child = gtk_widget_get_first_child (GTK_WIDGET (self));
child != NULL;
child = gtk_widget_get_next_sibling (child))
{
g_autoptr (FocusEventData) aux = NULL;
if (!(aux = create_focus_event_data_candidate (self, child)))
continue;
swap_focus_event_data (&candidate, g_steal_pointer (&aux));
g_assert (candidate != NULL);
if (candidate->widget == focused->widget)
continue;
if (!graphene_rect_intersection (&GRAPHENE_RECT_INIT (focused->rect.origin.x, 0, focused->rect.size.width, 1),
&GRAPHENE_RECT_INIT (candidate->rect.origin.x, 0, candidate->rect.size.width, 1),
NULL))
continue;
if (forward_or_backward && focused->focal_x != candidate->focal_x)
continue;
if ((downward && candidate->rect.origin.y < focused->rect.origin.y) ||
(!downward && candidate->rect.origin.y > focused->rect.origin.y))
continue;
if (nearest == NULL)
swap_focus_event_data (&nearest, g_steal_pointer (&candidate));
else if ((downward && candidate->rect.origin.y < nearest->rect.origin.y) ||
(!downward && candidate->rect.origin.y > nearest->rect.origin.y))
swap_focus_event_data (&nearest, g_steal_pointer (&candidate));
else if (downward && candidate->rect.origin.y == nearest->rect.origin.y &&
((is_rtl && candidate->focal_x > nearest->focal_x) ||
(!is_rtl && candidate->focal_x < nearest->focal_x)))
swap_focus_event_data (&nearest, g_steal_pointer (&candidate));
}
g_assert (nearest == NULL || nearest->widget != focused->widget);
GCAL_RETURN (nearest ? g_steal_pointer (&nearest->widget) : NULL);
}
static GtkWidget *
find_nearest_horizontal_event_widget (GcalMonthViewRow *self,
FocusEventData *focused,
@@ -749,7 +809,10 @@ gcal_month_view_row_focus (GtkWidget *widget,
case GTK_DIR_UP:
case GTK_DIR_DOWN:
return FALSE;
if ((new_focus = find_nearest_vertical_event_widget (self, focus_event_data, direction)))
return gtk_widget_grab_focus (new_focus);
else
return FALSE;
case GTK_DIR_LEFT:
case GTK_DIR_RIGHT: