1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QApplication>
#include <QByteArray>
#include <QDialog>
#include <QFile>
#include <QHttpServer>
#include <QListView>
#include <QMessageBox>
#include <QTcpServer>
#include <QWebEnginePage>
#include <QWebEngineProfile>
#include <QWebEngineSettings>
#include <QWebEngineView>
#include "ui_mediaPicker.h"
#include <QWebEngineDesktopMediaRequest>
// Test the screen/window selection and capturing APIs using QWebEngineDesktopMediaRequest,
// getDisplayMedia (js) and chooseDesktopMedia (hangouts)
// Note: Wayland compositors require Pipewire support in QWE
class Page : public QWebEnginePage
{
Q_OBJECT
public:
Page(QWebEngineProfile *profile, QObject *parent = nullptr);
private slots:
void handlePermissionRequest(QWebEnginePermission permission);
void handleDesktopMediaRequest(const QWebEngineDesktopMediaRequest &request);
};
Page::Page(QWebEngineProfile *profile, QObject *parent) : QWebEnginePage(profile, parent)
{
settings()->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, true);
connect(this, &QWebEnginePage::permissionRequested, this,
&Page::handlePermissionRequest);
connect(this, &QWebEnginePage::desktopMediaRequested, this, &Page::handleDesktopMediaRequest);
}
void Page::handlePermissionRequest(QWebEnginePermission permission)
{
if (QMessageBox::question(QApplication::activeWindow(), tr("Permission request"),
tr("allow access?"))
== QMessageBox::Yes)
permission.grant();
else
permission.deny();
}
void Page::handleDesktopMediaRequest(const QWebEngineDesktopMediaRequest &request)
{
Ui::MediaPickerDialog mediaPickerDialog;
QDialog dialog;
dialog.setModal(true);
mediaPickerDialog.setupUi(&dialog);
auto *screensView = mediaPickerDialog.screensView;
auto *windowsView = mediaPickerDialog.windowsView;
auto *screensModel = request.screensModel();
auto *windowsModel = request.windowsModel();
screensView->setModel(screensModel);
windowsView->setModel(windowsModel);
if (dialog.exec() == QDialog::Accepted) {
if (mediaPickerDialog.tabWidget->currentIndex() == 0) {
auto list = windowsView->selectionModel()->selectedIndexes();
if (!list.empty()) {
request.selectWindow(list.first());
return;
}
} else {
auto list = screensView->selectionModel()->selectedIndexes();
if (!list.empty()) {
request.selectScreen(list.first());
return;
}
}
}
request.cancel();
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QFile file(":index.html");
if (!file.open(QIODeviceBase::ReadOnly)) {
qWarning("failed to open file!");
return 0;
}
QByteArray data = file.readAll();
if (data.isEmpty()) {
qWarning("failed to read file!");
return 0;
}
QHttpServer httpServer;
httpServer.route("/index.html", [data]() { return data; });
auto tcpServer = new QTcpServer(&httpServer);
tcpServer->listen(QHostAddress::Any, 3000);
httpServer.bind(tcpServer);
QWebEngineView view;
Page *page = new Page(QWebEngineProfile::defaultProfile(), &view);
view.setPage(page);
view.resize(1024, 750);
view.setUrl(QUrl("http://localhost:3000/index.html"));
view.show();
return app.exec();
}
#include "main.moc"
|