blob: 5645b4f0eb937fd44fcb17d708b8e585fdb9f782 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/media/desktop_media_list_ash.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/browser_thread.h"
#include "media/base/video_util.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/image/image.h"
#include "ui/snapshot/snapshot.h"
using content::BrowserThread;
namespace {
// Update the list twice per second.
const int kDefaultUpdatePeriod = 500;
} // namespace
DesktopMediaListAsh::DesktopMediaListAsh(int source_types)
: DesktopMediaListBase(
base::TimeDelta::FromMilliseconds(kDefaultUpdatePeriod)),
source_types_(source_types),
pending_window_capture_requests_(0),
weak_factory_(this) {}
DesktopMediaListAsh::~DesktopMediaListAsh() {}
void DesktopMediaListAsh::Refresh() {
std::vector<SourceDescription> new_sources;
EnumerateSources(&new_sources);
UpdateSourcesList(new_sources);
}
void DesktopMediaListAsh::EnumerateWindowsForRoot(
std::vector<DesktopMediaListAsh::SourceDescription>* sources,
aura::Window* root_window,
int container_id) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
aura::Window* container = ash::Shell::GetContainer(root_window, container_id);
if (!container)
return;
for (aura::Window::Windows::const_iterator it = container->children().begin();
it != container->children().end(); ++it) {
if (!(*it)->IsVisible() || !(*it)->CanFocus())
continue;
content::DesktopMediaID id = content::DesktopMediaID::RegisterAuraWindow(
content::DesktopMediaID::TYPE_WINDOW, *it);
if (id.aura_id == view_dialog_id_.aura_id)
continue;
SourceDescription window_source(id, (*it)->title());
sources->push_back(window_source);
CaptureThumbnail(window_source.id, *it);
}
}
void DesktopMediaListAsh::EnumerateSources(
std::vector<DesktopMediaListAsh::SourceDescription>* sources) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
aura::Window::Windows root_windows = ash::Shell::GetAllRootWindows();
for (size_t i = 0; i < root_windows.size(); ++i) {
if (source_types_ & SCREENS) {
SourceDescription screen_source(
content::DesktopMediaID::RegisterAuraWindow(
content::DesktopMediaID::TYPE_SCREEN, root_windows[i]),
root_windows[i]->title());
if (root_windows[i] == ash::Shell::GetPrimaryRootWindow())
sources->insert(sources->begin(), screen_source);
else
sources->push_back(screen_source);
if (screen_source.name.empty()) {
if (root_windows.size() > 1) {
screen_source.name = l10n_util::GetStringFUTF16Int(
IDS_DESKTOP_MEDIA_PICKER_MULTIPLE_SCREEN_NAME,
static_cast<int>(i + 1));
} else {
screen_source.name = l10n_util::GetStringUTF16(
IDS_DESKTOP_MEDIA_PICKER_SINGLE_SCREEN_NAME);
}
}
CaptureThumbnail(screen_source.id, root_windows[i]);
}
if (source_types_ & WINDOWS) {
EnumerateWindowsForRoot(
sources, root_windows[i], ash::kShellWindowId_DefaultContainer);
EnumerateWindowsForRoot(
sources, root_windows[i], ash::kShellWindowId_AlwaysOnTopContainer);
EnumerateWindowsForRoot(
sources, root_windows[i], ash::kShellWindowId_DockedContainer);
}
}
}
void DesktopMediaListAsh::CaptureThumbnail(content::DesktopMediaID id,
aura::Window* window) {
gfx::Rect window_rect(window->bounds().width(), window->bounds().height());
gfx::Rect scaled_rect = media::ComputeLetterboxRegion(
gfx::Rect(thumbnail_size_), window_rect.size());
++pending_window_capture_requests_;
ui::GrabWindowSnapshotAndScaleAsync(
window,
window_rect,
scaled_rect.size(),
BrowserThread::GetBlockingPool(),
base::Bind(&DesktopMediaListAsh::OnThumbnailCaptured,
weak_factory_.GetWeakPtr(),
id));
}
void DesktopMediaListAsh::OnThumbnailCaptured(content::DesktopMediaID id,
const gfx::Image& image) {
UpdateSourceThumbnail(id, image.AsImageSkia());
--pending_window_capture_requests_;
DCHECK_GE(pending_window_capture_requests_, 0);
if (!pending_window_capture_requests_) {
// Once we've finished capturing all windows post a task for the next list
// update.
ScheduleNextRefresh();
}
}