Skip to content

Commit 5cc8864

Browse files
authored
Merge pull request #124 from CefView/feature/context-menu
Feature/context menu
2 parents 131aa4b + 70f13f4 commit 5cc8864

12 files changed

+470
-62
lines changed

example/QCefViewTest/MainWindow.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#include "MainWindow.h"
1+
#include "MainWindow.h"
22

33
#include <QCoreApplication>
44
#include <QDir>
@@ -66,14 +66,18 @@ MainWindow::createCefView()
6666
// this site is for test web events
6767
cefViewWidget = new CefViewWidget("http://output.jsbin.com/rinece", &setting, this);
6868

69+
//
70+
// cefViewWidget = new CefViewWidget("https://mdn.dev/", &setting, this);
71+
6972
// this site is for test OSR performance
7073
// cefViewWidget = new CefViewWidget("https://www.testufo.com", &setting, this);
7174

7275
// this site is test for input devices
7376
// cefViewWidget = new CefViewWidget("https://devicetests.com", &setting);
7477

7578
ui.cefContainer->layout()->addWidget(cefViewWidget);
76-
cefViewWidget->setStyleSheet("background-color: blue;");
79+
80+
// cefViewWidget->setCefContextMenuPolicy(Qt::CefDisableAllContextMenu);
7781

7882
// connect the invokeMethod to the slot
7983
connect(cefViewWidget, &QCefView::invokeMethod, this, &MainWindow::onInvokeMethod);

include/QCefView.h

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,26 +27,28 @@ class QCEFVIEW_EXPORT QCefView : public QWidget
2727
QScopedPointer<QCefViewPrivate> d_ptr;
2828

2929
public:
30+
/// <summary>
31+
/// The main frame identity
32+
/// </summary>
3033
static const qint64 MainFrameID = 0;
3134

32-
public:
3335
/// <summary>
34-
///
36+
/// Represents the CEF popup windows open disposition
3537
/// </summary>
36-
enum WindowOpenDisposition
38+
enum CefWindowOpenDisposition
3739
{
38-
WOD_UNKNOWN,
39-
WOD_CURRENT_TAB,
40-
WOD_SINGLETON_TAB,
41-
WOD_NEW_FOREGROUND_TAB,
42-
WOD_NEW_BACKGROUND_TAB,
43-
WOD_NEW_POPUP,
44-
WOD_NEW_WINDOW,
45-
WOD_SAVE_TO_DISK,
46-
WOD_OFF_THE_RECORD,
47-
WOD_IGNORE_ACTION
40+
CefWindowOpenDispositionUnknown,
41+
CefWindowOpenDispositionCurrentTab,
42+
CefWindowOpenDispositionSingletonTab,
43+
CefWindowOpenDispositionNewForeGroundTab,
44+
CefWindowOpenDispositionNewBackgroundTab,
45+
CefWindowOpenDispositionNewPopup,
46+
CefWindowOpenDispositionNewWindow,
47+
CefWindowOpenDispositionSaveToDisk,
48+
CefWindowOpenDispositionOffTheRecord,
49+
CefWindowOpenDispositionIgnoreAction,
4850
};
49-
Q_ENUM(WindowOpenDisposition)
51+
Q_ENUM(CefWindowOpenDisposition)
5052

5153
public:
5254
/// <summary>
@@ -205,10 +207,22 @@ class QCEFVIEW_EXPORT QCefView : public QWidget
205207
/// The preference value, if this value is QVariant::UnknownType or QVariant::Invalid, the
206208
/// preference will be restored to default value
207209
/// </param>
208-
/// <param name="error">The error message populated on failure</param> <returns>True
209-
/// on successful; otherwise false</returns>
210+
/// <param name="error">The error message populated on failure</param>
211+
// <returns>True on successful; otherwise false</returns>
210212
bool setPreference(const QString& name, const QVariant& value, const QString& error);
211213

214+
/// <summary>
215+
/// Sets whether to disable the context menu for popup browser
216+
/// </summary>
217+
/// <param name="disable">True to disable; otherwise false</param>
218+
void setDisablePopupContextMenu(bool disable);
219+
220+
/// <summary>
221+
/// Gets whether to disable the context menu for popup browser
222+
/// </summary>
223+
/// <returns>True to disable; otherwise false</returns>
224+
bool isPopupContextMenuDisabled();
225+
212226
signals:
213227
/// <summary>
214228
/// Gets called on loading state changed
@@ -344,7 +358,7 @@ public slots:
344358
virtual void onBrowserWindowCreated(QWindow* win);
345359

346360
/// <summary>
347-
/// Gets called before the pop-up browser created
361+
/// Gets called before the popup browser created
348362
/// </summary>
349363
/// <param name="frameId">The source frame id</param>
350364
/// <param name="targetUrl">The target URL</param>
@@ -356,12 +370,12 @@ public slots:
356370
virtual bool onBeforePopup(qint64 frameId,
357371
const QString& targetUrl,
358372
const QString& targetFrameName,
359-
QCefView::WindowOpenDisposition targetDisposition,
373+
QCefView::CefWindowOpenDisposition targetDisposition,
360374
QCefSetting& settings,
361375
bool& DisableJavascriptAccess);
362376

363377
/// <summary>
364-
/// Gets called right after the pop-up browser was created
378+
/// Gets called right after the popup browser was created
365379
/// </summary>
366380
/// <param name="wnd">The host window of new created browser</param>
367381
virtual void onPopupCreated(QWindow* wnd);
@@ -449,6 +463,8 @@ public slots:
449463
/// Please refer to QWidget::wheelEvent
450464
/// </summary>
451465
void wheelEvent(QWheelEvent* event) override;
466+
467+
void contextMenuEvent(QContextMenuEvent* event) override;
452468
#pragma endregion
453469
};
454470

src/QCefView.cpp

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include "details/QCefEventPrivate.h"
1515
#include "details/QCefViewPrivate.h"
16+
#include "details/utils/CommonUtils.h"
1617

1718
QCefView::QCefView(const QString url, const QCefSetting* setting, QWidget* parent /*= 0*/)
1819
: QWidget(parent)
@@ -191,6 +192,22 @@ QCefView::setPreference(const QString& name, const QVariant& value, const QStrin
191192
return d->setPreference(name, value, error);
192193
}
193194

195+
void
196+
QCefView::setDisablePopupContextMenu(bool disable)
197+
{
198+
Q_D(QCefView);
199+
200+
d->disablePopuContextMenu_ = disable;
201+
}
202+
203+
bool
204+
QCefView::isPopupContextMenuDisabled()
205+
{
206+
Q_D(QCefView);
207+
208+
return d->disablePopuContextMenu_;
209+
}
210+
194211
void
195212
QCefView::setFocus(Qt::FocusReason reason)
196213
{
@@ -207,7 +224,7 @@ bool
207224
QCefView::onBeforePopup(qint64 frameId,
208225
const QString& targetUrl,
209226
const QString& targetFrameName,
210-
QCefView::WindowOpenDisposition targetDisposition,
227+
QCefView::CefWindowOpenDisposition targetDisposition,
211228
QCefSetting& settings,
212229
bool& DisableJavascriptAccess)
213230
{
@@ -249,7 +266,7 @@ QCefView::paintEvent(QPaintEvent* event)
249266
opt.initFrom(this);
250267
style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);
251268

252-
// 4. paint the CEF view and pop-up
269+
// 4. paint the CEF view and popup
253270
// get current scale factor
254271
qreal scaleFactor = devicePixelRatio();
255272

@@ -262,7 +279,7 @@ QCefView::paintEvent(QPaintEvent* event)
262279
painter.drawImage(QRect{ 0, 0, width, height }, d->osr.qCefViewFrame_);
263280
}
264281
{
265-
// paint cef pop-up
282+
// paint cef popup
266283
QMutexLocker lock(&(d->osr.qPopupPaintLock_));
267284
if (d->osr.showPopup_) {
268285
painter.drawImage(d->osr.qPopupRect_, d->osr.qCefPopupFrame_);
@@ -368,3 +385,17 @@ QCefView::wheelEvent(QWheelEvent* event)
368385
d->onViewWheelEvent(event);
369386
QWidget::wheelEvent(event);
370387
}
388+
389+
void
390+
QCefView::contextMenuEvent(QContextMenuEvent* event)
391+
{
392+
FLog();
393+
394+
#if defined(CEF_USE_OSR)
395+
Q_D(QCefView);
396+
397+
if (d->osr.isShowingContextMenu_) {
398+
d->osr.contextMenu_->popup(mapToGlobal(event->pos()));
399+
}
400+
#endif
401+
}
Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
#include "CCefClientDelegate.h"
22

3+
#include <QDebug>
4+
#include <QThread>
5+
6+
#include "utils/CommonUtils.h"
7+
#include "utils/MenuBuilder.h"
8+
39
#include "QCefViewPrivate.h"
410

511
void
@@ -8,12 +14,31 @@ CCefClientDelegate::onBeforeContextMenu(CefRefPtr<CefBrowser> browser,
814
CefRefPtr<CefContextMenuParams> params,
915
CefRefPtr<CefMenuModel> model)
1016
{
11-
#if defined(CEF_USE_OSR)
12-
// Context menu will not disappear on left click under OSR
13-
// mode, so we just disable the default one. You need to
14-
// implement your own context menu.
15-
model->Clear();
16-
#endif
17+
FLog();
18+
19+
if (!pCefViewPrivate_)
20+
return;
21+
22+
// popup browser doesn't involve off-screen rendering
23+
if (browser->IsPopup()) {
24+
if (pCefViewPrivate_->disablePopuContextMenu_) {
25+
model->Clear();
26+
}
27+
28+
return;
29+
}
30+
31+
// main browser
32+
auto policy = pCefViewPrivate_->q_ptr->contextMenuPolicy();
33+
if (Qt::DefaultContextMenu != policy) {
34+
model->Clear();
35+
return;
36+
}
37+
38+
auto menuData = MenuBuilder::CreateMenuDataFromCefMenu(model.get());
39+
QMetaObject::invokeMethod(pCefViewPrivate_, [=]() { pCefViewPrivate_->onBeforeCefContextMenu(menuData); });
40+
41+
return;
1742
}
1843

1944
bool
@@ -23,7 +48,21 @@ CCefClientDelegate::onRunContextMenu(CefRefPtr<CefBrowser> browser,
2348
CefRefPtr<CefMenuModel> model,
2449
CefRefPtr<CefRunContextMenuCallback> callback)
2550
{
26-
return false;
51+
FLog();
52+
53+
if (browser->IsPopup()) {
54+
return false;
55+
}
56+
57+
auto policy = pCefViewPrivate_->q_ptr->contextMenuPolicy();
58+
if (Qt::DefaultContextMenu != policy) {
59+
return false;
60+
}
61+
62+
QPoint pos(params->GetXCoord(), params->GetYCoord());
63+
QMetaObject::invokeMethod(pCefViewPrivate_, [=]() { pCefViewPrivate_->onRunCefContextMenu(pos, callback); });
64+
65+
return true;
2766
}
2867

2968
bool
@@ -33,9 +72,15 @@ CCefClientDelegate::onContextMenuCommand(CefRefPtr<CefBrowser> browser,
3372
int command_id,
3473
CefContextMenuHandler::EventFlags event_flags)
3574
{
75+
FLog();
76+
3677
return false;
3778
}
3879

3980
void
4081
CCefClientDelegate::onContextMenuDismissed(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame)
41-
{}
82+
{
83+
FLog();
84+
85+
QMetaObject::invokeMethod(pCefViewPrivate_, [=]() { pCefViewPrivate_->onCefContextMenuDismissed(); });
86+
}

src/details/CCefClientDelegate_KeyboardHandler.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
#include "CCefClientDelegate.h"
22

33
#include <QDebug>
4-
#include <QImage>
5-
#include <QScreen>
64

75
#include "QCefViewPrivate.h"
86

src/details/CCefClientDelegate_LifeSpanHandler.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,21 @@ CCefClientDelegate::onBeforePopup(CefRefPtr<CefBrowser>& browser,
2121
auto name = QString::fromStdString(targetFrameName);
2222

2323
QCefSetting s;
24-
QCefView::WindowOpenDisposition d = (QCefView::WindowOpenDisposition)targetDisposition;
24+
QCefView::CefWindowOpenDisposition d = (QCefView::CefWindowOpenDisposition)targetDisposition;
2525
QCefSettingPrivate::CopyFromCefBrowserSettings(&s, &settings);
2626

2727
Qt::ConnectionType c = pCefViewPrivate_->q_ptr->thread() == QThread::currentThread() ? Qt::DirectConnection
2828
: Qt::BlockingQueuedConnection;
2929
QMetaObject::invokeMethod(pCefViewPrivate_->q_ptr,
30-
"onBeforePopup", //
31-
c, //
32-
Q_RETURN_ARG(bool, result), //
33-
Q_ARG(qint64, frameId), //
34-
Q_ARG(const QString&, url), //
35-
Q_ARG(const QString&, name), //
36-
Q_ARG(QCefView::WindowOpenDisposition, d), //
37-
Q_ARG(QCefSetting&, s), //
38-
Q_ARG(bool&, DisableJavascriptAccess) //
30+
"onBeforePopup", //
31+
c, //
32+
Q_RETURN_ARG(bool, result), //
33+
Q_ARG(qint64, frameId), //
34+
Q_ARG(const QString&, url), //
35+
Q_ARG(const QString&, name), //
36+
Q_ARG(QCefView::CefWindowOpenDisposition, d), //
37+
Q_ARG(QCefSetting&, s), //
38+
Q_ARG(bool&, DisableJavascriptAccess) //
3939
);
4040
QCefSettingPrivate::CopyToCefBrowserSettings(&s, &settings);
4141
}

0 commit comments

Comments
 (0)