Skip to content

Commit

Permalink
[GTK] Implement GTK4 accessibility
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=227528

Reviewed by Carlos Garcia Campos.

WebKit maintains a complete AT-SPI accessible tree within the web
process, under a separate D-Bus name. This conflicts with GTK4's
expectations of having instances of GtkAccessible objects in process
that can be built in an internal tree.

GTK4 recently introduced support for bridging out-of-process AT-SPI
accessible trees using a new GtkAtSpiSocket object that implements
GtkAccessible [1]. The availability of this object is guarded by the
GTK_ACCESSIBILITY_ATSPI ifdef.

Use this new socket object from GTK to bridge the web page accessible
tree, and the UI process' one. Mark the textview widget as hidden from
the accessible tree.

Create the GtkAtSpiSocket accessible when the web page reports to be
ready. Inject the socket accessible as the first GtkAccessible child
of WebKitWebViewBase.

[1] https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/6827

* Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp:
(webkitWebViewBaseAccessibleGetFirstAccessibleChild):
(webkitWebViewBaseAccessibleInterfaceInit):
(webkitWebViewBaseSetPlugID):
* Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h:
* Source/WebKit/UIProcess/gtk/KeyBindingTranslator.cpp:
(WebKit::KeyBindingTranslator::KeyBindingTranslator):
* Source/WebKit/UIProcess/gtk/WebPageProxyGtk.cpp:
(WebKit::WebPageProxy::bindAccessibilityTree):
* Source/WebKit/WebProcess/WebPage/glib/WebPageGLib.cpp:
(WebKit::WebPage::platformInitialize):

Canonical link: https://commits.webkit.org/274201@main
  • Loading branch information
GeorgesStavracas authored and carlosgcampos committed Feb 7, 2024
1 parent eb1d01c commit da96990
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 8 deletions.
69 changes: 67 additions & 2 deletions Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@
#include "WebFullScreenManagerProxy.h"
#endif

#if USE(GTK4) && defined(GTK_ACCESSIBILITY_ATSPI)
#include <gtk/a11y/gtkatspi.h>
#endif

using namespace WebKit;
using namespace WebCore;

Expand Down Expand Up @@ -300,7 +304,11 @@ struct _WebKitWebViewBasePrivate {
CString tooltipText;
IntRect tooltipArea;
WebHitTestResultData::IsScrollbar mouseIsOverScrollbar;
#if !USE(GTK4)
#if USE(GTK4)
#ifdef GTK_ACCESSIBILITY_ATSPI
GRefPtr<GtkAccessible> socketAccessible;
#endif
#else
GRefPtr<AtkObject> accessible;
#endif
GtkWidget* dialog { nullptr };
Expand Down Expand Up @@ -376,7 +384,10 @@ struct _WebKitWebViewBasePrivate {
*/

#if USE(GTK4)
WEBKIT_DEFINE_TYPE(WebKitWebViewBase, webkit_web_view_base, GTK_TYPE_WIDGET)
static void webkitWebViewBaseAccessibleInterfaceInit(GtkAccessibleInterface*);

WEBKIT_DEFINE_TYPE_WITH_CODE(WebKitWebViewBase, webkit_web_view_base, GTK_TYPE_WIDGET,
G_IMPLEMENT_INTERFACE(GTK_TYPE_ACCESSIBLE, webkitWebViewBaseAccessibleInterfaceInit))
#else
WEBKIT_DEFINE_TYPE(WebKitWebViewBase, webkit_web_view_base, GTK_TYPE_CONTAINER)
#endif
Expand All @@ -387,6 +398,29 @@ static void webkitWebViewBaseDidExitFullScreen(WebKitWebViewBase*);
static void webkitWebViewBaseRequestExitFullScreen(WebKitWebViewBase*);
#endif

#if USE(GTK4)
static GtkAccessible* webkitWebViewBaseAccessibleGetFirstAccessibleChild(GtkAccessible* accessible)
{
WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(accessible);

#ifdef GTK_ACCESSIBILITY_ATSPI
if (webView->priv->socketAccessible)
return GTK_ACCESSIBLE(g_object_ref(webView->priv->socketAccessible.get()));
#endif

if (auto* widget = gtk_widget_get_first_child(GTK_WIDGET(webView)))
return GTK_ACCESSIBLE(g_object_ref(widget));

return nullptr;
}

static void
webkitWebViewBaseAccessibleInterfaceInit(GtkAccessibleInterface* iface)
{
iface->get_first_accessible_child = webkitWebViewBaseAccessibleGetFirstAccessibleChild;
}
#endif

static void webkitWebViewBaseUpdateDisplayID(WebKitWebViewBase* webViewBase, GdkMonitor* monitor)
{
if (!monitor)
Expand Down Expand Up @@ -3440,3 +3474,34 @@ void webkitWebViewBaseCallAfterNextPresentationUpdate(WebKitWebViewBase* webView
{
webkitWebViewBaseNextPresentationUpdateMonitorStart(webViewBase, WTFMove(callback));
}

#if USE(GTK4)
void webkitWebViewBaseSetPlugID(WebKitWebViewBase* webViewBase, const String& plugID)
{
#ifdef GTK_ACCESSIBILITY_ATSPI
WebKitWebViewBasePrivate* priv = webViewBase->priv;

if (priv->socketAccessible) {
gtk_accessible_set_accessible_parent(priv->socketAccessible.get(), nullptr, nullptr);
priv->socketAccessible = nullptr;
}

Vector<String> tokens = plugID.split(':');
RELEASE_ASSERT(tokens.size() == 2);

GUniqueOutPtr<GError> error;
GUniquePtr<char> busName(g_strdup_printf(":%s", tokens[0].utf8().data()));

priv->socketAccessible = adoptGRef(gtk_at_spi_socket_new(busName.get(), tokens[1].utf8().data(), &error.outPtr()));

if (priv->socketAccessible) {
auto* widget = gtk_widget_get_first_child(GTK_WIDGET(webViewBase));
gtk_accessible_set_accessible_parent(priv->socketAccessible.get(), GTK_ACCESSIBLE(webViewBase), GTK_ACCESSIBLE(widget));
} else
g_warning("Error creating WebKitWebView a11y socket: %s", error->message);
#else
UNUSED_PARAM(webViewBase);
UNUSED_PARAM(plugID);
#endif // GTK_ACCESSIBILITY_ATSPI
}
#endif
4 changes: 4 additions & 0 deletions Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,7 @@ void webkitWebViewBaseToplevelWindowStateChanged(WebKitWebViewBase*, uint32_t, u
void webkitWebViewBaseToplevelWindowMonitorChanged(WebKitWebViewBase*, GdkMonitor*);

void webkitWebViewBaseCallAfterNextPresentationUpdate(WebKitWebViewBase*, CompletionHandler<void()>&&);

#if USE(GTK4)
void webkitWebViewBaseSetPlugID(WebKitWebViewBase*, const String&);
#endif
3 changes: 3 additions & 0 deletions Source/WebKit/UIProcess/gtk/KeyBindingTranslator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,9 @@ static void moveCursorCallback(GtkWidget* widget, GtkMovementStep step, gint cou
KeyBindingTranslator::KeyBindingTranslator()
: m_nativeWidget(gtk_text_view_new())
{
#if USE(GTK4)
gtk_accessible_update_state(GTK_ACCESSIBLE(m_nativeWidget.get()), GTK_ACCESSIBLE_STATE_HIDDEN, TRUE, -1);
#endif
g_signal_connect(m_nativeWidget.get(), "backspace", G_CALLBACK(backspaceCallback), this);
g_signal_connect(m_nativeWidget.get(), "cut-clipboard", G_CALLBACK(cutClipboardCallback), this);
g_signal_connect(m_nativeWidget.get(), "copy-clipboard", G_CALLBACK(copyClipboardCallback), this);
Expand Down
3 changes: 1 addition & 2 deletions Source/WebKit/UIProcess/gtk/WebPageProxyGtk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ GtkWidget* WebPageProxy::viewWidget()
void WebPageProxy::bindAccessibilityTree(const String& plugID)
{
#if USE(GTK4)
// FIXME: We need a way to override accessible interface of WebView and send the atspi reference to the web process.
ASSERT_NOT_IMPLEMENTED_YET();
webkitWebViewBaseSetPlugID(WEBKIT_WEB_VIEW_BASE(viewWidget()), plugID);
#else
auto* accessible = gtk_widget_get_accessible(viewWidget());
atk_socket_embed(ATK_SOCKET(accessible), const_cast<char*>(plugID.utf8().data()));
Expand Down
4 changes: 0 additions & 4 deletions Source/WebKit/WebProcess/WebPage/glib/WebPageGLib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,6 @@ void WebPage::platformInitialize(const WebPageCreationParameters&)
// entry point to the Web process, and send a message to the UI
// process to connect the two worlds through the accessibility
// object there specifically placed for that purpose (the socket).
#if PLATFORM(GTK) && USE(GTK4)
// FIXME: we need a way to connect DOM and app a11y tree in GTK4.
#else
if (auto* page = corePage()) {
m_accessibilityRootObject = AccessibilityRootAtspi::create(*page);
m_accessibilityRootObject->registerObject([&](const String& plugID) {
Expand All @@ -72,7 +69,6 @@ void WebPage::platformInitialize(const WebPageCreationParameters&)
});
}
#endif
#endif
}

void WebPage::platformDetach()
Expand Down

0 comments on commit da96990

Please sign in to comment.