views/month-view-row: Additive inverse in right-to-left languages

"Additive inverse" basically means transforming a positive number
into a negative equivalent, or vice-versa; for example, from 5 to -5.

Instead of inverting conditions in right-to-left languages to
compare the X coordinate, a much simpler approach to this is to
normalize the X coordinate by applying additive inverse in
right-to-left languages.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-calendar/-/merge_requests/744>
This commit is contained in:
Hari Rana
2026-07-05 14:56:44 -04:00
parent 1f06a71ee0
commit 5f21144fbb
+25 -33
View File
@@ -100,7 +100,7 @@ typedef struct
{ {
GtkWidget *widget; GtkWidget *widget;
graphene_rect_t rect; graphene_rect_t rect;
gint focal_x; gint normalized_x;
} FocusEventData; } FocusEventData;
static void static void
@@ -116,13 +116,13 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (FocusEventData, focus_event_data_free)
static FocusEventData * static FocusEventData *
focus_event_data_new (GtkWidget *widget, focus_event_data_new (GtkWidget *widget,
const graphene_rect_t *rect, const graphene_rect_t *rect,
gint focal_x) gint normalized_x)
{ {
g_autoptr (FocusEventData) focus_event_data = NULL; g_autoptr (FocusEventData) focus_event_data = NULL;
focus_event_data = g_new0 (FocusEventData, 1); focus_event_data = g_new0 (FocusEventData, 1);
focus_event_data->widget = widget; focus_event_data->widget = widget;
focus_event_data->focal_x = focal_x; focus_event_data->normalized_x = normalized_x;
graphene_rect_init_from_rect (&focus_event_data->rect, rect); graphene_rect_init_from_rect (&focus_event_data->rect, rect);
return g_steal_pointer (&focus_event_data); return g_steal_pointer (&focus_event_data);
@@ -147,9 +147,9 @@ static FocusEventData *
create_focus_event_data (GcalMonthViewRow *self, create_focus_event_data (GcalMonthViewRow *self,
GtkWidget *child) GtkWidget *child)
{ {
gint focal_x, normalized_x;
graphene_rect_t rect; graphene_rect_t rect;
gboolean is_rtl; gboolean is_rtl;
gint focal_x;
g_assert (GTK_IS_WIDGET (child)); g_assert (GTK_IS_WIDGET (child));
@@ -158,8 +158,9 @@ create_focus_event_data (GcalMonthViewRow *self,
is_rtl = gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL; is_rtl = gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL;
focal_x = rect.origin.x + (is_rtl ? rect.size.width : 0); focal_x = rect.origin.x + (is_rtl ? rect.size.width : 0);
normalized_x = is_rtl ? -focal_x : focal_x;
return focus_event_data_new (child, &rect, focal_x); return focus_event_data_new (child, &rect, normalized_x);
} }
static FocusEventData * static FocusEventData *
@@ -189,9 +190,6 @@ find_first_event_widget (GcalMonthViewRow *self)
g_autoptr (FocusEventData) candidate = NULL; g_autoptr (FocusEventData) candidate = NULL;
g_autoptr (FocusEventData) nearest = NULL; g_autoptr (FocusEventData) nearest = NULL;
GtkWidget *child; GtkWidget *child;
gboolean is_rtl;
is_rtl = gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL;
for (child = gtk_widget_get_first_child (GTK_WIDGET (self)); for (child = gtk_widget_get_first_child (GTK_WIDGET (self));
child != NULL; child != NULL;
@@ -207,10 +205,10 @@ find_first_event_widget (GcalMonthViewRow *self)
if (nearest == NULL) if (nearest == NULL)
swap_focus_event_data (&nearest, g_steal_pointer (&candidate)); swap_focus_event_data (&nearest, g_steal_pointer (&candidate));
else if ((is_rtl && candidate->focal_x > nearest->focal_x) || else if (candidate->normalized_x < nearest->normalized_x)
(!is_rtl && candidate->focal_x < nearest->focal_x))
swap_focus_event_data (&nearest, g_steal_pointer (&candidate)); swap_focus_event_data (&nearest, g_steal_pointer (&candidate));
else if (candidate->focal_x == nearest->focal_x && candidate->rect.origin.y < nearest->rect.origin.y) else if (candidate->normalized_x == nearest->normalized_x &&
candidate->rect.origin.y < nearest->rect.origin.y)
swap_focus_event_data (&nearest, g_steal_pointer (&candidate)); swap_focus_event_data (&nearest, g_steal_pointer (&candidate));
} }
@@ -225,9 +223,6 @@ find_last_event_widget (GcalMonthViewRow *self)
g_autoptr (FocusEventData) candidate = NULL; g_autoptr (FocusEventData) candidate = NULL;
g_autoptr (FocusEventData) nearest = NULL; g_autoptr (FocusEventData) nearest = NULL;
GtkWidget *child; GtkWidget *child;
gboolean is_rtl;
is_rtl = gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL;
for (child = gtk_widget_get_first_child (GTK_WIDGET (self)); for (child = gtk_widget_get_first_child (GTK_WIDGET (self));
child != NULL; child != NULL;
@@ -243,10 +238,10 @@ find_last_event_widget (GcalMonthViewRow *self)
if (nearest == NULL) if (nearest == NULL)
swap_focus_event_data (&nearest, g_steal_pointer (&candidate)); swap_focus_event_data (&nearest, g_steal_pointer (&candidate));
else if ((is_rtl && candidate->focal_x < nearest->focal_x) || else if (candidate->normalized_x > nearest->normalized_x)
(!is_rtl && candidate->focal_x > nearest->focal_x))
swap_focus_event_data (&nearest, g_steal_pointer (&candidate)); swap_focus_event_data (&nearest, g_steal_pointer (&candidate));
else if (candidate->focal_x == nearest->focal_x && candidate->rect.origin.y > nearest->rect.origin.y) else if (candidate->normalized_x == nearest->normalized_x &&
candidate->rect.origin.y > nearest->rect.origin.y)
swap_focus_event_data (&nearest, g_steal_pointer (&candidate)); swap_focus_event_data (&nearest, g_steal_pointer (&candidate));
} }
@@ -264,14 +259,12 @@ find_nearest_vertical_event_widget (GcalMonthViewRow *self,
g_autoptr (FocusEventData) nearest = NULL; g_autoptr (FocusEventData) nearest = NULL;
GtkWidget *child; GtkWidget *child;
gboolean downward, upward, forward_or_backward; gboolean downward, upward, forward_or_backward;
gboolean is_rtl;
GCAL_ENTRY; GCAL_ENTRY;
downward = direction == GTK_DIR_DOWN || direction == GTK_DIR_TAB_FORWARD; downward = direction == GTK_DIR_DOWN || direction == GTK_DIR_TAB_FORWARD;
upward = !downward; upward = !downward;
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; forward_or_backward = direction == GTK_DIR_TAB_FORWARD || direction == GTK_DIR_TAB_BACKWARD;
for (child = gtk_widget_get_first_child (GTK_WIDGET (self)); for (child = gtk_widget_get_first_child (GTK_WIDGET (self));
@@ -294,7 +287,7 @@ find_nearest_vertical_event_widget (GcalMonthViewRow *self,
NULL)) NULL))
continue; continue;
if (forward_or_backward && focused->focal_x != candidate->focal_x) if (forward_or_backward && focused->normalized_x != candidate->normalized_x)
continue; continue;
if ((downward && candidate->rect.origin.y < focused->rect.origin.y) || if ((downward && candidate->rect.origin.y < focused->rect.origin.y) ||
@@ -307,8 +300,7 @@ find_nearest_vertical_event_widget (GcalMonthViewRow *self,
(upward && candidate->rect.origin.y > nearest->rect.origin.y)) (upward && candidate->rect.origin.y > nearest->rect.origin.y))
swap_focus_event_data (&nearest, g_steal_pointer (&candidate)); swap_focus_event_data (&nearest, g_steal_pointer (&candidate));
else if (downward && candidate->rect.origin.y == nearest->rect.origin.y && else if (downward && candidate->rect.origin.y == nearest->rect.origin.y &&
((is_rtl && candidate->focal_x > nearest->focal_x) || candidate->normalized_x < nearest->normalized_x)
(!is_rtl && candidate->focal_x < nearest->focal_x)))
swap_focus_event_data (&nearest, g_steal_pointer (&candidate)); swap_focus_event_data (&nearest, g_steal_pointer (&candidate));
} }
@@ -358,7 +350,6 @@ find_nearest_horizontal_event_widget (GcalMonthViewRow *self,
{ {
g_autoptr (FocusEventData) aux = NULL; g_autoptr (FocusEventData) aux = NULL;
gboolean candidate_intersects_vertically; gboolean candidate_intersects_vertically;
gboolean candidate_in_opposite_direction;
if (!(aux = create_focus_event_data_candidate (self, child))) if (!(aux = create_focus_event_data_candidate (self, child)))
continue; continue;
@@ -369,28 +360,29 @@ find_nearest_horizontal_event_widget (GcalMonthViewRow *self,
if (candidate->widget == focused->widget) if (candidate->widget == focused->widget)
continue; continue;
if (forward_or_backward &&
((lateral == GTK_DIR_LEFT && candidate->focal_x >= focused->focal_x) || if ((direction == GTK_DIR_TAB_FORWARD && candidate->normalized_x <= focused->normalized_x) ||
(lateral == GTK_DIR_RIGHT && candidate->focal_x <= focused->focal_x))) (direction == GTK_DIR_TAB_BACKWARD && candidate->normalized_x >= focused->normalized_x))
continue; continue;
candidate_in_opposite_direction = ((lateral == GTK_DIR_LEFT && candidate->focal_x > focused->focal_x) || if ((direction == GTK_DIR_LEFT && ABS (candidate->normalized_x) > ABS (focused->normalized_x)) ||
(lateral == GTK_DIR_RIGHT && candidate->focal_x < focused->focal_x)); (direction == GTK_DIR_RIGHT && ABS (candidate->normalized_x) < ABS (focused->normalized_x)))
continue;
candidate_intersects_vertically = candidate_intersects_vertically =
graphene_rect_intersection (&GRAPHENE_RECT_INIT (0, focused->rect.origin.y, 1, focused->rect.size.height), graphene_rect_intersection (&GRAPHENE_RECT_INIT (0, focused->rect.origin.y, 1, focused->rect.size.height),
&GRAPHENE_RECT_INIT (0, candidate->rect.origin.y, 1, candidate->rect.size.height), &GRAPHENE_RECT_INIT (0, candidate->rect.origin.y, 1, candidate->rect.size.height),
NULL); NULL);
if (!forward_or_backward && (!candidate_intersects_vertically || candidate_in_opposite_direction)) if (!forward_or_backward && !candidate_intersects_vertically)
continue; continue;
if (nearest == NULL) if (nearest == NULL)
swap_focus_event_data (&nearest, g_steal_pointer (&candidate)); swap_focus_event_data (&nearest, g_steal_pointer (&candidate));
else if ((lateral == GTK_DIR_LEFT && candidate->focal_x > nearest->focal_x) || else if ((lateral == GTK_DIR_LEFT && ABS (candidate->normalized_x) > ABS (nearest->normalized_x)) ||
(lateral == GTK_DIR_RIGHT && candidate->focal_x < nearest->focal_x)) (lateral == GTK_DIR_RIGHT && ABS (candidate->normalized_x) < ABS (nearest->normalized_x)))
swap_focus_event_data (&nearest, g_steal_pointer (&candidate)); swap_focus_event_data (&nearest, g_steal_pointer (&candidate));
else if (candidate->focal_x == nearest->focal_x && else if (ABS (candidate->normalized_x) == ABS (nearest->normalized_x) &&
((direction == GTK_DIR_TAB_FORWARD && candidate->rect.origin.y < nearest->rect.origin.y) || ((direction == GTK_DIR_TAB_FORWARD && candidate->rect.origin.y < nearest->rect.origin.y) ||
(direction == GTK_DIR_TAB_BACKWARD && candidate->rect.origin.y > nearest->rect.origin.y))) (direction == GTK_DIR_TAB_BACKWARD && candidate->rect.origin.y > nearest->rect.origin.y)))
swap_focus_event_data (&nearest, g_steal_pointer (&candidate)); swap_focus_event_data (&nearest, g_steal_pointer (&candidate));
@@ -1465,7 +1457,7 @@ gcal_month_view_row_focus_adjacent_cell (GcalMonthViewRow *self,
data = create_focus_event_data (self, widget); data = create_focus_event_data (self, widget);
cell = gcal_month_view_row_get_cell_at_x (self, data->focal_x); cell = gcal_month_view_row_get_cell_at_x (self, ABS (data->normalized_x));
return gtk_widget_grab_focus (cell); return gtk_widget_grab_focus (cell);
} }