Commit 1764980d authored by jianli@chromium.org's avatar jianli@chromium.org

We now changed to always provide the custom thumbnail for stacked panels.

The following issues have been fixed:
1) If one or more panels in the stack are collapsed, the live preview is not shown correctly.
2) If the whole stack is minimized by the system, the live preview is not shown correctly.

BUG=177743
TEST=Manual tests by collapsing a panel or system-minimzing a stack and then hover over the taskbar icon

Review URL: https://chromiumcodereview.appspot.com/16035007

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@203016 0039d316-1c4b-4281-b951-d872f2087c98
parent 40b389af
......@@ -19,7 +19,6 @@
#if defined(OS_WIN)
#include "base/win/windows_version.h"
#include "chrome/browser/shell_integration.h"
#include "chrome/browser/ui/views/panels/taskbar_window_thumbnailer_win.h"
#include "ui/base/win/shell.h"
#include "ui/views/win/hwnd_util.h"
#endif
......@@ -152,7 +151,7 @@ void PanelStackView::EndBatchUpdatePanelBounds() {
}
bounds_updates_started_ = false;
delegate_->PanelBoundsBatchUpdateCompleted();
NotifyBoundsUpdateCompleted();
return;
}
......@@ -163,16 +162,25 @@ void PanelStackView::EndBatchUpdatePanelBounds() {
bounds_animator_->Start();
}
void PanelStackView::NotifyBoundsUpdateCompleted() {
delegate_->PanelBoundsBatchUpdateCompleted();
#if defined(OS_WIN)
// Refresh the thumbnail each time when any bounds updates are done.
RefreshLivePreviewThumbnail();
#endif
}
bool PanelStackView::IsAnimatingPanelBounds() const {
return bounds_updates_started_ && animate_bounds_updates_;
}
void PanelStackView::Minimize() {
#if defined(OS_WIN)
// When the owner stack window is minimized by the system, its live preview
// is lost. We need to set it explicitly. This has to be done before the
// minimization.
CaptureThumbnailForLivePreview();
// When the stack window is minimized by the system, its snapshot could not
// be obtained. We need to capture the snapshot before the minimization.
if (thumbnailer_)
thumbnailer_->CaptureSnapshot();
#endif
window_->Minimize();
......@@ -190,6 +198,10 @@ void PanelStackView::DrawSystemAttention(bool draw_attention) {
is_drawing_attention_ = draw_attention;
#if defined(OS_WIN)
// Refresh the thumbnail when a panel could change something for the
// attention.
RefreshLivePreviewThumbnail();
if (draw_attention) {
// The default implementation of Widget::FlashFrame only flashes 5 times.
// We need more than that.
......@@ -270,14 +282,6 @@ void PanelStackView::OnWidgetDestroying(views::Widget* widget) {
window_ = NULL;
}
void PanelStackView::OnWidgetActivationChanged(views::Widget* widget,
bool active) {
#if defined(OS_WIN)
if (active && thumbnailer_)
thumbnailer_->Stop();
#endif
}
void PanelStackView::OnNativeFocusChange(gfx::NativeView focused_before,
gfx::NativeView focused_now) {
// When the user selects the stacked panels via ALT-TAB or WIN-TAB, the
......@@ -306,7 +310,7 @@ void PanelStackView::AnimationEnded(const ui::Animation* animation) {
}
bounds_updates_.clear();
delegate_->PanelBoundsBatchUpdateCompleted();
NotifyBoundsUpdateCompleted();
}
void PanelStackView::AnimationProgressed(const ui::Animation* animation) {
......@@ -378,6 +382,12 @@ gfx::Rect PanelStackView::GetStackWindowBounds() const {
void PanelStackView::UpdateStackWindowBounds() {
window_->SetBounds(GetStackWindowBounds());
#if defined(OS_WIN)
// Refresh the thumbnail each time whne the stack window is changed, due to
// adding or removing a panel.
RefreshLivePreviewThumbnail();
#endif
}
// static
......@@ -440,6 +450,12 @@ views::Widget* PanelStackView::CreateWindowWithBounds(const gfx::Rect& bounds) {
ShellIntegration::GetAppModelIdForProfile(UTF8ToWide(panel->app_name()),
panel->profile()->GetPath()),
views::HWNDForWidget(window));
if (base::win::GetVersion() >= base::win::VERSION_WIN7) {
HWND native_window = views::HWNDForWidget(window);
thumbnailer_.reset(new TaskbarWindowThumbnailerWin(native_window, this));
thumbnailer_->Start();
}
#endif
return window;
......@@ -455,19 +471,7 @@ void PanelStackView::EnsureWindowCreated() {
}
#if defined(OS_WIN)
void PanelStackView::CaptureThumbnailForLivePreview() {
// Live preview is only available since Windows 7.
if (base::win::GetVersion() < base::win::VERSION_WIN7)
return;
HWND native_window = views::HWNDForWidget(window_);
if (!thumbnailer_.get()) {
DCHECK(native_window);
thumbnailer_.reset(new TaskbarWindowThumbnailerWin(native_window));
ui::HWNDSubclass::AddFilterToTarget(native_window, thumbnailer_.get());
}
std::vector<HWND> PanelStackView::GetSnapshotWindowHandles() const {
std::vector<HWND> native_panel_windows;
for (Panels::const_iterator iter = panels_.begin();
iter != panels_.end(); ++iter) {
......@@ -476,7 +480,13 @@ void PanelStackView::CaptureThumbnailForLivePreview() {
views::HWNDForWidget(
static_cast<PanelView*>(panel->native_panel())->window()));
}
thumbnailer_->Start(native_panel_windows);
return native_panel_windows;
}
void PanelStackView::RefreshLivePreviewThumbnail() {
if (!thumbnailer_.get())
return;
thumbnailer_->InvalidateSnapshot();
}
void PanelStackView::DeferUpdateNativeWindowBounds(HDWP defer_window_pos_info,
......
......@@ -15,7 +15,10 @@
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/widget/widget_observer.h"
class TaskbarWindowThumbnailerWin;
#if defined(OS_WIN)
#include "chrome/browser/ui/views/panels/taskbar_window_thumbnailer_win.h"
#endif
namespace ui {
class LinearAnimation;
}
......@@ -29,6 +32,9 @@ class PanelStackView : public NativePanelStackWindow,
public views::WidgetObserver,
public views::WidgetDelegateView,
public views::WidgetFocusChangeListener,
#if defined(OS_WIN)
public TaskbarWindowThumbnailerDelegateWin,
#endif
public ui::AnimationDelegate {
public:
explicit PanelStackView(NativePanelStackWindowDelegate* delegate);
......@@ -69,8 +75,6 @@ class PanelStackView : public NativePanelStackWindow,
// Overridden from views::WidgetObserver:
virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE;
virtual void OnWidgetActivationChanged(views::Widget* widget,
bool active) OVERRIDE;
// Overridden from views::WidgetFocusChangeListener:
virtual void OnNativeFocusChange(gfx::NativeView focused_before,
......@@ -83,6 +87,9 @@ class PanelStackView : public NativePanelStackWindow,
// Updates the bounds of panels as specified in batch update data.
void UpdatePanelsBounds();
// Notifies the delegate that the updates of the panel bounds are completed.
void NotifyBoundsUpdateCompleted();
// Computes/updates the minimum bounds that could fit all panels.
gfx::Rect GetStackWindowBounds() const;
void UpdateStackWindowBounds();
......@@ -97,9 +104,12 @@ class PanelStackView : public NativePanelStackWindow,
PanelStackView* stack_window);
#if defined(OS_WIN)
// Capture the thumbnail of the whole stack and provide it to live preview
// (available since Windows 7).
void CaptureThumbnailForLivePreview();
// Overridden from TaskbarWindowThumbnailerDelegateWin:
virtual std::vector<HWND> GetSnapshotWindowHandles() const OVERRIDE;
// Updates the live preview snapshot when something changes, like
// adding/removing/moving/resizing a stacked panel.
void RefreshLivePreviewThumbnail();
// Updates the bounds of the widget window in a deferred way.
void DeferUpdateNativeWindowBounds(HDWP defer_window_pos_info,
......@@ -121,7 +131,9 @@ class PanelStackView : public NativePanelStackWindow,
bool is_drawing_attention_;
#if defined(OS_WIN)
// Used to provide custom taskbar thumbnail for Windows 7 and later.
// The custom live preview snapshot is always provided for the stack window.
// This is because the system might not show the snapshot correctly for
// a small window, like collapsed panel.
scoped_ptr<TaskbarWindowThumbnailerWin> thumbnailer_;
#endif
......
......@@ -604,6 +604,9 @@ void PanelView::PanelExpansionStateChanging(Panel::ExpansionState old_state,
if (base::win::GetVersion() < base::win::VERSION_WIN7)
return;
if (panel_->collection()->type() != PanelCollection::DOCKED)
return;
bool is_minimized = old_state != Panel::EXPANDED;
bool will_be_minimized = new_state != Panel::EXPANDED;
if (is_minimized == will_be_minimized)
......@@ -613,8 +616,7 @@ void PanelView::PanelExpansionStateChanging(Panel::ExpansionState old_state,
if (!thumbnailer_.get()) {
DCHECK(native_window);
thumbnailer_.reset(new TaskbarWindowThumbnailerWin(native_window));
ui::HWNDSubclass::AddFilterToTarget(native_window, thumbnailer_.get());
thumbnailer_.reset(new TaskbarWindowThumbnailerWin(native_window, NULL));
}
// Cache the image at this point.
......@@ -628,8 +630,9 @@ void PanelView::PanelExpansionStateChanging(Panel::ExpansionState old_state,
RDW_NOCHILDREN | RDW_INVALIDATE | RDW_UPDATENOW);
}
std::vector<HWND> snapshot_hwnds;
thumbnailer_->Start(snapshot_hwnds);
// Start the thumbnailer and capture the snapshot now.
thumbnailer_->Start();
thumbnailer_->CaptureSnapshot();
} else {
force_to_paint_as_inactive_ = false;
thumbnailer_->Stop();
......
......@@ -50,21 +50,19 @@ void EnableCustomThumbnail(HWND hwnd, bool enable) {
} // namespace
TaskbarWindowThumbnailerWin::TaskbarWindowThumbnailerWin(HWND hwnd)
: hwnd_(hwnd) {
TaskbarWindowThumbnailerWin::TaskbarWindowThumbnailerWin(
HWND hwnd, TaskbarWindowThumbnailerDelegateWin* delegate)
: hwnd_(hwnd),
delegate_(delegate) {
ui::HWNDSubclass::AddFilterToTarget(hwnd_, this);
}
TaskbarWindowThumbnailerWin::~TaskbarWindowThumbnailerWin() {
ui::HWNDSubclass::RemoveFilterFromAllTargets(this);
}
void TaskbarWindowThumbnailerWin::Start(
const std::vector<HWND>& snapshot_hwnds) {
snapshot_hwnds_ = snapshot_hwnds;
if (snapshot_hwnds_.empty())
snapshot_hwnds_.push_back(hwnd_);
capture_bitmap_.reset(CaptureWindowImage());
if (capture_bitmap_)
EnableCustomThumbnail(hwnd_, true);
void TaskbarWindowThumbnailerWin::Start() {
EnableCustomThumbnail(hwnd_, true);
}
void TaskbarWindowThumbnailerWin::Stop() {
......@@ -72,6 +70,18 @@ void TaskbarWindowThumbnailerWin::Stop() {
EnableCustomThumbnail(hwnd_, false);
}
void TaskbarWindowThumbnailerWin::CaptureSnapshot() {
if (!capture_bitmap_)
capture_bitmap_.reset(CaptureWindowImage());
}
void TaskbarWindowThumbnailerWin::InvalidateSnapshot() {
capture_bitmap_.reset();
// The snapshot feeded to the system could be cached. Invalidate it.
::DwmInvalidateIconicBitmaps(hwnd_);
}
bool TaskbarWindowThumbnailerWin::FilterMessage(HWND hwnd,
UINT message,
WPARAM w_param,
......@@ -91,7 +101,7 @@ bool TaskbarWindowThumbnailerWin::FilterMessage(HWND hwnd,
bool TaskbarWindowThumbnailerWin::OnDwmSendIconicThumbnail(
int width, int height, LRESULT* l_result) {
DCHECK(capture_bitmap_.get());
CaptureSnapshot();
SkBitmap* thumbnail_bitmap = capture_bitmap_.get();
......@@ -119,26 +129,32 @@ bool TaskbarWindowThumbnailerWin::OnDwmSendIconicThumbnail(
bool TaskbarWindowThumbnailerWin::OnDwmSendIconicLivePreviewBitmap(
LRESULT* l_result) {
scoped_ptr<SkBitmap> live_bitmap(CaptureWindowImage());
HBITMAP native_bitmap = GetNativeBitmapFromSkBitmap(*live_bitmap);
CaptureSnapshot();
HBITMAP native_bitmap = GetNativeBitmapFromSkBitmap(*capture_bitmap_);
::DwmSetIconicLivePreviewBitmap(hwnd_, native_bitmap, NULL, 0);
::DeleteObject(native_bitmap);
*l_result = 0;
return true;
}
SkBitmap* TaskbarWindowThumbnailerWin::CaptureWindowImage() const {
std::vector<HWND> snapshot_hwnds;
if (delegate_)
snapshot_hwnds = delegate_->GetSnapshotWindowHandles();
if (snapshot_hwnds.empty())
snapshot_hwnds.push_back(hwnd_);
int enclosing_x = 0;
int enclosing_y = 0;
int enclosing_right = 0;
int enclosing_bottom = 0;
for (std::vector<HWND>::const_iterator iter = snapshot_hwnds_.begin();
iter != snapshot_hwnds_.end(); ++iter) {
for (std::vector<HWND>::const_iterator iter = snapshot_hwnds.begin();
iter != snapshot_hwnds.end(); ++iter) {
RECT bounds;
if (!::GetWindowRect(*iter, &bounds))
continue;
if (iter == snapshot_hwnds_.begin()) {
if (iter == snapshot_hwnds.begin()) {
enclosing_x = bounds.left;
enclosing_y = bounds.top;
enclosing_right = bounds.right;
......@@ -164,8 +180,8 @@ SkBitmap* TaskbarWindowThumbnailerWin::CaptureWindowImage() const {
{
skia::ScopedPlatformPaint scoped_platform_paint(canvas.sk_canvas());
HDC target_dc = scoped_platform_paint.GetPlatformSurface();
for (std::vector<HWND>::const_iterator iter = snapshot_hwnds_.begin();
iter != snapshot_hwnds_.end(); ++iter) {
for (std::vector<HWND>::const_iterator iter = snapshot_hwnds.begin();
iter != snapshot_hwnds.end(); ++iter) {
HWND current_hwnd = *iter;
RECT current_bounds;
if (!::GetWindowRect(current_hwnd, &current_bounds))
......
......@@ -11,19 +11,37 @@
class SkBitmap;
class TaskbarWindowThumbnailerDelegateWin {
public:
// Returns the list of handles for all windows that are used to construct the
// thumbnail. If empty list is returned, the snapshot of current window
// is used.
virtual std::vector<HWND> GetSnapshotWindowHandles() const = 0;
};
// Provides the custom thumbnail and live preview for the window that appears
// in the taskbar (Windows 7 and later).
class TaskbarWindowThumbnailerWin : public ui::HWNDMessageFilter {
public:
explicit TaskbarWindowThumbnailerWin(HWND hwnd);
TaskbarWindowThumbnailerWin(HWND hwnd,
TaskbarWindowThumbnailerDelegateWin* delegate);
virtual ~TaskbarWindowThumbnailerWin();
// Use the snapshots from all the windows in |snapshot_hwnds| to construct
// the thumbnail. If |snapshot_hwnds| is empty, use the snapshot of current
// window.
void Start(const std::vector<HWND>& snapshot_hwnds);
// Starts using the custom snapshot for live preview. The snapshot is only
// captured once when the system requests it, so the updates of the panels'
// content will not be automatically reflected in the thumbnail.
void Start();
// Stops providing the custom snapshot for live preview.
void Stop();
// Captures the snapshot now instead of when the system requests it.
void CaptureSnapshot();
// Invalidates the snapshot such that a fresh copy can be obtained next time
// when the system requests it.
void InvalidateSnapshot();
private:
// Overridden from ui::HWNDMessageFilter:
virtual bool FilterMessage(HWND hwnd,
......@@ -33,8 +51,7 @@ class TaskbarWindowThumbnailerWin : public ui::HWNDMessageFilter {
LRESULT* l_result) OVERRIDE;
// Message handlers.
bool OnDwmSendIconicThumbnail(
int width, int height, LRESULT* l_result);
bool OnDwmSendIconicThumbnail(int width, int height, LRESULT* l_result);
bool OnDwmSendIconicLivePreviewBitmap(LRESULT* l_result);
// Captures and returns the screenshot of the window. The caller is
......@@ -42,7 +59,7 @@ class TaskbarWindowThumbnailerWin : public ui::HWNDMessageFilter {
SkBitmap* CaptureWindowImage() const;
HWND hwnd_;
std::vector<HWND> snapshot_hwnds_;
TaskbarWindowThumbnailerDelegateWin* delegate_; // Weak, owns us.
scoped_ptr<SkBitmap> capture_bitmap_;
DISALLOW_COPY_AND_ASSIGN(TaskbarWindowThumbnailerWin);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment