[GTK] Missing DRT AccessibilityUIElement::addNotificationListener implementation

https://bugs.webkit.org/show_bug.cgi?id=119883

Tools:

Implemented the notification listener for AccessibilityUIElement. The signal is generated
by AXObjectCache::postPlatformNotification() and received by axObjectEventListener().
axObjectEventListener will then invoke JSObjectCallAsFunction() with the respective
callback function. The global callback function and callbacks for specific elements are
stored in a HashMap in AccessibilityCallbacksAtk.cpp.

Patch by Denis Nomiyama <d.nomiyama@samsung.com> on 2013-08-27
Reviewed by Chris Fleizach.

* DumpRenderTree/AccessibilityUIElement.h: Added a notification handler for GTK+
* DumpRenderTree/atk/AccessibilityCallbacks.h: Added addAccessibilityNotificationListener()
and removeAccessibilityNotificationListener()
* DumpRenderTree/atk/AccessibilityCallbacksAtk.cpp:
(axObjectEventListener): Call JS callback for global notification or for a specific element
(disconnectAccessibilityCallbacks): Only disconnect if logging is off and there is no
notification handler
(addAccessibilityNotificationHandler): Add notification listener to the list
(removeAccessibilityNotificationHandler): Remove notification listener from the list
* DumpRenderTree/atk/AccessibilityControllerAtk.cpp:
(AccessibilityController::setLogAccessibilityEvents): Set logging off before disconnecting
* DumpRenderTree/atk/AccessibilityNotificationHandlerAtk.cpp: Added.
(AccessibilityNotificationHandler::AccessibilityNotificationHandler): Create handler
(AccessibilityNotificationHandler::~AccessibilityNotificationHandler): Destroy handler.
Remove handler from the list and disconnect callbacks
(AccessibilityNotificationHandler::setNotificationFunctionCallback): Set the notification
callback and connect callbacks to signals
* DumpRenderTree/atk/AccessibilityNotificationHandlerAtk.h: Added.
(AccessibilityNotificationHandler::setPlatformElement): Set platform element
(AccessibilityNotificationHandler::platformElement): Get platform element
(AccessibilityNotificationHandler::notificationFunctionCallback): Get notification callback
* DumpRenderTree/atk/AccessibilityUIElementAtk.cpp:
(AccessibilityUIElement::addNotificationListener): Create notification handler, set the
platform element and the notification callback
(AccessibilityUIElement::removeNotificationListener):
* DumpRenderTree/efl/CMakeLists.txt: Added AccessibilityNotificationHandlerAtk.cpp/h
* GNUmakefile.am: Added AccessibilityNotificationHandlerAtk.cpp/h

LayoutTests:

Unskipped the checkbox notification test in a11y and added the expected results.

Patch by Denis Nomiyama <d.nomiyama@samsung.com> on 2013-08-27
Reviewed by Chris Fleizach.

* platform/gtk/TestExpectations: Unskipped the checkbox notification test in a11y.
* platform/gtk/accessibility/aria-checkbox-sends-notification-expected.txt: Added.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@154697 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent ba1f6989
2013-08-27 Denis Nomiyama <d.nomiyama@samsung.com>
[GTK] Missing DRT AccessibilityUIElement::addNotificationListener implementation
https://bugs.webkit.org/show_bug.cgi?id=119883
Unskipped the checkbox notification test in a11y and added the expected results.
Reviewed by Chris Fleizach.
* platform/gtk/TestExpectations: Unskipped the checkbox notification test in a11y.
* platform/gtk/accessibility/aria-checkbox-sends-notification-expected.txt: Added.
2013-08-27 Ádám Kallai <kadam@inf.u-szeged.hu>
[Qt] Delete unnecessary empty directory.
......@@ -782,9 +782,6 @@ webkit.org/b/61826 fast/events/drag-image-filename.html [ Timeout ]
webkit.org/b/98350 accessibility/aria-invalid.html [ Timeout ]
# Missing DRT AccessibilityController::addNotificationListener implementation
webkit.org/b/70606 accessibility/aria-checkbox-sends-notification.html [ Timeout ]
Bug(GTK) media/progress-events-generated-correctly.html [ Failure Timeout ]
webkit.org/b/102257 fast/dom/Window/open-window-min-size.html [ Timeout ]
......
Test Checkbox
This tests that checking of an aria checkbox sends a notification.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS successfullyParsed is true
TEST COMPLETE
Got notification: CheckedStateChanged
Got notification: CheckedStateChanged
2013-08-27 Denis Nomiyama <d.nomiyama@samsung.com>
[GTK] Missing DRT AccessibilityUIElement::addNotificationListener implementation
https://bugs.webkit.org/show_bug.cgi?id=119883
Implemented the notification listener for AccessibilityUIElement. The signal is generated
by AXObjectCache::postPlatformNotification() and received by axObjectEventListener().
axObjectEventListener will then invoke JSObjectCallAsFunction() with the respective
callback function. The global callback function and callbacks for specific elements are
stored in a HashMap in AccessibilityCallbacksAtk.cpp.
Reviewed by Chris Fleizach.
* DumpRenderTree/AccessibilityUIElement.h: Added a notification handler for GTK+
* DumpRenderTree/atk/AccessibilityCallbacks.h: Added addAccessibilityNotificationListener()
and removeAccessibilityNotificationListener()
* DumpRenderTree/atk/AccessibilityCallbacksAtk.cpp:
(axObjectEventListener): Call JS callback for global notification or for a specific element
(disconnectAccessibilityCallbacks): Only disconnect if logging is off and there is no
notification handler
(addAccessibilityNotificationHandler): Add notification listener to the list
(removeAccessibilityNotificationHandler): Remove notification listener from the list
* DumpRenderTree/atk/AccessibilityControllerAtk.cpp:
(AccessibilityController::setLogAccessibilityEvents): Set logging off before disconnecting
* DumpRenderTree/atk/AccessibilityNotificationHandlerAtk.cpp: Added.
(AccessibilityNotificationHandler::AccessibilityNotificationHandler): Create handler
(AccessibilityNotificationHandler::~AccessibilityNotificationHandler): Destroy handler.
Remove handler from the list and disconnect callbacks
(AccessibilityNotificationHandler::setNotificationFunctionCallback): Set the notification
callback and connect callbacks to signals
* DumpRenderTree/atk/AccessibilityNotificationHandlerAtk.h: Added.
(AccessibilityNotificationHandler::setPlatformElement): Set platform element
(AccessibilityNotificationHandler::platformElement): Get platform element
(AccessibilityNotificationHandler::notificationFunctionCallback): Get notification callback
* DumpRenderTree/atk/AccessibilityUIElementAtk.cpp:
(AccessibilityUIElement::addNotificationListener): Create notification handler, set the
platform element and the notification callback
(AccessibilityUIElement::removeNotificationListener):
* DumpRenderTree/efl/CMakeLists.txt: Added AccessibilityNotificationHandlerAtk.cpp/h
* GNUmakefile.am: Added AccessibilityNotificationHandlerAtk.cpp/h
2013-08-27 Carlos Garcia Campos <cgarcia@igalia.com>
Unreviewed. Fix GTK+ build after r154601.
......
......@@ -46,6 +46,7 @@ typedef struct objc_object* PlatformUIElement;
typedef COMPtr<IAccessible> PlatformUIElement;
#elif HAVE(ACCESSIBILITY) && (PLATFORM(GTK) || PLATFORM(EFL))
#include "AccessibilityNotificationHandlerAtk.h"
#include <atk/atk.h>
typedef AtkObject* PlatformUIElement;
#else
......@@ -273,6 +274,10 @@ private:
#if PLATFORM(MAC)
NotificationHandler m_notificationHandler;
#endif
#if PLATFORM(GTK) || PLATFORM(EFL)
RefPtr<AccessibilityNotificationHandler> m_notificationHandler;
#endif
};
#endif // AccessibilityUIElement_h
......@@ -29,7 +29,14 @@
#ifndef AccessibilityCallbacks_h
#define AccessibilityCallbacks_h
#include "AccessibilityNotificationHandlerAtk.h"
#include "AccessibilityUIElement.h"
const PlatformUIElement GlobalNotificationKey = 0;
void connectAccessibilityCallbacks();
void disconnectAccessibilityCallbacks();
void addAccessibilityNotificationHandler(AccessibilityNotificationHandler*);
void removeAccessibilityNotificationHandler(AccessibilityNotificationHandler*);
#endif
......@@ -32,7 +32,9 @@
#if HAVE(ACCESSIBILITY)
#include "AccessibilityController.h"
#include "AccessibilityNotificationHandlerAtk.h"
#include "DumpRenderTree.h"
#include "JSRetainPtr.h"
#include <atk/atk.h>
#include <wtf/gobject/GOwnPtr.h>
......@@ -52,6 +54,9 @@ static guint activeDescendantChangedListenerId = 0;
static guint childrenChangedListenerId = 0;
static guint propertyChangedListenerId = 0;
static guint visibleDataChangedListenerId = 0;
static HashMap<PlatformUIElement, AccessibilityNotificationHandler*> notificationHandlers;
extern bool loggingAccessibilityEvents;
static void printAccessibilityEvent(AtkObject* accessible, const gchar* signalName, const gchar* signalValue)
{
......@@ -87,12 +92,15 @@ static gboolean axObjectEventListener(GSignalInvocationHint *signalHint, guint n
GSignalQuery signalQuery;
GOwnPtr<gchar> signalName;
GOwnPtr<gchar> signalValue;
String notificationName;
g_signal_query(signalHint->signal_id, &signalQuery);
if (!g_strcmp0(signalQuery.signal_name, "state-change")) {
signalName.set(g_strdup_printf("state-change:%s", g_value_get_string(&paramValues[1])));
signalValue.set(g_strdup_printf("%d", g_value_get_boolean(&paramValues[2])));
if (!g_strcmp0(g_value_get_string(&paramValues[1]), "checked"))
notificationName = "CheckedStateChanged";
} else if (!g_strcmp0(signalQuery.signal_name, "focus-event")) {
signalName.set(g_strdup("focus-event"));
signalValue.set(g_strdup_printf("%d", g_value_get_boolean(&paramValues[1])));
......@@ -104,7 +112,37 @@ static gboolean axObjectEventListener(GSignalInvocationHint *signalHint, guint n
else
signalName.set(g_strdup(signalQuery.signal_name));
printAccessibilityEvent(accessible, signalName.get(), signalValue.get());
if (loggingAccessibilityEvents)
printAccessibilityEvent(accessible, signalName.get(), signalValue.get());
#if PLATFORM(GTK)
JSGlobalContextRef jsContext = webkit_web_frame_get_global_context(mainFrame);
#else
JSContextRef jsContext = 0;
#endif
if (!jsContext)
return TRUE;
if (notificationName.length()) {
for (HashMap<PlatformUIElement, AccessibilityNotificationHandler*>::iterator it = notificationHandlers.begin(); it != notificationHandlers.end(); ++it) {
if (it->key == accessible || it->key == GlobalNotificationKey) {
JSRetainPtr<JSStringRef> jsNotificationEventName(Adopt, JSStringCreateWithUTF8CString(reinterpret_cast<const char*>(notificationName.utf8().data())));
JSValueRef notificationNameArgument = JSValueMakeString(jsContext, jsNotificationEventName.get());
AccessibilityNotificationHandler* notificationHandler = it->value;
if (notificationHandler->platformElement()) {
JSValueRef argument = notificationNameArgument;
// Listener for one element just gets one argument, the notification name.
JSObjectCallAsFunction(jsContext, notificationHandler->notificationFunctionCallback(), 0, 1, &argument, 0);
} else {
// A global listener gets the element and the notification name as arguments.
JSValueRef arguments[2];
arguments[0] = AccessibilityUIElement::makeJSAccessibilityUIElement(jsContext, AccessibilityUIElement(accessible));
arguments[1] = notificationNameArgument;
JSObjectCallAsFunction(jsContext, notificationHandler->notificationFunctionCallback(), 0, 2, arguments, 0);
}
}
}
}
return TRUE;
}
......@@ -140,6 +178,10 @@ void connectAccessibilityCallbacks()
void disconnectAccessibilityCallbacks()
{
// Only disconnect if logging is off and there is no notification handler.
if (loggingAccessibilityEvents || !notificationHandlers.isEmpty())
return;
// AtkObject signals.
if (stateChangeListenerId) {
atk_remove_global_event_listener(stateChangeListenerId);
......@@ -167,4 +209,57 @@ void disconnectAccessibilityCallbacks()
}
}
void addAccessibilityNotificationHandler(AccessibilityNotificationHandler* notificationHandler)
{
if (!notificationHandler)
return;
#if PLATFORM(GTK)
JSGlobalContextRef jsContext = webkit_web_frame_get_global_context(mainFrame);
#else
JSContextRef jsContext = 0;
#endif
if (!jsContext)
return;
JSValueProtect(jsContext, notificationHandler->notificationFunctionCallback());
// Check if this notification handler is related to a specific element.
if (notificationHandler->platformElement()) {
if (notificationHandlers.contains(notificationHandler->platformElement())) {
JSValueUnprotect(jsContext, notificationHandlers.find(notificationHandler->platformElement())->value->notificationFunctionCallback());
notificationHandlers.remove(notificationHandler->platformElement());
}
notificationHandlers.add(notificationHandler->platformElement(), notificationHandler);
} else {
if (notificationHandlers.contains(GlobalNotificationKey)) {
JSValueUnprotect(jsContext, notificationHandlers.find(GlobalNotificationKey)->value->notificationFunctionCallback());
notificationHandlers.remove(GlobalNotificationKey);
}
notificationHandlers.add(GlobalNotificationKey, notificationHandler);
}
connectAccessibilityCallbacks();
}
void removeAccessibilityNotificationHandler(AccessibilityNotificationHandler* notificationHandler)
{
if (!notificationHandler)
return;
#if PLATFORM(GTK)
JSGlobalContextRef jsContext = webkit_web_frame_get_global_context(mainFrame);
#else
JSGlobalContextRef jsContext = 0;
#endif
if (!jsContext)
return;
for (HashMap<PlatformUIElement, AccessibilityNotificationHandler*>::iterator it = notificationHandlers.begin(); it != notificationHandlers.end(); ++it) {
if (it->value == notificationHandler) {
JSValueUnprotect(jsContext, notificationHandler->notificationFunctionCallback());
notificationHandlers.remove(it);
}
}
}
#endif
......@@ -35,7 +35,7 @@
#include <atk/atk.h>
static bool loggingAccessibilityEvents = false;
bool loggingAccessibilityEvents = false;
AccessibilityController::AccessibilityController()
{
......@@ -70,8 +70,8 @@ void AccessibilityController::setLogAccessibilityEvents(bool logAccessibilityEve
return;
if (!logAccessibilityEvents) {
disconnectAccessibilityCallbacks();
loggingAccessibilityEvents = false;
disconnectAccessibilityCallbacks();
return;
}
......
/*
* Copyright (C) 2013 Samsung Electronics Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "config.h"
#include "AccessibilityNotificationHandlerAtk.h"
#include "AccessibilityCallbacks.h"
AccessibilityNotificationHandler::AccessibilityNotificationHandler(void)
: m_platformElement(GlobalNotificationKey)
, m_notificationFunctionCallback(0)
{
}
AccessibilityNotificationHandler::~AccessibilityNotificationHandler()
{
removeAccessibilityNotificationHandler(this);
disconnectAccessibilityCallbacks();
}
void AccessibilityNotificationHandler::setNotificationFunctionCallback(JSObjectRef notificationFunctionCallback)
{
if (!notificationFunctionCallback) {
removeAccessibilityNotificationHandler(this);
return;
}
if (m_notificationFunctionCallback)
removeAccessibilityNotificationHandler(this);
m_notificationFunctionCallback = notificationFunctionCallback;
connectAccessibilityCallbacks();
addAccessibilityNotificationHandler(this);
}
/*
* Copyright (C) 2013 Samsung Electronics Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef AccessibilityNotificationHandlerAtk_h
#define AccessibilityNotificationHandlerAtk_h
#include <JavaScriptCore/JSObjectRef.h>
#include <atk/atk.h>
#include <wtf/RefCounted.h>
class AccessibilityNotificationHandler : public RefCounted<AccessibilityNotificationHandler> {
public:
AccessibilityNotificationHandler(void);
~AccessibilityNotificationHandler();
void setPlatformElement(AtkObject* platformElement) { m_platformElement = platformElement; }
AtkObject* platformElement(void) const { return m_platformElement; }
void setNotificationFunctionCallback(JSObjectRef);
JSObjectRef notificationFunctionCallback(void) const { return m_notificationFunctionCallback; }
private:
AtkObject* m_platformElement;
JSObjectRef m_notificationFunctionCallback;
};
#endif // AccessibilityNotificationHandlerAtk_h
......@@ -29,6 +29,7 @@
#if HAVE(ACCESSIBILITY)
#include "AccessibilityNotificationHandlerAtk.h"
#include <JavaScriptCore/JSStringRef.h>
#include <JavaScriptCore/OpaqueJSString.h>
#include <atk/atk.h>
......@@ -1027,13 +1028,26 @@ JSStringRef AccessibilityUIElement::url()
bool AccessibilityUIElement::addNotificationListener(JSObjectRef functionCallback)
{
// FIXME: implement
return false;
if (!functionCallback)
return false;
// Only one notification listener per element.
if (m_notificationHandler)
return false;
m_notificationHandler = new AccessibilityNotificationHandler();
m_notificationHandler->setPlatformElement(platformUIElement());
m_notificationHandler->setNotificationFunctionCallback(functionCallback);
return true;
}
void AccessibilityUIElement::removeNotificationListener()
{
// FIXME: implement
// Programmers should not be trying to remove a listener that's already removed.
ASSERT(m_notificationHandler);
m_notificationHandler = 0;
}
bool AccessibilityUIElement::isFocusable() const
......
......@@ -10,6 +10,7 @@ set(DumpRenderTree_SOURCES
${TOOLS_DIR}/DumpRenderTree/WorkQueue.cpp
${TOOLS_DIR}/DumpRenderTree/atk/AccessibilityCallbacksAtk.cpp
${TOOLS_DIR}/DumpRenderTree/atk/AccessibilityControllerAtk.cpp
${TOOLS_DIR}/DumpRenderTree/atk/AccessibilityNotificationHandlerAtk.cpp
${TOOLS_DIR}/DumpRenderTree/atk/AccessibilityUIElementAtk.cpp
${TOOLS_DIR}/DumpRenderTree/cairo/PixelDumpSupportCairo.cpp
${TOOLS_DIR}/DumpRenderTree/efl/AccessibilityControllerEfl.cpp
......
......@@ -155,6 +155,8 @@ Programs_DumpRenderTree_SOURCES = \
Tools/DumpRenderTree/atk/AccessibilityCallbacks.h \
Tools/DumpRenderTree/atk/AccessibilityCallbacksAtk.cpp \
Tools/DumpRenderTree/atk/AccessibilityControllerAtk.cpp \
Tools/DumpRenderTree/atk/AccessibilityNotificationHandlerAtk.cpp \
Tools/DumpRenderTree/atk/AccessibilityNotificationHandlerAtk.h \
Tools/DumpRenderTree/atk/AccessibilityUIElementAtk.cpp \
Tools/DumpRenderTree/cairo/PixelDumpSupportCairo.cpp \
Tools/DumpRenderTree/cairo/PixelDumpSupportCairo.h \
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment