Skip to content

Commit

Permalink
feat: add support for DesktopCapturerSource.appIcon
Browse files Browse the repository at this point in the history
Useful to get the icon of the application owning the source.
Only available for sources of type window, i.e. not for screen.

#14845
  • Loading branch information
CapOM authored and Cheng Zhao committed Dec 4, 2018
1 parent 77f7383 commit 1f55f16
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 15 deletions.
17 changes: 13 additions & 4 deletions atom/browser/api/atom_api_desktop_capturer.cc
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
}
};
Expand All @@ -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()) {
Expand Down Expand Up @@ -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_));
Expand Down Expand Up @@ -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
Expand Down
7 changes: 6 additions & 1 deletion atom/browser/api/atom_api_desktop_capturer.h
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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)
Expand Down
8 changes: 7 additions & 1 deletion chromium_src/BUILD.gn
Expand Up @@ -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" ]
}
Expand All @@ -93,13 +94,15 @@ 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",
]
}

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",
Expand All @@ -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" ]
}
}
Expand Down
3 changes: 3 additions & 0 deletions docs/api/desktop-capturer.md
Expand Up @@ -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)
Expand Down
4 changes: 4 additions & 0 deletions docs/api/structures/desktop-capturer-source.md
Expand Up @@ -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.
16 changes: 9 additions & 7 deletions lib/browser/desktop-capturer.js
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
}
})

Expand All @@ -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)
}
}
8 changes: 6 additions & 2 deletions lib/renderer/api/desktop-capturer.js
Expand Up @@ -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 = []
Expand All @@ -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
Expand Down

0 comments on commit 1f55f16

Please sign in to comment.