OLD | NEW |
| (Empty) |
1 // Copyright 2014 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. | |
4 | |
5 #include "components/native_app_window/native_app_window_views.h" | |
6 | |
7 #include "base/threading/sequenced_worker_pool.h" | |
8 #include "content/public/browser/render_view_host.h" | |
9 #include "content/public/browser/render_widget_host_view.h" | |
10 #include "content/public/browser/web_contents.h" | |
11 #include "extensions/browser/app_window/app_window.h" | |
12 #include "extensions/common/draggable_region.h" | |
13 #include "third_party/skia/include/core/SkRegion.h" | |
14 #include "ui/gfx/path.h" | |
15 #include "ui/views/controls/webview/webview.h" | |
16 #include "ui/views/widget/widget.h" | |
17 #include "ui/views/window/non_client_view.h" | |
18 | |
19 #if defined(USE_AURA) | |
20 #include "ui/aura/window.h" | |
21 #endif | |
22 | |
23 using extensions::AppWindow; | |
24 | |
25 namespace native_app_window { | |
26 | |
27 NativeAppWindowViews::NativeAppWindowViews() | |
28 : app_window_(NULL), | |
29 web_view_(NULL), | |
30 widget_(NULL), | |
31 frameless_(false), | |
32 resizable_(false) { | |
33 } | |
34 | |
35 void NativeAppWindowViews::Init(AppWindow* app_window, | |
36 const AppWindow::CreateParams& create_params) { | |
37 app_window_ = app_window; | |
38 frameless_ = create_params.frame == AppWindow::FRAME_NONE; | |
39 resizable_ = create_params.resizable; | |
40 size_constraints_.set_minimum_size( | |
41 create_params.GetContentMinimumSize(gfx::Insets())); | |
42 size_constraints_.set_maximum_size( | |
43 create_params.GetContentMaximumSize(gfx::Insets())); | |
44 Observe(app_window_->web_contents()); | |
45 | |
46 widget_ = new views::Widget; | |
47 InitializeWindow(app_window, create_params); | |
48 | |
49 OnViewWasResized(); | |
50 widget_->AddObserver(this); | |
51 } | |
52 | |
53 NativeAppWindowViews::~NativeAppWindowViews() { | |
54 web_view_->SetWebContents(NULL); | |
55 } | |
56 | |
57 void NativeAppWindowViews::OnCanHaveAlphaEnabledChanged() { | |
58 app_window_->OnNativeWindowChanged(); | |
59 } | |
60 | |
61 void NativeAppWindowViews::InitializeWindow( | |
62 AppWindow* app_window, | |
63 const AppWindow::CreateParams& create_params) { | |
64 // Stub implementation. See also ChromeNativeAppWindowViews. | |
65 views::Widget::InitParams init_params(views::Widget::InitParams::TYPE_WINDOW); | |
66 init_params.delegate = this; | |
67 init_params.keep_on_top = create_params.always_on_top; | |
68 widget_->Init(init_params); | |
69 widget_->CenterWindow( | |
70 create_params.GetInitialWindowBounds(gfx::Insets()).size()); | |
71 } | |
72 | |
73 // ui::BaseWindow implementation. | |
74 | |
75 bool NativeAppWindowViews::IsActive() const { | |
76 return widget_->IsActive(); | |
77 } | |
78 | |
79 bool NativeAppWindowViews::IsMaximized() const { | |
80 return widget_->IsMaximized(); | |
81 } | |
82 | |
83 bool NativeAppWindowViews::IsMinimized() const { | |
84 return widget_->IsMinimized(); | |
85 } | |
86 | |
87 bool NativeAppWindowViews::IsFullscreen() const { | |
88 return widget_->IsFullscreen(); | |
89 } | |
90 | |
91 gfx::NativeWindow NativeAppWindowViews::GetNativeWindow() { | |
92 return widget_->GetNativeWindow(); | |
93 } | |
94 | |
95 gfx::Rect NativeAppWindowViews::GetRestoredBounds() const { | |
96 return widget_->GetRestoredBounds(); | |
97 } | |
98 | |
99 ui::WindowShowState NativeAppWindowViews::GetRestoredState() const { | |
100 // Stub implementation. See also ChromeNativeAppWindowViews. | |
101 if (IsMaximized()) | |
102 return ui::SHOW_STATE_MAXIMIZED; | |
103 if (IsFullscreen()) | |
104 return ui::SHOW_STATE_FULLSCREEN; | |
105 return ui::SHOW_STATE_NORMAL; | |
106 } | |
107 | |
108 gfx::Rect NativeAppWindowViews::GetBounds() const { | |
109 return widget_->GetWindowBoundsInScreen(); | |
110 } | |
111 | |
112 void NativeAppWindowViews::Show() { | |
113 if (widget_->IsVisible()) { | |
114 widget_->Activate(); | |
115 return; | |
116 } | |
117 widget_->Show(); | |
118 } | |
119 | |
120 void NativeAppWindowViews::ShowInactive() { | |
121 if (widget_->IsVisible()) | |
122 return; | |
123 | |
124 widget_->ShowInactive(); | |
125 } | |
126 | |
127 void NativeAppWindowViews::Hide() { | |
128 widget_->Hide(); | |
129 } | |
130 | |
131 void NativeAppWindowViews::Close() { | |
132 widget_->Close(); | |
133 } | |
134 | |
135 void NativeAppWindowViews::Activate() { | |
136 widget_->Activate(); | |
137 } | |
138 | |
139 void NativeAppWindowViews::Deactivate() { | |
140 widget_->Deactivate(); | |
141 } | |
142 | |
143 void NativeAppWindowViews::Maximize() { | |
144 widget_->Maximize(); | |
145 } | |
146 | |
147 void NativeAppWindowViews::Minimize() { | |
148 widget_->Minimize(); | |
149 } | |
150 | |
151 void NativeAppWindowViews::Restore() { | |
152 widget_->Restore(); | |
153 } | |
154 | |
155 void NativeAppWindowViews::SetBounds(const gfx::Rect& bounds) { | |
156 widget_->SetBounds(bounds); | |
157 } | |
158 | |
159 void NativeAppWindowViews::FlashFrame(bool flash) { | |
160 widget_->FlashFrame(flash); | |
161 } | |
162 | |
163 bool NativeAppWindowViews::IsAlwaysOnTop() const { | |
164 // Stub implementation. See also ChromeNativeAppWindowViews. | |
165 return widget_->IsAlwaysOnTop(); | |
166 } | |
167 | |
168 void NativeAppWindowViews::SetAlwaysOnTop(bool always_on_top) { | |
169 widget_->SetAlwaysOnTop(always_on_top); | |
170 } | |
171 | |
172 gfx::NativeView NativeAppWindowViews::GetHostView() const { | |
173 return widget_->GetNativeView(); | |
174 } | |
175 | |
176 gfx::Point NativeAppWindowViews::GetDialogPosition(const gfx::Size& size) { | |
177 gfx::Size app_window_size = widget_->GetWindowBoundsInScreen().size(); | |
178 return gfx::Point(app_window_size.width() / 2 - size.width() / 2, | |
179 app_window_size.height() / 2 - size.height() / 2); | |
180 } | |
181 | |
182 gfx::Size NativeAppWindowViews::GetMaximumDialogSize() { | |
183 return widget_->GetWindowBoundsInScreen().size(); | |
184 } | |
185 | |
186 void NativeAppWindowViews::AddObserver( | |
187 web_modal::ModalDialogHostObserver* observer) { | |
188 observer_list_.AddObserver(observer); | |
189 } | |
190 void NativeAppWindowViews::RemoveObserver( | |
191 web_modal::ModalDialogHostObserver* observer) { | |
192 observer_list_.RemoveObserver(observer); | |
193 } | |
194 | |
195 void NativeAppWindowViews::OnViewWasResized() { | |
196 FOR_EACH_OBSERVER(web_modal::ModalDialogHostObserver, | |
197 observer_list_, | |
198 OnPositionRequiresUpdate()); | |
199 } | |
200 | |
201 // WidgetDelegate implementation. | |
202 | |
203 void NativeAppWindowViews::OnWidgetMove() { | |
204 app_window_->OnNativeWindowChanged(); | |
205 } | |
206 | |
207 views::View* NativeAppWindowViews::GetInitiallyFocusedView() { | |
208 return web_view_; | |
209 } | |
210 | |
211 bool NativeAppWindowViews::CanResize() const { | |
212 return resizable_ && !size_constraints_.HasFixedSize() && | |
213 !WidgetHasHitTestMask(); | |
214 } | |
215 | |
216 bool NativeAppWindowViews::CanMaximize() const { | |
217 return resizable_ && !size_constraints_.HasMaximumSize() && | |
218 !app_window_->window_type_is_panel() && !WidgetHasHitTestMask(); | |
219 } | |
220 | |
221 bool NativeAppWindowViews::CanMinimize() const { | |
222 return true; | |
223 } | |
224 | |
225 base::string16 NativeAppWindowViews::GetWindowTitle() const { | |
226 return app_window_->GetTitle(); | |
227 } | |
228 | |
229 bool NativeAppWindowViews::ShouldShowWindowTitle() const { | |
230 return app_window_->window_type() == AppWindow::WINDOW_TYPE_V1_PANEL; | |
231 } | |
232 | |
233 bool NativeAppWindowViews::ShouldShowWindowIcon() const { | |
234 return app_window_->window_type() == AppWindow::WINDOW_TYPE_V1_PANEL; | |
235 } | |
236 | |
237 void NativeAppWindowViews::SaveWindowPlacement(const gfx::Rect& bounds, | |
238 ui::WindowShowState show_state) { | |
239 views::WidgetDelegate::SaveWindowPlacement(bounds, show_state); | |
240 app_window_->OnNativeWindowChanged(); | |
241 } | |
242 | |
243 void NativeAppWindowViews::DeleteDelegate() { | |
244 widget_->RemoveObserver(this); | |
245 app_window_->OnNativeClose(); | |
246 } | |
247 | |
248 views::Widget* NativeAppWindowViews::GetWidget() { | |
249 return widget_; | |
250 } | |
251 | |
252 const views::Widget* NativeAppWindowViews::GetWidget() const { | |
253 return widget_; | |
254 } | |
255 | |
256 views::View* NativeAppWindowViews::GetContentsView() { | |
257 return this; | |
258 } | |
259 | |
260 bool NativeAppWindowViews::ShouldDescendIntoChildForEventHandling( | |
261 gfx::NativeView child, | |
262 const gfx::Point& location) { | |
263 #if defined(USE_AURA) | |
264 if (child->Contains(web_view_->web_contents()->GetNativeView())) { | |
265 // App window should claim mouse events that fall within the draggable | |
266 // region. | |
267 return !draggable_region_.get() || | |
268 !draggable_region_->contains(location.x(), location.y()); | |
269 } | |
270 #endif | |
271 | |
272 return true; | |
273 } | |
274 | |
275 // WidgetObserver implementation. | |
276 | |
277 void NativeAppWindowViews::OnWidgetVisibilityChanged(views::Widget* widget, | |
278 bool visible) { | |
279 app_window_->OnNativeWindowChanged(); | |
280 } | |
281 | |
282 void NativeAppWindowViews::OnWidgetActivationChanged(views::Widget* widget, | |
283 bool active) { | |
284 app_window_->OnNativeWindowChanged(); | |
285 if (active) | |
286 app_window_->OnNativeWindowActivated(); | |
287 } | |
288 | |
289 // WebContentsObserver implementation. | |
290 | |
291 void NativeAppWindowViews::RenderViewCreated( | |
292 content::RenderViewHost* render_view_host) { | |
293 if (app_window_->requested_alpha_enabled() && CanHaveAlphaEnabled()) { | |
294 content::RenderWidgetHostView* view = render_view_host->GetView(); | |
295 DCHECK(view); | |
296 view->SetBackgroundOpaque(false); | |
297 } | |
298 } | |
299 | |
300 void NativeAppWindowViews::RenderViewHostChanged( | |
301 content::RenderViewHost* old_host, | |
302 content::RenderViewHost* new_host) { | |
303 OnViewWasResized(); | |
304 } | |
305 | |
306 // views::View implementation. | |
307 | |
308 void NativeAppWindowViews::Layout() { | |
309 DCHECK(web_view_); | |
310 web_view_->SetBounds(0, 0, width(), height()); | |
311 OnViewWasResized(); | |
312 } | |
313 | |
314 void NativeAppWindowViews::ViewHierarchyChanged( | |
315 const ViewHierarchyChangedDetails& details) { | |
316 if (details.is_add && details.child == this) { | |
317 web_view_ = new views::WebView(NULL); | |
318 AddChildView(web_view_); | |
319 web_view_->SetWebContents(app_window_->web_contents()); | |
320 } | |
321 } | |
322 | |
323 gfx::Size NativeAppWindowViews::GetMinimumSize() const { | |
324 return size_constraints_.GetMinimumSize(); | |
325 } | |
326 | |
327 gfx::Size NativeAppWindowViews::GetMaximumSize() const { | |
328 return size_constraints_.GetMaximumSize(); | |
329 } | |
330 | |
331 void NativeAppWindowViews::OnFocus() { | |
332 web_view_->RequestFocus(); | |
333 } | |
334 | |
335 // NativeAppWindow implementation. | |
336 | |
337 void NativeAppWindowViews::SetFullscreen(int fullscreen_types) { | |
338 // Stub implementation. See also ChromeNativeAppWindowViews. | |
339 widget_->SetFullscreen(fullscreen_types != AppWindow::FULLSCREEN_TYPE_NONE); | |
340 } | |
341 | |
342 bool NativeAppWindowViews::IsFullscreenOrPending() const { | |
343 // Stub implementation. See also ChromeNativeAppWindowViews. | |
344 return widget_->IsFullscreen(); | |
345 } | |
346 | |
347 void NativeAppWindowViews::UpdateWindowIcon() { | |
348 widget_->UpdateWindowIcon(); | |
349 } | |
350 | |
351 void NativeAppWindowViews::UpdateWindowTitle() { | |
352 widget_->UpdateWindowTitle(); | |
353 } | |
354 | |
355 void NativeAppWindowViews::UpdateBadgeIcon() { | |
356 // Stub implementation. See also ChromeNativeAppWindowViews. | |
357 } | |
358 | |
359 void NativeAppWindowViews::UpdateDraggableRegions( | |
360 const std::vector<extensions::DraggableRegion>& regions) { | |
361 // Draggable region is not supported for non-frameless window. | |
362 if (!frameless_) | |
363 return; | |
364 | |
365 draggable_region_.reset(AppWindow::RawDraggableRegionsToSkRegion(regions)); | |
366 OnViewWasResized(); | |
367 } | |
368 | |
369 SkRegion* NativeAppWindowViews::GetDraggableRegion() { | |
370 return draggable_region_.get(); | |
371 } | |
372 | |
373 void NativeAppWindowViews::UpdateShape(scoped_ptr<SkRegion> region) { | |
374 // Stub implementation. See also ChromeNativeAppWindowViews. | |
375 } | |
376 | |
377 void NativeAppWindowViews::HandleKeyboardEvent( | |
378 const content::NativeWebKeyboardEvent& event) { | |
379 unhandled_keyboard_event_handler_.HandleKeyboardEvent(event, | |
380 GetFocusManager()); | |
381 } | |
382 | |
383 bool NativeAppWindowViews::IsFrameless() const { | |
384 return frameless_; | |
385 } | |
386 | |
387 bool NativeAppWindowViews::HasFrameColor() const { | |
388 return false; | |
389 } | |
390 | |
391 SkColor NativeAppWindowViews::ActiveFrameColor() const { | |
392 return SK_ColorBLACK; | |
393 } | |
394 | |
395 SkColor NativeAppWindowViews::InactiveFrameColor() const { | |
396 return SK_ColorBLACK; | |
397 } | |
398 | |
399 gfx::Insets NativeAppWindowViews::GetFrameInsets() const { | |
400 if (frameless_) | |
401 return gfx::Insets(); | |
402 | |
403 // The pretend client_bounds passed in need to be large enough to ensure that | |
404 // GetWindowBoundsForClientBounds() doesn't decide that it needs more than | |
405 // the specified amount of space to fit the window controls in, and return a | |
406 // number larger than the real frame insets. Most window controls are smaller | |
407 // than 1000x1000px, so this should be big enough. | |
408 gfx::Rect client_bounds = gfx::Rect(1000, 1000); | |
409 gfx::Rect window_bounds = | |
410 widget_->non_client_view()->GetWindowBoundsForClientBounds(client_bounds); | |
411 return window_bounds.InsetsFrom(client_bounds); | |
412 } | |
413 | |
414 void NativeAppWindowViews::HideWithApp() { | |
415 } | |
416 | |
417 void NativeAppWindowViews::ShowWithApp() { | |
418 } | |
419 | |
420 void NativeAppWindowViews::UpdateShelfMenu() { | |
421 } | |
422 | |
423 gfx::Size NativeAppWindowViews::GetContentMinimumSize() const { | |
424 return size_constraints_.GetMinimumSize(); | |
425 } | |
426 | |
427 gfx::Size NativeAppWindowViews::GetContentMaximumSize() const { | |
428 return size_constraints_.GetMaximumSize(); | |
429 } | |
430 | |
431 void NativeAppWindowViews::SetContentSizeConstraints( | |
432 const gfx::Size& min_size, | |
433 const gfx::Size& max_size) { | |
434 size_constraints_.set_minimum_size(min_size); | |
435 size_constraints_.set_maximum_size(max_size); | |
436 widget_->OnSizeConstraintsChanged(); | |
437 } | |
438 | |
439 bool NativeAppWindowViews::CanHaveAlphaEnabled() const { | |
440 return widget_->IsTranslucentWindowOpacitySupported(); | |
441 } | |
442 | |
443 void NativeAppWindowViews::SetVisibleOnAllWorkspaces(bool always_visible) { | |
444 widget_->SetVisibleOnAllWorkspaces(always_visible); | |
445 } | |
446 | |
447 } // namespace native_app_window | |
OLD | NEW |