blob: 3f8a6bcd51918cb16dbf567c92a47183311fbcc5 [file] [log] [blame]
/*
* Copyright (C) 2012 Igalia S.L.
*
* 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 "WebKitHitTestResult.h"
#include "WebHitTestResultData.h"
#include "WebKitHitTestResultPrivate.h"
#include <glib/gi18n-lib.h>
#include <wtf/glib/WTFGType.h>
#include <wtf/text/CString.h>
using namespace WebKit;
/**
* SECTION: WebKitHitTestResult
* @Short_description: Result of a Hit Test
* @Title: WebKitHitTestResult
* @See_also: #WebKitWebView
*
* A Hit Test is an operation to get context information about a given
* point in a #WebKitWebView. #WebKitHitTestResult represents the
* result of a Hit Test. It provides context information about what is
* at the coordinates of the Hit Test, such as if there's a link,
* an image or a media.
*
* You can get the context of the HitTestResult with
* webkit_hit_test_result_get_context() that returns a bitmask of
* #WebKitHitTestResultContext flags. You can also use
* webkit_hit_test_result_context_is_link(), webkit_hit_test_result_context_is_image() and
* webkit_hit_test_result_context_is_media() to determine whether there's
* a link, image or a media element at the coordinates of the Hit Test.
* Note that it's possible that several #WebKitHitTestResultContext flags
* are active at the same time, for example if there's a link containing an image.
*
* When the mouse is moved over a #WebKitWebView a Hit Test is performed
* for the mouse coordinates and #WebKitWebView::mouse-target-changed
* signal is emitted with a #WebKitHitTestResult.
*
*/
enum {
PROP_0,
PROP_CONTEXT,
PROP_LINK_URI,
PROP_LINK_TITLE,
PROP_LINK_LABEL,
PROP_IMAGE_URI,
PROP_MEDIA_URI
};
struct _WebKitHitTestResultPrivate {
unsigned int context;
CString linkURI;
CString linkTitle;
CString linkLabel;
CString imageURI;
CString mediaURI;
};
WEBKIT_DEFINE_TYPE(WebKitHitTestResult, webkit_hit_test_result, G_TYPE_OBJECT)
static void webkitHitTestResultGetProperty(GObject* object, guint propId, GValue* value, GParamSpec* paramSpec)
{
WebKitHitTestResult* hitTestResult = WEBKIT_HIT_TEST_RESULT(object);
switch (propId) {
case PROP_CONTEXT:
g_value_set_uint(value, webkit_hit_test_result_get_context(hitTestResult));
break;
case PROP_LINK_URI:
g_value_set_string(value, webkit_hit_test_result_get_link_uri(hitTestResult));
break;
case PROP_LINK_TITLE:
g_value_set_string(value, webkit_hit_test_result_get_link_title(hitTestResult));
break;
case PROP_LINK_LABEL:
g_value_set_string(value, webkit_hit_test_result_get_link_label(hitTestResult));
break;
case PROP_IMAGE_URI:
g_value_set_string(value, webkit_hit_test_result_get_image_uri(hitTestResult));
break;
case PROP_MEDIA_URI:
g_value_set_string(value, webkit_hit_test_result_get_media_uri(hitTestResult));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec);
}
}
static void webkitHitTestResultSetProperty(GObject* object, guint propId, const GValue* value, GParamSpec* paramSpec)
{
WebKitHitTestResult* hitTestResult = WEBKIT_HIT_TEST_RESULT(object);
switch (propId) {
case PROP_CONTEXT:
hitTestResult->priv->context = g_value_get_uint(value);
break;
case PROP_LINK_URI:
hitTestResult->priv->linkURI = g_value_get_string(value);
break;
case PROP_LINK_TITLE:
hitTestResult->priv->linkTitle = g_value_get_string(value);
break;
case PROP_LINK_LABEL:
hitTestResult->priv->linkLabel = g_value_get_string(value);
break;
case PROP_IMAGE_URI:
hitTestResult->priv->imageURI = g_value_get_string(value);
break;
case PROP_MEDIA_URI:
hitTestResult->priv->mediaURI = g_value_get_string(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec);
}
}
static void webkit_hit_test_result_class_init(WebKitHitTestResultClass* hitTestResultClass)
{
GObjectClass* objectClass = G_OBJECT_CLASS(hitTestResultClass);
objectClass->get_property = webkitHitTestResultGetProperty;
objectClass->set_property = webkitHitTestResultSetProperty;
GParamFlags paramFlags = static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
/**
* WebKitHitTestResult:context:
*
* Bitmask of #WebKitHitTestResultContext flags representing
* the context of the #WebKitHitTestResult.
*/
g_object_class_install_property(objectClass,
PROP_CONTEXT,
g_param_spec_uint("context",
_("Context"),
_("Flags with the context of the WebKitHitTestResult"),
0, G_MAXUINT, 0,
paramFlags));
/**
* WebKitHitTestResult:link-uri:
*
* The URI of the link if flag %WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK
* is present in #WebKitHitTestResult:context
*/
g_object_class_install_property(objectClass,
PROP_LINK_URI,
g_param_spec_string("link-uri",
_("Link URI"),
_("The link URI"),
0,
paramFlags));
/**
* WebKitHitTestResult:link-title:
*
* The title of the link if flag %WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK
* is present in #WebKitHitTestResult:context
*/
g_object_class_install_property(objectClass,
PROP_LINK_TITLE,
g_param_spec_string("link-title",
_("Link Title"),
_("The link title"),
0,
paramFlags));
/**
* WebKitHitTestResult:link-label:
*
* The label of the link if flag %WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK
* is present in #WebKitHitTestResult:context
*/
g_object_class_install_property(objectClass,
PROP_LINK_LABEL,
g_param_spec_string("link-label",
_("Link Label"),
_("The link label"),
0,
paramFlags));
/**
* WebKitHitTestResult:image-uri:
*
* The URI of the image if flag %WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE
* is present in #WebKitHitTestResult:context
*/
g_object_class_install_property(objectClass,
PROP_IMAGE_URI,
g_param_spec_string("image-uri",
_("Image URI"),
_("The image URI"),
0,
paramFlags));
/**
* WebKitHitTestResult:media-uri:
*
* The URI of the media if flag %WEBKIT_HIT_TEST_RESULT_CONTEXT_MEDIA
* is present in #WebKitHitTestResult:context
*/
g_object_class_install_property(objectClass,
PROP_MEDIA_URI,
g_param_spec_string("media-uri",
_("Media URI"),
_("The media URI"),
0,
paramFlags));
}
WebKitHitTestResult* webkitHitTestResultCreate(const WebHitTestResultData& hitTestResult)
{
unsigned context = WEBKIT_HIT_TEST_RESULT_CONTEXT_DOCUMENT;
if (!hitTestResult.absoluteLinkURL.isEmpty())
context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK;
if (!hitTestResult.absoluteImageURL.isEmpty())
context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE;
if (!hitTestResult.absoluteMediaURL.isEmpty())
context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_MEDIA;
if (hitTestResult.isContentEditable)
context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_EDITABLE;
if (hitTestResult.isScrollbar)
context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_SCROLLBAR;
if (hitTestResult.isSelected)
context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_SELECTION;
return WEBKIT_HIT_TEST_RESULT(g_object_new(WEBKIT_TYPE_HIT_TEST_RESULT,
"context", context,
"link-uri", context & WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK ? hitTestResult.absoluteLinkURL.utf8().data() : nullptr,
"image-uri", context & WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE ? hitTestResult.absoluteImageURL.utf8().data() : nullptr,
"media-uri", context & WEBKIT_HIT_TEST_RESULT_CONTEXT_MEDIA ? hitTestResult.absoluteMediaURL.utf8().data() : nullptr,
"link-title", !hitTestResult.linkTitle.isEmpty() ? hitTestResult.linkTitle.utf8().data() : nullptr,
"link-label", !hitTestResult.linkLabel.isEmpty() ? hitTestResult.linkLabel.utf8().data() : nullptr,
nullptr));
}
static bool stringIsEqualToCString(const String& string, const CString& cString)
{
return ((string.isEmpty() && cString.isNull()) || (string.utf8() == cString));
}
bool webkitHitTestResultCompare(WebKitHitTestResult* hitTestResult, const WebHitTestResultData& webHitTestResult)
{
WebKitHitTestResultPrivate* priv = hitTestResult->priv;
return webHitTestResult.isContentEditable == webkit_hit_test_result_context_is_editable(hitTestResult)
&& webHitTestResult.isScrollbar == webkit_hit_test_result_context_is_scrollbar(hitTestResult)
&& webHitTestResult.isSelected == webkit_hit_test_result_context_is_selection(hitTestResult)
&& stringIsEqualToCString(webHitTestResult.absoluteLinkURL, priv->linkURI)
&& stringIsEqualToCString(webHitTestResult.linkTitle, priv->linkTitle)
&& stringIsEqualToCString(webHitTestResult.linkLabel, priv->linkLabel)
&& stringIsEqualToCString(webHitTestResult.absoluteImageURL, priv->imageURI)
&& stringIsEqualToCString(webHitTestResult.absoluteMediaURL, priv->mediaURI);
}
/**
* webkit_hit_test_result_get_context:
* @hit_test_result: a #WebKitHitTestResult
*
* Gets the value of the #WebKitHitTestResult:context property.
*
* Returns: a bitmask of #WebKitHitTestResultContext flags
*/
guint webkit_hit_test_result_get_context(WebKitHitTestResult* hitTestResult)
{
g_return_val_if_fail(WEBKIT_IS_HIT_TEST_RESULT(hitTestResult), 0);
return hitTestResult->priv->context;
}
/**
* webkit_hit_test_result_context_is_link:
* @hit_test_result: a #WebKitHitTestResult
*
* Gets whether %WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK flag is present in
* #WebKitHitTestResult:context.
*
* Returns: %TRUE if there's a link element in the coordinates of the Hit Test,
* or %FALSE otherwise
*/
gboolean webkit_hit_test_result_context_is_link(WebKitHitTestResult* hitTestResult)
{
g_return_val_if_fail(WEBKIT_IS_HIT_TEST_RESULT(hitTestResult), FALSE);
return hitTestResult->priv->context & WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK;
}
/**
* webkit_hit_test_result_context_is_image:
* @hit_test_result: a #WebKitHitTestResult
*
* Gets whether %WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE flag is present in
* #WebKitHitTestResult:context.
*
* Returns: %TRUE if there's an image element in the coordinates of the Hit Test,
* or %FALSE otherwise
*/
gboolean webkit_hit_test_result_context_is_image(WebKitHitTestResult* hitTestResult)
{
g_return_val_if_fail(WEBKIT_IS_HIT_TEST_RESULT(hitTestResult), FALSE);
return hitTestResult->priv->context & WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE;
}
/**
* webkit_hit_test_result_context_is_media:
* @hit_test_result: a #WebKitHitTestResult
*
* Gets whether %WEBKIT_HIT_TEST_RESULT_CONTEXT_MEDIA flag is present in
* #WebKitHitTestResult:context.
*
* Returns: %TRUE if there's a media element in the coordinates of the Hit Test,
* or %FALSE otherwise
*/
gboolean webkit_hit_test_result_context_is_media(WebKitHitTestResult* hitTestResult)
{
g_return_val_if_fail(WEBKIT_IS_HIT_TEST_RESULT(hitTestResult), FALSE);
return hitTestResult->priv->context & WEBKIT_HIT_TEST_RESULT_CONTEXT_MEDIA;
}
/**
* webkit_hit_test_result_context_is_editable:
* @hit_test_result: a #WebKitHitTestResult
*
* Gets whether %WEBKIT_HIT_TEST_RESULT_CONTEXT_EDITABLE flag is present in
* #WebKitHitTestResult:context.
*
* Returns: %TRUE if there's an editable element at the coordinates of the @hit_test_result,
* or %FALSE otherwise
*/
gboolean webkit_hit_test_result_context_is_editable(WebKitHitTestResult* hitTestResult)
{
g_return_val_if_fail(WEBKIT_IS_HIT_TEST_RESULT(hitTestResult), FALSE);
return hitTestResult->priv->context & WEBKIT_HIT_TEST_RESULT_CONTEXT_EDITABLE;
}
/**
* webkit_hit_test_result_context_is_selection:
* @hit_test_result: a #WebKitHitTestResult
*
* Gets whether %WEBKIT_HIT_TEST_RESULT_CONTEXT_SELECTION flag is present in
* #WebKitHitTestResult:context.
*
* Returns: %TRUE if there's a selected element at the coordinates of the @hit_test_result,
* or %FALSE otherwise
*
* Since: 2.8
*/
gboolean webkit_hit_test_result_context_is_selection(WebKitHitTestResult* hitTestResult)
{
g_return_val_if_fail(WEBKIT_IS_HIT_TEST_RESULT(hitTestResult), FALSE);
return hitTestResult->priv->context & WEBKIT_HIT_TEST_RESULT_CONTEXT_SELECTION;
}
/**
* webkit_hit_test_result_get_link_uri:
* @hit_test_result: a #WebKitHitTestResult
*
* Gets the value of the #WebKitHitTestResult:link-uri property.
*
* Returns: the URI of the link element in the coordinates of the Hit Test,
* or %NULL if there isn't a link element in @hit_test_result context
*/
const gchar* webkit_hit_test_result_get_link_uri(WebKitHitTestResult* hitTestResult)
{
g_return_val_if_fail(WEBKIT_IS_HIT_TEST_RESULT(hitTestResult), 0);
return hitTestResult->priv->linkURI.data();
}
/**
* webkit_hit_test_result_get_link_title:
* @hit_test_result: a #WebKitHitTestResult
*
* Gets the value of the #WebKitHitTestResult:link-title property.
*
* Returns: the title of the link element in the coordinates of the Hit Test,
* or %NULL if there isn't a link element in @hit_test_result context or the
* link element doesn't have a title
*/
const gchar* webkit_hit_test_result_get_link_title(WebKitHitTestResult* hitTestResult)
{
g_return_val_if_fail(WEBKIT_IS_HIT_TEST_RESULT(hitTestResult), 0);
return hitTestResult->priv->linkTitle.data();
}
/**
* webkit_hit_test_result_get_link_label:
* @hit_test_result: a #WebKitHitTestResult
*
* Gets the value of the #WebKitHitTestResult:link-label property.
*
* Returns: the label of the link element in the coordinates of the Hit Test,
* or %NULL if there isn't a link element in @hit_test_result context or the
* link element doesn't have a label
*/
const gchar* webkit_hit_test_result_get_link_label(WebKitHitTestResult* hitTestResult)
{
g_return_val_if_fail(WEBKIT_IS_HIT_TEST_RESULT(hitTestResult), 0);
return hitTestResult->priv->linkLabel.data();
}
/**
* webkit_hit_test_result_get_image_uri:
* @hit_test_result: a #WebKitHitTestResult
*
* Gets the value of the #WebKitHitTestResult:image-uri property.
*
* Returns: the URI of the image element in the coordinates of the Hit Test,
* or %NULL if there isn't an image element in @hit_test_result context
*/
const gchar* webkit_hit_test_result_get_image_uri(WebKitHitTestResult* hitTestResult)
{
g_return_val_if_fail(WEBKIT_IS_HIT_TEST_RESULT(hitTestResult), 0);
return hitTestResult->priv->imageURI.data();
}
/**
* webkit_hit_test_result_get_media_uri:
* @hit_test_result: a #WebKitHitTestResult
*
* Gets the value of the #WebKitHitTestResult:media-uri property.
*
* Returns: the URI of the media element in the coordinates of the Hit Test,
* or %NULL if there isn't a media element in @hit_test_result context
*/
const gchar* webkit_hit_test_result_get_media_uri(WebKitHitTestResult* hitTestResult)
{
g_return_val_if_fail(WEBKIT_IS_HIT_TEST_RESULT(hitTestResult), 0);
return hitTestResult->priv->mediaURI.data();
}
/**
* webkit_hit_test_result_context_is_scrollbar:
* @hit_test_result: a #WebKitHitTestResult
*
* Gets whether %WEBKIT_HIT_TEST_RESULT_CONTEXT_SCROLLBAR flag is present in
* #WebKitHitTestResult:context.
*
* Returns: %TRUE if there's a scrollbar element at the coordinates of the @hit_test_result,
* or %FALSE otherwise
*/
gboolean webkit_hit_test_result_context_is_scrollbar(WebKitHitTestResult* hitTestResult)
{
g_return_val_if_fail(WEBKIT_IS_HIT_TEST_RESULT(hitTestResult), FALSE);
return hitTestResult->priv->context & WEBKIT_HIT_TEST_RESULT_CONTEXT_SCROLLBAR;
}