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

Side by Side Diff: ui/views/widget/widget_unittest.cc

Issue 1059853007: Mac/Linux: Ensure window size constraints propagate to the window server during Init (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Cracked the case on Windows Created 5 years, 8 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
« no previous file with comments | « ui/views/widget/native_widget_mac.mm ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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 <algorithm> 5 #include <algorithm>
6 #include <set> 6 #include <set>
7 7
8 #include "base/basictypes.h" 8 #include "base/basictypes.h"
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/scoped_ptr.h"
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 private: 202 private:
203 void RecordEvent(const ui::Event& event) { 203 void RecordEvent(const ui::Event& event) {
204 ++event_count_[event.type()]; 204 ++event_count_[event.type()];
205 } 205 }
206 206
207 std::map<ui::EventType, int> event_count_; 207 std::map<ui::EventType, int> event_count_;
208 208
209 DISALLOW_COPY_AND_ASSIGN(EventCountHandler); 209 DISALLOW_COPY_AND_ASSIGN(EventCountHandler);
210 }; 210 };
211 211
212 // A helper WidgetDelegate for tests that require hooks into WidgetDelegate
213 // calls, and removes some of the boilerplate for initializing a Widget. Calls
214 // Widget::CloseNow() when destroyed if it hasn't already been done.
215 class TestDesktopWidgetDelegate : public WidgetDelegate {
216 public:
217 TestDesktopWidgetDelegate() : widget_(new Widget) {}
218
219 ~TestDesktopWidgetDelegate() override {
220 if (widget_)
221 widget_->CloseNow();
222 EXPECT_FALSE(widget_);
223 }
224
225 // Initialize the Widget, adding some meaningful default InitParams.
226 void InitWidget(Widget::InitParams init_params) {
227 init_params.delegate = this;
228 #if !defined(OS_CHROMEOS)
229 init_params.native_widget = new PlatformDesktopNativeWidget(widget_);
230 #endif
231 init_params.bounds = initial_bounds_;
232 widget_->Init(init_params);
233 }
234
235 // Set the contents view to be used during Widget initialization. For Widgets
236 // that use non-client views, this will be the contents_view used to
237 // initialize the ClientView in WidgetDelegate::CreateClientView(). Otherwise,
238 // it is the ContentsView of the Widget's RootView. Ownership passes to the
239 // view hierarchy during InitWidget().
240 void set_contents_view(View* contents_view) {
241 contents_view_ = contents_view;
242 }
243
244 int window_closing_count() const { return window_closing_count_; }
245 const gfx::Rect& initial_bounds() { return initial_bounds_; }
246
247 // WidgetDelegate overrides:
248 void WindowClosing() override {
249 window_closing_count_++;
250 widget_ = nullptr;
251 }
252
253 Widget* GetWidget() override { return widget_; }
254 const Widget* GetWidget() const override { return widget_; }
255
256 View* GetContentsView() override {
257 return contents_view_ ? contents_view_ : WidgetDelegate::GetContentsView();
258 }
259
260 bool ShouldAdvanceFocusToTopLevelWidget() const override {
261 return true; // Same default as DefaultWidgetDelegate in widget.cc.
262 }
263
264 private:
265 Widget* widget_;
266 View* contents_view_ = nullptr;
267 int window_closing_count_ = 0;
268 gfx::Rect initial_bounds_ = gfx::Rect(100, 100, 200, 200);
269
270 DISALLOW_COPY_AND_ASSIGN(TestDesktopWidgetDelegate);
271 };
272
212 TEST_F(WidgetTest, WidgetInitParams) { 273 TEST_F(WidgetTest, WidgetInitParams) {
213 // Widgets are not transparent by default. 274 // Widgets are not transparent by default.
214 Widget::InitParams init1; 275 Widget::InitParams init1;
215 EXPECT_EQ(Widget::InitParams::INFER_OPACITY, init1.opacity); 276 EXPECT_EQ(Widget::InitParams::INFER_OPACITY, init1.opacity);
216 } 277 }
217 278
218 TEST_F(WidgetTest, NativeWindowProperty) { 279 TEST_F(WidgetTest, NativeWindowProperty) {
219 const char* key = "foo"; 280 const char* key = "foo";
220 int value = 3; 281 int value = 3;
221 282
(...skipping 888 matching lines...) Expand 10 before | Expand all | Expand 10 after
1110 #endif 1171 #endif
1111 1172
1112 widget->SetFullscreen(false); 1173 widget->SetFullscreen(false);
1113 native_widget->GetWindowPlacement(&restored_bounds, &show_state); 1174 native_widget->GetWindowPlacement(&restored_bounds, &show_state);
1114 EXPECT_EQ(ui::SHOW_STATE_NORMAL, show_state); 1175 EXPECT_EQ(ui::SHOW_STATE_NORMAL, show_state);
1115 EXPECT_EQ(expected_bounds, restored_bounds); 1176 EXPECT_EQ(expected_bounds, restored_bounds);
1116 1177
1117 widget->CloseNow(); 1178 widget->CloseNow();
1118 } 1179 }
1119 1180
1181 // Test that widget size constraints are properly applied immediately after
1182 // Init(), and that SetBounds() calls are appropriately clamped.
1183 TEST_F(WidgetTest, MinimumSizeConstraints) {
1184 TestDesktopWidgetDelegate delegate;
1185 gfx::Size minimum_size(100, 100);
1186 const gfx::Size smaller_size(90, 90);
1187
1188 delegate.set_contents_view(new StaticSizedView(minimum_size));
1189 delegate.InitWidget(CreateParams(Widget::InitParams::TYPE_WINDOW));
1190 Widget* widget = delegate.GetWidget();
1191
1192 // On desktop Linux, the Widget must be shown to ensure the window is mapped.
1193 // On other platforms this line is optional.
1194 widget->Show();
1195
1196 // Sanity checks.
1197 EXPECT_GT(delegate.initial_bounds().width(), minimum_size.width());
1198 EXPECT_GT(delegate.initial_bounds().height(), minimum_size.height());
1199 EXPECT_EQ(delegate.initial_bounds().size(),
1200 widget->GetWindowBoundsInScreen().size());
1201 // Note: StaticSizedView doesn't currently provide a maximum size.
1202 EXPECT_EQ(gfx::Size(), widget->GetMaximumSize());
1203
1204 if (!widget->ShouldUseNativeFrame()) {
1205 // The test environment may have dwm disabled on Windows. In this case,
1206 // CustomFrameView is used instead of the NativeFrameView, which will
1207 // provide a minimum size that includes frame decorations.
1208 minimum_size = widget->non_client_view()->GetWindowBoundsForClientBounds(
1209 gfx::Rect(minimum_size)).size();
1210 }
1211
1212 EXPECT_EQ(minimum_size, widget->GetMinimumSize());
1213 EXPECT_EQ(minimum_size, GetNativeWidgetMinimumContentSize(widget));
1214
1215 // Trying to resize smaller than the minimum size should restrict the content
1216 // size to the minimum size.
1217 widget->SetBounds(gfx::Rect(smaller_size));
1218 EXPECT_EQ(minimum_size, widget->GetClientAreaBoundsInScreen().size());
1219
1220 widget->SetSize(smaller_size);
1221 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
1222 // TODO(tapted): Desktop Linux ignores size constraints for SetSize. Fix it.
1223 EXPECT_EQ(smaller_size, widget->GetClientAreaBoundsInScreen().size());
1224 #else
1225 EXPECT_EQ(minimum_size, widget->GetClientAreaBoundsInScreen().size());
1226 #endif
1227 }
1228
1120 // Tests that SetBounds() and GetWindowBoundsInScreen() is symmetric when the 1229 // Tests that SetBounds() and GetWindowBoundsInScreen() is symmetric when the
1121 // widget is visible and not maximized or fullscreen. 1230 // widget is visible and not maximized or fullscreen.
1122 TEST_F(WidgetTest, GetWindowBoundsInScreen) { 1231 TEST_F(WidgetTest, GetWindowBoundsInScreen) {
1123 // Choose test coordinates away from edges and dimensions that are "small" 1232 // Choose test coordinates away from edges and dimensions that are "small"
1124 // (but not too small) to ensure the OS doesn't try to adjust them. 1233 // (but not too small) to ensure the OS doesn't try to adjust them.
1125 const gfx::Rect kTestBounds(150, 150, 400, 300); 1234 const gfx::Rect kTestBounds(150, 150, 400, 300);
1126 const gfx::Size kTestSize(200, 180); 1235 const gfx::Size kTestSize(200, 180);
1127 1236
1128 // First test a toplevel widget. 1237 // First test a toplevel widget.
1129 Widget* widget = CreateTopLevelPlatformWidget(); 1238 Widget* widget = CreateTopLevelPlatformWidget();
(...skipping 631 matching lines...) Expand 10 before | Expand all | Expand 10 after
1761 generator.ClickLeftButton(); 1870 generator.ClickLeftButton();
1762 1871
1763 EXPECT_EQ(1, event_count_view->GetEventCount(ui::ET_MOUSE_PRESSED)); 1872 EXPECT_EQ(1, event_count_view->GetEventCount(ui::ET_MOUSE_PRESSED));
1764 EXPECT_EQ(1, event_count_view->GetEventCount(ui::ET_MOUSE_RELEASED)); 1873 EXPECT_EQ(1, event_count_view->GetEventCount(ui::ET_MOUSE_RELEASED));
1765 1874
1766 widget->CloseNow(); 1875 widget->CloseNow();
1767 } 1876 }
1768 1877
1769 #endif // !defined(OS_MACOSX) || defined(USE_AURA) 1878 #endif // !defined(OS_MACOSX) || defined(USE_AURA)
1770 1879
1771 // Used by SingleWindowClosing to count number of times WindowClosing() has
1772 // been invoked.
1773 class ClosingDelegate : public WidgetDelegate {
1774 public:
1775 ClosingDelegate() : count_(0), widget_(NULL) {}
1776
1777 int count() const { return count_; }
1778
1779 void set_widget(views::Widget* widget) { widget_ = widget; }
1780
1781 // WidgetDelegate overrides:
1782 Widget* GetWidget() override { return widget_; }
1783 const Widget* GetWidget() const override { return widget_; }
1784 void WindowClosing() override { count_++; }
1785
1786 private:
1787 int count_;
1788 views::Widget* widget_;
1789
1790 DISALLOW_COPY_AND_ASSIGN(ClosingDelegate);
1791 };
1792
1793 // Verifies WindowClosing() is invoked correctly on the delegate when a Widget 1880 // Verifies WindowClosing() is invoked correctly on the delegate when a Widget
1794 // is closed. 1881 // is closed.
1795 TEST_F(WidgetTest, SingleWindowClosing) { 1882 TEST_F(WidgetTest, SingleWindowClosing) {
1796 scoped_ptr<ClosingDelegate> delegate(new ClosingDelegate()); 1883 TestDesktopWidgetDelegate delegate;
1797 Widget* widget = new Widget(); // Destroyed by CloseNow() below. 1884 delegate.InitWidget(CreateParams(Widget::InitParams::TYPE_WINDOW));
1798 Widget::InitParams init_params = 1885 EXPECT_EQ(0, delegate.window_closing_count());
1799 CreateParams(Widget::InitParams::TYPE_WINDOW); 1886 delegate.GetWidget()->CloseNow();
1800 init_params.bounds = gfx::Rect(0, 0, 200, 200); 1887 EXPECT_EQ(1, delegate.window_closing_count());
1801 init_params.delegate = delegate.get();
1802 #if !defined(OS_CHROMEOS)
1803 init_params.native_widget = new PlatformDesktopNativeWidget(widget);
1804 #endif
1805 widget->Init(init_params);
1806 EXPECT_EQ(0, delegate->count());
1807 widget->CloseNow();
1808 EXPECT_EQ(1, delegate->count());
1809 } 1888 }
1810 1889
1811 class WidgetWindowTitleTest : public WidgetTest { 1890 class WidgetWindowTitleTest : public WidgetTest {
1812 protected: 1891 protected:
1813 void RunTest(bool desktop_native_widget) { 1892 void RunTest(bool desktop_native_widget) {
1814 Widget* widget = new Widget(); // Destroyed by CloseNow() below. 1893 Widget* widget = new Widget(); // Destroyed by CloseNow() below.
1815 Widget::InitParams init_params = 1894 Widget::InitParams init_params =
1816 CreateParams(Widget::InitParams::TYPE_WINDOW); 1895 CreateParams(Widget::InitParams::TYPE_WINDOW);
1817 widget->Init(init_params); 1896 widget->Init(init_params);
1818 1897
(...skipping 1267 matching lines...) Expand 10 before | Expand all | Expand 10 after
3086 top_level_widget.Init(init_params); 3165 top_level_widget.Init(init_params);
3087 top_level_widget.SetFullscreen(true); 3166 top_level_widget.SetFullscreen(true);
3088 EXPECT_EQ(top_level_widget.IsVisible(), 3167 EXPECT_EQ(top_level_widget.IsVisible(),
3089 IsNativeWindowVisible(top_level_widget.GetNativeWindow())); 3168 IsNativeWindowVisible(top_level_widget.GetNativeWindow()));
3090 top_level_widget.CloseNow(); 3169 top_level_widget.CloseNow();
3091 } 3170 }
3092 #endif 3171 #endif
3093 } 3172 }
3094 #if defined(OS_WIN) 3173 #if defined(OS_WIN)
3095 3174
3096 // Provides functionality to test widget activation via an activation flag
3097 // which can be set by an accessor.
3098 class ModalWindowTestWidgetDelegate : public WidgetDelegate {
3099 public:
3100 ModalWindowTestWidgetDelegate()
3101 : widget_(NULL),
3102 can_activate_(true) {}
3103
3104 virtual ~ModalWindowTestWidgetDelegate() {}
3105
3106 // Overridden from WidgetDelegate:
3107 virtual void DeleteDelegate() override {
3108 delete this;
3109 }
3110 virtual Widget* GetWidget() override {
3111 return widget_;
3112 }
3113 virtual const Widget* GetWidget() const override {
3114 return widget_;
3115 }
3116 virtual bool CanActivate() const override {
3117 return can_activate_;
3118 }
3119 virtual bool ShouldAdvanceFocusToTopLevelWidget() const override {
3120 return true;
3121 }
3122
3123 void set_can_activate(bool can_activate) {
3124 can_activate_ = can_activate;
3125 }
3126
3127 void set_widget(Widget* widget) {
3128 widget_ = widget;
3129 }
3130
3131 private:
3132 Widget* widget_;
3133 bool can_activate_;
3134
3135 DISALLOW_COPY_AND_ASSIGN(ModalWindowTestWidgetDelegate);
3136 };
3137
3138 // Tests whether we can activate the top level widget when a modal dialog is 3175 // Tests whether we can activate the top level widget when a modal dialog is
3139 // active. 3176 // active.
3140 TEST_F(WidgetTest, WindowModalityActivationTest) { 3177 TEST_F(WidgetTest, WindowModalityActivationTest) {
3141 // Destroyed when the top level widget created below is destroyed. 3178 TestDesktopWidgetDelegate widget_delegate;
3142 ModalWindowTestWidgetDelegate* widget_delegate = 3179 widget_delegate.InitWidget(CreateParams(Widget::InitParams::TYPE_WINDOW));
3143 new ModalWindowTestWidgetDelegate;
3144 // Create a top level widget.
3145 Widget top_level_widget;
3146 Widget::InitParams init_params =
3147 CreateParams(Widget::InitParams::TYPE_WINDOW);
3148 init_params.show_state = ui::SHOW_STATE_NORMAL;
3149 gfx::Rect initial_bounds(0, 0, 500, 500);
3150 init_params.bounds = initial_bounds;
3151 init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
3152 init_params.native_widget = new DesktopNativeWidgetAura(&top_level_widget);
3153 init_params.delegate = widget_delegate;
3154 top_level_widget.Init(init_params);
3155 widget_delegate->set_widget(&top_level_widget);
3156 top_level_widget.Show();
3157 EXPECT_TRUE(top_level_widget.IsVisible());
3158 3180
3159 HWND win32_window = views::HWNDForWidget(&top_level_widget); 3181 Widget* top_level_widget = widget_delegate.GetWidget();
3182 top_level_widget->Show();
3183 EXPECT_TRUE(top_level_widget->IsVisible());
3184
3185 HWND win32_window = views::HWNDForWidget(top_level_widget);
3160 EXPECT_TRUE(::IsWindow(win32_window)); 3186 EXPECT_TRUE(::IsWindow(win32_window));
3161 3187
3162 // This instance will be destroyed when the dialog is destroyed. 3188 // This instance will be destroyed when the dialog is destroyed.
3163 ModalDialogDelegate* dialog_delegate = new ModalDialogDelegate; 3189 ModalDialogDelegate* dialog_delegate = new ModalDialogDelegate;
3164 3190
3165 // We should be able to activate the window even if the WidgetDelegate 3191 // We should be able to activate the window even if the WidgetDelegate
3166 // says no, when a modal dialog is active. 3192 // says no, when a modal dialog is active.
3167 widget_delegate->set_can_activate(false); 3193 widget_delegate.set_can_activate(false);
3168 3194
3169 Widget* modal_dialog_widget = views::DialogDelegate::CreateDialogWidget( 3195 Widget* modal_dialog_widget = views::DialogDelegate::CreateDialogWidget(
3170 dialog_delegate, NULL, top_level_widget.GetNativeWindow()); 3196 dialog_delegate, NULL, top_level_widget->GetNativeView());
3171 modal_dialog_widget->SetBounds(gfx::Rect(100, 100, 200, 200)); 3197 modal_dialog_widget->SetBounds(gfx::Rect(100, 100, 200, 200));
3172 modal_dialog_widget->Show(); 3198 modal_dialog_widget->Show();
3173 EXPECT_TRUE(modal_dialog_widget->IsVisible()); 3199 EXPECT_TRUE(modal_dialog_widget->IsVisible());
3174 3200
3175 LRESULT activate_result = ::SendMessage( 3201 LRESULT activate_result = ::SendMessage(
3176 win32_window, 3202 win32_window,
3177 WM_MOUSEACTIVATE, 3203 WM_MOUSEACTIVATE,
3178 reinterpret_cast<WPARAM>(win32_window), 3204 reinterpret_cast<WPARAM>(win32_window),
3179 MAKELPARAM(WM_LBUTTONDOWN, HTCLIENT)); 3205 MAKELPARAM(WM_LBUTTONDOWN, HTCLIENT));
3180 EXPECT_EQ(activate_result, MA_ACTIVATE); 3206 EXPECT_EQ(activate_result, MA_ACTIVATE);
3181 3207
3182 modal_dialog_widget->CloseNow(); 3208 modal_dialog_widget->CloseNow();
3183 top_level_widget.CloseNow();
3184 } 3209 }
3185 #endif // defined(OS_WIN) 3210 #endif // defined(OS_WIN)
3186 #endif // !defined(OS_CHROMEOS) 3211 #endif // !defined(OS_CHROMEOS)
3187 3212
3188 namespace { 3213 namespace {
3189 3214
3190 class FullscreenAwareFrame : public views::NonClientFrameView { 3215 class FullscreenAwareFrame : public views::NonClientFrameView {
3191 public: 3216 public:
3192 explicit FullscreenAwareFrame(views::Widget* widget) 3217 explicit FullscreenAwareFrame(views::Widget* widget)
3193 : widget_(widget), fullscreen_layout_called_(false) {} 3218 : widget_(widget), fullscreen_layout_called_(false) {}
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
3403 bool handled = false; 3428 bool handled = false;
3404 target->HandleKeyboardMessage(WM_CHAR, 0, 0, &handled); 3429 target->HandleKeyboardMessage(WM_CHAR, 0, 0, &handled);
3405 target->HandleKeyboardMessage(WM_SYSCHAR, 0, 0, &handled); 3430 target->HandleKeyboardMessage(WM_SYSCHAR, 0, 0, &handled);
3406 target->HandleKeyboardMessage(WM_SYSDEADCHAR, 0, 0, &handled); 3431 target->HandleKeyboardMessage(WM_SYSDEADCHAR, 0, 0, &handled);
3407 widget.CloseNow(); 3432 widget.CloseNow();
3408 } 3433 }
3409 #endif 3434 #endif
3410 3435
3411 } // namespace test 3436 } // namespace test
3412 } // namespace views 3437 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/widget/native_widget_mac.mm ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698