feat: add support for DesktopCapturerSource.appIcon
Useful to get the icon of the application owning the source. Only available for sources of type window, i.e. not for screen. https://github.com/electron/electron/issues/14845
This commit is contained in:
parent
77f73830e8
commit
1f55f1635f
7 changed files with 48 additions and 15 deletions
|
@ -14,6 +14,7 @@
|
|||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/threading/thread_restrictions.h"
|
||||
#include "chrome/browser/media/webrtc/desktop_media_list.h"
|
||||
#include "chrome/browser/media/webrtc/window_icon_util.h"
|
||||
#include "content/public/browser/desktop_capture.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
|
||||
|
@ -42,6 +43,12 @@ struct Converter<atom::api::DesktopCapturer::Source> {
|
|||
atom::api::NativeImage::Create(
|
||||
isolate, gfx::Image(source.media_list_source.thumbnail)));
|
||||
dict.Set("display_id", source.display_id);
|
||||
if (source.fetch_icon) {
|
||||
dict.Set(
|
||||
"appIcon",
|
||||
atom::api::NativeImage::Create(
|
||||
isolate, gfx::Image(GetWindowIcon(source.media_list_source.id))));
|
||||
}
|
||||
return ConvertToV8(isolate, dict);
|
||||
}
|
||||
};
|
||||
|
@ -60,7 +67,9 @@ DesktopCapturer::~DesktopCapturer() {}
|
|||
|
||||
void DesktopCapturer::StartHandling(bool capture_window,
|
||||
bool capture_screen,
|
||||
const gfx::Size& thumbnail_size) {
|
||||
const gfx::Size& thumbnail_size,
|
||||
bool fetch_window_icons) {
|
||||
fetch_window_icons_ = fetch_window_icons;
|
||||
#if defined(OS_WIN)
|
||||
if (content::desktop_capture::CreateDesktopCaptureOptions()
|
||||
.allow_directx_capturer()) {
|
||||
|
@ -134,8 +143,8 @@ void DesktopCapturer::UpdateSourcesList(DesktopMediaList* list) {
|
|||
capture_window_ = false;
|
||||
const auto& media_list_sources = list->GetSources();
|
||||
for (const auto& media_list_source : media_list_sources) {
|
||||
window_sources.emplace_back(
|
||||
DesktopCapturer::Source{media_list_source, std::string()});
|
||||
window_sources.emplace_back(DesktopCapturer::Source{
|
||||
media_list_source, std::string(), fetch_window_icons_});
|
||||
}
|
||||
std::move(window_sources.begin(), window_sources.end(),
|
||||
std::back_inserter(captured_sources_));
|
||||
|
@ -187,7 +196,7 @@ void DesktopCapturer::UpdateSourcesList(DesktopMediaList* list) {
|
|||
}
|
||||
|
||||
if (!capture_window_ && !capture_screen_)
|
||||
Emit("finished", captured_sources_);
|
||||
Emit("finished", captured_sources_, fetch_window_icons_);
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -25,6 +25,9 @@ class DesktopCapturer : public mate::EventEmitter<DesktopCapturer>,
|
|||
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 mate::Handle<DesktopCapturer> Create(v8::Isolate* isolate);
|
||||
|
@ -34,7 +37,8 @@ class DesktopCapturer : public mate::EventEmitter<DesktopCapturer>,
|
|||
|
||||
void StartHandling(bool capture_window,
|
||||
bool capture_screen,
|
||||
const gfx::Size& thumbnail_size);
|
||||
const gfx::Size& thumbnail_size,
|
||||
bool fetch_window_icons);
|
||||
|
||||
protected:
|
||||
explicit DesktopCapturer(v8::Isolate* isolate);
|
||||
|
@ -59,6 +63,7 @@ class DesktopCapturer : public mate::EventEmitter<DesktopCapturer>,
|
|||
std::vector<DesktopCapturer::Source> captured_sources_;
|
||||
bool capture_window_ = false;
|
||||
bool capture_screen_ = false;
|
||||
bool fetch_window_icons_ = false;
|
||||
#if defined(OS_WIN)
|
||||
bool using_directx_capturer_ = false;
|
||||
#endif // defined(OS_WIN)
|
||||
|
|
|
@ -72,6 +72,7 @@ static_library("chrome") {
|
|||
"//chrome/browser/media/webrtc/desktop_media_list_observer.h",
|
||||
"//chrome/browser/media/webrtc/native_desktop_media_list.cc",
|
||||
"//chrome/browser/media/webrtc/native_desktop_media_list.h",
|
||||
"//chrome/browser/media/webrtc/window_icon_util.h",
|
||||
]
|
||||
deps += [ "//ui/snapshot" ]
|
||||
}
|
||||
|
@ -93,6 +94,7 @@ static_library("chrome") {
|
|||
|
||||
if (is_mac) {
|
||||
sources += [
|
||||
"//chrome/browser/media/webrtc/window_icon_util_mac.mm",
|
||||
"//chrome/browser/ui/cocoa/color_chooser_mac.h",
|
||||
"//chrome/browser/ui/cocoa/color_chooser_mac.mm",
|
||||
]
|
||||
|
@ -100,6 +102,7 @@ static_library("chrome") {
|
|||
|
||||
if (is_win) {
|
||||
sources += [
|
||||
"//chrome/browser/media/webrtc/window_icon_util_win.cc",
|
||||
"//chrome/browser/ui/views/color_chooser_dialog.cc",
|
||||
"//chrome/browser/ui/views/color_chooser_dialog.h",
|
||||
"//chrome/browser/ui/views/color_chooser_win.cc",
|
||||
|
@ -126,7 +129,10 @@ static_library("chrome") {
|
|||
]
|
||||
|
||||
if (is_linux) {
|
||||
sources += [ "//chrome/browser/speech/tts_linux.cc" ]
|
||||
sources += [
|
||||
"//chrome/browser/media/webrtc/window_icon_util_x11.cc",
|
||||
"//chrome/browser/speech/tts_linux.cc",
|
||||
]
|
||||
deps += [ "//third_party/speech-dispatcher" ]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,6 +84,9 @@ The `desktopCapturer` module has the following methods:
|
|||
to be captured, available types are `screen` and `window`.
|
||||
* `thumbnailSize` [Size](structures/size.md) (optional) - The size that the media source thumbnail
|
||||
should be scaled to. Default is `150` x `150`.
|
||||
* `fetchWindowIcons` Boolean (optional) - Set to true to enable fetching window icons. The default
|
||||
value is false. When false the appIcon property of the sources return null. Same if a source has
|
||||
the type screen.
|
||||
* `callback` Function
|
||||
* `error` Error
|
||||
* `sources` [DesktopCapturerSource[]](structures/desktop-capturer-source.md)
|
||||
|
|
|
@ -17,3 +17,7 @@
|
|||
On some platforms, this is equivalent to the `XX` portion of the `id` field
|
||||
above and on others it will differ. It will be an empty string if not
|
||||
available.
|
||||
* `appIcon` [NativeImage](../native-image.md) - An icon image of the
|
||||
application that owns the window or null if the source has a type screen.
|
||||
The size of the icon is not known in advance and depends on what the
|
||||
the application provides.
|
||||
|
|
|
@ -11,19 +11,20 @@ let requestsQueue = []
|
|||
const electronSources = 'ELECTRON_BROWSER_DESKTOP_CAPTURER_GET_SOURCES'
|
||||
const capturerResult = (id) => `ELECTRON_RENDERER_DESKTOP_CAPTURER_RESULT_${id}`
|
||||
|
||||
ipcMain.on(electronSources, (event, captureWindow, captureScreen, thumbnailSize, id) => {
|
||||
ipcMain.on(electronSources, (event, captureWindow, captureScreen, thumbnailSize, fetchWindowIcons, id) => {
|
||||
const request = {
|
||||
id,
|
||||
options: {
|
||||
captureWindow,
|
||||
captureScreen,
|
||||
thumbnailSize
|
||||
thumbnailSize,
|
||||
fetchWindowIcons
|
||||
},
|
||||
webContents: event.sender
|
||||
}
|
||||
requestsQueue.push(request)
|
||||
if (requestsQueue.length === 1) {
|
||||
desktopCapturer.startHandling(captureWindow, captureScreen, thumbnailSize)
|
||||
desktopCapturer.startHandling(captureWindow, captureScreen, thumbnailSize, fetchWindowIcons)
|
||||
}
|
||||
|
||||
// If the WebContents is destroyed before receiving result, just remove the
|
||||
|
@ -33,7 +34,7 @@ ipcMain.on(electronSources, (event, captureWindow, captureScreen, thumbnailSize,
|
|||
})
|
||||
})
|
||||
|
||||
desktopCapturer.emit = (event, name, sources) => {
|
||||
desktopCapturer.emit = (event, name, sources, fetchWindowIcons) => {
|
||||
// Receiving sources result from main process, now send them back to renderer.
|
||||
const handledRequest = requestsQueue.shift()
|
||||
const handledWebContents = handledRequest.webContents
|
||||
|
@ -44,7 +45,8 @@ desktopCapturer.emit = (event, name, sources) => {
|
|||
id: source.id,
|
||||
name: source.name,
|
||||
thumbnail: source.thumbnail.toDataURL(),
|
||||
display_id: source.display_id
|
||||
display_id: source.display_id,
|
||||
appIcon: (fetchWindowIcons && source.appIcon) ? source.appIcon.toDataURL() : null
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -67,7 +69,7 @@ desktopCapturer.emit = (event, name, sources) => {
|
|||
|
||||
// If the requestsQueue is not empty, start a new request handling.
|
||||
if (requestsQueue.length > 0) {
|
||||
const { captureWindow, captureScreen, thumbnailSize } = requestsQueue[0].options
|
||||
return desktopCapturer.startHandling(captureWindow, captureScreen, thumbnailSize)
|
||||
const { captureWindow, captureScreen, thumbnailSize, fetchWindowIcons } = requestsQueue[0].options
|
||||
return desktopCapturer.startHandling(captureWindow, captureScreen, thumbnailSize, fetchWindowIcons)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,9 +28,12 @@ exports.getSources = function (options, callback) {
|
|||
height: 150
|
||||
}
|
||||
}
|
||||
if (options.fetchWindowIcons == null) {
|
||||
options.fetchWindowIcons = false
|
||||
}
|
||||
|
||||
const id = incrementId()
|
||||
ipcRenderer.send('ELECTRON_BROWSER_DESKTOP_CAPTURER_GET_SOURCES', captureWindow, captureScreen, options.thumbnailSize, id)
|
||||
ipcRenderer.send('ELECTRON_BROWSER_DESKTOP_CAPTURER_GET_SOURCES', captureWindow, captureScreen, options.thumbnailSize, options.fetchWindowIcons, id)
|
||||
return ipcRenderer.once(`ELECTRON_RENDERER_DESKTOP_CAPTURER_RESULT_${id}`, (event, sources) => {
|
||||
callback(null, (() => {
|
||||
const results = []
|
||||
|
@ -39,7 +42,8 @@ exports.getSources = function (options, callback) {
|
|||
id: source.id,
|
||||
name: source.name,
|
||||
thumbnail: nativeImage.createFromDataURL(source.thumbnail),
|
||||
display_id: source.display_id
|
||||
display_id: source.display_id,
|
||||
appIcon: source.appIcon ? nativeImage.createFromDataURL(source.appIcon) : null
|
||||
})
|
||||
})
|
||||
return results
|
||||
|
|
Loading…
Reference in a new issue