[gjs/ewlsh/gtk4-a11y: 1/2] overrides: Add Gtk.AccessibleRelationList




commit cbdb14c71752b9fbf780157e8788aa2e04f9ff46
Author: Evan Welsh <contact evanwelsh com>
Date:   Thu Aug 26 21:33:52 2021 -0700

    overrides: Add Gtk.AccessibleRelationList
    
    This function wraps a list of Gtk.Accessible objects in a GList and
    stores the result as a pointer in a GValue.
    
    The pointer is not accessible from JavaScript.
    
    Fixes #392

 gi/private.cpp                | 59 +++++++++++++++++++++++++++++++++++++++++++
 modules/core/overrides/Gtk.js | 12 +++++++++
 2 files changed, 71 insertions(+)
---
diff --git a/gi/private.cpp b/gi/private.cpp
index a6ecc723..88628cf1 100644
--- a/gi/private.cpp
+++ b/gi/private.cpp
@@ -7,6 +7,7 @@
 
 #include <stdint.h>
 
+#include <girepository.h>
 #include <glib-object.h>
 #include <glib.h>
 
@@ -19,6 +20,7 @@
 #include <js/Utility.h>  // for UniqueChars
 #include <jsapi.h>       // for JS_GetElement
 
+#include "gi/boxed.h"
 #include "gi/gobject.h"
 #include "gi/gtype.h"
 #include "gi/interface.h"
@@ -393,6 +395,62 @@ static bool gjs_signal_new(JSContext* cx, unsigned argc, JS::Value* vp) {
     return true;
 }
 
+GJS_JSAPI_RETURN_CONVENTION
+static bool gjs_build_object_list(JSContext* cx, unsigned argc, JS::Value* vp) {
+    JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+
+    JS::RootedObject object(cx);
+    if (!gjs_parse_call_args(cx, "build_object_list", args, "o", "array",
+                             &object))
+        return false;
+
+    bool is_array;
+    if (!JS::IsArrayObject(cx, object, &is_array))
+        return false;
+
+    if (!is_array) {
+        gjs_throw(cx, "Expected array object.");
+        return false;
+    }
+
+    uint32_t length;
+    if (!JS::GetArrayLength(cx, object, &length))
+        return false;
+
+    GList* list = nullptr;
+    for (uint32_t i = 0; i < length; i++) {
+        JS::RootedValue v_elem(cx);
+        JS_GetElement(cx, object, i, &v_elem);
+        if (!v_elem.isObject()) {
+            gjs_throw(cx, "Unexpected non-object in array.");
+            return false;
+        }
+
+        JS::RootedObject elem(cx, &v_elem.toObject());
+        ObjectInstance* instance = ObjectInstance::for_js(cx, elem);
+        if (!instance) {
+            gjs_throw(cx, "Object does not inherit from GObject.Object");
+            return false;
+        }
+
+        list = g_list_append(list, instance->ptr());
+    }
+
+    GValue value = G_VALUE_INIT;
+    g_value_init(&value, G_TYPE_POINTER);
+    g_value_set_pointer(&value, list);
+
+    GjsAutoBaseInfo boxed_info =
+        g_irepository_find_by_name(nullptr, "GObject", "Value");
+    JS::RootedObject value_obj(
+        cx, BoxedInstance::new_for_c_struct(cx, boxed_info, &value));
+    if (!value_obj)
+        return false;
+
+    args.rval().setObject(*value_obj);
+    return true;
+}
+
 template <GjsSymbolAtom GjsAtoms::*member>
 GJS_JSAPI_RETURN_CONVENTION static bool symbol_getter(JSContext* cx,
                                                       unsigned argc,
@@ -409,6 +467,7 @@ static JSFunctionSpec private_module_funcs[] = {
           GJS_MODULE_PROP_FLAGS),
     JS_FN("register_type", gjs_register_type, 4, GJS_MODULE_PROP_FLAGS),
     JS_FN("signal_new", gjs_signal_new, 6, GJS_MODULE_PROP_FLAGS),
+    JS_FN("build_object_list", gjs_build_object_list, 1, GJS_MODULE_PROP_FLAGS),
     JS_FS_END,
 };
 
diff --git a/modules/core/overrides/Gtk.js b/modules/core/overrides/Gtk.js
index 306f7d3f..3dd2904c 100644
--- a/modules/core/overrides/Gtk.js
+++ b/modules/core/overrides/Gtk.js
@@ -3,6 +3,7 @@
 // SPDX-FileCopyrightText: 2013 Giovanni Campagna
 
 const Legacy = imports._legacy;
+const Gi = imports._gi;
 const {Gio, GjsPrivate, GObject} = imports.gi;
 
 let Gtk;
@@ -126,6 +127,17 @@ function _init() {
             }
         });
     }
+
+    if (Gtk.Accessible.prototype.update_relation) {
+        Gtk.AccessibleRelationList = function AccessibleRelationList(values) {
+            if (Array.isArray(values)) {
+                const incorrectValues = values.filter(value => !(value instanceof Gtk.Accessible));
+                if (incorrectValues.length !== 0)
+                    throw new Error(`Found objects not inheriting from Gtk.Accessible: 
${incorrectValues.map(value => `${value}`).join(', ')}.`);
+            }
+            return Gi.build_object_list(values);
+        };
+    }
 }
 
 function _createClosure(builder, thisArg, handlerName, swapped, connectObject) {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]