mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2025-01-15 14:50:06 +00:00
Implement GtkAccessibleText for GtkText
This commit is contained in:
parent
eeee3151b6
commit
a44701faa2
164
gtk/gtktext.c
164
gtk/gtktext.c
@ -23,6 +23,7 @@
|
||||
|
||||
#include "gtktextprivate.h"
|
||||
|
||||
#include "gtkaccessibletext-private.h"
|
||||
#include "gtkactionable.h"
|
||||
#include "gtkadjustment.h"
|
||||
#include "gtkbox.h"
|
||||
@ -69,6 +70,8 @@
|
||||
#include "gtkactionmuxerprivate.h"
|
||||
#include "gtkjoinedmenuprivate.h"
|
||||
#include "deprecated/gtkrender.h"
|
||||
#include "gtkaccessibletext-private.h"
|
||||
#include "a11y/gtkatspipangoprivate.h"
|
||||
|
||||
#include <cairo-gobject.h>
|
||||
#include <string.h>
|
||||
@ -706,9 +709,14 @@ static const GtkTextHistoryFuncs history_funcs = {
|
||||
gtk_text_history_select_cb,
|
||||
};
|
||||
|
||||
static void gtk_text_accessible_text_init (GtkAccessibleTextInterface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkText, gtk_text, GTK_TYPE_WIDGET,
|
||||
G_ADD_PRIVATE (GtkText)
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE, gtk_text_editable_init))
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE, gtk_text_editable_init)
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_ACCESSIBLE_TEXT,
|
||||
gtk_text_accessible_text_init))
|
||||
|
||||
|
||||
static void
|
||||
add_move_binding (GtkWidgetClass *widget_class,
|
||||
@ -3440,6 +3448,11 @@ gtk_text_insert_text (GtkText *self,
|
||||
if (n_inserted != n_chars)
|
||||
gtk_widget_error_bell (GTK_WIDGET (self));
|
||||
|
||||
gtk_accessible_text_update_contents (GTK_ACCESSIBLE_TEXT (self),
|
||||
GTK_ACCESSIBLE_TEXT_CONTENT_CHANGE_INSERT,
|
||||
*position,
|
||||
n_inserted);
|
||||
|
||||
*position += n_inserted;
|
||||
|
||||
update_placeholder_visibility (self);
|
||||
@ -3460,6 +3473,11 @@ gtk_text_delete_text (GtkText *self,
|
||||
if (start_pos == end_pos)
|
||||
return;
|
||||
|
||||
gtk_accessible_text_update_contents (GTK_ACCESSIBLE_TEXT (self),
|
||||
GTK_ACCESSIBLE_TEXT_CONTENT_CHANGE_REMOVE,
|
||||
start_pos,
|
||||
end_pos);
|
||||
|
||||
if (priv->change_count == 0)
|
||||
gtk_text_history_begin_irreversible_action (priv->history);
|
||||
begin_change (self);
|
||||
@ -3484,6 +3502,9 @@ gtk_text_delete_selection (GtkText *self)
|
||||
int end_pos = MAX (priv->selection_bound, priv->current_pos);
|
||||
|
||||
gtk_editable_delete_text (GTK_EDITABLE (self), start_pos, end_pos);
|
||||
gtk_accessible_text_update_contents (GTK_ACCESSIBLE_TEXT (self),
|
||||
GTK_ACCESSIBLE_TEXT_CONTENT_CHANGE_REMOVE,
|
||||
start_pos, end_pos);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -3504,6 +3525,9 @@ gtk_text_set_selection_bounds (GtkText *self,
|
||||
gtk_text_set_positions (self, MIN (end, length), MIN (start, length));
|
||||
|
||||
gtk_text_update_primary_selection (self);
|
||||
|
||||
gtk_accessible_text_update_caret_position (GTK_ACCESSIBLE_TEXT (self));
|
||||
gtk_accessible_text_update_selection_bound (GTK_ACCESSIBLE_TEXT (self));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -3985,6 +4009,10 @@ gtk_text_insert_at_cursor (GtkText *self,
|
||||
begin_change (self);
|
||||
gtk_text_reset_im_context (self);
|
||||
gtk_editable_insert_text (GTK_EDITABLE (self), str, -1, &pos);
|
||||
gtk_accessible_text_update_contents (GTK_ACCESSIBLE_TEXT (self),
|
||||
GTK_ACCESSIBLE_TEXT_CONTENT_CHANGE_INSERT,
|
||||
pos,
|
||||
pos + g_utf8_strlen (str, -1));
|
||||
gtk_text_set_selection_bounds (self, pos, pos);
|
||||
end_change (self);
|
||||
}
|
||||
@ -4059,7 +4087,6 @@ gtk_text_delete_from_cursor (GtkText *self,
|
||||
gtk_editable_delete_text (GTK_EDITABLE (self), 0, priv->current_pos);
|
||||
else
|
||||
gtk_editable_delete_text (GTK_EDITABLE (self), priv->current_pos, -1);
|
||||
|
||||
break;
|
||||
|
||||
case GTK_DELETE_DISPLAY_LINES:
|
||||
@ -4139,8 +4166,12 @@ gtk_text_backspace (GtkText *self)
|
||||
int pos = priv->current_pos;
|
||||
|
||||
gtk_editable_insert_text (GTK_EDITABLE (self), normalized_text,
|
||||
g_utf8_offset_to_pointer (normalized_text, len - 1) - normalized_text,
|
||||
&pos);
|
||||
g_utf8_offset_to_pointer (normalized_text, len - 1) - normalized_text,
|
||||
&pos);
|
||||
gtk_accessible_text_update_contents (GTK_ACCESSIBLE_TEXT (self),
|
||||
GTK_ACCESSIBLE_TEXT_CONTENT_CHANGE_INSERT,
|
||||
pos,
|
||||
pos + len);
|
||||
gtk_text_set_selection_bounds (self, pos, pos);
|
||||
}
|
||||
|
||||
@ -4426,6 +4457,9 @@ gtk_text_enter_text (GtkText *self,
|
||||
|
||||
tmp_pos = priv->current_pos;
|
||||
gtk_editable_insert_text (GTK_EDITABLE (self), str, strlen (str), &tmp_pos);
|
||||
gtk_accessible_text_update_contents (GTK_ACCESSIBLE_TEXT (self),
|
||||
GTK_ACCESSIBLE_TEXT_CONTENT_CHANGE_INSERT,
|
||||
tmp_pos, tmp_pos + g_utf8_strlen (str, -1));
|
||||
gtk_text_set_selection_bounds (self, tmp_pos, tmp_pos);
|
||||
|
||||
end_change (self);
|
||||
@ -5389,6 +5423,9 @@ paste_received (GObject *clipboard,
|
||||
|
||||
pos = priv->current_pos;
|
||||
gtk_editable_insert_text (GTK_EDITABLE (self), text, length, &pos);
|
||||
gtk_accessible_text_update_contents (GTK_ACCESSIBLE_TEXT (self),
|
||||
GTK_ACCESSIBLE_TEXT_CONTENT_CHANGE_INSERT,
|
||||
pos, pos + length);
|
||||
gtk_text_set_selection_bounds (self, pos, pos);
|
||||
end_change (self);
|
||||
|
||||
@ -5620,8 +5657,14 @@ gtk_text_set_text (GtkText *self,
|
||||
begin_change (self);
|
||||
g_object_freeze_notify (G_OBJECT (self));
|
||||
gtk_editable_delete_text (GTK_EDITABLE (self), 0, -1);
|
||||
gtk_accessible_text_update_contents (GTK_ACCESSIBLE_TEXT (self),
|
||||
GTK_ACCESSIBLE_TEXT_CONTENT_CHANGE_REMOVE,
|
||||
0, G_MAXUINT);
|
||||
tmp_pos = 0;
|
||||
gtk_editable_insert_text (GTK_EDITABLE (self), text, strlen (text), &tmp_pos);
|
||||
gtk_accessible_text_update_contents (GTK_ACCESSIBLE_TEXT (self),
|
||||
GTK_ACCESSIBLE_TEXT_CONTENT_CHANGE_INSERT,
|
||||
tmp_pos, tmp_pos + g_utf8_strlen (text, -1));
|
||||
g_object_thaw_notify (G_OBJECT (self));
|
||||
end_change (self);
|
||||
|
||||
@ -6420,6 +6463,9 @@ gtk_text_drag_drop (GtkDropTarget *dest,
|
||||
drop_position > priv->current_pos)
|
||||
{
|
||||
gtk_editable_insert_text (GTK_EDITABLE (self), str, length, &drop_position);
|
||||
gtk_accessible_text_update_contents (GTK_ACCESSIBLE_TEXT (self),
|
||||
GTK_ACCESSIBLE_TEXT_CONTENT_CHANGE_INSERT,
|
||||
drop_position, drop_position + length);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -6429,6 +6475,9 @@ gtk_text_drag_drop (GtkDropTarget *dest,
|
||||
gtk_text_delete_selection (self);
|
||||
pos = MIN (priv->selection_bound, priv->current_pos);
|
||||
gtk_editable_insert_text (GTK_EDITABLE (self), str, length, &pos);
|
||||
gtk_accessible_text_update_contents (GTK_ACCESSIBLE_TEXT (self),
|
||||
GTK_ACCESSIBLE_TEXT_CONTENT_CHANGE_INSERT,
|
||||
pos, pos + length);
|
||||
end_change (self);
|
||||
}
|
||||
|
||||
@ -7004,6 +7053,9 @@ emoji_picked (GtkEmojiChooser *chooser,
|
||||
|
||||
pos = priv->current_pos;
|
||||
gtk_editable_insert_text (GTK_EDITABLE (self), text, -1, &pos);
|
||||
gtk_accessible_text_update_contents (GTK_ACCESSIBLE_TEXT (self),
|
||||
GTK_ACCESSIBLE_TEXT_CONTENT_CHANGE_INSERT,
|
||||
pos, pos + 1);
|
||||
gtk_text_set_selection_bounds (self, pos, pos);
|
||||
end_change (self);
|
||||
}
|
||||
@ -7331,6 +7383,9 @@ gtk_text_history_insert_cb (gpointer funcs_data,
|
||||
int location = begin;
|
||||
|
||||
gtk_editable_insert_text (GTK_EDITABLE (text), str, len, &location);
|
||||
gtk_accessible_text_update_contents (GTK_ACCESSIBLE_TEXT (text),
|
||||
GTK_ACCESSIBLE_TEXT_CONTENT_CHANGE_INSERT,
|
||||
location, location + len);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -7381,3 +7436,104 @@ gtk_text_update_history (GtkText *self)
|
||||
priv->visible &&
|
||||
priv->editable);
|
||||
}
|
||||
|
||||
/* {{{ GtkAccessibleText implementation */
|
||||
|
||||
static GBytes *
|
||||
gtk_text_accessible_text_get_contents (GtkAccessibleText *self,
|
||||
unsigned int start,
|
||||
unsigned int end)
|
||||
{
|
||||
const char *text;
|
||||
int len;
|
||||
char *string;
|
||||
gsize size;
|
||||
|
||||
text = gtk_editable_get_text (GTK_EDITABLE (self));
|
||||
len = g_utf8_strlen (text, -1);
|
||||
|
||||
start = CLAMP (start, 0, len);
|
||||
end = CLAMP (end, 0, len);
|
||||
|
||||
if (end <= start)
|
||||
{
|
||||
string = g_strdup ("");
|
||||
size = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *p, *q;
|
||||
p = g_utf8_offset_to_pointer (text, start);
|
||||
q = g_utf8_offset_to_pointer (text, end);
|
||||
size = q - p + 1;
|
||||
string = g_strndup (p, q - p);
|
||||
}
|
||||
|
||||
return g_bytes_new_take (string, size);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
gtk_text_accessible_text_get_caret_position (GtkAccessibleText *self)
|
||||
{
|
||||
return gtk_editable_get_position (GTK_EDITABLE (self));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_text_accessible_text_get_selection (GtkAccessibleText *self,
|
||||
gsize *n_ranges,
|
||||
GtkAccessibleTextRange **ranges)
|
||||
{
|
||||
int start, end;
|
||||
|
||||
if (!gtk_editable_get_selection_bounds (GTK_EDITABLE (self), &start, &end))
|
||||
return FALSE;
|
||||
|
||||
*n_ranges = 1;
|
||||
*ranges = g_new (GtkAccessibleTextRange, 1);
|
||||
(*ranges)[0].start = start;
|
||||
(*ranges)[0].length = end - start;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_text_accessible_text_get_attributes (GtkAccessibleText *self,
|
||||
unsigned int offset,
|
||||
gsize *n_ranges,
|
||||
GtkAccessibleTextRange **ranges,
|
||||
char ***attribute_names,
|
||||
char ***attribute_values)
|
||||
{
|
||||
PangoLayout *layout = gtk_text_get_layout (GTK_TEXT (self));
|
||||
unsigned int start, end;
|
||||
char **names, **values;
|
||||
|
||||
gtk_pango_get_run_attributes (layout, offset, &names, &values, &start, &end);
|
||||
|
||||
*n_ranges = g_strv_length (names);
|
||||
*ranges = g_new (GtkAccessibleTextRange, *n_ranges);
|
||||
|
||||
for (unsigned i = 0; i < *n_ranges; i++)
|
||||
{
|
||||
GtkAccessibleTextRange *range = &(*ranges)[i];
|
||||
|
||||
range->start = start;
|
||||
range->length = end - start;
|
||||
}
|
||||
|
||||
*attribute_names = names;
|
||||
*attribute_values = values;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_text_accessible_text_init (GtkAccessibleTextInterface *iface)
|
||||
{
|
||||
iface->get_contents = gtk_text_accessible_text_get_contents;
|
||||
iface->get_caret_position = gtk_text_accessible_text_get_caret_position;
|
||||
iface->get_selection = gtk_text_accessible_text_get_selection;
|
||||
iface->get_attributes = gtk_text_accessible_text_get_attributes;
|
||||
}
|
||||
|
||||
/* vim:set foldmethod=marker expandtab: */
|
||||
|
Loading…
Reference in New Issue
Block a user