forked from AuroraMiddleware/gtk
atspi: Implement Text interface for labels
This is a not-quite-complete implementation of the Text interface for GtkLabel. The missing parts are anything around extents and positions, as well as the ScrollSubstring apis.
This commit is contained in:
parent
7c8a16812e
commit
b80272a7e7
@ -26,6 +26,7 @@
|
||||
#include "gtkatspirootprivate.h"
|
||||
#include "gtkatspiprivate.h"
|
||||
#include "gtkatspiutilsprivate.h"
|
||||
#include "gtkatspipangoprivate.h"
|
||||
|
||||
#include "a11y/atspi/atspi-accessible.h"
|
||||
#include "a11y/atspi/atspi-text.h"
|
||||
@ -33,6 +34,7 @@
|
||||
#include "gtkdebug.h"
|
||||
#include "gtkwindow.h"
|
||||
#include "gtklabel.h"
|
||||
#include "gtklabelprivate.h"
|
||||
#include "gtkroot.h"
|
||||
|
||||
#include <gio/gio.h>
|
||||
@ -421,6 +423,8 @@ handle_accessible_method (GDBusConnection *connection,
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("as"));
|
||||
|
||||
g_variant_builder_add (&builder, "s", "org.a11y.atspi.Accessible");
|
||||
if (GTK_IS_LABEL (accessible))
|
||||
g_variant_builder_add (&builder, "s", "org.a11y.atspi.Text");
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(as)", &builder));
|
||||
}
|
||||
|
||||
@ -505,6 +509,336 @@ static const GDBusInterfaceVTable accessible_vtable = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static void
|
||||
handle_text_method (GDBusConnection *connection,
|
||||
const gchar *sender,
|
||||
const gchar *object_path,
|
||||
const gchar *interface_name,
|
||||
const gchar *method_name,
|
||||
GVariant *parameters,
|
||||
GDBusMethodInvocation *invocation,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkAtSpiContext *self = user_data;
|
||||
GtkAccessible *accessible = gtk_at_context_get_accessible (GTK_AT_CONTEXT (self));
|
||||
GtkWidget *widget = GTK_WIDGET (accessible);
|
||||
|
||||
if (g_strcmp0 (method_name, "GetCaretOffset") == 0)
|
||||
{
|
||||
int offset;
|
||||
|
||||
offset = _gtk_label_get_cursor_position (GTK_LABEL (widget));
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(i)", offset));
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "SetCaretOffset") == 0)
|
||||
{
|
||||
int offset;
|
||||
|
||||
g_variant_get (parameters, "(i)", &offset);
|
||||
|
||||
if (gtk_label_get_selectable (GTK_LABEL (widget)))
|
||||
gtk_label_select_region (GTK_LABEL (widget), offset, offset);
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, NULL);
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetText") == 0)
|
||||
{
|
||||
int start, end;
|
||||
const char *text;
|
||||
int len;
|
||||
char *string;
|
||||
|
||||
g_variant_get (parameters, "(ii)", &start, &end);
|
||||
|
||||
text = gtk_label_get_text (GTK_LABEL (widget));
|
||||
len = g_utf8_strlen (text, -1);
|
||||
|
||||
start = CLAMP (start, 0, len);
|
||||
end = CLAMP (end, 0, len);
|
||||
|
||||
if (end <= start)
|
||||
string = g_strdup ("");
|
||||
else
|
||||
{
|
||||
const char *p, *q;
|
||||
p = g_utf8_offset_to_pointer (text, start);
|
||||
q = g_utf8_offset_to_pointer (text, end);
|
||||
string = g_strndup (p, q - p);
|
||||
}
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", string));
|
||||
g_free (string);
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetTextBeforeOffset") == 0)
|
||||
{
|
||||
PangoLayout *layout = gtk_label_get_layout (GTK_LABEL (widget));
|
||||
int offset;
|
||||
AtspiTextBoundaryType boundary_type;
|
||||
char *string;
|
||||
int start, end;
|
||||
|
||||
g_variant_get (parameters, "(iu)", &offset, &boundary_type);
|
||||
string = gtk_pango_get_text_before (layout, offset, boundary_type, &start, &end);
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(sii)", string, start, end));
|
||||
g_free (string);
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetTextAtOffset") == 0)
|
||||
{
|
||||
PangoLayout *layout = gtk_label_get_layout (GTK_LABEL (widget));
|
||||
int offset;
|
||||
AtspiTextBoundaryType boundary_type;
|
||||
char *string;
|
||||
int start, end;
|
||||
|
||||
g_variant_get (parameters, "(iu)", &offset, &boundary_type);
|
||||
string = gtk_pango_get_text_at (layout, offset, boundary_type, &start, &end);
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(sii)", string, start, end));
|
||||
g_free (string);
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetTextAfterOffset") == 0)
|
||||
{
|
||||
PangoLayout *layout = gtk_label_get_layout (GTK_LABEL (widget));
|
||||
int offset;
|
||||
AtspiTextBoundaryType boundary_type;
|
||||
char *string;
|
||||
int start, end;
|
||||
|
||||
g_variant_get (parameters, "(iu)", &offset, &boundary_type);
|
||||
string = gtk_pango_get_text_after (layout, offset, boundary_type, &start, &end);
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(sii)", string, start, end));
|
||||
g_free (string);
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetCharacterAtOffset") == 0)
|
||||
{
|
||||
int offset;
|
||||
const char *text;
|
||||
gunichar ch = 0;
|
||||
|
||||
g_variant_get (parameters, "(i)", &offset);
|
||||
|
||||
text = gtk_label_get_text (GTK_LABEL (widget));
|
||||
|
||||
if (0 <= offset && offset < g_utf8_strlen (text, -1))
|
||||
ch = g_utf8_get_char (g_utf8_offset_to_pointer (text, offset));
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new_int32 (ch));
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetStringAtOffset") == 0)
|
||||
{
|
||||
PangoLayout *layout = gtk_label_get_layout (GTK_LABEL (widget));
|
||||
int offset;
|
||||
AtspiTextGranularity granularity;
|
||||
char *string;
|
||||
int start, end;
|
||||
|
||||
g_variant_get (parameters, "(iu)", &offset, &granularity);
|
||||
|
||||
string = gtk_pango_get_string_at (layout, offset, granularity, &start, &end);
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(sii)", string, start, end));
|
||||
g_free (string);
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetAttributes") == 0)
|
||||
{
|
||||
PangoLayout *layout = gtk_label_get_layout (GTK_LABEL (widget));
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||
int offset;
|
||||
int start, end;
|
||||
|
||||
g_variant_get (parameters, "(i)", &offset);
|
||||
|
||||
gtk_pango_get_run_attributes (layout, &builder, offset, &start, &end);
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss}ii)", &builder, start, end));
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetAttributeValue") == 0)
|
||||
{
|
||||
PangoLayout *layout = gtk_label_get_layout (GTK_LABEL (widget));
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||
int offset;
|
||||
const char *name;
|
||||
int start, end;
|
||||
GVariant *attrs;
|
||||
const char *val;
|
||||
|
||||
g_variant_get (parameters, "(i&s)", &offset, &name);
|
||||
gtk_pango_get_run_attributes (layout, &builder, offset, &start, &end);
|
||||
attrs = g_variant_builder_end (&builder);
|
||||
if (!g_variant_lookup (attrs, name, "&s", &val))
|
||||
val = "";
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", val));
|
||||
g_variant_unref (attrs);
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetAttributeRun") == 0)
|
||||
{
|
||||
PangoLayout *layout = gtk_label_get_layout (GTK_LABEL (widget));
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||
int offset;
|
||||
gboolean include_defaults;
|
||||
int start, end;
|
||||
|
||||
g_variant_get (parameters, "(ib)", &offset, &include_defaults);
|
||||
|
||||
if (include_defaults)
|
||||
gtk_pango_get_default_attributes (layout, &builder);
|
||||
|
||||
gtk_pango_get_run_attributes (layout, &builder, offset, &start, &end);
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss}ii)", &builder, start, end));
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetDefaultAttributes") == 0 ||
|
||||
g_strcmp0 (method_name, "GetDefaultAttributeSet") == 0)
|
||||
{
|
||||
PangoLayout *layout = gtk_label_get_layout (GTK_LABEL (widget));
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||
|
||||
gtk_pango_get_default_attributes (layout, &builder);
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss})", &builder));
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetNSelections") == 0)
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
if (gtk_label_get_selection_bounds (GTK_LABEL (widget), NULL, NULL))
|
||||
n = 1;
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new_int32 (n));
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetSelection") == 0)
|
||||
{
|
||||
int num;
|
||||
int start, end;
|
||||
|
||||
g_variant_get (parameters, "(i)", &num);
|
||||
|
||||
if (num != 0 ||
|
||||
!gtk_label_get_selection_bounds (GTK_LABEL (widget), &start, &end))
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Not a valid selection: %d", num);
|
||||
else
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(ii)", start, end));
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "AddSelection") == 0)
|
||||
{
|
||||
int start, end;
|
||||
gboolean ret;
|
||||
|
||||
g_variant_get (parameters, "(ii)", &start, &end);
|
||||
|
||||
if (!gtk_label_get_selectable (GTK_LABEL (widget)) ||
|
||||
gtk_label_get_selection_bounds (GTK_LABEL (widget), NULL, NULL))
|
||||
{
|
||||
ret = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_label_select_region (GTK_LABEL (widget), start, end);
|
||||
ret = TRUE;
|
||||
}
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new_boolean (ret));
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "RemoveSelection") == 0)
|
||||
{
|
||||
int num;
|
||||
int start, end;
|
||||
gboolean ret;
|
||||
|
||||
g_variant_get (parameters, "(i)", &num);
|
||||
|
||||
if (num != 0 ||
|
||||
!gtk_label_get_selectable (GTK_LABEL (widget)) ||
|
||||
!gtk_label_get_selection_bounds (GTK_LABEL (widget), &start, &end))
|
||||
{
|
||||
ret = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_label_select_region (GTK_LABEL (widget), end, end);
|
||||
ret = TRUE;
|
||||
}
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new_boolean (ret));
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "SetSelection") == 0)
|
||||
{
|
||||
int num;
|
||||
int start, end;
|
||||
gboolean ret;
|
||||
|
||||
g_variant_get (parameters, "(iii)", &num, &start, &end);
|
||||
|
||||
if (num != 0 ||
|
||||
!gtk_label_get_selectable (GTK_LABEL (widget)) ||
|
||||
!gtk_label_get_selection_bounds (GTK_LABEL (widget), NULL, NULL))
|
||||
{
|
||||
ret = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_label_select_region (GTK_LABEL (widget), start, end);
|
||||
ret = TRUE;
|
||||
}
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new_boolean (ret));
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetCharacterExtents") == 0)
|
||||
{
|
||||
g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "");
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetRangeExtents") == 0)
|
||||
{
|
||||
g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "");
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetBoundedRanges") == 0)
|
||||
{
|
||||
g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "");
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "ScrollSubstringTo") == 0)
|
||||
{
|
||||
g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "");
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "ScrollSubstringToPoint") == 0)
|
||||
{
|
||||
g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "");
|
||||
}
|
||||
}
|
||||
|
||||
static GVariant *
|
||||
handle_text_get_property (GDBusConnection *connection,
|
||||
const gchar *sender,
|
||||
const gchar *object_path,
|
||||
const gchar *interface_name,
|
||||
const gchar *property_name,
|
||||
GError **error,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkAtSpiContext *self = user_data;
|
||||
GtkAccessible *accessible = gtk_at_context_get_accessible (GTK_AT_CONTEXT (self));
|
||||
GtkWidget *widget = GTK_WIDGET (accessible);
|
||||
|
||||
if (g_strcmp0 (property_name, "CharacterCount") == 0)
|
||||
{
|
||||
const char *text;
|
||||
int len;
|
||||
|
||||
text = gtk_label_get_text (GTK_LABEL (widget));
|
||||
len = g_utf8_strlen (text, -1);
|
||||
|
||||
return g_variant_new_int32 (len);
|
||||
}
|
||||
else if (g_strcmp0 (property_name, "CaretOffset") == 0)
|
||||
{
|
||||
return g_variant_new_int32 (0);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const GDBusInterfaceVTable text_vtable = {
|
||||
handle_text_method,
|
||||
handle_text_get_property,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static void
|
||||
gtk_at_spi_context_register_object (GtkAtSpiContext *self)
|
||||
{
|
||||
@ -515,6 +849,17 @@ gtk_at_spi_context_register_object (GtkAtSpiContext *self)
|
||||
self,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (GTK_IS_LABEL (gtk_at_context_get_accessible (GTK_AT_CONTEXT (self))))
|
||||
{
|
||||
g_dbus_connection_register_object (self->connection,
|
||||
self->context_path,
|
||||
(GDBusInterfaceInfo *) &atspi_text_interface,
|
||||
&text_vtable,
|
||||
self,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
Loading…
Reference in New Issue
Block a user