Messagelib

webhittest.cpp
1/*
2 SPDX-FileCopyrightText: 2016-2024 Laurent Montel <montel@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "webhittest.h"
8#include "webenginemanagescript.h"
9#include "webhittestresult.h"
10#include <QWebEnginePage>
11
12using namespace WebEngineViewer;
13template<typename Arg, typename R, typename C>
14
15struct InvokeWrapperWebhittest {
16 R *receiver;
17 void (C::*memberFunction)(Arg);
18 void operator()(Arg result)
19 {
20 (receiver->*memberFunction)(result);
21 }
22};
23
24template<typename Arg, typename R, typename C>
25
26InvokeWrapperWebhittest<Arg, R, C> invoke(R *receiver, void (C::*memberFunction)(Arg))
27{
28 InvokeWrapperWebhittest<Arg, R, C> wrapper = {receiver, memberFunction};
29 return wrapper;
30}
31
32class WebEngineViewer::WebHitTestPrivate
33{
34public:
35 WebHitTestPrivate(const QPoint &pos, const QPoint &zoomedPos)
36 : m_zoomedPos(zoomedPos)
37 , m_pos(pos)
38 {
39 }
40
41 QPoint m_zoomedPos;
42 QPoint m_pos;
43 QUrl m_pageUrl;
44};
45
46WebHitTest::WebHitTest(QWebEnginePage *page, const QPoint &zoomedPos, const QPoint &pos, QObject *parent)
47 : QObject(parent)
48 , d(new WebHitTestPrivate(pos, zoomedPos))
49{
50 QString source = QStringLiteral(
51 "(function() {"
52 "var e = document.elementFromPoint(%1, %2);"
53 "if (!e)"
54 " return;"
55 "function isMediaElement(e) {"
56 " return e.tagName.toLowerCase() == 'audio' || e.tagName.toLowerCase() == 'video';"
57 "}"
58 "function isEditableElement(e) {"
59 " if (e.isContentEditable)"
60 " return true;"
61 " if (e.tagName.toLowerCase() == 'input' || e.tagName.toLowerCase() == 'textarea')"
62 " return e.getAttribute('readonly') != 'readonly';"
63 " return false;"
64 "}"
65 "function isSelected(e) {"
66 " var selection = window.getSelection();"
67 " if (selection.type != 'Range')"
68 " return false;"
69 " return window.getSelection().containsNode(e, true);"
70 "}"
71 "function attributeStr(e, a) {"
72 " return e.getAttribute(a) || '';"
73 "}"
74 "var res = {"
75 " alternateText: e.getAttribute('alt'),"
76 " boundingRect: '',"
77 " imageUrl: '',"
78 " contentEditable: isEditableElement(e),"
79 " contentSelected: isSelected(e),"
80 " linkTitle: '',"
81 " linkUrl: '',"
82 " mediaUrl: '',"
83 " tagName: e.tagName.toLowerCase()"
84 "};"
85 "var r = e.getBoundingClientRect();"
86 "res.boundingRect = [r.top, r.left, r.width, r.height];"
87 "if (e.tagName.toLowerCase() == 'img')"
88 " res.imageUrl = attributeStr(e, 'src').trim();"
89 "if (e.tagName.toLowerCase() == 'a') {"
90 " res.linkTitle = e.text;"
91 " res.linkUrl = attributeStr(e, 'href').trim();"
92 "}"
93 "while (e) {"
94 " if (res.linkTitle == '' && e.tagName.toLowerCase() == 'a')"
95 " res.linkTitle = e.text;"
96 " if (res.linkUrl == '' && e.tagName.toLowerCase() == 'a')"
97 " res.linkUrl = attributeStr(e, 'href').trim();"
98 " if (res.mediaUrl == '' && isMediaElement(e)) {"
99 " res.mediaUrl = e.currentSrc;"
100 " res.mediaPaused = e.paused;"
101 " res.mediaMuted = e.muted;"
102 " }"
103 " e = e.parentElement;"
104 "}"
105 "return res;"
106 "})()");
107
108 const QString &js = source.arg(d->m_zoomedPos.x()).arg(d->m_zoomedPos.y());
109 d->m_pageUrl = page->url();
110 page->runJavaScript(js, WebEngineViewer::WebEngineManageScript::scriptWordId(), invoke(this, &WebHitTest::handleHitTest));
111}
112
113WebHitTest::~WebHitTest() = default;
114
115void WebHitTest::handleHitTest(const QVariant &result)
116{
117 const WebHitTestResult webHitResult(d->m_pos, d->m_pageUrl, result);
118 Q_EMIT finished(webHitResult);
119 deleteLater();
120}
121
122#include "moc_webhittest.cpp"
The WebHitTestResult class.
Q_EMITQ_EMIT
void deleteLater()
QString arg(Args &&... args) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:07:25 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.