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

Side by Side Diff: ash/root_window_controller.cc

Issue 224113005: Eliminate ash::internal namespace (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 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 | Annotate | Revision Log
« no previous file with comments | « ash/root_window_controller.h ('k') | ash/root_window_controller_unittest.cc » ('j') | 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 "ash/root_window_controller.h" 5 #include "ash/root_window_controller.h"
6 6
7 #include <queue> 7 #include <queue>
8 #include <vector> 8 #include <vector>
9 9
10 #include "ash/ash_constants.h" 10 #include "ash/ash_constants.h"
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 88
89 // Creates a new window for use as a container. 89 // Creates a new window for use as a container.
90 aura::Window* CreateContainer(int window_id, 90 aura::Window* CreateContainer(int window_id,
91 const char* name, 91 const char* name,
92 aura::Window* parent) { 92 aura::Window* parent) {
93 aura::Window* container = new aura::Window(NULL); 93 aura::Window* container = new aura::Window(NULL);
94 container->set_id(window_id); 94 container->set_id(window_id);
95 container->SetName(name); 95 container->SetName(name);
96 container->Init(aura::WINDOW_LAYER_NOT_DRAWN); 96 container->Init(aura::WINDOW_LAYER_NOT_DRAWN);
97 parent->AddChild(container); 97 parent->AddChild(container);
98 if (window_id != internal::kShellWindowId_UnparentedControlContainer) 98 if (window_id != kShellWindowId_UnparentedControlContainer)
99 container->Show(); 99 container->Show();
100 return container; 100 return container;
101 } 101 }
102 102
103 float ToRelativeValue(int value, int src, int dst) { 103 float ToRelativeValue(int value, int src, int dst) {
104 return static_cast<float>(value) / static_cast<float>(src) * dst; 104 return static_cast<float>(value) / static_cast<float>(src) * dst;
105 } 105 }
106 106
107 void MoveOriginRelativeToSize(const gfx::Size& src_size, 107 void MoveOriginRelativeToSize(const gfx::Size& src_size,
108 const gfx::Size& dst_size, 108 const gfx::Size& dst_size,
109 gfx::Rect* bounds_in_out) { 109 gfx::Rect* bounds_in_out) {
110 gfx::Point origin = bounds_in_out->origin(); 110 gfx::Point origin = bounds_in_out->origin();
111 bounds_in_out->set_origin(gfx::Point( 111 bounds_in_out->set_origin(gfx::Point(
112 ToRelativeValue(origin.x(), src_size.width(), dst_size.width()), 112 ToRelativeValue(origin.x(), src_size.width(), dst_size.width()),
113 ToRelativeValue(origin.y(), src_size.height(), dst_size.height()))); 113 ToRelativeValue(origin.y(), src_size.height(), dst_size.height())));
114 } 114 }
115 115
116 // Reparents |window| to |new_parent|. 116 // Reparents |window| to |new_parent|.
117 void ReparentWindow(aura::Window* window, aura::Window* new_parent) { 117 void ReparentWindow(aura::Window* window, aura::Window* new_parent) {
118 const gfx::Size src_size = window->parent()->bounds().size(); 118 const gfx::Size src_size = window->parent()->bounds().size();
119 const gfx::Size dst_size = new_parent->bounds().size(); 119 const gfx::Size dst_size = new_parent->bounds().size();
120 // Update the restore bounds to make it relative to the display. 120 // Update the restore bounds to make it relative to the display.
121 wm::WindowState* state = wm::GetWindowState(window); 121 wm::WindowState* state = wm::GetWindowState(window);
122 gfx::Rect restore_bounds; 122 gfx::Rect restore_bounds;
123 bool has_restore_bounds = state->HasRestoreBounds(); 123 bool has_restore_bounds = state->HasRestoreBounds();
124 124
125 bool update_bounds = (state->IsNormalOrSnapped() || state->IsMinimized()) && 125 bool update_bounds = (state->IsNormalOrSnapped() || state->IsMinimized()) &&
126 new_parent->id() != internal::kShellWindowId_DockedContainer; 126 new_parent->id() != kShellWindowId_DockedContainer;
127 gfx::Rect local_bounds; 127 gfx::Rect local_bounds;
128 if (update_bounds) { 128 if (update_bounds) {
129 local_bounds = state->window()->bounds(); 129 local_bounds = state->window()->bounds();
130 MoveOriginRelativeToSize(src_size, dst_size, &local_bounds); 130 MoveOriginRelativeToSize(src_size, dst_size, &local_bounds);
131 } 131 }
132 132
133 if (has_restore_bounds) { 133 if (has_restore_bounds) {
134 restore_bounds = state->GetRestoreBoundsInParent(); 134 restore_bounds = state->GetRestoreBoundsInParent();
135 MoveOriginRelativeToSize(src_size, dst_size, &restore_bounds); 135 MoveOriginRelativeToSize(src_size, dst_size, &restore_bounds);
136 } 136 }
137 137
138 new_parent->AddChild(window); 138 new_parent->AddChild(window);
139 139
140 // Docked windows have bounds handled by the layout manager in AddChild(). 140 // Docked windows have bounds handled by the layout manager in AddChild().
141 if (update_bounds) 141 if (update_bounds)
142 window->SetBounds(local_bounds); 142 window->SetBounds(local_bounds);
143 143
144 if (has_restore_bounds) 144 if (has_restore_bounds)
145 state->SetRestoreBoundsInParent(restore_bounds); 145 state->SetRestoreBoundsInParent(restore_bounds);
146 } 146 }
147 147
148 // Reparents the appropriate set of windows from |src| to |dst|. 148 // Reparents the appropriate set of windows from |src| to |dst|.
149 void ReparentAllWindows(aura::Window* src, aura::Window* dst) { 149 void ReparentAllWindows(aura::Window* src, aura::Window* dst) {
150 // Set of windows to move. 150 // Set of windows to move.
151 const int kContainerIdsToMove[] = { 151 const int kContainerIdsToMove[] = {
152 internal::kShellWindowId_DefaultContainer, 152 kShellWindowId_DefaultContainer,
153 internal::kShellWindowId_DockedContainer, 153 kShellWindowId_DockedContainer,
154 internal::kShellWindowId_PanelContainer, 154 kShellWindowId_PanelContainer,
155 internal::kShellWindowId_AlwaysOnTopContainer, 155 kShellWindowId_AlwaysOnTopContainer,
156 internal::kShellWindowId_SystemModalContainer, 156 kShellWindowId_SystemModalContainer,
157 internal::kShellWindowId_LockSystemModalContainer, 157 kShellWindowId_LockSystemModalContainer,
158 internal::kShellWindowId_InputMethodContainer, 158 kShellWindowId_InputMethodContainer,
159 internal::kShellWindowId_UnparentedControlContainer, 159 kShellWindowId_UnparentedControlContainer, };
160 };
161 for (size_t i = 0; i < arraysize(kContainerIdsToMove); i++) { 160 for (size_t i = 0; i < arraysize(kContainerIdsToMove); i++) {
162 int id = kContainerIdsToMove[i]; 161 int id = kContainerIdsToMove[i];
163 aura::Window* src_container = Shell::GetContainer(src, id); 162 aura::Window* src_container = Shell::GetContainer(src, id);
164 aura::Window* dst_container = Shell::GetContainer(dst, id); 163 aura::Window* dst_container = Shell::GetContainer(dst, id);
165 while (!src_container->children().empty()) { 164 while (!src_container->children().empty()) {
166 // Restart iteration from the source container windows each time as they 165 // Restart iteration from the source container windows each time as they
167 // may change as a result of moving other windows. 166 // may change as a result of moving other windows.
168 aura::Window::Windows::const_iterator iter = 167 aura::Window::Windows::const_iterator iter =
169 src_container->children().begin(); 168 src_container->children().begin();
170 while (iter != src_container->children().end() && 169 while (iter != src_container->children().end() &&
171 internal::SystemModalContainerLayoutManager::IsModalBackground( 170 SystemModalContainerLayoutManager::IsModalBackground(*iter)) {
172 *iter)) {
173 ++iter; 171 ++iter;
174 } 172 }
175 // If the entire window list is modal background windows then stop. 173 // If the entire window list is modal background windows then stop.
176 if (iter == src_container->children().end()) 174 if (iter == src_container->children().end())
177 break; 175 break;
178 ReparentWindow(*iter, dst_container); 176 ReparentWindow(*iter, dst_container);
179 } 177 }
180 } 178 }
181 } 179 }
182 180
183 // Mark the container window so that a widget added to this container will 181 // Mark the container window so that a widget added to this container will
184 // use the virtual screeen coordinates instead of parent. 182 // use the virtual screeen coordinates instead of parent.
185 void SetUsesScreenCoordinates(aura::Window* container) { 183 void SetUsesScreenCoordinates(aura::Window* container) {
186 container->SetProperty(internal::kUsesScreenCoordinatesKey, true); 184 container->SetProperty(kUsesScreenCoordinatesKey, true);
187 } 185 }
188 186
189 // Mark the container window so that a widget added to this container will 187 // Mark the container window so that a widget added to this container will
190 // say in the same root window regardless of the bounds specified. 188 // say in the same root window regardless of the bounds specified.
191 void DescendantShouldStayInSameRootWindow(aura::Window* container) { 189 void DescendantShouldStayInSameRootWindow(aura::Window* container) {
192 container->SetProperty(internal::kStayInSameRootWindowKey, true); 190 container->SetProperty(kStayInSameRootWindowKey, true);
193 } 191 }
194 192
195 void SetUsesEasyResizeTargeter(aura::Window* container) { 193 void SetUsesEasyResizeTargeter(aura::Window* container) {
196 gfx::Insets mouse_extend(-kResizeOutsideBoundsSize, 194 gfx::Insets mouse_extend(-kResizeOutsideBoundsSize,
197 -kResizeOutsideBoundsSize, 195 -kResizeOutsideBoundsSize,
198 -kResizeOutsideBoundsSize, 196 -kResizeOutsideBoundsSize,
199 -kResizeOutsideBoundsSize); 197 -kResizeOutsideBoundsSize);
200 gfx::Insets touch_extend = mouse_extend.Scale( 198 gfx::Insets touch_extend = mouse_extend.Scale(
201 kResizeOutsideBoundsScaleForTouch); 199 kResizeOutsideBoundsScaleForTouch);
202 container->SetEventTargeter(scoped_ptr<ui::EventTargeter>( 200 container->SetEventTargeter(scoped_ptr<ui::EventTargeter>(
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 return false; 251 return false;
254 } 252 }
255 virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {} 253 virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {}
256 254
257 private: 255 private:
258 DISALLOW_COPY_AND_ASSIGN(EmptyWindowDelegate); 256 DISALLOW_COPY_AND_ASSIGN(EmptyWindowDelegate);
259 }; 257 };
260 258
261 } // namespace 259 } // namespace
262 260
263 namespace internal {
264
265 void RootWindowController::CreateForPrimaryDisplay(aura::WindowTreeHost* host) { 261 void RootWindowController::CreateForPrimaryDisplay(aura::WindowTreeHost* host) {
266 RootWindowController* controller = new RootWindowController(host); 262 RootWindowController* controller = new RootWindowController(host);
267 controller->Init(RootWindowController::PRIMARY, 263 controller->Init(RootWindowController::PRIMARY,
268 Shell::GetInstance()->delegate()->IsFirstRunAfterBoot()); 264 Shell::GetInstance()->delegate()->IsFirstRunAfterBoot());
269 } 265 }
270 266
271 void RootWindowController::CreateForSecondaryDisplay( 267 void RootWindowController::CreateForSecondaryDisplay(
272 aura::WindowTreeHost* host) { 268 aura::WindowTreeHost* host) {
273 RootWindowController* controller = new RootWindowController(host); 269 RootWindowController* controller = new RootWindowController(host);
274 controller->Init(RootWindowController::SECONDARY, false /* first run */); 270 controller->Init(RootWindowController::SECONDARY, false /* first run */);
(...skipping 12 matching lines...) Expand all
287 } 283 }
288 284
289 // static 285 // static
290 RootWindowController* RootWindowController::ForWindow( 286 RootWindowController* RootWindowController::ForWindow(
291 const aura::Window* window) { 287 const aura::Window* window) {
292 return GetRootWindowController(window->GetRootWindow()); 288 return GetRootWindowController(window->GetRootWindow());
293 } 289 }
294 290
295 // static 291 // static
296 RootWindowController* RootWindowController::ForTargetRootWindow() { 292 RootWindowController* RootWindowController::ForTargetRootWindow() {
297 return internal::GetRootWindowController(Shell::GetTargetRootWindow()); 293 return GetRootWindowController(Shell::GetTargetRootWindow());
298 } 294 }
299 295
300 // static 296 // static
301 aura::Window* RootWindowController::GetContainerForWindow( 297 aura::Window* RootWindowController::GetContainerForWindow(
302 aura::Window* window) { 298 aura::Window* window) {
303 aura::Window* container = window->parent(); 299 aura::Window* container = window->parent();
304 while (container && container->type() != ui::wm::WINDOW_TYPE_UNKNOWN) 300 while (container && container->type() != ui::wm::WINDOW_TYPE_UNKNOWN)
305 container = container->parent(); 301 container = container->parent();
306 return container; 302 return container;
307 } 303 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 Shell::GetPrimaryRootWindow() == root_window() ? 339 Shell::GetPrimaryRootWindow() == root_window() ?
344 NULL : Shell::GetPrimaryRootWindow()); 340 NULL : Shell::GetPrimaryRootWindow());
345 } 341 }
346 342
347 CloseChildWindows(); 343 CloseChildWindows();
348 GetRootWindowSettings(root_window())->controller = NULL; 344 GetRootWindowSettings(root_window())->controller = NULL;
349 screen_dimmer_.reset(); 345 screen_dimmer_.reset();
350 workspace_controller_.reset(); 346 workspace_controller_.reset();
351 // Forget with the display ID so that display lookup 347 // Forget with the display ID so that display lookup
352 // ends up with invalid display. 348 // ends up with invalid display.
353 internal::GetRootWindowSettings(root_window())->display_id = 349 GetRootWindowSettings(root_window())->display_id =
354 gfx::Display::kInvalidDisplayID; 350 gfx::Display::kInvalidDisplayID;
355 internal::GetRootWindowSettings(root_window())->shutdown = true; 351 GetRootWindowSettings(root_window())->shutdown = true;
356 352
357 system_background_.reset(); 353 system_background_.reset();
358 aura::client::SetScreenPositionClient(root_window(), NULL); 354 aura::client::SetScreenPositionClient(root_window(), NULL);
359 } 355 }
360 356
361 SystemModalContainerLayoutManager* 357 SystemModalContainerLayoutManager*
362 RootWindowController::GetSystemModalLayoutManager(aura::Window* window) { 358 RootWindowController::GetSystemModalLayoutManager(aura::Window* window) {
363 aura::Window* modal_container = NULL; 359 aura::Window* modal_container = NULL;
364 if (window) { 360 if (window) {
365 aura::Window* window_container = GetContainerForWindow(window); 361 aura::Window* window_container = GetContainerForWindow(window);
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 717
722 aura::Window* default_container = 718 aura::Window* default_container =
723 GetContainer(kShellWindowId_DefaultContainer); 719 GetContainer(kShellWindowId_DefaultContainer);
724 // Workspace manager has its own layout managers. 720 // Workspace manager has its own layout managers.
725 workspace_controller_.reset( 721 workspace_controller_.reset(
726 new WorkspaceController(default_container)); 722 new WorkspaceController(default_container));
727 723
728 aura::Window* always_on_top_container = 724 aura::Window* always_on_top_container =
729 GetContainer(kShellWindowId_AlwaysOnTopContainer); 725 GetContainer(kShellWindowId_AlwaysOnTopContainer);
730 always_on_top_container->SetLayoutManager( 726 always_on_top_container->SetLayoutManager(
731 new internal::WorkspaceLayoutManager( 727 new WorkspaceLayoutManager(always_on_top_container));
732 always_on_top_container)); 728 always_on_top_controller_.reset(new AlwaysOnTopController);
733 always_on_top_controller_.reset(new internal::AlwaysOnTopController);
734 always_on_top_controller_->SetAlwaysOnTopContainer(always_on_top_container); 729 always_on_top_controller_->SetAlwaysOnTopContainer(always_on_top_container);
735 730
736 DCHECK(!shelf_.get()); 731 DCHECK(!shelf_.get());
737 aura::Window* shelf_container = 732 aura::Window* shelf_container = GetContainer(kShellWindowId_ShelfContainer);
738 GetContainer(internal::kShellWindowId_ShelfContainer);
739 // TODO(harrym): Remove when status area is view. 733 // TODO(harrym): Remove when status area is view.
740 aura::Window* status_container = 734 aura::Window* status_container = GetContainer(kShellWindowId_StatusContainer);
741 GetContainer(internal::kShellWindowId_StatusContainer);
742 shelf_.reset(new ShelfWidget( 735 shelf_.reset(new ShelfWidget(
743 shelf_container, status_container, workspace_controller())); 736 shelf_container, status_container, workspace_controller()));
744 737
745 if (!Shell::GetInstance()->session_state_delegate()-> 738 if (!Shell::GetInstance()->session_state_delegate()->
746 IsActiveUserSessionStarted()) { 739 IsActiveUserSessionStarted()) {
747 // This window exists only to be a event target on login screen. 740 // This window exists only to be a event target on login screen.
748 // It does not have to handle events, nor be visible. 741 // It does not have to handle events, nor be visible.
749 mouse_event_target_.reset(new aura::Window(new EmptyWindowDelegate)); 742 mouse_event_target_.reset(new aura::Window(new EmptyWindowDelegate));
750 mouse_event_target_->Init(aura::WINDOW_LAYER_NOT_DRAWN); 743 mouse_event_target_->Init(aura::WINDOW_LAYER_NOT_DRAWN);
751 744
752 aura::Window* lock_background_container = 745 aura::Window* lock_background_container =
753 GetContainer(internal::kShellWindowId_LockScreenBackgroundContainer); 746 GetContainer(kShellWindowId_LockScreenBackgroundContainer);
754 lock_background_container->AddChild(mouse_event_target_.get()); 747 lock_background_container->AddChild(mouse_event_target_.get());
755 mouse_event_target_->Show(); 748 mouse_event_target_->Show();
756 } 749 }
757 750
758 // Create Docked windows layout manager 751 // Create Docked windows layout manager
759 aura::Window* docked_container = GetContainer( 752 aura::Window* docked_container = GetContainer(kShellWindowId_DockedContainer);
760 internal::kShellWindowId_DockedContainer);
761 docked_layout_manager_ = 753 docked_layout_manager_ =
762 new internal::DockedWindowLayoutManager(docked_container, 754 new DockedWindowLayoutManager(docked_container, workspace_controller());
763 workspace_controller());
764 docked_container->SetLayoutManager(docked_layout_manager_); 755 docked_container->SetLayoutManager(docked_layout_manager_);
765 756
766 // Create Panel layout manager 757 // Create Panel layout manager
767 aura::Window* panel_container = GetContainer( 758 aura::Window* panel_container = GetContainer(kShellWindowId_PanelContainer);
768 internal::kShellWindowId_PanelContainer); 759 panel_layout_manager_ = new PanelLayoutManager(panel_container);
769 panel_layout_manager_ =
770 new internal::PanelLayoutManager(panel_container);
771 panel_container->SetLayoutManager(panel_layout_manager_); 760 panel_container->SetLayoutManager(panel_layout_manager_);
772 panel_container_handler_.reset(new PanelWindowEventHandler); 761 panel_container_handler_.reset(new PanelWindowEventHandler);
773 panel_container->AddPreTargetHandler(panel_container_handler_.get()); 762 panel_container->AddPreTargetHandler(panel_container_handler_.get());
774 } 763 }
775 764
776 void RootWindowController::InitTouchHuds() { 765 void RootWindowController::InitTouchHuds() {
777 CommandLine* command_line = CommandLine::ForCurrentProcess(); 766 CommandLine* command_line = CommandLine::ForCurrentProcess();
778 if (command_line->HasSwitch(switches::kAshTouchHud)) 767 if (command_line->HasSwitch(switches::kAshTouchHud))
779 set_touch_hud_debug(new TouchHudDebug(root_window())); 768 set_touch_hud_debug(new TouchHudDebug(root_window()));
780 if (Shell::GetInstance()->is_touch_hud_projection_enabled()) 769 if (Shell::GetInstance()->is_touch_hud_projection_enabled())
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
911 non_lock_screen_containers); 900 non_lock_screen_containers);
912 ::wm::SetChildWindowVisibilityChangesAnimated(input_method_container); 901 ::wm::SetChildWindowVisibilityChangesAnimated(input_method_container);
913 SetUsesScreenCoordinates(input_method_container); 902 SetUsesScreenCoordinates(input_method_container);
914 903
915 // TODO(beng): Figure out if we can make this use 904 // TODO(beng): Figure out if we can make this use
916 // SystemModalContainerEventFilter instead of stops_event_propagation. 905 // SystemModalContainerEventFilter instead of stops_event_propagation.
917 aura::Window* lock_container = CreateContainer( 906 aura::Window* lock_container = CreateContainer(
918 kShellWindowId_LockScreenContainer, 907 kShellWindowId_LockScreenContainer,
919 "LockScreenContainer", 908 "LockScreenContainer",
920 lock_screen_containers); 909 lock_screen_containers);
921 lock_container->SetLayoutManager( 910 lock_container->SetLayoutManager(new WorkspaceLayoutManager(lock_container));
922 new internal::WorkspaceLayoutManager(lock_container));
923 SetUsesScreenCoordinates(lock_container); 911 SetUsesScreenCoordinates(lock_container);
924 // TODO(beng): stopsevents 912 // TODO(beng): stopsevents
925 913
926 aura::Window* lock_modal_container = CreateContainer( 914 aura::Window* lock_modal_container = CreateContainer(
927 kShellWindowId_LockSystemModalContainer, 915 kShellWindowId_LockSystemModalContainer,
928 "LockSystemModalContainer", 916 "LockSystemModalContainer",
929 lock_screen_containers); 917 lock_screen_containers);
930 lock_modal_container->SetLayoutManager( 918 lock_modal_container->SetLayoutManager(
931 new SystemModalContainerLayoutManager(lock_modal_container)); 919 new SystemModalContainerLayoutManager(lock_modal_container));
932 ::wm::SetChildWindowVisibilityChangesAnimated(lock_modal_container); 920 ::wm::SetChildWindowVisibilityChangesAnimated(lock_modal_container);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1007 EnableTouchHudProjection(); 995 EnableTouchHudProjection();
1008 else 996 else
1009 DisableTouchHudProjection(); 997 DisableTouchHudProjection();
1010 } 998 }
1011 999
1012 RootWindowController* GetRootWindowController( 1000 RootWindowController* GetRootWindowController(
1013 const aura::Window* root_window) { 1001 const aura::Window* root_window) {
1014 return root_window ? GetRootWindowSettings(root_window)->controller : NULL; 1002 return root_window ? GetRootWindowSettings(root_window)->controller : NULL;
1015 } 1003 }
1016 1004
1017 } // namespace internal
1018 } // namespace ash 1005 } // namespace ash
OLDNEW
« no previous file with comments | « ash/root_window_controller.h ('k') | ash/root_window_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698