Messagelib

webhittest.cpp
1 /*
2  SPDX-FileCopyrightText: 2016-2023 Laurent Montel <[email protected]>
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 
12 using namespace WebEngineViewer;
13 template<typename Arg, typename R, typename C>
14 
15 struct InvokeWrapperWebhittest {
16  R *receiver;
17  void (C::*memberFunction)(Arg);
18  void operator()(Arg result)
19  {
20  (receiver->*memberFunction)(result);
21  }
22 };
23 
24 template<typename Arg, typename R, typename C>
25 
26 InvokeWrapperWebhittest<Arg, R, C> invoke(R *receiver, void (C::*memberFunction)(Arg))
27 {
28  InvokeWrapperWebhittest<Arg, R, C> wrapper = {receiver, memberFunction};
29  return wrapper;
30 }
31 
32 class WebEngineViewer::WebHitTestPrivate
33 {
34 public:
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 
46 WebHitTest::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 
113 WebHitTest::~WebHitTest() = default;
114 
115 void 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 }
Q_EMITQ_EMIT
The WebHitTestResult class.
void deleteLater()
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Mar 27 2023 04:08:19 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.