Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(988)

Side by Side Diff: chrome/browser/ui/views/panels/panel_stack_view.cc

Issue 16035007: Provide the custom thumbnail for live preview of stacked panels (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/views/panels/panel_stack_view.h" 5 #include "chrome/browser/ui/views/panels/panel_stack_view.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/utf_string_conversions.h" 8 #include "base/utf_string_conversions.h"
9 #include "chrome/browser/profiles/profile.h" 9 #include "chrome/browser/profiles/profile.h"
10 #include "chrome/browser/ui/panels/panel.h" 10 #include "chrome/browser/ui/panels/panel.h"
11 #include "chrome/browser/ui/panels/panel_manager.h" 11 #include "chrome/browser/ui/panels/panel_manager.h"
12 #include "chrome/browser/ui/panels/stacked_panel_collection.h" 12 #include "chrome/browser/ui/panels/stacked_panel_collection.h"
13 #include "chrome/browser/ui/views/panels/panel_view.h" 13 #include "chrome/browser/ui/views/panels/panel_view.h"
14 #include "ui/base/animation/linear_animation.h" 14 #include "ui/base/animation/linear_animation.h"
15 #include "ui/gfx/image/image_skia.h" 15 #include "ui/gfx/image/image_skia.h"
16 #include "ui/gfx/rect.h" 16 #include "ui/gfx/rect.h"
17 #include "ui/views/widget/widget.h" 17 #include "ui/views/widget/widget.h"
18 18
19 #if defined(OS_WIN) 19 #if defined(OS_WIN)
20 #include "base/win/windows_version.h" 20 #include "base/win/windows_version.h"
21 #include "chrome/browser/shell_integration.h" 21 #include "chrome/browser/shell_integration.h"
22 #include "chrome/browser/ui/views/panels/taskbar_window_thumbnailer_win.h"
23 #include "ui/base/win/shell.h" 22 #include "ui/base/win/shell.h"
24 #include "ui/views/win/hwnd_util.h" 23 #include "ui/views/win/hwnd_util.h"
25 #endif 24 #endif
26 25
27 namespace { 26 namespace {
28 // These values are experimental and subjective. 27 // These values are experimental and subjective.
29 const int kDefaultFramerateHz = 50; 28 const int kDefaultFramerateHz = 50;
30 const int kSetBoundsAnimationMs = 180; 29 const int kSetBoundsAnimationMs = 180;
31 } 30 }
32 31
33 // static 32 // static
34 NativePanelStackWindow* NativePanelStackWindow::Create( 33 NativePanelStackWindow* NativePanelStackWindow::Create(
35 NativePanelStackWindowDelegate* delegate) { 34 NativePanelStackWindowDelegate* delegate) {
36 #if defined(OS_WIN) 35 #if defined(OS_WIN)
37 return new PanelStackView(delegate); 36 return new PanelStackView(delegate);
38 #else 37 #else
39 NOTIMPLEMENTED(); 38 NOTIMPLEMENTED();
40 return NULL; 39 return NULL;
41 #endif 40 #endif
42 } 41 }
43 42
44 PanelStackView::PanelStackView(NativePanelStackWindowDelegate* delegate) 43 PanelStackView::PanelStackView(NativePanelStackWindowDelegate* delegate)
45 : delegate_(delegate), 44 : delegate_(delegate),
46 window_(NULL), 45 window_(NULL),
47 is_closing_(false), 46 is_closing_(false),
48 is_drawing_attention_(false), 47 is_drawing_attention_(false),
48 is_minimizing_(false),
49 animate_bounds_updates_(false), 49 animate_bounds_updates_(false),
50 bounds_updates_started_(false) { 50 bounds_updates_started_(false) {
51 DCHECK(delegate); 51 DCHECK(delegate);
52 views::WidgetFocusManager::GetInstance()->AddFocusChangeListener(this); 52 views::WidgetFocusManager::GetInstance()->AddFocusChangeListener(this);
53 } 53 }
54 54
55 PanelStackView::~PanelStackView() { 55 PanelStackView::~PanelStackView() {
56 } 56 }
57 57
58 void PanelStackView::Close() { 58 void PanelStackView::Close() {
59 is_closing_ = true; 59 is_closing_ = true;
60 delegate_ = NULL; 60 delegate_ = NULL;
61 if (bounds_animator_) 61 if (bounds_animator_)
62 bounds_animator_.reset(); 62 bounds_animator_.reset();
63 if (window_) 63 if (window_)
64 window_->Close(); 64 window_->Close();
65 views::WidgetFocusManager::GetInstance()->RemoveFocusChangeListener(this); 65 views::WidgetFocusManager::GetInstance()->RemoveFocusChangeListener(this);
66 } 66 }
67 67
68 void PanelStackView::AddPanel(Panel* panel) { 68 void PanelStackView::AddPanel(Panel* panel) {
69 panels_.push_back(panel); 69 panels_.push_back(panel);
70 70
71 EnsureWindowCreated(); 71 EnsureWindowCreated();
72 MakeStackWindowOwnPanelWindow(panel, this); 72 MakeStackWindowOwnPanelWindow(panel, this);
73 UpdateStackWindowBounds(); 73 UpdateStackWindowBounds();
74 74
75 window_->UpdateWindowTitle(); 75 window_->UpdateWindowTitle();
76 window_->UpdateWindowIcon(); 76 window_->UpdateWindowIcon();
77
78 #if defined(OS_WIN)
79 StartOrStopCustomThumbnailForMinimizePanel();
80 #endif
77 } 81 }
78 82
79 void PanelStackView::RemovePanel(Panel* panel) { 83 void PanelStackView::RemovePanel(Panel* panel) {
80 panels_.remove(panel); 84 panels_.remove(panel);
81 85
82 MakeStackWindowOwnPanelWindow(panel, NULL); 86 MakeStackWindowOwnPanelWindow(panel, NULL);
83 UpdateStackWindowBounds(); 87 UpdateStackWindowBounds();
88
89 #if defined(OS_WIN)
90 StartOrStopCustomThumbnailForMinimizePanel();
91 #endif
84 } 92 }
85 93
86 void PanelStackView::MergeWith(NativePanelStackWindow* another) { 94 void PanelStackView::MergeWith(NativePanelStackWindow* another) {
87 PanelStackView* another_stack = static_cast<PanelStackView*>(another); 95 PanelStackView* another_stack = static_cast<PanelStackView*>(another);
88 96
89 for (Panels::const_iterator iter = another_stack->panels_.begin(); 97 for (Panels::const_iterator iter = another_stack->panels_.begin();
90 iter != another_stack->panels_.end(); ++iter) { 98 iter != another_stack->panels_.end(); ++iter) {
91 Panel* panel = *iter; 99 Panel* panel = *iter;
92 panels_.push_back(panel); 100 panels_.push_back(panel);
93 MakeStackWindowOwnPanelWindow(panel, this); 101 MakeStackWindowOwnPanelWindow(panel, this);
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 173
166 bool PanelStackView::IsAnimatingPanelBounds() const { 174 bool PanelStackView::IsAnimatingPanelBounds() const {
167 return bounds_updates_started_ && animate_bounds_updates_; 175 return bounds_updates_started_ && animate_bounds_updates_;
168 } 176 }
169 177
170 void PanelStackView::Minimize() { 178 void PanelStackView::Minimize() {
171 #if defined(OS_WIN) 179 #if defined(OS_WIN)
172 // When the owner stack window is minimized by the system, its live preview 180 // When the owner stack window is minimized by the system, its live preview
173 // is lost. We need to set it explicitly. This has to be done before the 181 // is lost. We need to set it explicitly. This has to be done before the
174 // minimization. 182 // minimization.
175 CaptureThumbnailForLivePreview(); 183 CaptureThumbnailForLivePreview(true);
176 #endif 184 #endif
177 185
186 // On Windows, the system will activate the window before it is minimized.
187 // Set this flag such that the thumbnailer will not be stopped in
188 // OnWidgetActivationChanged.
189 is_minimizing_ = true;
178 window_->Minimize(); 190 window_->Minimize();
191 is_minimizing_ = false;
179 } 192 }
180 193
181 bool PanelStackView::IsMinimized() const { 194 bool PanelStackView::IsMinimized() const {
182 return window_ ? window_->IsMinimized() : false; 195 return window_ ? window_->IsMinimized() : false;
183 } 196 }
184 197
185 void PanelStackView::DrawSystemAttention(bool draw_attention) { 198 void PanelStackView::DrawSystemAttention(bool draw_attention) {
186 // The underlying call of FlashFrame, FlashWindowEx, seems not to work 199 // The underlying call of FlashFrame, FlashWindowEx, seems not to work
187 // correctly if it is called more than once consecutively. 200 // correctly if it is called more than once consecutively.
188 if (draw_attention == is_drawing_attention_) 201 if (draw_attention == is_drawing_attention_)
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 } 279 }
267 280
268 void PanelStackView::OnWidgetDestroying(views::Widget* widget) { 281 void PanelStackView::OnWidgetDestroying(views::Widget* widget) {
269 if (widget == window_) 282 if (widget == window_)
270 window_ = NULL; 283 window_ = NULL;
271 } 284 }
272 285
273 void PanelStackView::OnWidgetActivationChanged(views::Widget* widget, 286 void PanelStackView::OnWidgetActivationChanged(views::Widget* widget,
274 bool active) { 287 bool active) {
275 #if defined(OS_WIN) 288 #if defined(OS_WIN)
276 if (active && thumbnailer_) 289 if (active && !is_minimizing_ && thumbnailer_)
277 thumbnailer_->Stop(); 290 thumbnailer_->Stop();
278 #endif 291 #endif
279 } 292 }
280 293
281 void PanelStackView::OnNativeFocusChange(gfx::NativeView focused_before, 294 void PanelStackView::OnNativeFocusChange(gfx::NativeView focused_before,
282 gfx::NativeView focused_now) { 295 gfx::NativeView focused_now) {
283 // When the user selects the stacked panels via ALT-TAB or WIN-TAB, the 296 // When the user selects the stacked panels via ALT-TAB or WIN-TAB, the
284 // background stack window, instead of the foreground panel window, receives 297 // background stack window, instead of the foreground panel window, receives
285 // WM_SETFOCUS message. To deal with this, we listen to the focus change event 298 // WM_SETFOCUS message. To deal with this, we listen to the focus change event
286 // and activate the most recently active panel. 299 // and activate the most recently active panel.
287 // Note that OnNativeFocusChange might be called when window_ has not be 300 // Note that OnNativeFocusChange might be called when window_ has not be
288 // created yet. 301 // created yet.
289 #if defined(OS_WIN) 302 #if defined(OS_WIN)
290 if (!panels_.empty() && window_ && focused_now == window_->GetNativeView()) { 303 if (!panels_.empty() && window_ && focused_now == window_->GetNativeView()) {
291 Panel* panel_to_focus = 304 Panel* panel_to_focus =
292 panels_.front()->stack()->most_recently_active_panel(); 305 panels_.front()->stack()->most_recently_active_panel();
293 if (panel_to_focus) 306 if (panel_to_focus)
294 panel_to_focus->Activate(); 307 panel_to_focus->Activate();
295 } 308 }
296 #endif 309 #endif
297 } 310 }
298 311
312 #if defined(OS_WIN)
313 std::vector<HWND> PanelStackView::GetSnapshotWindowHandles() const {
314 std::vector<HWND> native_panel_windows;
315 for (Panels::const_iterator iter = panels_.begin();
316 iter != panels_.end(); ++iter) {
317 Panel* panel = *iter;
318 native_panel_windows.push_back(
319 views::HWNDForWidget(
320 static_cast<PanelView*>(panel->native_panel())->window()));
321 }
322 return native_panel_windows;
323 }
324 #endif
325
299 void PanelStackView::AnimationEnded(const ui::Animation* animation) { 326 void PanelStackView::AnimationEnded(const ui::Animation* animation) {
300 bounds_updates_started_ = false; 327 bounds_updates_started_ = false;
301 328
302 PanelManager* panel_manager = PanelManager::GetInstance(); 329 PanelManager* panel_manager = PanelManager::GetInstance();
303 for (BoundsUpdates::const_iterator iter = bounds_updates_.begin(); 330 for (BoundsUpdates::const_iterator iter = bounds_updates_.begin();
304 iter != bounds_updates_.end(); ++iter) { 331 iter != bounds_updates_.end(); ++iter) {
305 panel_manager->OnPanelAnimationEnded(iter->first); 332 panel_manager->OnPanelAnimationEnded(iter->first);
306 } 333 }
307 bounds_updates_.clear(); 334 bounds_updates_.clear();
308 335
309 delegate_->PanelBoundsBatchUpdateCompleted(); 336 delegate_->PanelBoundsBatchUpdateCompleted();
337
338 #if defined(OS_WIN)
339 StartOrStopCustomThumbnailForMinimizePanel();
340 #endif
310 } 341 }
311 342
312 void PanelStackView::AnimationProgressed(const ui::Animation* animation) { 343 void PanelStackView::AnimationProgressed(const ui::Animation* animation) {
313 UpdatePanelsBounds(); 344 UpdatePanelsBounds();
314 } 345 }
315 346
316 void PanelStackView::UpdatePanelsBounds() { 347 void PanelStackView::UpdatePanelsBounds() {
317 #if defined(OS_WIN) 348 #if defined(OS_WIN)
318 // Add an extra count for the background stack window. 349 // Add an extra count for the background stack window.
319 HDWP defer_update = ::BeginDeferWindowPos(bounds_updates_.size() + 1); 350 HDWP defer_update = ::BeginDeferWindowPos(bounds_updates_.size() + 1);
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
448 void PanelStackView::EnsureWindowCreated() { 479 void PanelStackView::EnsureWindowCreated() {
449 if (window_) 480 if (window_)
450 return; 481 return;
451 482
452 // Empty size is not allowed so a temporary small size is passed. SetBounds 483 // Empty size is not allowed so a temporary small size is passed. SetBounds
453 // will be called later to update the bounds. 484 // will be called later to update the bounds.
454 window_ = CreateWindowWithBounds(gfx::Rect(0, 0, 1, 1)); 485 window_ = CreateWindowWithBounds(gfx::Rect(0, 0, 1, 1));
455 } 486 }
456 487
457 #if defined(OS_WIN) 488 #if defined(OS_WIN)
458 void PanelStackView::CaptureThumbnailForLivePreview() { 489 void PanelStackView::StartOrStopCustomThumbnailForMinimizePanel() {
Dmitry Titov 2013/05/29 01:14:48 Is it possible to have a StartThumbnailer() and St
jianli 2013/05/29 18:31:52 All 3 places need the same code because otherwise
490 bool has_minimized_panel = false;
491 for (Panels::const_iterator iter = panels_.begin();
492 iter != panels_.end(); ++iter) {
493 if ((*iter)->IsMinimized()) {
494 has_minimized_panel = true;
495 break;
496 }
497 }
498
499 // If custom thumbnail is still needed, stopping the thumbnailer and starting
500 // it again will make the system use the fresh snapshot.
501 if (thumbnailer_)
502 thumbnailer_->Stop();
503
504 // Start the thumbnailer to capture the snapshot only when the system requests
505 // it. When a panel has just been changed, its rendering might not be
506 // completed at this point. So we want to delay the snapshot until the system
507 // asks for it.
508 if (has_minimized_panel)
509 CaptureThumbnailForLivePreview(false);
510 }
511
512 void PanelStackView::CaptureThumbnailForLivePreview(bool should_capture_now) {
459 // Live preview is only available since Windows 7. 513 // Live preview is only available since Windows 7.
460 if (base::win::GetVersion() < base::win::VERSION_WIN7) 514 if (base::win::GetVersion() < base::win::VERSION_WIN7)
461 return; 515 return;
462 516
463 HWND native_window = views::HWNDForWidget(window_); 517 HWND native_window = views::HWNDForWidget(window_);
464 518
465 if (!thumbnailer_.get()) { 519 if (!thumbnailer_.get()) {
466 DCHECK(native_window); 520 DCHECK(native_window);
467 thumbnailer_.reset(new TaskbarWindowThumbnailerWin(native_window)); 521 thumbnailer_.reset(new TaskbarWindowThumbnailerWin(native_window, this));
468 ui::HWNDSubclass::AddFilterToTarget(native_window, thumbnailer_.get()); 522 ui::HWNDSubclass::AddFilterToTarget(native_window, thumbnailer_.get());
469 } 523 }
470 524
471 std::vector<HWND> native_panel_windows; 525 thumbnailer_->Start(should_capture_now);
472 for (Panels::const_iterator iter = panels_.begin();
473 iter != panels_.end(); ++iter) {
474 Panel* panel = *iter;
475 native_panel_windows.push_back(
476 views::HWNDForWidget(
477 static_cast<PanelView*>(panel->native_panel())->window()));
478 }
479 thumbnailer_->Start(native_panel_windows);
480 } 526 }
481 527
482 void PanelStackView::DeferUpdateNativeWindowBounds(HDWP defer_window_pos_info, 528 void PanelStackView::DeferUpdateNativeWindowBounds(HDWP defer_window_pos_info,
483 views::Widget* window, 529 views::Widget* window,
484 const gfx::Rect& bounds) { 530 const gfx::Rect& bounds) {
485 ::DeferWindowPos(defer_window_pos_info, 531 ::DeferWindowPos(defer_window_pos_info,
486 views::HWNDForWidget(window), 532 views::HWNDForWidget(window),
487 NULL, 533 NULL,
488 bounds.x(), 534 bounds.x(),
489 bounds.y(), 535 bounds.y(),
490 bounds.width(), 536 bounds.width(),
491 bounds.height(), 537 bounds.height(),
492 SWP_NOACTIVATE | SWP_NOZORDER); 538 SWP_NOACTIVATE | SWP_NOZORDER);
493 } 539 }
494 #endif 540 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698