views/month-view-row: Implement keyboard navigation for event widgets vertically
This commit is contained in:
@@ -243,6 +243,66 @@ find_last_event_widget (GcalMonthViewRow *self)
|
|||||||
GCAL_RETURN (nearest ? g_steal_pointer (&nearest->widget) : NULL);
|
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 *
|
static GtkWidget *
|
||||||
find_nearest_horizontal_event_widget (GcalMonthViewRow *self,
|
find_nearest_horizontal_event_widget (GcalMonthViewRow *self,
|
||||||
FocusEventData *focused,
|
FocusEventData *focused,
|
||||||
@@ -749,7 +809,10 @@ gcal_month_view_row_focus (GtkWidget *widget,
|
|||||||
|
|
||||||
case GTK_DIR_UP:
|
case GTK_DIR_UP:
|
||||||
case GTK_DIR_DOWN:
|
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_LEFT:
|
||||||
case GTK_DIR_RIGHT:
|
case GTK_DIR_RIGHT:
|
||||||
|
|||||||
Reference in New Issue
Block a user