905e41bbdd
* fix: use StartUpdating method for PipeWire capturer Fixed a crash related to PipeWire capturer by adapting to Chromium's interface changes. Chromium expects a call to `NativeDesktopMediaList::StartUpdating` with an implementation of `DesktopMediaListObserver` for delegated capturers like PipeWire. This interface allows listening to user permission events and listing sources only after the user has made a choice on the permission dialog. The interface has been implemented by an inner class to allow listening to screen and window capture permissions concurrently using two instances of the class. A patch that was resetting the capturer on the first refresh has been changed to exclude PipeWire. PipeWire capturer object will follow the lifecycle of `NativeDesktopMediaList`, as is the case in Chromium. Fixes #37463 * fix: wait for thumbnails from PipeWire when necessary The PipeWire stream starts after the dialog is dismissed. If the sources are listed immediately afterwards, the thumbnail may not have been generated by that time. Explicitly wait for both thumbnail generation and a selection on the source dialog before listing sources.
111 lines
3.7 KiB
C++
111 lines
3.7 KiB
C++
// Copyright (c) 2015 GitHub, Inc.
|
|
// Use of this source code is governed by the MIT license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef ELECTRON_SHELL_BROWSER_API_ELECTRON_API_DESKTOP_CAPTURER_H_
|
|
#define ELECTRON_SHELL_BROWSER_API_ELECTRON_API_DESKTOP_CAPTURER_H_
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "chrome/browser/media/webrtc/desktop_media_list_observer.h"
|
|
#include "chrome/browser/media/webrtc/native_desktop_media_list.h"
|
|
#include "gin/handle.h"
|
|
#include "gin/wrappable.h"
|
|
#include "shell/common/gin_helper/pinnable.h"
|
|
|
|
namespace electron::api {
|
|
|
|
class DesktopCapturer : public gin::Wrappable<DesktopCapturer>,
|
|
public gin_helper::Pinnable<DesktopCapturer>,
|
|
public DesktopMediaListObserver {
|
|
public:
|
|
struct Source {
|
|
DesktopMediaList::Source media_list_source;
|
|
// Will be an empty string if not available.
|
|
std::string display_id;
|
|
|
|
// Whether or not this source should provide an icon.
|
|
bool fetch_icon = false;
|
|
};
|
|
|
|
static gin::Handle<DesktopCapturer> Create(v8::Isolate* isolate);
|
|
|
|
void StartHandling(bool capture_window,
|
|
bool capture_screen,
|
|
const gfx::Size& thumbnail_size,
|
|
bool fetch_window_icons);
|
|
|
|
// gin::Wrappable
|
|
static gin::WrapperInfo kWrapperInfo;
|
|
gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
|
v8::Isolate* isolate) override;
|
|
const char* GetTypeName() override;
|
|
|
|
// disable copy
|
|
DesktopCapturer(const DesktopCapturer&) = delete;
|
|
DesktopCapturer& operator=(const DesktopCapturer&) = delete;
|
|
|
|
protected:
|
|
explicit DesktopCapturer(v8::Isolate* isolate);
|
|
~DesktopCapturer() override;
|
|
|
|
// DesktopMediaListObserver:
|
|
void OnSourceAdded(int index) override {}
|
|
void OnSourceRemoved(int index) override {}
|
|
void OnSourceMoved(int old_index, int new_index) override {}
|
|
void OnSourceNameChanged(int index) override {}
|
|
void OnSourceThumbnailChanged(int index) override {}
|
|
void OnSourcePreviewChanged(size_t index) override {}
|
|
void OnDelegatedSourceListSelection() override {}
|
|
void OnDelegatedSourceListDismissed() override {}
|
|
|
|
private:
|
|
using OnceCallback = base::OnceClosure;
|
|
|
|
class DesktopListListener : public DesktopMediaListObserver {
|
|
public:
|
|
DesktopListListener(OnceCallback update_callback,
|
|
OnceCallback failure_callback,
|
|
bool skip_thumbnails);
|
|
~DesktopListListener() override;
|
|
|
|
protected:
|
|
void OnSourceAdded(int index) override {}
|
|
void OnSourceRemoved(int index) override {}
|
|
void OnSourceMoved(int old_index, int new_index) override {}
|
|
void OnSourceNameChanged(int index) override {}
|
|
void OnSourceThumbnailChanged(int index) override;
|
|
void OnSourcePreviewChanged(size_t index) override {}
|
|
void OnDelegatedSourceListSelection() override;
|
|
void OnDelegatedSourceListDismissed() override;
|
|
|
|
private:
|
|
OnceCallback update_callback_;
|
|
OnceCallback failure_callback_;
|
|
bool have_selection_ = false;
|
|
bool have_thumbnail_ = false;
|
|
};
|
|
|
|
void UpdateSourcesList(DesktopMediaList* list);
|
|
void HandleFailure();
|
|
|
|
std::unique_ptr<DesktopListListener> window_listener_;
|
|
std::unique_ptr<DesktopListListener> screen_listener_;
|
|
std::unique_ptr<DesktopMediaList> window_capturer_;
|
|
std::unique_ptr<DesktopMediaList> screen_capturer_;
|
|
std::vector<DesktopCapturer::Source> captured_sources_;
|
|
bool capture_window_ = false;
|
|
bool capture_screen_ = false;
|
|
bool fetch_window_icons_ = false;
|
|
#if BUILDFLAG(IS_WIN)
|
|
bool using_directx_capturer_ = false;
|
|
#endif // BUILDFLAG(IS_WIN)
|
|
|
|
base::WeakPtrFactory<DesktopCapturer> weak_ptr_factory_{this};
|
|
};
|
|
|
|
} // namespace electron::api
|
|
|
|
#endif // ELECTRON_SHELL_BROWSER_API_ELECTRON_API_DESKTOP_CAPTURER_H_
|