1/* 2 * Copyright (C) 2009 Collabora Ltd. 3 * Copyright (C) 2009 Igalia S.L. 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Library General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Library General Public License for more details. 14 * 15 * You should have received a copy of the GNU Library General Public License 16 * along with this library; see the file COPYING.LIB. If not, write to 17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 * Boston, MA 02110-1301, USA. 19 */ 20 21#include "config.h" 22#include "webkithittestresult.h" 23 24#include "Frame.h" 25#include "FrameView.h" 26#include "HitTestResult.h" 27#include "KURL.h" 28#include "WebKitDOMNodePrivate.h" 29#include "webkitenumtypes.h" 30#include "webkitglobals.h" 31#include "webkitglobalsprivate.h" 32#include <glib/gi18n-lib.h> 33#include <wtf/gobject/GOwnPtr.h> 34#include <wtf/gobject/GRefPtr.h> 35#include <wtf/text/CString.h> 36 37/** 38 * SECTION:webkithittestresult 39 * @short_description: The target of a mouse event 40 * 41 * This class holds context information about the coordinates 42 * specified by a GDK event. 43 */ 44 45G_DEFINE_TYPE(WebKitHitTestResult, webkit_hit_test_result, G_TYPE_OBJECT) 46 47struct _WebKitHitTestResultPrivate { 48 guint context; 49 char* linkURI; 50 char* imageURI; 51 char* mediaURI; 52 GRefPtr<WebKitDOMNode> innerNode; 53 WebCore::IntPoint position; 54}; 55 56enum { 57 PROP_0, 58 59 PROP_CONTEXT, 60 PROP_LINK_URI, 61 PROP_IMAGE_URI, 62 PROP_MEDIA_URI, 63 PROP_INNER_NODE, 64 PROP_X, 65 PROP_Y 66}; 67 68static void webkit_hit_test_result_finalize(GObject* object) 69{ 70 WebKitHitTestResult* web_hit_test_result = WEBKIT_HIT_TEST_RESULT(object); 71 WebKitHitTestResultPrivate* priv = web_hit_test_result->priv; 72 73 g_free(priv->linkURI); 74 g_free(priv->imageURI); 75 g_free(priv->mediaURI); 76 77 G_OBJECT_CLASS(webkit_hit_test_result_parent_class)->finalize(object); 78} 79 80static void webkit_hit_test_result_dispose(GObject* object) 81{ 82 WEBKIT_HIT_TEST_RESULT(object)->priv->~WebKitHitTestResultPrivate(); 83 84 G_OBJECT_CLASS(webkit_hit_test_result_parent_class)->dispose(object); 85} 86 87static void webkit_hit_test_result_get_property(GObject* object, guint propertyID, GValue* value, GParamSpec* pspec) 88{ 89 WebKitHitTestResult* web_hit_test_result = WEBKIT_HIT_TEST_RESULT(object); 90 WebKitHitTestResultPrivate* priv = web_hit_test_result->priv; 91 92 switch(propertyID) { 93 case PROP_CONTEXT: 94 g_value_set_flags(value, priv->context); 95 break; 96 case PROP_LINK_URI: 97 g_value_set_string(value, priv->linkURI); 98 break; 99 case PROP_IMAGE_URI: 100 g_value_set_string(value, priv->imageURI); 101 break; 102 case PROP_MEDIA_URI: 103 g_value_set_string(value, priv->mediaURI); 104 break; 105 case PROP_INNER_NODE: 106 g_value_set_object(value, priv->innerNode.get()); 107 break; 108 case PROP_X: 109 g_value_set_int(value, priv->position.x()); 110 break; 111 case PROP_Y: 112 g_value_set_int(value, priv->position.y()); 113 break; 114 default: 115 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyID, pspec); 116 } 117} 118 119static void webkit_hit_test_result_set_property(GObject* object, guint propertyID, const GValue* value, GParamSpec* pspec) 120{ 121 WebKitHitTestResult* web_hit_test_result = WEBKIT_HIT_TEST_RESULT(object); 122 WebKitHitTestResultPrivate* priv = web_hit_test_result->priv; 123 124 switch(propertyID) { 125 case PROP_CONTEXT: 126 priv->context = g_value_get_flags(value); 127 break; 128 case PROP_LINK_URI: 129 g_free (priv->linkURI); 130 priv->linkURI = g_value_dup_string(value); 131 break; 132 case PROP_IMAGE_URI: 133 g_free (priv->imageURI); 134 priv->imageURI = g_value_dup_string(value); 135 break; 136 case PROP_MEDIA_URI: 137 g_free (priv->mediaURI); 138 priv->mediaURI = g_value_dup_string(value); 139 break; 140 case PROP_INNER_NODE: 141 priv->innerNode = static_cast<WebKitDOMNode*>(g_value_get_object(value)); 142 break; 143 case PROP_X: 144 priv->position.setX(g_value_get_int(value)); 145 break; 146 case PROP_Y: 147 priv->position.setY(g_value_get_int(value)); 148 break; 149 default: 150 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyID, pspec); 151 } 152} 153 154static void webkit_hit_test_result_class_init(WebKitHitTestResultClass* webHitTestResultClass) 155{ 156 GObjectClass* objectClass = G_OBJECT_CLASS(webHitTestResultClass); 157 158 objectClass->finalize = webkit_hit_test_result_finalize; 159 objectClass->dispose = webkit_hit_test_result_dispose; 160 objectClass->get_property = webkit_hit_test_result_get_property; 161 objectClass->set_property = webkit_hit_test_result_set_property; 162 163 webkitInit(); 164 165 /** 166 * WebKitHitTestResult:context: 167 * 168 * Flags indicating the kind of target that received the event. 169 * 170 * Since: 1.1.15 171 */ 172 g_object_class_install_property(objectClass, PROP_CONTEXT, 173 g_param_spec_flags("context", 174 _("Context"), 175 _("Flags indicating the kind of target that received the event."), 176 WEBKIT_TYPE_HIT_TEST_RESULT_CONTEXT, 177 WEBKIT_HIT_TEST_RESULT_CONTEXT_DOCUMENT, 178 static_cast<GParamFlags>((WEBKIT_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)))); 179 180 /** 181 * WebKitHitTestResult:link-uri: 182 * 183 * The URI to which the target that received the event points, if any. 184 * 185 * Since: 1.1.15 186 */ 187 g_object_class_install_property(objectClass, PROP_LINK_URI, 188 g_param_spec_string("link-uri", 189 _("Link URI"), 190 _("The URI to which the target that received the event points, if any."), 191 NULL, 192 static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY))); 193 194 /** 195 * WebKitHitTestResult:image-uri: 196 * 197 * The URI of the image that is part of the target that received the event, if any. 198 * 199 * Since: 1.1.15 200 */ 201 g_object_class_install_property(objectClass, PROP_IMAGE_URI, 202 g_param_spec_string("image-uri", 203 _("Image URI"), 204 _("The URI of the image that is part of the target that received the event, if any."), 205 NULL, 206 static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY))); 207 208 /** 209 * WebKitHitTestResult:media-uri: 210 * 211 * The URI of the media that is part of the target that received the event, if any. 212 * 213 * Since: 1.1.15 214 */ 215 g_object_class_install_property(objectClass, PROP_MEDIA_URI, 216 g_param_spec_string("media-uri", 217 _("Media URI"), 218 _("The URI of the media that is part of the target that received the event, if any."), 219 NULL, 220 static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY))); 221 222 /** 223 * WebKitHitTestResult:inner-node: 224 * 225 * The DOM node at the coordinates where the hit test 226 * happened. Keep in mind that the node might not be 227 * representative of the information given in the context 228 * property, since WebKit uses a series of heuristics to figure 229 * out that information. One common example is inner-node having 230 * the text node inside the anchor (<a>) tag; WebKit knows the 231 * whole context and will put WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK 232 * in the 'context' property, but the user might be confused by 233 * the lack of any link tag in 'inner-node'. 234 * 235 * Since: 1.3.2 236 */ 237 g_object_class_install_property(objectClass, PROP_INNER_NODE, 238 g_param_spec_object("inner-node", 239 _("Inner node"), 240 _("The inner DOM node associated with the hit test result."), 241 WEBKIT_TYPE_DOM_NODE, 242 static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY))); 243 244 /** 245 * WebKitHitTestResult:x: 246 * 247 * The x coordinate of the event relative to the view's window. 248 * 249 * Since: 1.10 250 */ 251 g_object_class_install_property(objectClass, PROP_X, 252 g_param_spec_int("x", 253 _("X coordinate"), 254 _("The x coordinate of the event relative to the view's window."), 255 G_MININT, G_MAXINT, 0, 256 static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY))); 257 258 /** 259 * WebKitHitTestResult:y: 260 * 261 * The x coordinate of the event relative to the view's window. 262 * 263 * Since: 1.10 264 */ 265 g_object_class_install_property(objectClass, PROP_Y, 266 g_param_spec_int("y", 267 _("Y coordinate"), 268 _("The y coordinate of the event relative to the view's window."), 269 G_MININT, G_MAXINT, 0, 270 static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY))); 271 272 g_type_class_add_private(webHitTestResultClass, sizeof(WebKitHitTestResultPrivate)); 273} 274 275static void webkit_hit_test_result_init(WebKitHitTestResult* web_hit_test_result) 276{ 277 web_hit_test_result->priv = G_TYPE_INSTANCE_GET_PRIVATE(web_hit_test_result, WEBKIT_TYPE_HIT_TEST_RESULT, WebKitHitTestResultPrivate); 278 new (web_hit_test_result->priv) WebKitHitTestResultPrivate(); 279} 280 281namespace WebKit { 282 283WebKitHitTestResult* kit(const WebCore::HitTestResult& result) 284{ 285 guint context = WEBKIT_HIT_TEST_RESULT_CONTEXT_DOCUMENT; 286 GOwnPtr<char> linkURI(0); 287 GOwnPtr<char> imageURI(0); 288 GOwnPtr<char> mediaURI(0); 289 WebKitDOMNode* node = 0; 290 WebCore::Frame* innerNodeFrame; 291 WebCore::IntPoint point; 292 293 if (!result.absoluteLinkURL().isEmpty()) { 294 context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK; 295 linkURI.set(g_strdup(result.absoluteLinkURL().string().utf8().data())); 296 } 297 298 if (!result.absoluteImageURL().isEmpty()) { 299 context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE; 300 imageURI.set(g_strdup(result.absoluteImageURL().string().utf8().data())); 301 } 302 303 if (!result.absoluteMediaURL().isEmpty()) { 304 context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_MEDIA; 305 mediaURI.set(g_strdup(result.absoluteMediaURL().string().utf8().data())); 306 } 307 308 if (result.isSelected()) 309 context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_SELECTION; 310 311 if (result.isContentEditable()) 312 context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_EDITABLE; 313 314 if (result.innerNonSharedNode()) 315 node = kit(result.innerNonSharedNode()); 316 317 innerNodeFrame = result.innerNodeFrame(); 318 if (innerNodeFrame && innerNodeFrame->view()) { 319 // Convert document coords to widget coords. 320 point = innerNodeFrame->view()->contentsToWindow(result.roundedPointInInnerNodeFrame()); 321 } else { 322 // FIXME: Main frame coords is not the same as window coords, 323 // but we do not have pointer to mainframe view here. 324 point = result.roundedPointInMainFrame(); 325 } 326 327 return WEBKIT_HIT_TEST_RESULT(g_object_new(WEBKIT_TYPE_HIT_TEST_RESULT, 328 "link-uri", linkURI.get(), 329 "image-uri", imageURI.get(), 330 "media-uri", mediaURI.get(), 331 "context", context, 332 "inner-node", node, 333 "x", point.x(), 334 "y", point.y(), 335 NULL)); 336} 337 338} 339