1/* 2 * Copyright (C) 2011, 2012 Igalia S.L. 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Library General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Library General Public License for more details. 13 * 14 * You should have received a copy of the GNU Library General Public License 15 * along with this library; see the file COPYING.LIB. If not, write to 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 */ 19 20#include "config.h" 21#include "WebKitAccessibleInterfaceValue.h" 22 23#if HAVE(ACCESSIBILITY) 24 25#include "AccessibilityObject.h" 26#include "HTMLNames.h" 27#include "WebKitAccessibleUtil.h" 28#include "WebKitAccessibleWrapperAtk.h" 29#include <wtf/text/CString.h> 30 31using namespace WebCore; 32 33static AccessibilityObject* core(AtkValue* value) 34{ 35 if (!WEBKIT_IS_ACCESSIBLE(value)) 36 return 0; 37 38 return webkitAccessibleGetAccessibilityObject(WEBKIT_ACCESSIBLE(value)); 39} 40 41static bool webkitAccessibleSetNewValue(AtkValue* coreValue, const gdouble newValue) 42{ 43 AccessibilityObject* coreObject = core(coreValue); 44 if (!coreObject->canSetValueAttribute()) 45 return FALSE; 46 47 // Check value against range limits 48 double value; 49 value = std::max(static_cast<double>(coreObject->minValueForRange()), newValue); 50 value = std::min(static_cast<double>(coreObject->maxValueForRange()), newValue); 51 52 coreObject->setValue(String::number(value)); 53 return TRUE; 54} 55 56static float webkitAccessibleGetIncrementValue(AccessibilityObject* coreObject) 57{ 58 if (!coreObject->getAttribute(HTMLNames::stepAttr).isEmpty()) 59 return coreObject->stepValueForRange(); 60 61 // If 'step' attribute is not defined, WebCore assumes a 5% of the 62 // range between minimum and maximum values. Implicit value of step should be one or larger. 63 float step = (coreObject->maxValueForRange() - coreObject->minValueForRange()) * 0.05; 64 return step < 1 ? 1 : step; 65} 66 67#if ATK_CHECK_VERSION(2,11,92) 68static void webkitAccessibleGetValueAndText(AtkValue* value, gdouble* currentValue, gchar** alternativeText) 69{ 70 g_return_if_fail(ATK_VALUE(value)); 71 returnIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(value)); 72 73 AccessibilityObject* coreObject = core(value); 74 if (!coreObject) 75 return; 76 77 if (currentValue) 78 *currentValue = coreObject->valueForRange(); 79 if (alternativeText) 80 *alternativeText = g_strdup_printf("%s", coreObject->valueDescription().utf8().data()); 81} 82 83static double webkitAccessibleGetIncrement(AtkValue* value) 84{ 85 g_return_val_if_fail(ATK_VALUE(value), 0); 86 returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(value), 0); 87 88 AccessibilityObject* coreObject = core(value); 89 if (!coreObject) 90 return 0; 91 92 return webkitAccessibleGetIncrementValue(coreObject); 93} 94 95static void webkitAccessibleSetValue(AtkValue* value, const gdouble newValue) 96{ 97 g_return_if_fail(ATK_VALUE(value)); 98 returnIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(value)); 99 100 webkitAccessibleSetNewValue(value, newValue); 101} 102 103static AtkRange* webkitAccessibleGetRange(AtkValue* value) 104{ 105 g_return_val_if_fail(ATK_VALUE(value), nullptr); 106 returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(value), nullptr); 107 108 AccessibilityObject* coreObject = core(value); 109 if (!coreObject) 110 return nullptr; 111 112 gdouble minValue = coreObject->minValueForRange(); 113 gdouble maxValue = coreObject->maxValueForRange(); 114 gchar* valueDescription = g_strdup_printf("%s", coreObject->valueDescription().utf8().data()); 115 return atk_range_new(minValue, maxValue, valueDescription); 116} 117#else 118static void webkitAccessibleValueGetCurrentValue(AtkValue* value, GValue* gValue) 119{ 120 g_return_if_fail(ATK_VALUE(value)); 121 returnIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(value)); 122 123 memset(gValue, 0, sizeof(GValue)); 124 g_value_init(gValue, G_TYPE_FLOAT); 125 g_value_set_float(gValue, core(value)->valueForRange()); 126} 127 128static void webkitAccessibleValueGetMaximumValue(AtkValue* value, GValue* gValue) 129{ 130 g_return_if_fail(ATK_VALUE(value)); 131 returnIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(value)); 132 133 memset(gValue, 0, sizeof(GValue)); 134 g_value_init(gValue, G_TYPE_FLOAT); 135 g_value_set_float(gValue, core(value)->maxValueForRange()); 136} 137 138static void webkitAccessibleValueGetMinimumValue(AtkValue* value, GValue* gValue) 139{ 140 g_return_if_fail(ATK_VALUE(value)); 141 returnIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(value)); 142 143 memset(gValue, 0, sizeof(GValue)); 144 g_value_init(gValue, G_TYPE_FLOAT); 145 g_value_set_float(gValue, core(value)->minValueForRange()); 146} 147 148static gboolean webkitAccessibleValueSetCurrentValue(AtkValue* value, const GValue* gValue) 149{ 150 g_return_val_if_fail(ATK_VALUE(value), FALSE); 151 returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(value), FALSE); 152 153 double newValue; 154 if (G_VALUE_HOLDS_DOUBLE(gValue)) 155 newValue = g_value_get_double(gValue); 156 else if (G_VALUE_HOLDS_FLOAT(gValue)) 157 newValue = g_value_get_float(gValue); 158 else if (G_VALUE_HOLDS_INT64(gValue)) 159 newValue = g_value_get_int64(gValue); 160 else if (G_VALUE_HOLDS_INT(gValue)) 161 newValue = g_value_get_int(gValue); 162 else if (G_VALUE_HOLDS_LONG(gValue)) 163 newValue = g_value_get_long(gValue); 164 else if (G_VALUE_HOLDS_ULONG(gValue)) 165 newValue = g_value_get_ulong(gValue); 166 else if (G_VALUE_HOLDS_UINT64(gValue)) 167 newValue = g_value_get_uint64(gValue); 168 else if (G_VALUE_HOLDS_UINT(gValue)) 169 newValue = g_value_get_uint(gValue); 170 else 171 return FALSE; 172 173 return webkitAccessibleSetNewValue(value, newValue); 174} 175 176static void webkitAccessibleValueGetMinimumIncrement(AtkValue* value, GValue* gValue) 177{ 178 g_return_if_fail(ATK_VALUE(value)); 179 returnIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(value)); 180 181 memset(gValue, 0, sizeof(GValue)); 182 g_value_init(gValue, G_TYPE_FLOAT); 183 184 AccessibilityObject* coreObject = core(value); 185 g_value_set_float(gValue, webkitAccessibleGetIncrementValue(coreObject)); 186} 187#endif 188 189void webkitAccessibleValueInterfaceInit(AtkValueIface* iface) 190{ 191#if ATK_CHECK_VERSION(2,11,92) 192 iface->get_value_and_text = webkitAccessibleGetValueAndText; 193 iface->get_increment = webkitAccessibleGetIncrement; 194 iface->set_value = webkitAccessibleSetValue; 195 iface->get_range = webkitAccessibleGetRange; 196#else 197 iface->get_current_value = webkitAccessibleValueGetCurrentValue; 198 iface->get_maximum_value = webkitAccessibleValueGetMaximumValue; 199 iface->get_minimum_value = webkitAccessibleValueGetMinimumValue; 200 iface->set_current_value = webkitAccessibleValueSetCurrentValue; 201 iface->get_minimum_increment = webkitAccessibleValueGetMinimumIncrement; 202#endif 203} 204 205#endif 206