Bonjour hypra !
J'ai donc passé ma journée d'hier sur Evince et j'ai terminé une
première implémentation en suivant les mêmes pratiques que pour
GtkTextView.
Le code ci-dessous est aussi disponible dans sa branche, sur:
https://gitlab.gnome.org/mpieuchot/evince/tree/issue1203
J'ai eu un peu de mal avec accerciser et Evince. Le fait de
sélectionner n'importe quelle page dans une document n'actualise pas
l'objet `acc' qui correspond à la page actuel.
Apparemment le builder du gitlab ne semble pas avoir la bonne version
d'Atk, du coup je ne sais pas si je dois ce qu'il faut faire. Samuel,
un conseil?
https://gitlab.gnome.org/mpieuchot/evince/-/jobs/459795
J'ai aussi crée une merge request pour Gtk, comme demandé:
https://gitlab.gnome.org/GNOME/gtk/merge_requests/1120
J'espère que cela exportera la discussion, au pire cela sert de
référence pour les futures implémentations et discussions :o)
Voila, au final une journée productive. Je pense passer la seconde
journée du mois sur LibreOffice et attendant les retours de la communauté
avant de peaufiner cette implémentation (ou pas).
Je commence maintenant à me projeter sur les prochains bugs. Si vous
avez d'autres urgences dans GNOME cela me permettrait de mutualiser et
rentabiliser le temps passer sur le gitlab (:
Martin
diff --git libview/ev-page-accessible.c libview/ev-page-accessible.c
index 455a0bf4..0736a224 100644
--- libview/ev-page-accessible.c
+++ libview/ev-page-accessible.c
@@ -1042,6 +1042,143 @@ ev_page_accessible_add_selection (AtkText *text,
}
+static gboolean
+ev_page_accessible_scroll_substring_to (AtkText *text,
+ gint start_pos,
+ gint end_pos,
+ AtkScrollType type)
+{
+ EvPageAccessible *self = EV_PAGE_ACCESSIBLE (text);
+ EvView *view = ev_page_accessible_get_view (self);
+ GdkRectangle start_rect, end_rect;
+ GdkPoint start_point, end_point;
+ gdouble hpage_size, vpage_size;
+ EvRectangle *areas = NULL;
+ guint pos, n_areas = 0;
+
+ if (end_pos < start_pos)
+ return FALSE;
+
+ ev_page_cache_get_text_layout (view->page_cache, self->priv->page,
&areas, &n_areas);
+ if (start_pos < 0 || end_pos >= n_areas)
+ return FALSE;
+
+ _ev_view_transform_doc_rect_to_view_rect (view, self->priv->page, areas
+ start_pos, &start_rect);
+ _ev_view_transform_doc_rect_to_view_rect (view, self->priv->page, areas
+ end_pos - 1, &end_rect);
+ start_point.x = start_rect.x;
+ start_point.y = start_rect.y;
+ end_point.x = end_rect.x + end_rect.width;
+ end_point.y = end_rect.y + end_rect.height;
+
+ hpage_size = gtk_adjustment_get_page_size (view->hadjustment);
+ vpage_size = gtk_adjustment_get_page_size (view->vadjustment);
+
+ switch (type) {
+ case ATK_SCROLL_TOP_LEFT:
+ gtk_adjustment_clamp_page (view->hadjustment, start_point.x,
start_point.x + hpage_size);
+ gtk_adjustment_changed (view->hadjustment);
+ gtk_adjustment_clamp_page (view->vadjustment, start_point.y,
start_point.y + vpage_size);
+ gtk_adjustment_changed (view->vadjustment);
+ break;
+ case ATK_SCROLL_BOTTOM_RIGHT:
+ gtk_adjustment_clamp_page (view->hadjustment, end_point.x -
hpage_size, end_point.x);
+ gtk_adjustment_changed (view->hadjustment);
+ gtk_adjustment_clamp_page (view->vadjustment, end_point.y -
vpage_size, end_point.y);
+ gtk_adjustment_changed (view->vadjustment);
+ break;
+ case ATK_SCROLL_TOP_EDGE:
+ gtk_adjustment_clamp_page (view->vadjustment, start_point.y,
start_point.y + vpage_size);
+ gtk_adjustment_changed (view->vadjustment);
+ break;
+ case ATK_SCROLL_BOTTOM_EDGE:
+ gtk_adjustment_clamp_page (view->vadjustment, end_point.y -
vpage_size, end_point.y);
+ gtk_adjustment_changed (view->vadjustment);
+ break;
+ case ATK_SCROLL_LEFT_EDGE:
+ gtk_adjustment_clamp_page (view->hadjustment, start_point.x,
start_point.x + hpage_size);
+ gtk_adjustment_changed (view->hadjustment);
+ break;
+ case ATK_SCROLL_RIGHT_EDGE:
+ gtk_adjustment_clamp_page (view->hadjustment, end_point.x -
hpage_size, end_point.x);
+ gtk_adjustment_changed (view->hadjustment);
+ break;
+ case ATK_SCROLL_ANYWHERE:
+ _ev_view_ensure_rectangle_is_visible (view, &end_rect);
+ _ev_view_ensure_rectangle_is_visible (view, &start_rect);
+ break;
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+ev_page_accessible_scroll_substring_to_point (AtkText *text,
+ gint start_pos,
+ gint end_pos,
+ AtkCoordType coords,
+ gint x,
+ gint y)
+{
+ EvPageAccessible *self = EV_PAGE_ACCESSIBLE (text);
+ EvView *view = ev_page_accessible_get_view (self);
+ GdkRectangle start_rect;
+ GdkPoint view_point, start_point;
+ gdouble hpage_size, vpage_size;
+ EvRectangle *areas = NULL;
+ guint n_areas = 0;
+ GtkWidget *toplevel;
+ gint x_widget, y_widget;
+ GtkBorder border;
+ GdkRectangle page_area;
+ gdouble doc_x, doc_y;
+
+ if (end_pos < start_pos)
+ return FALSE;
+
+ ev_page_cache_get_text_layout (view->page_cache, self->priv->page,
&areas, &n_areas);
+ if (start_pos < 0 || end_pos >= n_areas)
+ return FALSE;
+
+ /* Assume that the API wants to place the top left of the substring at
(x, y). */
+ _ev_view_transform_doc_rect_to_view_rect (view, self->priv->page, areas
+ start_pos, &start_rect);
+ start_point.x = start_rect.x;
+ start_point.y = start_rect.y;
+
+ hpage_size = gtk_adjustment_get_page_size (view->hadjustment);
+ vpage_size = gtk_adjustment_get_page_size (view->vadjustment);
+
+ view_point.x = x;
+ view_point.y = y;
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (view));
+ gtk_widget_translate_coordinates (GTK_WIDGET (view), toplevel, 0, 0,
&x_widget, &y_widget);
+ view_point.x -= x_widget;
+ view_point.y -= y_widget;
+
+ if (coords == ATK_XY_SCREEN) {
+ gint x_window, y_window;
+
+ gdk_window_get_origin (gtk_widget_get_window (toplevel),
&x_window, &y_window);
+ view_point.x -= x_window;
+ view_point.y -= y_window;
+ }
+
+ ev_view_get_page_extents (view, self->priv->page, &page_area, &border);
+ _ev_view_transform_view_point_to_doc_point (view, &view_point,
&page_area, &border, &doc_x, &doc_y);
+
+ /* Calculate scrolling difference */
+ start_point.x -= doc_x;
+ start_point.y -= doc_y;
+
+ gtk_adjustment_clamp_page (view->hadjustment, start_point.x,
start_point.x + hpage_size);
+ gtk_adjustment_changed (view->hadjustment);
+ gtk_adjustment_clamp_page (view->vadjustment, start_point.y,
start_point.y + vpage_size);
+ gtk_adjustment_changed (view->vadjustment);
+
+ return TRUE;
+}
+
static void
ev_page_accessible_init (EvPageAccessible *page)
{
@@ -1067,6 +1204,8 @@ ev_page_accessible_text_iface_init (AtkTextIface *iface)
iface->get_default_attributes =
ev_page_accessible_get_default_attributes;
iface->get_character_extents = ev_page_accessible_get_character_extents;
iface->get_offset_at_point = ev_page_accessible_get_offset_at_point;
+ iface->scroll_substring_to = ev_page_accessible_scroll_substring_to;
+ iface->scroll_substring_to_point =
ev_page_accessible_scroll_substring_to_point;
}
static GHashTable *
diff --git libview/ev-view-private.h libview/ev-view-private.h
index ba56c0cc..02562ddd 100644
--- libview/ev-view-private.h
+++ libview/ev-view-private.h
@@ -334,5 +334,8 @@ void _ev_view_set_focused_element (EvView *view,
void _ev_view_focus_form_field (EvView *view,
EvFormField *field);
+void _ev_view_ensure_rectangle_is_visible (EvView *view,
+ GdkRectangle *rect);
+
#endif /* __EV_VIEW_PRIVATE_H__ */
diff --git libview/ev-view.c libview/ev-view.c
index 2bb5e3c2..6567da47 100644
--- libview/ev-view.c
+++ libview/ev-view.c
@@ -120,8 +120,6 @@ typedef struct {
/*** Scrolling ***/
static void view_update_range_and_current_page (EvView
*view);
-static void ensure_rectangle_is_visible (EvView
*view,
- GdkRectangle
*rect);
/*** Geometry computations ***/
static void compute_border (EvView
*view,
@@ -1132,8 +1130,8 @@ ev_view_scroll_internal (EvView *view,
#define MARGIN 5
-static void
-ensure_rectangle_is_visible (EvView *view, GdkRectangle *rect)
+void
+_ev_view_ensure_rectangle_is_visible (EvView *view, GdkRectangle *rect)
{
GtkWidget *widget = GTK_WIDGET (view);
GtkAdjustment *adjustment;
@@ -2277,7 +2275,7 @@ _ev_view_set_focused_element (EvView *view,
ev_document_model_set_page (view->model, page);
view_rect.x += view->scroll_x;
view_rect.y += view->scroll_y;
- ensure_rectangle_is_visible (view, &view_rect);
+ _ev_view_ensure_rectangle_is_visible (view, &view_rect);
}
if (region) {
@@ -6607,7 +6605,7 @@ ev_view_move_cursor (EvView *view,
rect.y += view->scroll_y;
ev_document_model_set_page (view->model, view->cursor_page);
- ensure_rectangle_is_visible (view, &rect);
+ _ev_view_ensure_rectangle_is_visible (view, &rect);
g_signal_emit (view, signals[SIGNAL_CURSOR_MOVED], 0,
view->cursor_page, view->cursor_offset);
@@ -9042,7 +9040,7 @@ jump_to_find_result (EvView *view)
rect = ev_view_find_get_result (view, page, view->find_result);
_ev_view_transform_doc_rect_to_view_rect (view, page, rect,
&view_rect);
- ensure_rectangle_is_visible (view, &view_rect);
+ _ev_view_ensure_rectangle_is_visible (view, &view_rect);
if (view->caret_enabled && view->rotation == 0)
position_caret_cursor_at_doc_point (view, page,
rect->x1, rect->y1);
@@ -9276,7 +9274,7 @@ ev_view_highlight_forward_search (EvView *view,
ev_document_model_set_page (view->model, page);
_ev_view_transform_doc_rect_to_view_rect (view, page, &mapping->area,
&view_rect);
- ensure_rectangle_is_visible (view, &view_rect);
+ _ev_view_ensure_rectangle_is_visible (view, &view_rect);
gtk_widget_queue_draw (GTK_WIDGET (view));
}