[geany/geany] a8bc89: Merge branch 'scintilla/accessible-fixes'
Colomban Wendling
git-noreply at xxxxx
Tue Dec 20 20:47:51 UTC 2016
Branch: refs/heads/master
Author: Colomban Wendling <ban at herbesfolles.org>
Committer: Colomban Wendling <ban at herbesfolles.org>
Date: Tue, 20 Dec 2016 20:47:51 UTC
Commit: a8bc8905411ff65f825a504966fcf8fbef49af86
https://github.com/geany/geany/commit/a8bc8905411ff65f825a504966fcf8fbef49af86
Log Message:
-----------
Merge branch 'scintilla/accessible-fixes'
Fix some various issues with accessibility code in Scintilla.
Modified Paths:
--------------
scintilla/gtk/ScintillaGTKAccessible.cxx
scintilla/gtk/ScintillaGTKAccessible.h
Modified: scintilla/gtk/ScintillaGTKAccessible.cxx
83 lines changed, 56 insertions(+), 27 deletions(-)
===================================================================
@@ -3,6 +3,28 @@
/* Copyright 2016 by Colomban Wendling <colomban at geany.org>
* The License.txt file describes the conditions under which this software may be distributed. */
+// REFERENCES BETWEEN THE DIFFERENT OBJECTS
+//
+// ScintillaGTKAccessible is the actual implementation, as a C++ class.
+// ScintillaObjectAccessible is the GObject derived from AtkObject that
+// implements the various ATK interfaces, through ScintillaGTKAccessible.
+// This follows the same pattern as ScintillaGTK and ScintillaObject.
+//
+// ScintillaGTK owns a strong reference to the ScintillaObjectAccessible, and
+// is both responsible for creating and destroying that object.
+//
+// ScintillaObjectAccessible owns a strong reference to ScintillaGTKAccessible,
+// and is responsible for creating and destroying that object.
+//
+// ScintillaGTKAccessible has weak references to both the ScintillaGTK and
+// the ScintillaObjectAccessible objects associated, but does not own any
+// strong references to those objects.
+//
+// The chain of ownership is as follows:
+// ScintillaGTK -> ScintillaObjectAccessible -> ScintillaGTKAccessible
+
+// DETAILS ON THE GOBJECT TYPE IMPLEMENTATION
+//
// On GTK < 3.2, we need to use the AtkObjectFactory. We need to query
// the factory to see what type we should derive from, thus making use of
// dynamic inheritance. It's tricky, but it works so long as it's done
@@ -134,6 +156,7 @@ ScintillaGTKAccessible *ScintillaGTKAccessible::FromAccessible(GtkAccessible *ac
ScintillaGTKAccessible::ScintillaGTKAccessible(GtkAccessible *accessible_, GtkWidget *widget_) :
accessible(accessible_),
sci(ScintillaGTK::FromWidget(widget_)),
+ deletionLengthChar(0),
old_pos(-1) {
g_signal_connect(widget_, "sci-notify", G_CALLBACK(SciNotify), this);
}
@@ -455,7 +478,7 @@ void ScintillaGTKAccessible::GetCharacterExtents(int charOffset,
} else if (nextByteOffset > byteOffset) {
/* maybe next position was on the next line or something.
* just compute the expected character width */
- int style = sci->pdoc->StyleAt(byteOffset);
+ int style = StyleAt(byteOffset, true);
int len = nextByteOffset - byteOffset;
char *ch = new char[len + 1];
sci->pdoc->GetCharRange(ch, byteOffset, len);
@@ -531,15 +554,16 @@ AtkAttributeSet *ScintillaGTKAccessible::GetRunAttributes(int charOffset, int *s
}
int length = sci->pdoc->Length();
- g_return_val_if_fail(byteOffset < length, NULL);
+ g_return_val_if_fail(byteOffset <= length, NULL);
- const char style = sci->pdoc->StyleAt(byteOffset);
+ const char style = StyleAt(byteOffset, true);
// compute the range for this style
Position startByte = byteOffset;
+ // when going backwards, we know the style is already computed
while (startByte > 0 && sci->pdoc->StyleAt((startByte) - 1) == style)
(startByte)--;
- Position endByte = byteOffset;
- while ((endByte) + 1 < length && sci->pdoc->StyleAt((endByte) + 1) == style)
+ Position endByte = byteOffset + 1;
+ while (endByte < length && StyleAt(endByte, true) == style)
(endByte)++;
CharacterRangeFromByteRange(startByte, endByte, startChar, endChar);
@@ -835,10 +859,15 @@ void ScintillaGTKAccessible::Notify(GtkWidget *, gint, SCNotification *nt) {
g_signal_emit_by_name(accessible, "text-changed::insert", startChar, lengthChar);
UpdateCursor();
}
+ if (nt->modificationType & SC_MOD_BEFOREDELETE) {
+ // We cannot compute the deletion length in DELETETEXT as it requires accessing the
+ // buffer, so that the character are still present. So, we cache the value here,
+ // and use it in DELETETEXT that fires quickly after.
+ deletionLengthChar = sci->pdoc->CountCharacters(nt->position, nt->position + nt->length);
+ }
if (nt->modificationType & SC_MOD_DELETETEXT) {
int startChar = CharacterOffsetFromByteOffset(nt->position);
- int lengthChar = sci->pdoc->CountCharacters(nt->position, nt->position + nt->length);
- g_signal_emit_by_name(accessible, "text-changed::delete", startChar, lengthChar);
+ g_signal_emit_by_name(accessible, "text-changed::delete", startChar, deletionLengthChar);
UpdateCursor();
}
if (nt->modificationType & SC_MOD_CHANGESTYLE) {
@@ -1042,10 +1071,12 @@ static AtkObject *scintilla_object_accessible_new(GType parent_type, GObject *ob
// @p cache pointer to store the AtkObject between repeated calls. Might or might not be filled.
// @p widget_parent_class pointer to the widget's parent class (to chain up method calls).
AtkObject *ScintillaGTKAccessible::WidgetGetAccessibleImpl(GtkWidget *widget, AtkObject **cache, gpointer widget_parent_class G_GNUC_UNUSED) {
-#if HAVE_GTK_A11Y_H // just instantiate the accessible
- if (*cache == NULL) {
- *cache = scintilla_object_accessible_new(0, G_OBJECT(widget));
+ if (*cache != NULL) {
+ return *cache;
}
+
+#if HAVE_GTK_A11Y_H // just instantiate the accessible
+ *cache = scintilla_object_accessible_new(0, G_OBJECT(widget));
#elif HAVE_GTK_FACTORY // register in the factory and let GTK instantiate
static volatile gsize registered = 0;
@@ -1063,24 +1094,22 @@ AtkObject *ScintillaGTKAccessible::WidgetGetAccessibleImpl(GtkWidget *widget, At
}
g_once_init_leave(®istered, 1);
}
- *cache = GTK_WIDGET_CLASS(widget_parent_class)->get_accessible(widget);
+ AtkObject *obj = GTK_WIDGET_CLASS(widget_parent_class)->get_accessible(widget);
+ *cache = static_cast<AtkObject*>(g_object_ref(obj));
#else // no public API, no factory, so guess from the parent and instantiate
- if (*cache == NULL) {
- static GType parent_atk_type = 0;
-
- if (parent_atk_type == 0) {
- AtkObject *parent_obj = GTK_WIDGET_CLASS(widget_parent_class)->get_accessible(widget);
- if (parent_obj) {
- GType parent_atk_type = G_OBJECT_TYPE(parent_obj);
-
- // Figure out whether accessibility is enabled by looking at the type of the accessible
- // object which would be created for the parent type of ScintillaObject.
- if (g_type_is_a(parent_atk_type, GTK_TYPE_ACCESSIBLE)) {
- *cache = scintilla_object_accessible_new(parent_atk_type, G_OBJECT(widget));
- g_object_unref(parent_obj);
- } else {
- *cache = parent_obj;
- }
+ static GType parent_atk_type = 0;
+
+ if (parent_atk_type == 0) {
+ AtkObject *parent_obj = GTK_WIDGET_CLASS(widget_parent_class)->get_accessible(widget);
+ if (parent_obj) {
+ GType parent_atk_type = G_OBJECT_TYPE(parent_obj);
+
+ // Figure out whether accessibility is enabled by looking at the type of the accessible
+ // object which would be created for the parent type of ScintillaObject.
+ if (g_type_is_a(parent_atk_type, GTK_TYPE_ACCESSIBLE)) {
+ *cache = scintilla_object_accessible_new(parent_atk_type, G_OBJECT(widget));
+ } else {
+ *cache = static_cast<AtkObject*>(g_object_ref(parent_obj));
}
}
}
Modified: scintilla/gtk/ScintillaGTKAccessible.h
9 lines changed, 9 insertions(+), 0 deletions(-)
===================================================================
@@ -16,9 +16,12 @@ namespace Scintilla {
class ScintillaGTKAccessible {
private:
+ // weak references to related objects
GtkAccessible *accessible;
ScintillaGTK *sci;
+ // cached length of the deletion, in characters (see Notify())
+ int deletionLengthChar;
// local state for comparing
Position old_pos;
std::vector<SelectionRange> old_sels;
@@ -70,6 +73,12 @@ class ScintillaGTKAccessible {
return sci->pdoc->MovePositionOutsideChar(pos + 1, 1, true);
}
+ int StyleAt(Position position, bool ensureStyle = false) {
+ if (ensureStyle)
+ sci->pdoc->EnsureStyledTo(position);
+ return sci->pdoc->StyleAt(position);
+ }
+
// For AtkText
gchar *GetTextRangeUTF8(Position startByte, Position endByte);
gchar *GetText(int startChar, int endChar);
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
More information about the Commits
mailing list