Index: chrome/browser/media/native_desktop_media_list.cc |
diff --git a/chrome/browser/media/native_desktop_media_list.cc b/chrome/browser/media/native_desktop_media_list.cc |
index 48c76f974e7342447080de9c5436ebe4d6a371a0..7d8a2a030ddc6ad8bbdd1d3a0975be12861e37bb 100644 |
--- a/chrome/browser/media/native_desktop_media_list.cc |
+++ b/chrome/browser/media/native_desktop_media_list.cc |
@@ -8,6 +8,9 @@ |
#include "base/strings/utf_string_conversions.h" |
#include "base/threading/sequenced_worker_pool.h" |
#include "chrome/browser/media/desktop_media_list_observer.h" |
+#include "chrome/browser/ui/browser.h" |
+#include "chrome/browser/ui/browser_list.h" |
+#include "chrome/browser/ui/browser_window.h" |
#include "chrome/grit/generated_resources.h" |
#include "content/public/browser/browser_thread.h" |
#include "media/base/video_util.h" |
@@ -16,10 +19,13 @@ |
#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" |
#include "third_party/webrtc/modules/desktop_capture/screen_capturer.h" |
#include "third_party/webrtc/modules/desktop_capture/window_capturer.h" |
+#include "ui/aura/window.h" |
+#include "ui/aura/window_tree_host.h" |
#include "ui/base/l10n/l10n_util.h" |
+#include "ui/gfx/native_widget_types.h" |
+#include "ui/snapshot/snapshot.h" |
using content::BrowserThread; |
-using content::DesktopMediaID; |
namespace { |
@@ -30,7 +36,7 @@ const int kDefaultUpdatePeriod = 1000; |
// media source has changed. |
uint32_t GetFrameHash(webrtc::DesktopFrame* frame) { |
int data_size = frame->stride() * frame->size().height(); |
- return base::SuperFastHash(reinterpret_cast<char*>(frame->data()), data_size); |
+ return base::Hash(reinterpret_cast<char*>(frame->data()), data_size); |
} |
gfx::ImageSkia ScaleDesktopFrame(scoped_ptr<webrtc::DesktopFrame> frame, |
@@ -78,7 +84,8 @@ class NativeDesktopMediaList::Worker |
~Worker() override; |
void Refresh(const gfx::Size& thumbnail_size, |
- content::DesktopMediaID::Id view_dialog_id); |
+ DesktopMediaID::Id view_dialog_id, |
+ NativeAuraIdMap native_aura_id_map); |
private: |
typedef std::map<DesktopMediaID, uint32_t> ImageHashesMap; |
@@ -115,8 +122,10 @@ NativeDesktopMediaList::Worker::~Worker() {} |
void NativeDesktopMediaList::Worker::Refresh( |
const gfx::Size& thumbnail_size, |
- content::DesktopMediaID::Id view_dialog_id) { |
+ DesktopMediaID::Id view_dialog_id, |
+ NativeAuraIdMap native_aura_id_map) { |
std::vector<SourceDescription> sources; |
+ std::vector<DesktopMediaID> aura_media_ids; |
if (screen_capturer_) { |
webrtc::ScreenCapturer::ScreenList screens; |
@@ -145,13 +154,21 @@ void NativeDesktopMediaList::Worker::Refresh( |
it != windows.end(); ++it) { |
// Skip the picker dialog window. |
if (it->id != view_dialog_id) { |
- sources.push_back(SourceDescription( |
- DesktopMediaID(DesktopMediaID::TYPE_WINDOW, it->id), |
- base::UTF8ToUTF16(it->title))); |
+ DesktopMediaID media_id(DesktopMediaID::TYPE_WINDOW, it->id); |
+#if defined(USE_AURA) |
+ // Associate aura id with native id. |
+ if (native_aura_id_map.count(media_id.id)) { |
+ media_id.aura_id = native_aura_id_map[media_id.id]; |
+ aura_media_ids.push_back(media_id); |
+ } |
+#endif |
+ sources.push_back( |
+ SourceDescription(media_id, base::UTF8ToUTF16(it->title))); |
} |
} |
} |
} |
+ |
// Update list of windows before updating thumbnails. |
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
base::Bind(&NativeDesktopMediaList::UpdateSourcesList, |
@@ -162,6 +179,7 @@ void NativeDesktopMediaList::Worker::Refresh( |
// Get a thumbnail for each source. |
for (size_t i = 0; i < sources.size(); ++i) { |
SourceDescription& source = sources[i]; |
+ |
switch (source.id.type) { |
case DesktopMediaID::TYPE_SCREEN: |
if (!screen_capturer_->SelectScreen(source.id.id)) |
@@ -170,6 +188,10 @@ void NativeDesktopMediaList::Worker::Refresh( |
break; |
case DesktopMediaID::TYPE_WINDOW: |
+#if defined(USE_AURA) |
+ if (source.id.aura_id > 0) |
Sergey Ulanov
2016/03/07 21:01:50
Add a comment to explain what happens here.
Sergey Ulanov
2016/03/07 21:01:50
aura_id != DesktopMediaID::kInvalidId.
GeorgeZ
2016/03/07 23:29:20
Done.
GeorgeZ
2016/03/07 23:29:20
Done.
|
+ continue; |
+#endif |
if (!window_capturer_->SelectWindow(source.id.id)) |
continue; |
window_capturer_->Capture(webrtc::DesktopRegion()); |
@@ -193,17 +215,31 @@ void NativeDesktopMediaList::Worker::Refresh( |
ScaleDesktopFrame(std::move(current_frame_), thumbnail_size); |
BrowserThread::PostTask( |
BrowserThread::UI, FROM_HERE, |
- base::Bind(&NativeDesktopMediaList::OnSourceThumbnail, media_list_, |
- i, thumbnail)); |
+ base::Bind(&NativeDesktopMediaList::OnSourceThumbnailCaptured, |
+ media_list_, i, thumbnail)); |
} |
} |
} |
image_hashes_.swap(new_image_hashes); |
- BrowserThread::PostTask( |
- BrowserThread::UI, FROM_HERE, |
- base::Bind(&NativeDesktopMediaList::ScheduleNextRefresh, media_list_)); |
+#if defined(USE_AURA) |
+ // Aura thumbnail captures are at the last. When they are done, thumbnail |
+ // captures for all sources are done. |
+ for (const auto& media_id : aura_media_ids) { |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, |
+ base::Bind(&NativeDesktopMediaList::CaptureAuraWindowThumbnail, |
+ media_list_, media_id, aura_media_ids.size())); |
+ } |
+#endif |
+ |
+ // If no aura window need capture, we can schedule next refresh. |
+ if (aura_media_ids.size() == 0) { |
Sergey Ulanov
2016/03/07 21:01:50
The logic here is hard to follow. I suggest you po
GeorgeZ
2016/03/07 23:29:20
Good idea.
|
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, |
+ base::Bind(&NativeDesktopMediaList::ScheduleNextRefresh, media_list_)); |
+ } |
} |
void NativeDesktopMediaList::Worker::OnCaptureCompleted( |
@@ -231,12 +267,91 @@ NativeDesktopMediaList::~NativeDesktopMediaList() { |
} |
void NativeDesktopMediaList::Refresh() { |
+ NativeAuraIdMap native_aura_id_map; |
+#if defined(USE_AURA) |
+ native_aura_id_map = GetBrowserNativeAuraIdMap(); |
+#endif |
+ processed_aura_window_count_ = 0; |
+ cur_aura_thumbnail_hashes_.clear(); |
+ |
capture_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&Worker::Refresh, base::Unretained(worker_.get()), |
- thumbnail_size_, view_dialog_id_.id)); |
+ FROM_HERE, |
+ base::Bind(&Worker::Refresh, base::Unretained(worker_.get()), |
+ thumbnail_size_, view_dialog_id_.id, native_aura_id_map)); |
} |
-void NativeDesktopMediaList::OnSourceThumbnail(int index, |
- const gfx::ImageSkia& image) { |
+void NativeDesktopMediaList::OnSourceThumbnailCaptured( |
+ int index, |
+ const gfx::ImageSkia& image) { |
UpdateSourceThumbnail(GetSource(index).id, image); |
} |
+ |
+void NativeDesktopMediaList::OnAuraThumbnailCaptured(DesktopMediaID id, |
+ int total_aura_windows, |
+ const gfx::Image& image) { |
+ if (!image.IsEmpty()) { |
+ // Only new or changed thumbnail need update. |
+ cur_aura_thumbnail_hashes_[id] = DesktopMediaListBase::GetImageHash(image); |
+ if (!aura_thumbnail_hashes_.count(id) || |
+ aura_thumbnail_hashes_[id] != cur_aura_thumbnail_hashes_[id]) { |
+ UpdateSourceThumbnail(id, image.AsImageSkia()); |
+ } |
+ } |
+ |
+ // After all aura windows are processed, schedule next refresh; |
+ processed_aura_window_count_++; |
+ if (processed_aura_window_count_ == total_aura_windows) { |
+ swap(aura_thumbnail_hashes_, cur_aura_thumbnail_hashes_); |
+ ScheduleNextRefresh(); |
+ } |
+} |
+ |
+#if defined(USE_AURA) |
+ |
+NativeDesktopMediaList::NativeAuraIdMap |
+NativeDesktopMediaList::GetBrowserNativeAuraIdMap() { |
+ NativeAuraIdMap id_map; |
+ for (auto* browser : *BrowserList::GetInstance()) { |
+ const BrowserWindow* browser_window = browser->window(); |
+ if (!browser_window) |
+ continue; |
+ const gfx::NativeWindow native_window = browser_window->GetNativeWindow(); |
+ if (!native_window) |
+ continue; |
+ aura::WindowTreeHost* host = native_window->GetHost(); |
+ if (!host) |
+ continue; |
+ gfx::AcceleratedWidget widget = host->GetAcceleratedWidget(); |
+#if defined(OS_WIN) |
+ DesktopMediaID::Id native_id = reinterpret_cast<DesktopMediaID::Id>(widget); |
+#else |
+ DesktopMediaID::Id native_id = widget; |
+#endif |
+ DesktopMediaID media_id = DesktopMediaID::RegisterAuraWindow( |
+ DesktopMediaID::TYPE_WINDOW, native_window); |
+ id_map.insert(std::make_pair(native_id, media_id.aura_id)); |
+ } |
+ |
+ return id_map; |
+} |
+ |
+void NativeDesktopMediaList::CaptureAuraWindowThumbnail( |
+ DesktopMediaID id, |
+ int total_aura_windows) { |
+ gfx::NativeWindow window = DesktopMediaID::GetAuraWindowById(id); |
+ if (window == NULL) { |
Sergey Ulanov
2016/03/07 21:01:50
if (!window) for consistency with the code above
GeorgeZ
2016/03/07 23:29:20
Done.
|
+ OnAuraThumbnailCaptured(id, total_aura_windows, gfx::Image()); |
+ return; |
+ } |
+ |
+ gfx::Rect window_rect(window->bounds().width(), window->bounds().height()); |
+ gfx::Rect scaled_rect = media::ComputeLetterboxRegion( |
+ gfx::Rect(thumbnail_size_), window_rect.size()); |
+ |
+ ui::GrabWindowSnapshotAndScaleAsync( |
+ window, window_rect, scaled_rect.size(), BrowserThread::GetBlockingPool(), |
+ base::Bind(&NativeDesktopMediaList::OnAuraThumbnailCaptured, |
+ weak_factory_.GetWeakPtr(), id, total_aura_windows)); |
+} |
+ |
+#endif |
Sergey Ulanov
2016/03/07 21:01:50
// defined(USE_AURA)
GeorgeZ
2016/03/07 23:29:20
Done.
|