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

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: Patch to land Created 7 years, 6 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
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 void PanelStackView::EndBatchUpdatePanelBounds() { 144 void PanelStackView::EndBatchUpdatePanelBounds() {
146 DCHECK(bounds_updates_started_); 145 DCHECK(bounds_updates_started_);
147 146
148 if (bounds_updates_.empty() || !animate_bounds_updates_) { 147 if (bounds_updates_.empty() || !animate_bounds_updates_) {
149 if (!bounds_updates_.empty()) { 148 if (!bounds_updates_.empty()) {
150 UpdatePanelsBounds(); 149 UpdatePanelsBounds();
151 bounds_updates_.clear(); 150 bounds_updates_.clear();
152 } 151 }
153 152
154 bounds_updates_started_ = false; 153 bounds_updates_started_ = false;
155 delegate_->PanelBoundsBatchUpdateCompleted(); 154 NotifyBoundsUpdateCompleted();
156 return; 155 return;
157 } 156 }
158 157
159 bounds_animator_.reset(new ui::LinearAnimation( 158 bounds_animator_.reset(new ui::LinearAnimation(
160 PanelManager::AdjustTimeInterval(kSetBoundsAnimationMs), 159 PanelManager::AdjustTimeInterval(kSetBoundsAnimationMs),
161 kDefaultFramerateHz, 160 kDefaultFramerateHz,
162 this)); 161 this));
163 bounds_animator_->Start(); 162 bounds_animator_->Start();
164 } 163 }
165 164
165 void PanelStackView::NotifyBoundsUpdateCompleted() {
166 delegate_->PanelBoundsBatchUpdateCompleted();
167
168 #if defined(OS_WIN)
169 // Refresh the thumbnail each time when any bounds updates are done.
170 RefreshLivePreviewThumbnail();
171 #endif
172 }
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 stack window is minimized by the system, its snapshot could not
173 // is lost. We need to set it explicitly. This has to be done before the 181 // be obtained. We need to capture the snapshot before the minimization.
174 // minimization. 182 if (thumbnailer_)
175 CaptureThumbnailForLivePreview(); 183 thumbnailer_->CaptureSnapshot();
176 #endif 184 #endif
177 185
178 window_->Minimize(); 186 window_->Minimize();
179 } 187 }
180 188
181 bool PanelStackView::IsMinimized() const { 189 bool PanelStackView::IsMinimized() const {
182 return window_ ? window_->IsMinimized() : false; 190 return window_ ? window_->IsMinimized() : false;
183 } 191 }
184 192
185 void PanelStackView::DrawSystemAttention(bool draw_attention) { 193 void PanelStackView::DrawSystemAttention(bool draw_attention) {
186 // The underlying call of FlashFrame, FlashWindowEx, seems not to work 194 // The underlying call of FlashFrame, FlashWindowEx, seems not to work
187 // correctly if it is called more than once consecutively. 195 // correctly if it is called more than once consecutively.
188 if (draw_attention == is_drawing_attention_) 196 if (draw_attention == is_drawing_attention_)
189 return; 197 return;
190 is_drawing_attention_ = draw_attention; 198 is_drawing_attention_ = draw_attention;
191 199
192 #if defined(OS_WIN) 200 #if defined(OS_WIN)
201 // Refresh the thumbnail when a panel could change something for the
202 // attention.
203 RefreshLivePreviewThumbnail();
204
193 if (draw_attention) { 205 if (draw_attention) {
194 // The default implementation of Widget::FlashFrame only flashes 5 times. 206 // The default implementation of Widget::FlashFrame only flashes 5 times.
195 // We need more than that. 207 // We need more than that.
196 FLASHWINFO fwi; 208 FLASHWINFO fwi;
197 fwi.cbSize = sizeof(fwi); 209 fwi.cbSize = sizeof(fwi);
198 fwi.hwnd = views::HWNDForWidget(window_); 210 fwi.hwnd = views::HWNDForWidget(window_);
199 fwi.dwFlags = FLASHW_ALL; 211 fwi.dwFlags = FLASHW_ALL;
200 fwi.uCount = panel::kNumberOfTimesToFlashPanelForAttention; 212 fwi.uCount = panel::kNumberOfTimesToFlashPanelForAttention;
201 fwi.dwTimeout = 0; 213 fwi.dwTimeout = 0;
202 ::FlashWindowEx(&fwi); 214 ::FlashWindowEx(&fwi);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 // window is really being closed. 275 // window is really being closed.
264 if (is_closing_) 276 if (is_closing_)
265 delete this; 277 delete this;
266 } 278 }
267 279
268 void PanelStackView::OnWidgetDestroying(views::Widget* widget) { 280 void PanelStackView::OnWidgetDestroying(views::Widget* widget) {
269 if (widget == window_) 281 if (widget == window_)
270 window_ = NULL; 282 window_ = NULL;
271 } 283 }
272 284
273 void PanelStackView::OnWidgetActivationChanged(views::Widget* widget,
274 bool active) {
275 #if defined(OS_WIN)
276 if (active && thumbnailer_)
277 thumbnailer_->Stop();
278 #endif
279 }
280
281 void PanelStackView::OnNativeFocusChange(gfx::NativeView focused_before, 285 void PanelStackView::OnNativeFocusChange(gfx::NativeView focused_before,
282 gfx::NativeView focused_now) { 286 gfx::NativeView focused_now) {
283 // When the user selects the stacked panels via ALT-TAB or WIN-TAB, the 287 // 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 288 // 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 289 // WM_SETFOCUS message. To deal with this, we listen to the focus change event
286 // and activate the most recently active panel. 290 // and activate the most recently active panel.
287 // Note that OnNativeFocusChange might be called when window_ has not be 291 // Note that OnNativeFocusChange might be called when window_ has not be
288 // created yet. 292 // created yet.
289 #if defined(OS_WIN) 293 #if defined(OS_WIN)
290 if (!panels_.empty() && window_ && focused_now == window_->GetNativeView()) { 294 if (!panels_.empty() && window_ && focused_now == window_->GetNativeView()) {
291 Panel* panel_to_focus = 295 Panel* panel_to_focus =
292 panels_.front()->stack()->most_recently_active_panel(); 296 panels_.front()->stack()->most_recently_active_panel();
293 if (panel_to_focus) 297 if (panel_to_focus)
294 panel_to_focus->Activate(); 298 panel_to_focus->Activate();
295 } 299 }
296 #endif 300 #endif
297 } 301 }
298 302
299 void PanelStackView::AnimationEnded(const ui::Animation* animation) { 303 void PanelStackView::AnimationEnded(const ui::Animation* animation) {
300 bounds_updates_started_ = false; 304 bounds_updates_started_ = false;
301 305
302 PanelManager* panel_manager = PanelManager::GetInstance(); 306 PanelManager* panel_manager = PanelManager::GetInstance();
303 for (BoundsUpdates::const_iterator iter = bounds_updates_.begin(); 307 for (BoundsUpdates::const_iterator iter = bounds_updates_.begin();
304 iter != bounds_updates_.end(); ++iter) { 308 iter != bounds_updates_.end(); ++iter) {
305 panel_manager->OnPanelAnimationEnded(iter->first); 309 panel_manager->OnPanelAnimationEnded(iter->first);
306 } 310 }
307 bounds_updates_.clear(); 311 bounds_updates_.clear();
308 312
309 delegate_->PanelBoundsBatchUpdateCompleted(); 313 NotifyBoundsUpdateCompleted();
310 } 314 }
311 315
312 void PanelStackView::AnimationProgressed(const ui::Animation* animation) { 316 void PanelStackView::AnimationProgressed(const ui::Animation* animation) {
313 UpdatePanelsBounds(); 317 UpdatePanelsBounds();
314 } 318 }
315 319
316 void PanelStackView::UpdatePanelsBounds() { 320 void PanelStackView::UpdatePanelsBounds() {
317 #if defined(OS_WIN) 321 #if defined(OS_WIN)
318 // Add an extra count for the background stack window. 322 // Add an extra count for the background stack window.
319 HDWP defer_update = ::BeginDeferWindowPos(bounds_updates_.size() + 1); 323 HDWP defer_update = ::BeginDeferWindowPos(bounds_updates_.size() + 1);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 for (Panels::const_iterator iter = panels_.begin(); 375 for (Panels::const_iterator iter = panels_.begin();
372 iter != panels_.end(); ++iter) { 376 iter != panels_.end(); ++iter) {
373 Panel* panel = *iter; 377 Panel* panel = *iter;
374 enclosing_bounds = UnionRects(enclosing_bounds, panel->GetBounds()); 378 enclosing_bounds = UnionRects(enclosing_bounds, panel->GetBounds());
375 } 379 }
376 return enclosing_bounds; 380 return enclosing_bounds;
377 } 381 }
378 382
379 void PanelStackView::UpdateStackWindowBounds() { 383 void PanelStackView::UpdateStackWindowBounds() {
380 window_->SetBounds(GetStackWindowBounds()); 384 window_->SetBounds(GetStackWindowBounds());
385
386 #if defined(OS_WIN)
387 // Refresh the thumbnail each time whne the stack window is changed, due to
388 // adding or removing a panel.
389 RefreshLivePreviewThumbnail();
390 #endif
381 } 391 }
382 392
383 // static 393 // static
384 void PanelStackView::MakeStackWindowOwnPanelWindow( 394 void PanelStackView::MakeStackWindowOwnPanelWindow(
385 Panel* panel, PanelStackView* stack_window) { 395 Panel* panel, PanelStackView* stack_window) {
386 #if defined(OS_WIN) 396 #if defined(OS_WIN)
387 // The panel widget window might already be gone when a panel is closed. 397 // The panel widget window might already be gone when a panel is closed.
388 views::Widget* panel_window = 398 views::Widget* panel_window =
389 static_cast<PanelView*>(panel->native_panel())->window(); 399 static_cast<PanelView*>(panel->native_panel())->window();
390 if (!panel_window) 400 if (!panel_window)
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 window->AddObserver(this); 443 window->AddObserver(this);
434 window->ShowInactive(); 444 window->ShowInactive();
435 445
436 #if defined(OS_WIN) 446 #if defined(OS_WIN)
437 DCHECK(!panels_.empty()); 447 DCHECK(!panels_.empty());
438 Panel* panel = panels_.front(); 448 Panel* panel = panels_.front();
439 ui::win::SetAppIdForWindow( 449 ui::win::SetAppIdForWindow(
440 ShellIntegration::GetAppModelIdForProfile(UTF8ToWide(panel->app_name()), 450 ShellIntegration::GetAppModelIdForProfile(UTF8ToWide(panel->app_name()),
441 panel->profile()->GetPath()), 451 panel->profile()->GetPath()),
442 views::HWNDForWidget(window)); 452 views::HWNDForWidget(window));
453
454 if (base::win::GetVersion() >= base::win::VERSION_WIN7) {
455 HWND native_window = views::HWNDForWidget(window);
456 thumbnailer_.reset(new TaskbarWindowThumbnailerWin(native_window, this));
457 thumbnailer_->Start();
458 }
443 #endif 459 #endif
444 460
445 return window; 461 return window;
446 } 462 }
447 463
448 void PanelStackView::EnsureWindowCreated() { 464 void PanelStackView::EnsureWindowCreated() {
449 if (window_) 465 if (window_)
450 return; 466 return;
451 467
452 // Empty size is not allowed so a temporary small size is passed. SetBounds 468 // Empty size is not allowed so a temporary small size is passed. SetBounds
453 // will be called later to update the bounds. 469 // will be called later to update the bounds.
454 window_ = CreateWindowWithBounds(gfx::Rect(0, 0, 1, 1)); 470 window_ = CreateWindowWithBounds(gfx::Rect(0, 0, 1, 1));
455 } 471 }
456 472
457 #if defined(OS_WIN) 473 #if defined(OS_WIN)
458 void PanelStackView::CaptureThumbnailForLivePreview() { 474 std::vector<HWND> PanelStackView::GetSnapshotWindowHandles() const {
459 // Live preview is only available since Windows 7.
460 if (base::win::GetVersion() < base::win::VERSION_WIN7)
461 return;
462
463 HWND native_window = views::HWNDForWidget(window_);
464
465 if (!thumbnailer_.get()) {
466 DCHECK(native_window);
467 thumbnailer_.reset(new TaskbarWindowThumbnailerWin(native_window));
468 ui::HWNDSubclass::AddFilterToTarget(native_window, thumbnailer_.get());
469 }
470
471 std::vector<HWND> native_panel_windows; 475 std::vector<HWND> native_panel_windows;
472 for (Panels::const_iterator iter = panels_.begin(); 476 for (Panels::const_iterator iter = panels_.begin();
473 iter != panels_.end(); ++iter) { 477 iter != panels_.end(); ++iter) {
474 Panel* panel = *iter; 478 Panel* panel = *iter;
475 native_panel_windows.push_back( 479 native_panel_windows.push_back(
476 views::HWNDForWidget( 480 views::HWNDForWidget(
477 static_cast<PanelView*>(panel->native_panel())->window())); 481 static_cast<PanelView*>(panel->native_panel())->window()));
478 } 482 }
479 thumbnailer_->Start(native_panel_windows); 483 return native_panel_windows;
484 }
485
486 void PanelStackView::RefreshLivePreviewThumbnail() {
487 if (!thumbnailer_.get())
488 return;
489 thumbnailer_->InvalidateSnapshot();
480 } 490 }
481 491
482 void PanelStackView::DeferUpdateNativeWindowBounds(HDWP defer_window_pos_info, 492 void PanelStackView::DeferUpdateNativeWindowBounds(HDWP defer_window_pos_info,
483 views::Widget* window, 493 views::Widget* window,
484 const gfx::Rect& bounds) { 494 const gfx::Rect& bounds) {
485 ::DeferWindowPos(defer_window_pos_info, 495 ::DeferWindowPos(defer_window_pos_info,
486 views::HWNDForWidget(window), 496 views::HWNDForWidget(window),
487 NULL, 497 NULL,
488 bounds.x(), 498 bounds.x(),
489 bounds.y(), 499 bounds.y(),
490 bounds.width(), 500 bounds.width(),
491 bounds.height(), 501 bounds.height(),
492 SWP_NOACTIVATE | SWP_NOZORDER); 502 SWP_NOACTIVATE | SWP_NOZORDER);
493 } 503 }
494 #endif 504 #endif
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/panels/panel_stack_view.h ('k') | chrome/browser/ui/views/panels/panel_view.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698