Only fsync leveldb's directory when the manifest is being updated.
[chromium-blink-merge.git] / ash / wm / frame_painter_unittest.cc
blob3c9d55ce158182525f68a14b4fb6366cadb615e0
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ash/wm/frame_painter.h"
7 #include "ash/ash_constants.h"
8 #include "ash/shell.h"
9 #include "ash/shell_window_ids.h"
10 #include "ash/test/ash_test_base.h"
11 #include "ash/wm/property_util.h"
12 #include "ash/wm/window_properties.h"
13 #include "ash/wm/window_util.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "grit/ash_resources.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "ui/aura/client/aura_constants.h"
18 #include "ui/aura/root_window.h"
19 #include "ui/aura/window_observer.h"
20 #include "ui/base/hit_test.h"
21 #include "ui/base/theme_provider.h"
22 #include "ui/gfx/screen.h"
23 #include "ui/views/controls/button/button.h"
24 #include "ui/views/controls/button/image_button.h"
25 #include "ui/views/widget/widget.h"
26 #include "ui/views/widget/widget_delegate.h"
27 #include "ui/views/window/non_client_view.h"
29 using ui::ThemeProvider;
30 using views::Button;
31 using views::ImageButton;
32 using views::NonClientFrameView;
33 using views::ToggleImageButton;
34 using views::Widget;
36 namespace {
38 bool ImagesMatch(ImageButton* button,
39 int normal_image_id,
40 int hovered_image_id,
41 int pressed_image_id) {
42 ThemeProvider* theme = button->GetWidget()->GetThemeProvider();
43 gfx::ImageSkia* normal = theme->GetImageSkiaNamed(normal_image_id);
44 gfx::ImageSkia* hovered = theme->GetImageSkiaNamed(hovered_image_id);
45 gfx::ImageSkia* pressed = theme->GetImageSkiaNamed(pressed_image_id);
46 return button->GetImage(Button::STATE_NORMAL).BackedBySameObjectAs(*normal) &&
47 button->GetImage(Button::STATE_HOVERED).BackedBySameObjectAs(*hovered) &&
48 button->GetImage(Button::STATE_PRESSED).BackedBySameObjectAs(*pressed);
51 class ResizableWidgetDelegate : public views::WidgetDelegate {
52 public:
53 ResizableWidgetDelegate(views::Widget* widget) {
54 widget_ = widget;
57 virtual bool CanResize() const OVERRIDE { return true; }
58 // Implementations of the widget class.
59 virtual views::Widget* GetWidget() OVERRIDE { return widget_; }
60 virtual const views::Widget* GetWidget() const OVERRIDE { return widget_; }
61 virtual void DeleteDelegate() OVERRIDE {
62 delete this;
65 private:
66 views::Widget* widget_;
68 DISALLOW_COPY_AND_ASSIGN(ResizableWidgetDelegate);
71 class WindowRepaintChecker : public aura::WindowObserver {
72 public:
73 explicit WindowRepaintChecker(aura::Window* window)
74 : is_paint_scheduled_(false) {
75 window->AddObserver(this);
77 virtual ~WindowRepaintChecker() {
80 bool IsPaintScheduledAndReset() {
81 bool result = is_paint_scheduled_;
82 is_paint_scheduled_ = false;
83 return result;
86 private:
87 // aura::WindowObserver overrides:
88 virtual void OnWindowPaintScheduled(aura::Window* window,
89 const gfx::Rect& region) OVERRIDE {
90 is_paint_scheduled_ = true;
92 virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
93 window->RemoveObserver(this);
96 bool is_paint_scheduled_;
98 DISALLOW_COPY_AND_ASSIGN(WindowRepaintChecker);
101 // Modifies the values of kInactiveWindowOpacity, kActiveWindowOpacity, and
102 // kSoloWindowOpacity for the lifetime of the class. This is useful so that
103 // the constants each have different values.
104 class ScopedOpacityConstantModifier {
105 public:
106 ScopedOpacityConstantModifier()
107 : initial_active_window_opacity_(
108 ash::FramePainter::kActiveWindowOpacity),
109 initial_inactive_window_opacity_(
110 ash::FramePainter::kInactiveWindowOpacity),
111 initial_solo_window_opacity_(ash::FramePainter::kSoloWindowOpacity) {
112 ash::FramePainter::kActiveWindowOpacity = 100;
113 ash::FramePainter::kInactiveWindowOpacity = 120;
114 ash::FramePainter::kSoloWindowOpacity = 140;
116 ~ScopedOpacityConstantModifier() {
117 ash::FramePainter::kActiveWindowOpacity = initial_active_window_opacity_;
118 ash::FramePainter::kInactiveWindowOpacity =
119 initial_inactive_window_opacity_;
120 ash::FramePainter::kSoloWindowOpacity = initial_solo_window_opacity_;
123 private:
124 int initial_active_window_opacity_;
125 int initial_inactive_window_opacity_;
126 int initial_solo_window_opacity_;
128 DISALLOW_COPY_AND_ASSIGN(ScopedOpacityConstantModifier);
131 } // namespace
133 namespace ash {
135 class FramePainterTest : public ash::test::AshTestBase {
136 public:
137 // Creates a test widget that owns its native widget.
138 Widget* CreateTestWidget() {
139 Widget* widget = new Widget;
140 Widget::InitParams params;
141 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
142 params.context = CurrentContext();
143 widget->Init(params);
144 return widget;
147 Widget* CreateAlwaysOnTopWidget() {
148 Widget* widget = new Widget;
149 Widget::InitParams params;
150 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
151 params.context = CurrentContext();
152 params.keep_on_top = true;
153 widget->Init(params);
154 return widget;
157 Widget* CreatePanelWidget() {
158 Widget* widget = new Widget;
159 Widget::InitParams params;
160 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
161 params.context = CurrentContext();
162 params.type = Widget::InitParams::TYPE_PANEL;
163 widget->Init(params);
164 return widget;
167 Widget* CreateResizableWidget() {
168 Widget* widget = new Widget;
169 Widget::InitParams params;
170 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
171 params.context = CurrentContext();
172 params.keep_on_top = true;
173 params.delegate = new ResizableWidgetDelegate(widget);
174 params.type = Widget::InitParams::TYPE_WINDOW;
175 widget->Init(params);
176 return widget;
180 TEST_F(FramePainterTest, CreateAndDeleteSingleWindow) {
181 // Ensure that creating/deleting a window works well and doesn't cause
182 // crashes. See crbug.com/155634
183 aura::RootWindow* root = Shell::GetActiveRootWindow();
185 scoped_ptr<Widget> widget(CreateTestWidget());
186 scoped_ptr<FramePainter> painter(new FramePainter);
187 ImageButton size(NULL);
188 ImageButton close(NULL);
189 painter->Init(
190 widget.get(), NULL, &size, &close, FramePainter::SIZE_BUTTON_MAXIMIZES);
191 widget->Show();
193 // We only have one window, so it should use a solo header.
194 EXPECT_TRUE(painter->UseSoloWindowHeader());
195 EXPECT_TRUE(root->GetProperty(internal::kSoloWindowHeaderKey));
197 // Close the window.
198 widget.reset();
199 EXPECT_FALSE(root->GetProperty(internal::kSoloWindowHeaderKey));
201 // Recreate another window again.
202 painter.reset(new FramePainter);
203 widget.reset(CreateTestWidget());
205 painter->Init(
206 widget.get(), NULL, &size, &close, FramePainter::SIZE_BUTTON_MAXIMIZES);
207 widget->Show();
208 EXPECT_TRUE(painter->UseSoloWindowHeader());
209 EXPECT_TRUE(root->GetProperty(internal::kSoloWindowHeaderKey));
212 TEST_F(FramePainterTest, LayoutHeader) {
213 scoped_ptr<Widget> widget(CreateTestWidget());
214 ImageButton size_button(NULL);
215 ImageButton close_button(NULL);
216 NonClientFrameView* frame_view = widget->non_client_view()->frame_view();
217 frame_view->AddChildView(&size_button);
218 frame_view->AddChildView(&close_button);
219 scoped_ptr<FramePainter> painter(new FramePainter);
220 painter->Init(widget.get(),
221 NULL,
222 &size_button,
223 &close_button,
224 FramePainter::SIZE_BUTTON_MAXIMIZES);
225 widget->Show();
227 // Basic layout.
228 painter->LayoutHeader(frame_view, false);
229 EXPECT_TRUE(ImagesMatch(&close_button,
230 IDR_AURA_WINDOW_CLOSE,
231 IDR_AURA_WINDOW_CLOSE_H,
232 IDR_AURA_WINDOW_CLOSE_P));
233 EXPECT_TRUE(ImagesMatch(&size_button,
234 IDR_AURA_WINDOW_MAXIMIZE,
235 IDR_AURA_WINDOW_MAXIMIZE_H,
236 IDR_AURA_WINDOW_MAXIMIZE_P));
238 // Shorter layout.
239 painter->LayoutHeader(frame_view, true);
240 EXPECT_TRUE(ImagesMatch(&close_button,
241 IDR_AURA_WINDOW_MAXIMIZED_CLOSE,
242 IDR_AURA_WINDOW_MAXIMIZED_CLOSE_H,
243 IDR_AURA_WINDOW_MAXIMIZED_CLOSE_P));
244 EXPECT_TRUE(ImagesMatch(&size_button,
245 IDR_AURA_WINDOW_MAXIMIZED_RESTORE,
246 IDR_AURA_WINDOW_MAXIMIZED_RESTORE_H,
247 IDR_AURA_WINDOW_MAXIMIZED_RESTORE_P));
249 // Maximized shorter layout.
250 widget->Maximize();
251 painter->LayoutHeader(frame_view, true);
252 EXPECT_TRUE(ImagesMatch(&close_button,
253 IDR_AURA_WINDOW_MAXIMIZED_CLOSE2,
254 IDR_AURA_WINDOW_MAXIMIZED_CLOSE2_H,
255 IDR_AURA_WINDOW_MAXIMIZED_CLOSE2_P));
256 EXPECT_TRUE(ImagesMatch(&size_button,
257 IDR_AURA_WINDOW_MAXIMIZED_RESTORE2,
258 IDR_AURA_WINDOW_MAXIMIZED_RESTORE2_H,
259 IDR_AURA_WINDOW_MAXIMIZED_RESTORE2_P));
261 // Fullscreen can show the buttons during an immersive reveal, so it should
262 // use the same images as maximized.
263 widget->SetFullscreen(true);
264 painter->LayoutHeader(frame_view, true);
265 EXPECT_TRUE(ImagesMatch(&close_button,
266 IDR_AURA_WINDOW_MAXIMIZED_CLOSE2,
267 IDR_AURA_WINDOW_MAXIMIZED_CLOSE2_H,
268 IDR_AURA_WINDOW_MAXIMIZED_CLOSE2_P));
269 EXPECT_TRUE(ImagesMatch(&size_button,
270 IDR_AURA_WINDOW_MAXIMIZED_RESTORE2,
271 IDR_AURA_WINDOW_MAXIMIZED_RESTORE2_H,
272 IDR_AURA_WINDOW_MAXIMIZED_RESTORE2_P));
275 TEST_F(FramePainterTest, UseSoloWindowHeader) {
276 // Create a widget and a painter for it.
277 scoped_ptr<Widget> w1(CreateTestWidget());
278 FramePainter p1;
279 ImageButton size1(NULL);
280 ImageButton close1(NULL);
281 p1.Init(w1.get(), NULL, &size1, &close1, FramePainter::SIZE_BUTTON_MAXIMIZES);
282 w1->Show();
284 // We only have one window, so it should use a solo header.
285 EXPECT_TRUE(p1.UseSoloWindowHeader());
287 // Create a second widget and painter.
288 scoped_ptr<Widget> w2(CreateTestWidget());
289 FramePainter p2;
290 ImageButton size2(NULL);
291 ImageButton close2(NULL);
292 p2.Init(w2.get(), NULL, &size2, &close2, FramePainter::SIZE_BUTTON_MAXIMIZES);
293 w2->Show();
295 // Now there are two windows, so we should not use solo headers. This only
296 // needs to test |p1| because "solo window headers" are a per-root-window
297 // property.
298 EXPECT_FALSE(p1.UseSoloWindowHeader());
300 // Hide one window. Solo should be enabled.
301 w2->Hide();
302 EXPECT_TRUE(p1.UseSoloWindowHeader());
304 // Show that window. Solo should be disabled.
305 w2->Show();
306 EXPECT_FALSE(p1.UseSoloWindowHeader());
308 // Maximize the window, then activate the first window. The second window
309 // is in its own workspace, so solo should be active for the first one.
310 w2->Maximize();
311 w1->Activate();
312 EXPECT_TRUE(p1.UseSoloWindowHeader());
314 // Switch to the second window and restore it. Solo should be disabled.
315 w2->Activate();
316 w2->Restore();
317 EXPECT_FALSE(p2.UseSoloWindowHeader());
319 // Minimize the second window. Solo should be enabled.
320 w2->Minimize();
321 EXPECT_TRUE(p1.UseSoloWindowHeader());
323 // Close the minimized window.
324 w2.reset();
325 EXPECT_TRUE(p1.UseSoloWindowHeader());
327 // Open an always-on-top widget (which lives in a different container).
328 scoped_ptr<Widget> w3(CreateAlwaysOnTopWidget());
329 FramePainter p3;
330 ImageButton size3(NULL);
331 ImageButton close3(NULL);
332 p3.Init(w3.get(), NULL, &size3, &close3, FramePainter::SIZE_BUTTON_MAXIMIZES);
333 w3->Show();
334 EXPECT_FALSE(p3.UseSoloWindowHeader());
336 // Close the always-on-top widget.
337 w3.reset();
338 EXPECT_TRUE(p1.UseSoloWindowHeader());
341 // An open V2 app window should cause browser windows not to use the
342 // solo window header.
343 TEST_F(FramePainterTest, UseSoloWindowHeaderWithApp) {
344 // Create a widget and a painter for it.
345 scoped_ptr<Widget> w1(CreateTestWidget());
346 FramePainter p1;
347 ImageButton size1(NULL);
348 ImageButton close1(NULL);
349 p1.Init(w1.get(), NULL, &size1, &close1, FramePainter::SIZE_BUTTON_MAXIMIZES);
350 w1->Show();
352 // We only have one window, so it should use a solo header.
353 EXPECT_TRUE(p1.UseSoloWindowHeader());
355 // Simulate a V2 app window, which is part of the active workspace but does
356 // not have a frame painter.
357 scoped_ptr<Widget> w2(CreateTestWidget());
358 w2->Show();
360 // Now there are two windows, so we should not use solo headers.
361 EXPECT_FALSE(p1.UseSoloWindowHeader());
363 // Minimize the app window. The first window should go solo again.
364 w2->Minimize();
365 EXPECT_TRUE(p1.UseSoloWindowHeader());
367 // Restoring the app window turns off solo headers.
368 w2->Restore();
369 EXPECT_FALSE(p1.UseSoloWindowHeader());
372 // Panels should not "count" for computing solo window headers, and the panel
373 // itself should always have an opaque header.
374 TEST_F(FramePainterTest, UseSoloWindowHeaderWithPanel) {
375 // Create a widget and a painter for it.
376 scoped_ptr<Widget> w1(CreateTestWidget());
377 FramePainter p1;
378 ImageButton size1(NULL);
379 ImageButton close1(NULL);
380 p1.Init(w1.get(), NULL, &size1, &close1, FramePainter::SIZE_BUTTON_MAXIMIZES);
381 w1->Show();
383 // We only have one window, so it should use a solo header.
384 EXPECT_TRUE(p1.UseSoloWindowHeader());
386 // Create a panel and a painter for it.
387 scoped_ptr<Widget> w2(CreatePanelWidget());
388 FramePainter p2;
389 ImageButton size2(NULL);
390 ImageButton close2(NULL);
391 p2.Init(w2.get(), NULL, &size2, &close2, FramePainter::SIZE_BUTTON_MAXIMIZES);
392 w2->Show();
394 // Despite two windows, the first window should still be considered "solo"
395 // because panels aren't included in the computation.
396 EXPECT_TRUE(p1.UseSoloWindowHeader());
398 // The panel itself is not considered solo.
399 EXPECT_FALSE(p2.UseSoloWindowHeader());
401 // Even after closing the first window, the panel is still not considered
402 // solo.
403 w1.reset();
404 EXPECT_FALSE(p2.UseSoloWindowHeader());
407 // Modal dialogs should not use solo headers.
408 TEST_F(FramePainterTest, UseSoloWindowHeaderModal) {
409 // Create a widget and a painter for it.
410 scoped_ptr<Widget> w1(CreateTestWidget());
411 FramePainter p1;
412 ImageButton size1(NULL);
413 ImageButton close1(NULL);
414 p1.Init(w1.get(), NULL, &size1, &close1, FramePainter::SIZE_BUTTON_MAXIMIZES);
415 w1->Show();
417 // We only have one window, so it should use a solo header.
418 EXPECT_TRUE(p1.UseSoloWindowHeader());
420 // Create a fake modal window.
421 scoped_ptr<Widget> w2(CreateTestWidget());
422 w2->GetNativeWindow()->SetProperty(aura::client::kModalKey,
423 ui::MODAL_TYPE_WINDOW);
424 FramePainter p2;
425 ImageButton size2(NULL);
426 ImageButton close2(NULL);
427 p2.Init(w2.get(), NULL, &size2, &close2, FramePainter::SIZE_BUTTON_MAXIMIZES);
428 w2->Show();
430 // Despite two windows, the first window should still be considered "solo"
431 // because modal windows aren't included in the computation.
432 EXPECT_TRUE(p1.UseSoloWindowHeader());
434 // The modal window itself is not considered solo.
435 EXPECT_FALSE(p2.UseSoloWindowHeader());
438 // Constrained windows should not use solo headers.
439 TEST_F(FramePainterTest, UseSoloWindowHeaderConstrained) {
440 // Create a widget and a painter for it.
441 scoped_ptr<Widget> w1(CreateTestWidget());
442 FramePainter p1;
443 ImageButton size1(NULL);
444 ImageButton close1(NULL);
445 p1.Init(w1.get(), NULL, &size1, &close1, FramePainter::SIZE_BUTTON_MAXIMIZES);
446 w1->Show();
448 // We only have one window, so it should use a solo header.
449 EXPECT_TRUE(p1.UseSoloWindowHeader());
451 // Create a fake constrained window.
452 scoped_ptr<Widget> w2(CreateTestWidget());
453 w2->GetNativeWindow()->SetProperty(ash::kConstrainedWindowKey, true);
454 FramePainter p2;
455 ImageButton size2(NULL);
456 ImageButton close2(NULL);
457 p2.Init(w2.get(), NULL, &size2, &close2, FramePainter::SIZE_BUTTON_MAXIMIZES);
458 w2->Show();
460 // Despite two windows, the first window should still be considered "solo"
461 // because constrained windows aren't included in the computation.
462 EXPECT_TRUE(p1.UseSoloWindowHeader());
464 // The constrained window itself is not considered solo.
465 EXPECT_FALSE(p2.UseSoloWindowHeader());
468 #if defined(OS_WIN)
469 // Multiple displays are not supported on Windows Ash. http://crbug.com/165962
470 #define MAYBE_UseSoloWindowHeaderMultiDisplay \
471 DISABLED_UseSoloWindowHeaderMultiDisplay
472 #else
473 #define MAYBE_UseSoloWindowHeaderMultiDisplay \
474 UseSoloWindowHeaderMultiDisplay
475 #endif
477 TEST_F(FramePainterTest, MAYBE_UseSoloWindowHeaderMultiDisplay) {
478 UpdateDisplay("1000x600,600x400");
480 // Create two widgets and painters for them.
481 scoped_ptr<Widget> w1(CreateTestWidget());
482 FramePainter p1;
483 ImageButton size1(NULL);
484 ImageButton close1(NULL);
485 p1.Init(w1.get(), NULL, &size1, &close1, FramePainter::SIZE_BUTTON_MAXIMIZES);
486 w1->SetBounds(gfx::Rect(0, 0, 100, 100));
487 w1->Show();
488 WindowRepaintChecker checker1(w1->GetNativeWindow());
489 scoped_ptr<Widget> w2(CreateTestWidget());
490 FramePainter p2;
491 ImageButton size2(NULL);
492 ImageButton close2(NULL);
493 p2.Init(w2.get(), NULL, &size2, &close2, FramePainter::SIZE_BUTTON_MAXIMIZES);
494 w2->SetBounds(gfx::Rect(0, 0, 100, 100));
495 w2->Show();
496 WindowRepaintChecker checker2(w2->GetNativeWindow());
498 // Now there are two windows in the same display, so we should not use solo
499 // headers.
500 EXPECT_FALSE(p1.UseSoloWindowHeader());
501 EXPECT_FALSE(p2.UseSoloWindowHeader());
502 EXPECT_TRUE(checker1.IsPaintScheduledAndReset());
504 // Moves the second window to the secondary display. Both w1/w2 should be
505 // solo.
506 w2->SetBounds(gfx::Rect(1200, 0, 100, 100));
507 EXPECT_TRUE(p1.UseSoloWindowHeader());
508 EXPECT_TRUE(p2.UseSoloWindowHeader());
509 EXPECT_TRUE(checker1.IsPaintScheduledAndReset());
510 EXPECT_TRUE(checker2.IsPaintScheduledAndReset());
512 // Open two more windows in the primary display.
513 scoped_ptr<Widget> w3(CreateTestWidget());
514 FramePainter p3;
515 ImageButton size3(NULL);
516 ImageButton close3(NULL);
517 p3.Init(w3.get(), NULL, &size3, &close3, FramePainter::SIZE_BUTTON_MAXIMIZES);
518 w3->SetBounds(gfx::Rect(0, 0, 100, 100));
519 w3->Show();
520 scoped_ptr<Widget> w4(CreateTestWidget());
521 FramePainter p4;
522 ImageButton size4(NULL);
523 ImageButton close4(NULL);
524 p4.Init(w4.get(), NULL, &size4, &close4, FramePainter::SIZE_BUTTON_MAXIMIZES);
525 w4->SetBounds(gfx::Rect(0, 0, 100, 100));
526 w4->Show();
528 // Because the primary display has two windows w1 and w3, they shouldn't be
529 // solo. w2 should be solo.
530 EXPECT_FALSE(p1.UseSoloWindowHeader());
531 EXPECT_TRUE(p2.UseSoloWindowHeader());
532 EXPECT_FALSE(p3.UseSoloWindowHeader());
533 EXPECT_FALSE(p4.UseSoloWindowHeader());
534 EXPECT_TRUE(checker1.IsPaintScheduledAndReset());
536 // Moves the w4 to the secondary display. Now the w2 shouldn't be solo
537 // anymore.
538 w4->SetBounds(gfx::Rect(1200, 0, 100, 100));
539 EXPECT_FALSE(p1.UseSoloWindowHeader());
540 EXPECT_FALSE(p2.UseSoloWindowHeader());
541 EXPECT_FALSE(p3.UseSoloWindowHeader());
542 EXPECT_FALSE(p4.UseSoloWindowHeader());
543 EXPECT_TRUE(checker2.IsPaintScheduledAndReset());
545 // Moves the w3 to the secondary display too. Now w1 should be solo again.
546 w3->SetBounds(gfx::Rect(1200, 0, 100, 100));
547 EXPECT_TRUE(p1.UseSoloWindowHeader());
548 EXPECT_FALSE(p2.UseSoloWindowHeader());
549 EXPECT_FALSE(p3.UseSoloWindowHeader());
550 EXPECT_FALSE(p4.UseSoloWindowHeader());
551 EXPECT_TRUE(checker1.IsPaintScheduledAndReset());
553 // Change the w3 state to maximize. Doesn't affect to w1.
554 wm::MaximizeWindow(w3->GetNativeWindow());
555 EXPECT_TRUE(p1.UseSoloWindowHeader());
556 EXPECT_FALSE(p2.UseSoloWindowHeader());
557 EXPECT_FALSE(p3.UseSoloWindowHeader());
558 EXPECT_FALSE(p4.UseSoloWindowHeader());
560 // Close the w3 and w4.
561 w3.reset();
562 w4.reset();
563 EXPECT_TRUE(p1.UseSoloWindowHeader());
564 EXPECT_TRUE(p2.UseSoloWindowHeader());
565 EXPECT_TRUE(checker2.IsPaintScheduledAndReset());
567 // Move w2 back to the primary display.
568 w2->SetBounds(gfx::Rect(0, 0, 100, 100));
569 EXPECT_FALSE(p1.UseSoloWindowHeader());
570 EXPECT_FALSE(p2.UseSoloWindowHeader());
571 EXPECT_TRUE(checker1.IsPaintScheduledAndReset());
572 EXPECT_TRUE(checker2.IsPaintScheduledAndReset());
574 // Close w2.
575 w2.reset();
576 EXPECT_TRUE(p1.UseSoloWindowHeader());
577 EXPECT_TRUE(checker1.IsPaintScheduledAndReset());
580 TEST_F(FramePainterTest, GetHeaderOpacity) {
581 // Create a widget and a painter for it.
582 scoped_ptr<Widget> w1(CreateTestWidget());
583 FramePainter p1;
584 ImageButton size1(NULL);
585 ImageButton close1(NULL);
586 p1.Init(w1.get(), NULL, &size1, &close1, FramePainter::SIZE_BUTTON_MAXIMIZES);
587 w1->Show();
589 // Modify the values of the opacity constants so that they each have a
590 // different value.
591 ScopedOpacityConstantModifier opacity_constant_modifier;
593 // Solo active window has solo window opacity.
594 EXPECT_EQ(FramePainter::kSoloWindowOpacity,
595 p1.GetHeaderOpacity(FramePainter::ACTIVE,
596 IDR_AURA_WINDOW_HEADER_BASE_ACTIVE,
597 0));
599 // Create a second widget and painter.
600 scoped_ptr<Widget> w2(CreateTestWidget());
601 FramePainter p2;
602 ImageButton size2(NULL);
603 ImageButton close2(NULL);
604 p2.Init(w2.get(), NULL, &size2, &close2, FramePainter::SIZE_BUTTON_MAXIMIZES);
605 w2->Show();
607 // Active window has active window opacity.
608 EXPECT_EQ(FramePainter::kActiveWindowOpacity,
609 p2.GetHeaderOpacity(FramePainter::ACTIVE,
610 IDR_AURA_WINDOW_HEADER_BASE_ACTIVE,
611 0));
613 // Inactive window has inactive window opacity.
614 EXPECT_EQ(FramePainter::kInactiveWindowOpacity,
615 p2.GetHeaderOpacity(FramePainter::INACTIVE,
616 IDR_AURA_WINDOW_HEADER_BASE_INACTIVE,
617 0));
619 // Regular maximized windows are fully opaque.
620 ash::wm::MaximizeWindow(w1->GetNativeWindow());
621 EXPECT_EQ(255,
622 p1.GetHeaderOpacity(FramePainter::ACTIVE,
623 IDR_AURA_WINDOW_HEADER_BASE_ACTIVE,
624 0));
627 // Test that the minimal header style is used in the proper situations.
628 TEST_F(FramePainterTest, MinimalHeaderStyle) {
629 // Create a widget and a painter for it.
630 scoped_ptr<Widget> w(CreateTestWidget());
631 FramePainter p;
632 ImageButton size(NULL);
633 ImageButton close(NULL);
634 p.Init(w.get(), NULL, &size, &close, FramePainter::SIZE_BUTTON_MAXIMIZES);
635 w->Show();
637 // Regular non-maximized windows should not use the minimal header style.
638 EXPECT_FALSE(p.ShouldUseMinimalHeaderStyle(FramePainter::THEMED_NO));
640 // Regular maximized windows should use the minimal header style.
641 w->Maximize();
642 EXPECT_TRUE(p.ShouldUseMinimalHeaderStyle(FramePainter::THEMED_NO));
644 // Test cases where the maximized window should not use the minimal header
645 // style.
646 EXPECT_FALSE(p.ShouldUseMinimalHeaderStyle(FramePainter::THEMED_YES));
648 SetTrackedByWorkspace(w->GetNativeWindow(), false);
649 EXPECT_FALSE(p.ShouldUseMinimalHeaderStyle(FramePainter::THEMED_NO));
650 SetTrackedByWorkspace(w->GetNativeWindow(), true);
652 w->GetNativeWindow()->GetRootWindow()->SetProperty(
653 ash::internal::kCyclingThroughWorkspacesKey, true);
654 EXPECT_FALSE(p.ShouldUseMinimalHeaderStyle(FramePainter::THEMED_NO));
657 } // namespace ash