diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/media_capture_devices_dispatcher.cpp | 78 | ||||
-rw-r--r-- | src/core/render_widget_host_view_qt.cpp | 8 | ||||
-rw-r--r-- | src/core/web_contents_delegate_qt.cpp | 10 | ||||
-rw-r--r-- | src/core/web_contents_delegate_qt.h | 1 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebenginepage.cpp | 5 |
5 files changed, 83 insertions, 19 deletions
diff --git a/src/core/media_capture_devices_dispatcher.cpp b/src/core/media_capture_devices_dispatcher.cpp index ac74c509c..65c3df06a 100644 --- a/src/core/media_capture_devices_dispatcher.cpp +++ b/src/core/media_capture_devices_dispatcher.cpp @@ -71,6 +71,12 @@ #include <QtCore/qcoreapplication.h> +#if defined(WEBRTC_USE_X11) +#include <dlfcn.h> +#include <X11/extensions/Xrandr.h> +#include <X11/Xlib.h> +#endif + namespace QtWebEngineCore { using content::BrowserThread; @@ -117,25 +123,16 @@ void getDevicesForDesktopCapture(blink::MediaStreamDevices *devices, content::DesktopMediaID getDefaultScreenId() { - // While this function is executing another thread may also want to create a - // DesktopCapturer [1]. Unfortunately, creating a DesktopCapturer is not - // thread safe on X11 due to the use of webrtc::XErrorTrap. It's safe to - // disable this code on X11 since we don't actually need to create a - // DesktopCapturer to get the screen id anyway - // (ScreenCapturerLinux::GetSourceList always returns 0 as the id). - // - // [1]: webrtc::InProcessVideoCaptureDeviceLauncher::DoStartDesktopCaptureOnDeviceThread - -#if QT_CONFIG(webengine_webrtc) && !defined(WEBRTC_USE_X11) +#if QT_CONFIG(webengine_webrtc) // Source id patterns are different across platforms. - // On Linux, the hardcoded value "0" is used. + // On Linux and macOS, the source ids are randomish numbers assigned by the OS. // On Windows, the screens are enumerated consecutively in increasing order from 0. - // On macOS the source ids are randomish numbers assigned by the OS. // In order to provide a correct screen id, we query for the available screen ids, and // select the first one as the main display id. +#if !defined(WEBRTC_USE_X11) // The code is based on the file - // src/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc. + // chrome/browser/media/webrtc/native_desktop_media_list.cc. webrtc::DesktopCaptureOptions options = webrtc::DesktopCaptureOptions::CreateDefault(); options.set_disable_effects(false); @@ -150,7 +147,60 @@ content::DesktopMediaID getDefaultScreenId() } } } -#endif +#else + // This is a workaround to avoid thread issues with DesktopCapturer [1]. Unfortunately, + // creating a DesktopCapturer is not thread safe on X11 due to the use of webrtc::XErrorTrap. + // Can be removed if https://crbug.com/2022 and/or https://crbug.com/570852 are fixed. + // The code is based on the file + // third_party/webrtc/modules/desktop_capture/linux/screen_capturer_x11.cc. + // + // [1]: webrtc::InProcessVideoCaptureDeviceLauncher::DoStartDesktopCaptureOnDeviceThread + Display *display = XOpenDisplay(nullptr); + if (!display) { + qWarning("Unable to open display."); + return content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, 0); + } + + int randrEventBase = 0; + int errorBaseIgnored = 0; + if (!XRRQueryExtension(display, &randrEventBase, &errorBaseIgnored)) { + qWarning("X server does not support XRandR."); + return content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, 0); + } + + int majorVersion = 0; + int minorVersion = 0; + if (!XRRQueryVersion(display, &majorVersion, &minorVersion)) { + qWarning("X server does not support XRandR."); + return content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, 0); + } + + if (majorVersion < 1 || (majorVersion == 1 && minorVersion < 5)) { + qWarning("XRandR entension is older than v1.5."); + return content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, 0); + } + + typedef XRRMonitorInfo *(*GetMonitorsFunc)(Display *, Window, Bool, int *); + GetMonitorsFunc getMonitors = reinterpret_cast<GetMonitorsFunc>(dlsym(RTLD_DEFAULT, "XRRGetMonitors")); + typedef void (*FreeMonitorsFunc)(XRRMonitorInfo*); + FreeMonitorsFunc freeMonitors = reinterpret_cast<FreeMonitorsFunc>(dlsym(RTLD_DEFAULT, "XRRFreeMonitors")); + if (!getMonitors && !freeMonitors) { + qWarning("Unable to link XRandR monitor functions."); + return content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, 0); + } + + Window rootWindow = RootWindow(display, DefaultScreen(display)); + if (rootWindow == BadValue) { + qWarning("Unable to get the root window."); + return content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, 0); + } + + int numMonitors = 0; + XRRMonitorInfo *monitors = getMonitors(display, rootWindow, true, &numMonitors); + if (numMonitors > 0) + return content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, monitors[0].name); +#endif // !defined(WEBRTC_USE_X11) +#endif // QT_CONFIG(webengine_webrtc) return content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, 0); } diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp index 525e9924e..f8e20d188 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -1251,6 +1251,7 @@ void RenderWidgetHostViewQt::processMotionEvent(const ui::MotionEvent &motionEve QList<QTouchEvent::TouchPoint> RenderWidgetHostViewQt::mapTouchPointIds(const QList<QTouchEvent::TouchPoint> &inputPoints) { + QList<int> idsToRemove; QList<QTouchEvent::TouchPoint> outputPoints = inputPoints; for (int i = 0; i < outputPoints.size(); ++i) { QTouchEvent::TouchPoint &point = outputPoints[i]; @@ -1262,9 +1263,14 @@ QList<QTouchEvent::TouchPoint> RenderWidgetHostViewQt::mapTouchPointIds(const QL point.setId(it.value()); if (point.state() == Qt::TouchPointReleased) - m_touchIdMapping.remove(qtId); + idsToRemove.append(qtId); } + for (int qtId : qAsConst(idsToRemove)) + m_touchIdMapping.remove(qtId); + + Q_ASSERT(outputPoints.size() == std::accumulate(outputPoints.cbegin(), outputPoints.cend(), QSet<int>(), + [] (QSet<int> s, const QTouchEvent::TouchPoint &p) { s.insert(p.id()); return s; }).size()); return outputPoints; } diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index d5a3934fe..36af1b025 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -128,7 +128,7 @@ content::WebContents *WebContentsDelegateQt::OpenURLFromTab(content::WebContents content::SiteInstance *target_site_instance = params.source_site_instance.get(); content::Referrer referrer = params.referrer; if (params.disposition != WindowOpenDisposition::CURRENT_TAB) { - QSharedPointer<WebContentsAdapter> targetAdapter = createWindow(0, params.disposition, gfx::Rect(), params.user_gesture); + QSharedPointer<WebContentsAdapter> targetAdapter = createWindow(nullptr, params.disposition, gfx::Rect(), toQt(params.url), params.user_gesture); if (targetAdapter) { if (targetAdapter->profile() != source->GetBrowserContext()) { target_site_instance = nullptr; @@ -137,6 +137,8 @@ content::WebContents *WebContentsDelegateQt::OpenURLFromTab(content::WebContents if (!targetAdapter->isInitialized()) targetAdapter->initialize(target_site_instance); target = targetAdapter->webContents(); + } else { + return target; } } Q_ASSERT(target); @@ -235,7 +237,7 @@ QUrl WebContentsDelegateQt::url(content::WebContents* source) const { void WebContentsDelegateQt::AddNewContents(content::WebContents* source, std::unique_ptr<content::WebContents> new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture, bool* was_blocked) { Q_UNUSED(source) - QSharedPointer<WebContentsAdapter> newAdapter = createWindow(std::move(new_contents), disposition, initial_pos, user_gesture); + QSharedPointer<WebContentsAdapter> newAdapter = createWindow(std::move(new_contents), disposition, initial_pos, m_initialTargetUrl, user_gesture); // Chromium can forget to pass user-agent override settings to new windows (see QTBUG-61774 and QTBUG-76249), // so set it here. Note the actual value doesn't really matter here. Only the second value does, but we try // to give the correct user-agent anyway. @@ -675,7 +677,7 @@ void WebContentsDelegateQt::overrideWebPreferences(content::WebContents *webCont QSharedPointer<WebContentsAdapter> WebContentsDelegateQt::createWindow(std::unique_ptr<content::WebContents> new_contents, - WindowOpenDisposition disposition, const gfx::Rect &initial_pos, + WindowOpenDisposition disposition, const gfx::Rect &initial_pos, const QUrl &url, bool user_gesture) { QSharedPointer<WebContentsAdapter> newAdapter = QSharedPointer<WebContentsAdapter>::create(std::move(new_contents)); @@ -683,7 +685,7 @@ WebContentsDelegateQt::createWindow(std::unique_ptr<content::WebContents> new_co return m_viewClient->adoptNewWindow( std::move(newAdapter), static_cast<WebContentsAdapterClient::WindowOpenDisposition>(disposition), user_gesture, - toQt(initial_pos), m_initialTargetUrl); + toQt(initial_pos), url); } void WebContentsDelegateQt::allowCertificateError(const QSharedPointer<CertificateErrorController> &errorController) diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h index 159803840..e9ac3e7f4 100644 --- a/src/core/web_contents_delegate_qt.h +++ b/src/core/web_contents_delegate_qt.h @@ -205,6 +205,7 @@ private: QSharedPointer<WebContentsAdapter> createWindow(std::unique_ptr<content::WebContents> new_contents, WindowOpenDisposition disposition, const gfx::Rect &initial_pos, + const QUrl &url, bool user_gesture); void EmitLoadStarted(const QUrl &url, bool isErrorPage = false); void EmitLoadFinished(bool success, const QUrl &url, bool isErrorPage = false, int errorCode = 0, const QString &errorDescription = QString()); diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp index 6fb3c5c43..828a1ca79 100644 --- a/src/webenginewidgets/api/qwebenginepage.cpp +++ b/src/webenginewidgets/api/qwebenginepage.cpp @@ -337,8 +337,13 @@ QWebEnginePagePrivate::adoptNewWindow(QSharedPointer<WebContentsAdapter> newWebC Q_UNUSED(targetUrl); QWebEnginePage *newPage = q->createWindow(toWindowType(disposition)); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) if (!newPage) return nullptr; +#else + if (!newPage) + return adapter; +#endif if (!newWebContents->webContents()) return newPage->d_func()->adapter; // Reuse existing adapter |