OLD | NEW |
| (Empty) |
1 // Copyright 2015 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 // This has to be before any other includes, else default is picked up. | |
6 // See base/logging for details on this. | |
7 #define NOTIMPLEMENTED_POLICY 5 | |
8 | |
9 #include "ui/views/mus/native_widget_mus.h" | |
10 | |
11 #include <map> | |
12 #include <utility> | |
13 #include <vector> | |
14 | |
15 #include "base/callback.h" | |
16 #include "base/macros.h" | |
17 #include "base/memory/ptr_util.h" | |
18 #include "base/message_loop/message_loop.h" | |
19 #include "base/run_loop.h" | |
20 #include "base/threading/thread_task_runner_handle.h" | |
21 #include "services/ui/public/cpp/property_type_converters.h" | |
22 #include "services/ui/public/cpp/window.h" | |
23 #include "services/ui/public/cpp/window_observer.h" | |
24 #include "services/ui/public/cpp/window_property.h" | |
25 #include "services/ui/public/cpp/window_tree_client.h" | |
26 #include "services/ui/public/interfaces/cursor.mojom.h" | |
27 #include "services/ui/public/interfaces/window_manager.mojom.h" | |
28 #include "services/ui/public/interfaces/window_manager_constants.mojom.h" | |
29 #include "services/ui/public/interfaces/window_tree.mojom.h" | |
30 #include "ui/aura/client/default_capture_client.h" | |
31 #include "ui/aura/client/window_parenting_client.h" | |
32 #include "ui/aura/layout_manager.h" | |
33 #include "ui/aura/mus/mus_util.h" | |
34 #include "ui/aura/mus/property_converter.h" | |
35 #include "ui/aura/window.h" | |
36 #include "ui/aura/window_property.h" | |
37 #include "ui/base/hit_test.h" | |
38 #include "ui/display/display.h" | |
39 #include "ui/display/screen.h" | |
40 #include "ui/events/event.h" | |
41 #include "ui/gfx/canvas.h" | |
42 #include "ui/gfx/geometry/dip_util.h" | |
43 #include "ui/gfx/path.h" | |
44 #include "ui/native_theme/native_theme.h" | |
45 #include "ui/platform_window/platform_window_delegate.h" | |
46 #include "ui/views/corewm/tooltip.h" | |
47 #include "ui/views/corewm/tooltip_aura.h" | |
48 #include "ui/views/corewm/tooltip_controller.h" | |
49 #include "ui/views/drag_utils.h" | |
50 #include "ui/views/mus/drag_drop_client_mus.h" | |
51 #include "ui/views/mus/drop_target_mus.h" | |
52 #include "ui/views/mus/input_method_mus.h" | |
53 #include "ui/views/mus/window_manager_connection.h" | |
54 #include "ui/views/mus/window_manager_constants_converters.h" | |
55 #include "ui/views/mus/window_manager_frame_values.h" | |
56 #include "ui/views/mus/window_tree_host_mus.h" | |
57 #include "ui/views/widget/drop_helper.h" | |
58 #include "ui/views/widget/native_widget_aura.h" | |
59 #include "ui/views/widget/tooltip_manager_aura.h" | |
60 #include "ui/views/widget/widget_delegate.h" | |
61 #include "ui/views/window/custom_frame_view.h" | |
62 #include "ui/wm/core/base_focus_rules.h" | |
63 #include "ui/wm/core/capture_controller.h" | |
64 #include "ui/wm/core/cursor_manager.h" | |
65 #include "ui/wm/core/default_screen_position_client.h" | |
66 #include "ui/wm/core/focus_controller.h" | |
67 #include "ui/wm/core/native_cursor_manager.h" | |
68 | |
69 DECLARE_WINDOW_PROPERTY_TYPE(ui::Window*); | |
70 | |
71 using PrimitiveType = aura::PropertyConverter::PrimitiveType; | |
72 using ui::mojom::EventResult; | |
73 | |
74 namespace views { | |
75 namespace { | |
76 | |
77 DEFINE_WINDOW_PROPERTY_KEY(ui::Window*, kMusWindow, nullptr); | |
78 | |
79 MUS_DEFINE_WINDOW_PROPERTY_KEY(NativeWidgetMus*, kNativeWidgetMusKey, nullptr); | |
80 | |
81 // This ensures that only the top-level aura Window can be activated. | |
82 class FocusRulesImpl : public wm::BaseFocusRules { | |
83 public: | |
84 explicit FocusRulesImpl(aura::Window* root) : root_(root) {} | |
85 ~FocusRulesImpl() override {} | |
86 | |
87 bool SupportsChildActivation(aura::Window* window) const override { | |
88 return root_ == window; | |
89 } | |
90 | |
91 private: | |
92 aura::Window* root_; | |
93 | |
94 DISALLOW_COPY_AND_ASSIGN(FocusRulesImpl); | |
95 }; | |
96 | |
97 // This makes sure that an aura::Window focused (or activated) through the | |
98 // aura::client::FocusClient (or ActivationClient) focuses (or activates) the | |
99 // corresponding ui::Window too. | |
100 class FocusControllerMus : public wm::FocusController { | |
101 public: | |
102 explicit FocusControllerMus(wm::FocusRules* rules) : FocusController(rules) {} | |
103 ~FocusControllerMus() override {} | |
104 | |
105 private: | |
106 void FocusWindow(aura::Window* window) override { | |
107 FocusController::FocusWindow(window); | |
108 if (window) { | |
109 ui::Window* mus_window = window->GetRootWindow()->GetProperty(kMusWindow); | |
110 if (mus_window) | |
111 mus_window->SetFocus(); | |
112 } | |
113 } | |
114 | |
115 DISALLOW_COPY_AND_ASSIGN(FocusControllerMus); | |
116 }; | |
117 | |
118 class ContentWindowLayoutManager : public aura::LayoutManager { | |
119 public: | |
120 ContentWindowLayoutManager(aura::Window* outer, aura::Window* inner) | |
121 : outer_(outer), inner_(inner) {} | |
122 ~ContentWindowLayoutManager() override {} | |
123 | |
124 private: | |
125 // aura::LayoutManager: | |
126 void OnWindowResized() override { inner_->SetBounds(outer_->bounds()); } | |
127 void OnWindowAddedToLayout(aura::Window* child) override { | |
128 OnWindowResized(); | |
129 } | |
130 void OnWillRemoveWindowFromLayout(aura::Window* child) override {} | |
131 void OnWindowRemovedFromLayout(aura::Window* child) override {} | |
132 void OnChildWindowVisibilityChanged(aura::Window* child, | |
133 bool visible) override {} | |
134 void SetChildBounds(aura::Window* child, | |
135 const gfx::Rect& requested_bounds) override { | |
136 SetChildBoundsDirect(child, requested_bounds); | |
137 } | |
138 | |
139 aura::Window* outer_; | |
140 aura::Window* inner_; | |
141 | |
142 DISALLOW_COPY_AND_ASSIGN(ContentWindowLayoutManager); | |
143 }; | |
144 | |
145 class NativeWidgetMusWindowParentingClient | |
146 : public aura::client::WindowParentingClient { | |
147 public: | |
148 explicit NativeWidgetMusWindowParentingClient(aura::Window* root_window) | |
149 : root_window_(root_window) { | |
150 aura::client::SetWindowParentingClient(root_window_, this); | |
151 } | |
152 ~NativeWidgetMusWindowParentingClient() override { | |
153 aura::client::SetWindowParentingClient(root_window_, nullptr); | |
154 } | |
155 | |
156 // Overridden from client::WindowParentingClient: | |
157 aura::Window* GetDefaultParent(aura::Window* context, | |
158 aura::Window* window, | |
159 const gfx::Rect& bounds) override { | |
160 return root_window_; | |
161 } | |
162 | |
163 private: | |
164 aura::Window* root_window_; | |
165 | |
166 DISALLOW_COPY_AND_ASSIGN(NativeWidgetMusWindowParentingClient); | |
167 }; | |
168 | |
169 // A screen position client that applies the offset of the ui::Window. | |
170 class ScreenPositionClientMus : public wm::DefaultScreenPositionClient { | |
171 public: | |
172 explicit ScreenPositionClientMus(ui::Window* mus_window) | |
173 : mus_window_(mus_window) {} | |
174 ~ScreenPositionClientMus() override {} | |
175 | |
176 // wm::DefaultScreenPositionClient: | |
177 void ConvertPointToScreen(const aura::Window* window, | |
178 gfx::Point* point) override { | |
179 wm::DefaultScreenPositionClient::ConvertPointToScreen(window, point); | |
180 gfx::Rect mus_bounds = mus_window_->GetBoundsInRoot(); | |
181 point->Offset(-mus_bounds.x(), -mus_bounds.y()); | |
182 } | |
183 void ConvertPointFromScreen(const aura::Window* window, | |
184 gfx::Point* point) override { | |
185 gfx::Rect mus_bounds = mus_window_->GetBoundsInRoot(); | |
186 point->Offset(mus_bounds.x(), mus_bounds.y()); | |
187 wm::DefaultScreenPositionClient::ConvertPointFromScreen(window, point); | |
188 } | |
189 | |
190 private: | |
191 ui::Window* mus_window_; | |
192 | |
193 DISALLOW_COPY_AND_ASSIGN(ScreenPositionClientMus); | |
194 }; | |
195 | |
196 class NativeCursorManagerMus : public wm::NativeCursorManager { | |
197 public: | |
198 explicit NativeCursorManagerMus(ui::Window* mus_window) | |
199 : mus_window_(mus_window) {} | |
200 ~NativeCursorManagerMus() override {} | |
201 | |
202 // wm::NativeCursorManager: | |
203 void SetDisplay(const display::Display& display, | |
204 wm::NativeCursorManagerDelegate* delegate) override { | |
205 // We ignore this entirely, as cursor are set on the client. | |
206 } | |
207 | |
208 void SetCursor(gfx::NativeCursor cursor, | |
209 wm::NativeCursorManagerDelegate* delegate) override { | |
210 mus_window_->SetPredefinedCursor(ui::mojom::Cursor(cursor.native_type())); | |
211 delegate->CommitCursor(cursor); | |
212 } | |
213 | |
214 void SetVisibility(bool visible, | |
215 wm::NativeCursorManagerDelegate* delegate) override { | |
216 delegate->CommitVisibility(visible); | |
217 | |
218 if (visible) | |
219 SetCursor(delegate->GetCursor(), delegate); | |
220 else | |
221 mus_window_->SetPredefinedCursor(ui::mojom::Cursor::NONE); | |
222 } | |
223 | |
224 void SetCursorSet(ui::CursorSetType cursor_set, | |
225 wm::NativeCursorManagerDelegate* delegate) override { | |
226 // TODO(erg): For now, ignore the difference between SET_NORMAL and | |
227 // SET_LARGE here. This feels like a thing that mus should decide instead. | |
228 // | |
229 // Also, it's NOTIMPLEMENTED() in the desktop version!? Including not | |
230 // acknowledging the call in the delegate. | |
231 NOTIMPLEMENTED(); | |
232 } | |
233 | |
234 void SetMouseEventsEnabled( | |
235 bool enabled, | |
236 wm::NativeCursorManagerDelegate* delegate) override { | |
237 // TODO(erg): How do we actually implement this? | |
238 // | |
239 // Mouse event dispatch is potentially done in a different process, | |
240 // definitely in a different mojo service. Each app is fairly locked down. | |
241 delegate->CommitMouseEventsEnabled(enabled); | |
242 NOTIMPLEMENTED(); | |
243 } | |
244 | |
245 private: | |
246 ui::Window* mus_window_; | |
247 | |
248 DISALLOW_COPY_AND_ASSIGN(NativeCursorManagerMus); | |
249 }; | |
250 | |
251 // As the window manager renderers the non-client decorations this class does | |
252 // very little but honor the client area insets from the window manager. | |
253 class ClientSideNonClientFrameView : public NonClientFrameView { | |
254 public: | |
255 explicit ClientSideNonClientFrameView(views::Widget* widget) | |
256 : widget_(widget) {} | |
257 ~ClientSideNonClientFrameView() override {} | |
258 | |
259 private: | |
260 // Returns the default values of client area insets from the window manager. | |
261 static gfx::Insets GetDefaultWindowManagerInsets(bool is_maximized) { | |
262 const WindowManagerFrameValues& values = | |
263 WindowManagerFrameValues::instance(); | |
264 return is_maximized ? values.maximized_insets : values.normal_insets; | |
265 } | |
266 | |
267 // NonClientFrameView: | |
268 gfx::Rect GetBoundsForClientView() const override { | |
269 gfx::Rect result(GetLocalBounds()); | |
270 if (widget_->IsFullscreen()) | |
271 return result; | |
272 result.Inset(GetDefaultWindowManagerInsets(widget_->IsMaximized())); | |
273 return result; | |
274 } | |
275 gfx::Rect GetWindowBoundsForClientBounds( | |
276 const gfx::Rect& client_bounds) const override { | |
277 if (widget_->IsFullscreen()) | |
278 return client_bounds; | |
279 | |
280 const gfx::Insets insets( | |
281 GetDefaultWindowManagerInsets(widget_->IsMaximized())); | |
282 return gfx::Rect(client_bounds.x() - insets.left(), | |
283 client_bounds.y() - insets.top(), | |
284 client_bounds.width() + insets.width(), | |
285 client_bounds.height() + insets.height()); | |
286 } | |
287 int NonClientHitTest(const gfx::Point& point) override { return HTNOWHERE; } | |
288 void GetWindowMask(const gfx::Size& size, gfx::Path* window_mask) override { | |
289 // The window manager provides the shape; do nothing. | |
290 } | |
291 void ResetWindowControls() override { | |
292 // TODO(sky): push to wm? | |
293 } | |
294 | |
295 // These have no implementation. The Window Manager handles the actual | |
296 // rendering of the icon/title. See NonClientFrameViewMash. The values | |
297 // associated with these methods are pushed to the server by the way of | |
298 // NativeWidgetMus functions. | |
299 void UpdateWindowIcon() override {} | |
300 void UpdateWindowTitle() override {} | |
301 void SizeConstraintsChanged() override {} | |
302 | |
303 gfx::Size GetPreferredSize() const override { | |
304 return widget_->non_client_view() | |
305 ->GetWindowBoundsForClientBounds( | |
306 gfx::Rect(widget_->client_view()->GetPreferredSize())) | |
307 .size(); | |
308 } | |
309 gfx::Size GetMinimumSize() const override { | |
310 return widget_->non_client_view() | |
311 ->GetWindowBoundsForClientBounds( | |
312 gfx::Rect(widget_->client_view()->GetMinimumSize())) | |
313 .size(); | |
314 } | |
315 gfx::Size GetMaximumSize() const override { | |
316 gfx::Size max_size = widget_->client_view()->GetMaximumSize(); | |
317 gfx::Size converted_size = | |
318 widget_->non_client_view() | |
319 ->GetWindowBoundsForClientBounds(gfx::Rect(max_size)) | |
320 .size(); | |
321 return gfx::Size(max_size.width() == 0 ? 0 : converted_size.width(), | |
322 max_size.height() == 0 ? 0 : converted_size.height()); | |
323 } | |
324 | |
325 views::Widget* widget_; | |
326 | |
327 DISALLOW_COPY_AND_ASSIGN(ClientSideNonClientFrameView); | |
328 }; | |
329 | |
330 // Handles acknowledgment of an input event, either immediately when a nested | |
331 // message loop starts, or upon destruction. | |
332 class EventAckHandler : public base::MessageLoop::NestingObserver { | |
333 public: | |
334 explicit EventAckHandler( | |
335 std::unique_ptr<base::Callback<void(EventResult)>> ack_callback) | |
336 : ack_callback_(std::move(ack_callback)) { | |
337 DCHECK(ack_callback_); | |
338 base::MessageLoop::current()->AddNestingObserver(this); | |
339 } | |
340 | |
341 ~EventAckHandler() override { | |
342 base::MessageLoop::current()->RemoveNestingObserver(this); | |
343 if (ack_callback_) { | |
344 ack_callback_->Run(handled_ ? EventResult::HANDLED | |
345 : EventResult::UNHANDLED); | |
346 } | |
347 } | |
348 | |
349 void set_handled(bool handled) { handled_ = handled; } | |
350 | |
351 // base::MessageLoop::NestingObserver: | |
352 void OnBeginNestedMessageLoop() override { | |
353 // Acknowledge the event immediately if a nested message loop starts. | |
354 // Otherwise we appear unresponsive for the life of the nested message loop. | |
355 if (ack_callback_) { | |
356 ack_callback_->Run(EventResult::HANDLED); | |
357 ack_callback_.reset(); | |
358 } | |
359 } | |
360 | |
361 private: | |
362 std::unique_ptr<base::Callback<void(EventResult)>> ack_callback_; | |
363 bool handled_ = false; | |
364 | |
365 DISALLOW_COPY_AND_ASSIGN(EventAckHandler); | |
366 }; | |
367 | |
368 void OnMoveLoopEnd(bool* out_success, | |
369 base::Closure quit_closure, | |
370 bool in_success) { | |
371 *out_success = in_success; | |
372 quit_closure.Run(); | |
373 } | |
374 | |
375 ui::mojom::ShowState GetShowState(const ui::Window* window) { | |
376 if (!window || | |
377 !window->HasSharedProperty( | |
378 ui::mojom::WindowManager::kShowState_Property)) { | |
379 return ui::mojom::ShowState::DEFAULT; | |
380 } | |
381 | |
382 return static_cast<ui::mojom::ShowState>( | |
383 window->GetSharedProperty<PrimitiveType>( | |
384 ui::mojom::WindowManager::kShowState_Property)); | |
385 } | |
386 | |
387 // Set the app or window icon property for the window. | |
388 void SetIconProperty(ui::Window* window, | |
389 const char* const property, | |
390 const gfx::ImageSkia& icon) { | |
391 // TODO(crbug.com/667566): Support additional scales or gfx::Image[Skia]. | |
392 SkBitmap bitmap = icon.GetRepresentation(1.f).sk_bitmap(); | |
393 if (!bitmap.isNull()) | |
394 window->SetSharedProperty<SkBitmap>(property, bitmap); | |
395 else if (window->HasSharedProperty(property)) | |
396 window->ClearSharedProperty(property); | |
397 } | |
398 | |
399 // Helper function to get the device_scale_factor() of the display::Display | |
400 // nearest to |window|. | |
401 float ScaleFactorForDisplay(aura::Window* window) { | |
402 return display::Screen::GetScreen() | |
403 ->GetDisplayNearestWindow(window) | |
404 .device_scale_factor(); | |
405 } | |
406 | |
407 } // namespace | |
408 | |
409 class NativeWidgetMus::MusWindowObserver : public ui::WindowObserver { | |
410 public: | |
411 explicit MusWindowObserver(NativeWidgetMus* native_widget_mus) | |
412 : native_widget_mus_(native_widget_mus), | |
413 show_state_(ui::mojom::ShowState::DEFAULT) { | |
414 mus_window()->AddObserver(this); | |
415 } | |
416 | |
417 ~MusWindowObserver() override { | |
418 mus_window()->RemoveObserver(this); | |
419 } | |
420 | |
421 // ui::WindowObserver: | |
422 void OnWindowVisibilityChanging(ui::Window* window, bool visible) override { | |
423 native_widget_mus_->OnMusWindowVisibilityChanging(window, visible); | |
424 } | |
425 void OnWindowVisibilityChanged(ui::Window* window, bool visible) override { | |
426 native_widget_mus_->OnMusWindowVisibilityChanged(window, visible); | |
427 } | |
428 void OnWindowPredefinedCursorChanged(ui::Window* window, | |
429 ui::mojom::Cursor cursor) override { | |
430 DCHECK_EQ(window, mus_window()); | |
431 native_widget_mus_->set_last_cursor(cursor); | |
432 } | |
433 void OnWindowSharedPropertyChanged( | |
434 ui::Window* window, | |
435 const std::string& name, | |
436 const std::vector<uint8_t>* old_data, | |
437 const std::vector<uint8_t>* new_data) override { | |
438 if (name != ui::mojom::WindowManager::kShowState_Property) | |
439 return; | |
440 const ui::mojom::ShowState show_state = GetShowState(window); | |
441 if (show_state == show_state_) | |
442 return; | |
443 show_state_ = show_state; | |
444 ui::PlatformWindowState state = ui::PLATFORM_WINDOW_STATE_UNKNOWN; | |
445 switch (show_state_) { | |
446 case ui::mojom::ShowState::MINIMIZED: | |
447 state = ui::PLATFORM_WINDOW_STATE_MINIMIZED; | |
448 break; | |
449 case ui::mojom::ShowState::MAXIMIZED: | |
450 state = ui::PLATFORM_WINDOW_STATE_MAXIMIZED; | |
451 break; | |
452 case ui::mojom::ShowState::DEFAULT: | |
453 case ui::mojom::ShowState::INACTIVE: | |
454 case ui::mojom::ShowState::NORMAL: | |
455 case ui::mojom::ShowState::DOCKED: | |
456 // TODO(sky): support docked. | |
457 state = ui::PLATFORM_WINDOW_STATE_NORMAL; | |
458 break; | |
459 case ui::mojom::ShowState::FULLSCREEN: | |
460 state = ui::PLATFORM_WINDOW_STATE_FULLSCREEN; | |
461 break; | |
462 } | |
463 platform_window_delegate()->OnWindowStateChanged(state); | |
464 } | |
465 void OnWindowDestroyed(ui::Window* window) override { | |
466 DCHECK_EQ(mus_window(), window); | |
467 platform_window_delegate()->OnClosed(); | |
468 } | |
469 void OnWindowBoundsChanging(ui::Window* window, | |
470 const gfx::Rect& old_bounds, | |
471 const gfx::Rect& new_bounds) override { | |
472 DCHECK_EQ(window, mus_window()); | |
473 window_tree_host()->SetBoundsInPixels(gfx::ConvertRectToPixel( | |
474 ScaleFactorForDisplay(aura_window()), new_bounds)); | |
475 } | |
476 void OnWindowFocusChanged(ui::Window* gained_focus, | |
477 ui::Window* lost_focus) override { | |
478 if (gained_focus == mus_window()) | |
479 platform_window_delegate()->OnActivationChanged(true); | |
480 else if (lost_focus == mus_window()) | |
481 platform_window_delegate()->OnActivationChanged(false); | |
482 } | |
483 void OnRequestClose(ui::Window* window) override { | |
484 platform_window_delegate()->OnCloseRequest(); | |
485 } | |
486 | |
487 private: | |
488 ui::Window* mus_window() { return native_widget_mus_->window(); } | |
489 aura::Window* aura_window() { return native_widget_mus_->aura_window(); } | |
490 WindowTreeHostMus* window_tree_host() { | |
491 return native_widget_mus_->window_tree_host(); | |
492 } | |
493 ui::PlatformWindowDelegate* platform_window_delegate() { | |
494 return native_widget_mus_->window_tree_host(); | |
495 } | |
496 | |
497 NativeWidgetMus* native_widget_mus_; | |
498 ui::mojom::ShowState show_state_; | |
499 | |
500 DISALLOW_COPY_AND_ASSIGN(MusWindowObserver); | |
501 }; | |
502 | |
503 class NativeWidgetMus::MusCaptureClient | |
504 : public aura::client::DefaultCaptureClient { | |
505 public: | |
506 MusCaptureClient(aura::Window* root_window, | |
507 aura::Window* aura_window, | |
508 ui::Window* mus_window) | |
509 : aura::client::DefaultCaptureClient(root_window), | |
510 aura_window_(aura_window), | |
511 mus_window_(mus_window) {} | |
512 ~MusCaptureClient() override {} | |
513 | |
514 // aura::client::DefaultCaptureClient: | |
515 void SetCapture(aura::Window* window) override { | |
516 aura::client::DefaultCaptureClient::SetCapture(window); | |
517 if (aura_window_ == window) | |
518 mus_window_->SetCapture(); | |
519 } | |
520 void ReleaseCapture(aura::Window* window) override { | |
521 aura::client::DefaultCaptureClient::ReleaseCapture(window); | |
522 if (aura_window_ == window) | |
523 mus_window_->ReleaseCapture(); | |
524 } | |
525 | |
526 private: | |
527 aura::Window* aura_window_; | |
528 ui::Window* mus_window_; | |
529 | |
530 DISALLOW_COPY_AND_ASSIGN(MusCaptureClient); | |
531 }; | |
532 | |
533 //////////////////////////////////////////////////////////////////////////////// | |
534 // NativeWidgetMus, public: | |
535 | |
536 NativeWidgetMus::NativeWidgetMus( | |
537 internal::NativeWidgetDelegate* delegate, | |
538 ui::Window* window, | |
539 ui::mojom::CompositorFrameSinkType compositor_frame_sink_type) | |
540 : window_(window), | |
541 last_cursor_(ui::mojom::Cursor::CURSOR_NULL), | |
542 native_widget_delegate_(delegate), | |
543 compositor_frame_sink_type_(compositor_frame_sink_type), | |
544 show_state_before_fullscreen_(ui::mojom::ShowState::DEFAULT), | |
545 ownership_(Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET), | |
546 content_(new aura::Window(this)), | |
547 last_drop_operation_(ui::DragDropTypes::DRAG_NONE), | |
548 close_widget_factory_(this) { | |
549 window_->set_input_event_handler(this); | |
550 mus_window_observer_ = base::MakeUnique<MusWindowObserver>(this); | |
551 | |
552 // TODO(fsamuel): Figure out lifetime of |window_|. | |
553 aura::SetMusWindow(content_, window_); | |
554 window->SetLocalProperty(kNativeWidgetMusKey, this); | |
555 window_tree_host_ = base::MakeUnique<WindowTreeHostMus>(this, window_); | |
556 input_method_ = | |
557 base::MakeUnique<InputMethodMus>(window_tree_host_.get(), window_); | |
558 window_tree_host_->SetSharedInputMethod(input_method_.get()); | |
559 } | |
560 | |
561 NativeWidgetMus::~NativeWidgetMus() { | |
562 if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET) { | |
563 DCHECK(!window_); | |
564 delete native_widget_delegate_; | |
565 } else { | |
566 if (window_) | |
567 window_->set_input_event_handler(nullptr); | |
568 CloseNow(); | |
569 } | |
570 } | |
571 | |
572 // static | |
573 void NativeWidgetMus::NotifyFrameChanged(ui::WindowTreeClient* client) { | |
574 for (ui::Window* window : client->GetRoots()) { | |
575 NativeWidgetMus* native_widget = | |
576 window->GetLocalProperty(kNativeWidgetMusKey); | |
577 if (native_widget && native_widget->GetWidget()->non_client_view()) { | |
578 native_widget->GetWidget()->non_client_view()->Layout(); | |
579 native_widget->GetWidget()->non_client_view()->SchedulePaint(); | |
580 native_widget->UpdateClientArea(); | |
581 native_widget->UpdateHitTestMask(); | |
582 } | |
583 } | |
584 } | |
585 | |
586 // static | |
587 NativeWidgetMus* NativeWidgetMus::GetForWindow(ui::Window* window) { | |
588 DCHECK(window); | |
589 NativeWidgetMus* native_widget = | |
590 window->GetLocalProperty(kNativeWidgetMusKey); | |
591 return native_widget; | |
592 } | |
593 | |
594 // static | |
595 Widget* NativeWidgetMus::GetWidgetForWindow(ui::Window* window) { | |
596 NativeWidgetMus* native_widget = GetForWindow(window); | |
597 if (!native_widget) | |
598 return nullptr; | |
599 return native_widget->GetWidget(); | |
600 } | |
601 | |
602 aura::Window* NativeWidgetMus::GetRootWindow() { | |
603 return window_tree_host_->window(); | |
604 } | |
605 | |
606 void NativeWidgetMus::OnPlatformWindowClosed() { | |
607 native_widget_delegate_->OnNativeWidgetDestroying(); | |
608 | |
609 tooltip_manager_.reset(); | |
610 if (tooltip_controller_.get()) { | |
611 window_tree_host_->window()->RemovePreTargetHandler( | |
612 tooltip_controller_.get()); | |
613 aura::client::SetTooltipClient(window_tree_host_->window(), NULL); | |
614 tooltip_controller_.reset(); | |
615 } | |
616 | |
617 window_parenting_client_.reset(); // Uses |content_|. | |
618 capture_client_.reset(); // Uses |content_|. | |
619 | |
620 window_tree_host_->RemoveObserver(this); | |
621 window_tree_host_.reset(); | |
622 | |
623 cursor_manager_.reset(); // Uses |window_|. | |
624 | |
625 mus_window_observer_.reset(nullptr); | |
626 | |
627 window_ = nullptr; | |
628 content_ = nullptr; | |
629 | |
630 native_widget_delegate_->OnNativeWidgetDestroyed(); | |
631 if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET) | |
632 delete this; | |
633 } | |
634 | |
635 void NativeWidgetMus::OnActivationChanged(bool active) { | |
636 if (!native_widget_delegate_) | |
637 return; | |
638 if (active) { | |
639 native_widget_delegate_->OnNativeFocus(); | |
640 GetWidget()->GetFocusManager()->RestoreFocusedView(); | |
641 } else { | |
642 native_widget_delegate_->OnNativeBlur(); | |
643 GetWidget()->GetFocusManager()->StoreFocusedView(true); | |
644 } | |
645 native_widget_delegate_->OnNativeWidgetActivationChanged(active); | |
646 } | |
647 | |
648 void NativeWidgetMus::UpdateClientArea() { | |
649 if (is_parallel_widget_in_window_manager()) | |
650 return; | |
651 | |
652 NonClientView* non_client_view = | |
653 native_widget_delegate_->AsWidget()->non_client_view(); | |
654 if (!non_client_view || !non_client_view->client_view()) | |
655 return; | |
656 | |
657 const gfx::Rect client_area_rect(non_client_view->client_view()->bounds()); | |
658 window_->SetClientArea(gfx::Insets( | |
659 client_area_rect.y(), client_area_rect.x(), | |
660 non_client_view->bounds().height() - client_area_rect.bottom(), | |
661 non_client_view->bounds().width() - client_area_rect.right())); | |
662 } | |
663 | |
664 //////////////////////////////////////////////////////////////////////////////// | |
665 // NativeWidgetMus, private: | |
666 | |
667 // static | |
668 void NativeWidgetMus::ConfigurePropertiesForNewWindow( | |
669 const Widget::InitParams& init_params, | |
670 std::map<std::string, std::vector<uint8_t>>* properties) { | |
671 properties->insert(init_params.mus_properties.begin(), | |
672 init_params.mus_properties.end()); | |
673 if (!init_params.bounds.IsEmpty()) { | |
674 (*properties)[ui::mojom::WindowManager::kBounds_InitProperty] = | |
675 mojo::ConvertTo<std::vector<uint8_t>>(init_params.bounds); | |
676 } | |
677 if (!init_params.name.empty()) { | |
678 (*properties)[ui::mojom::WindowManager::kName_Property] = | |
679 mojo::ConvertTo<std::vector<uint8_t>>(init_params.name); | |
680 } | |
681 (*properties)[ui::mojom::WindowManager::kAlwaysOnTop_Property] = | |
682 mojo::ConvertTo<std::vector<uint8_t>>( | |
683 static_cast<PrimitiveType>(init_params.keep_on_top)); | |
684 | |
685 (*properties)[ui::mojom::WindowManager::kWindowType_InitProperty] = | |
686 mojo::ConvertTo<std::vector<uint8_t>>( | |
687 static_cast<int32_t>(init_params.type)); | |
688 | |
689 if (!Widget::RequiresNonClientView(init_params.type)) | |
690 return; | |
691 | |
692 if (init_params.delegate) { | |
693 if (properties->count(ui::mojom::WindowManager::kResizeBehavior_Property) == | |
694 0) { | |
695 (*properties)[ui::mojom::WindowManager::kResizeBehavior_Property] = | |
696 mojo::ConvertTo<std::vector<uint8_t>>(static_cast<PrimitiveType>( | |
697 init_params.delegate->GetResizeBehavior())); | |
698 } | |
699 | |
700 // TODO(crbug.com/667566): Support additional scales or gfx::Image[Skia]. | |
701 gfx::ImageSkia app_icon = init_params.delegate->GetWindowAppIcon(); | |
702 SkBitmap app_bitmap = app_icon.GetRepresentation(1.f).sk_bitmap(); | |
703 if (!app_bitmap.isNull()) { | |
704 (*properties)[ui::mojom::WindowManager::kAppIcon_Property] = | |
705 mojo::ConvertTo<std::vector<uint8_t>>(app_bitmap); | |
706 } | |
707 // TODO(crbug.com/667566): Support additional scales or gfx::Image[Skia]. | |
708 gfx::ImageSkia window_icon = init_params.delegate->GetWindowIcon(); | |
709 SkBitmap window_bitmap = window_icon.GetRepresentation(1.f).sk_bitmap(); | |
710 if (!window_bitmap.isNull()) { | |
711 (*properties)[ui::mojom::WindowManager::kWindowIcon_Property] = | |
712 mojo::ConvertTo<std::vector<uint8_t>>(window_bitmap); | |
713 } | |
714 } | |
715 } | |
716 | |
717 //////////////////////////////////////////////////////////////////////////////// | |
718 // NativeWidgetMus, internal::NativeWidgetPrivate implementation: | |
719 | |
720 NonClientFrameView* NativeWidgetMus::CreateNonClientFrameView() { | |
721 return new ClientSideNonClientFrameView(GetWidget()); | |
722 } | |
723 | |
724 void NativeWidgetMus::InitNativeWidget(const Widget::InitParams& params) { | |
725 NativeWidgetAura::RegisterNativeWidgetForWindow(this, content_); | |
726 aura::Window* hosted_window = window_tree_host_->window(); | |
727 | |
728 ownership_ = params.ownership; | |
729 window_->SetCanFocus(params.activatable == | |
730 Widget::InitParams::ACTIVATABLE_YES); | |
731 window_->SetCanAcceptEvents(params.accept_events); | |
732 | |
733 window_tree_host_->AddObserver(this); | |
734 window_tree_host_->InitHost(); | |
735 window_tree_host_->window()->Show(); | |
736 hosted_window->SetProperty(kMusWindow, window_); | |
737 | |
738 // TODO(moshayedi): crbug.com/641039. Investigate whether there are any cases | |
739 // where we need input method but don't have the WindowManagerConnection here. | |
740 if (WindowManagerConnection::Exists()) | |
741 input_method_->Init(WindowManagerConnection::Get()->connector()); | |
742 | |
743 focus_client_ = | |
744 base::MakeUnique<FocusControllerMus>(new FocusRulesImpl(hosted_window)); | |
745 | |
746 aura::client::SetFocusClient(hosted_window, focus_client_.get()); | |
747 aura::client::SetActivationClient(hosted_window, focus_client_.get()); | |
748 screen_position_client_ = base::MakeUnique<ScreenPositionClientMus>(window_); | |
749 aura::client::SetScreenPositionClient(hosted_window, | |
750 screen_position_client_.get()); | |
751 | |
752 drag_drop_client_ = base::MakeUnique<DragDropClientMus>(window_); | |
753 aura::client::SetDragDropClient(hosted_window, drag_drop_client_.get()); | |
754 drop_target_ = base::MakeUnique<DropTargetMus>(content_); | |
755 window_->SetCanAcceptDrops(drop_target_.get()); | |
756 drop_helper_ = base::MakeUnique<DropHelper>(GetWidget()->GetRootView()); | |
757 aura::client::SetDragDropDelegate(content_, this); | |
758 | |
759 if (params.type != Widget::InitParams::TYPE_TOOLTIP) { | |
760 tooltip_manager_ = base::MakeUnique<TooltipManagerAura>(GetWidget()); | |
761 tooltip_controller_ = base::MakeUnique<corewm::TooltipController>( | |
762 base::MakeUnique<corewm::TooltipAura>()); | |
763 aura::client::SetTooltipClient(window_tree_host_->window(), | |
764 tooltip_controller_.get()); | |
765 window_tree_host_->window()->AddPreTargetHandler(tooltip_controller_.get()); | |
766 } | |
767 | |
768 // TODO(erg): Remove this check when ash/mus/move_event_handler.cc's | |
769 // direct usage of ui::Window::SetPredefinedCursor() is switched to a | |
770 // private method on WindowManagerClient. | |
771 if (!is_parallel_widget_in_window_manager()) { | |
772 cursor_manager_ = base::MakeUnique<wm::CursorManager>( | |
773 base::MakeUnique<NativeCursorManagerMus>(window_)); | |
774 aura::client::SetCursorClient(hosted_window, cursor_manager_.get()); | |
775 } | |
776 | |
777 window_parenting_client_ = | |
778 base::MakeUnique<NativeWidgetMusWindowParentingClient>(hosted_window); | |
779 hosted_window->AddPreTargetHandler(focus_client_.get()); | |
780 hosted_window->SetLayoutManager( | |
781 new ContentWindowLayoutManager(hosted_window, content_)); | |
782 capture_client_ = | |
783 base::MakeUnique<MusCaptureClient>(hosted_window, content_, window_); | |
784 | |
785 content_->SetType(ui::wm::WINDOW_TYPE_NORMAL); | |
786 content_->Init(params.layer_type); | |
787 if (window_->visible()) | |
788 content_->Show(); | |
789 content_->SetTransparent(true); | |
790 content_->SetFillsBoundsCompletely(false); | |
791 content_->set_ignore_events(!params.accept_events); | |
792 hosted_window->AddChild(content_); | |
793 | |
794 ui::Window* parent_mus = params.parent_mus; | |
795 | |
796 // Set-up transiency if appropriate. | |
797 if (params.parent && !params.child) { | |
798 aura::Window* parent_root_aura = params.parent->GetRootWindow(); | |
799 ui::Window* parent_root_mus = parent_root_aura->GetProperty(kMusWindow); | |
800 if (parent_root_mus) { | |
801 parent_root_mus->AddTransientWindow(window_); | |
802 if (!parent_mus) | |
803 parent_mus = parent_root_mus; | |
804 } | |
805 } | |
806 | |
807 if (parent_mus) | |
808 parent_mus->AddChild(window_); | |
809 | |
810 // TODO(sky): deal with show state. | |
811 if (!params.bounds.size().IsEmpty()) | |
812 SetBounds(params.bounds); | |
813 | |
814 // TODO(beng): much else, see [Desktop]NativeWidgetAura. | |
815 | |
816 native_widget_delegate_->OnNativeWidgetCreated(false); | |
817 } | |
818 | |
819 void NativeWidgetMus::OnWidgetInitDone() { | |
820 // The client area is calculated from the NonClientView. During | |
821 // InitNativeWidget() the NonClientView has not been created. When this | |
822 // function is called the NonClientView has been created, so that we can | |
823 // correctly calculate the client area and push it to the ui::Window. | |
824 UpdateClientArea(); | |
825 UpdateHitTestMask(); | |
826 } | |
827 | |
828 bool NativeWidgetMus::ShouldUseNativeFrame() const { | |
829 NOTIMPLEMENTED(); | |
830 return false; | |
831 } | |
832 | |
833 bool NativeWidgetMus::ShouldWindowContentsBeTransparent() const { | |
834 NOTIMPLEMENTED(); | |
835 return true; | |
836 } | |
837 | |
838 void NativeWidgetMus::FrameTypeChanged() { | |
839 NOTIMPLEMENTED(); | |
840 } | |
841 | |
842 Widget* NativeWidgetMus::GetWidget() { | |
843 return native_widget_delegate_->AsWidget(); | |
844 } | |
845 | |
846 const Widget* NativeWidgetMus::GetWidget() const { | |
847 return native_widget_delegate_->AsWidget(); | |
848 } | |
849 | |
850 gfx::NativeView NativeWidgetMus::GetNativeView() const { | |
851 return content_; | |
852 } | |
853 | |
854 gfx::NativeWindow NativeWidgetMus::GetNativeWindow() const { | |
855 return content_; | |
856 } | |
857 | |
858 Widget* NativeWidgetMus::GetTopLevelWidget() { | |
859 return GetWidget(); | |
860 } | |
861 | |
862 const ui::Compositor* NativeWidgetMus::GetCompositor() const { | |
863 return window_tree_host_->compositor(); | |
864 } | |
865 | |
866 const ui::Layer* NativeWidgetMus::GetLayer() const { | |
867 return content_ ? content_->layer() : nullptr; | |
868 } | |
869 | |
870 void NativeWidgetMus::ReorderNativeViews() { | |
871 NOTIMPLEMENTED(); | |
872 } | |
873 | |
874 void NativeWidgetMus::ViewRemoved(View* view) { | |
875 NOTIMPLEMENTED(); | |
876 } | |
877 | |
878 // These methods are wrong in mojo. They're not usually used to associate data | |
879 // with a window; they are used to pass data from one layer to another (and in | |
880 // chrome/ to unsafely pass raw pointers around--I can only find two places | |
881 // where we do the "safe" thing and even that requires casting an integer to a | |
882 // void*). They can't be used safely in a world where we separate things with | |
883 // mojo. | |
884 // | |
885 // It's also used to communicate between views and aura; in views, we set | |
886 // properties on a widget, and read these properties directly in aura code. | |
887 void NativeWidgetMus::SetNativeWindowProperty(const char* name, void* value) { | |
888 if (content_) | |
889 content_->SetNativeWindowProperty(name, value); | |
890 } | |
891 | |
892 void* NativeWidgetMus::GetNativeWindowProperty(const char* name) const { | |
893 return content_ ? content_->GetNativeWindowProperty(name) : nullptr; | |
894 } | |
895 | |
896 TooltipManager* NativeWidgetMus::GetTooltipManager() const { | |
897 return tooltip_manager_.get(); | |
898 } | |
899 | |
900 void NativeWidgetMus::SetCapture() { | |
901 if (content_) | |
902 content_->SetCapture(); | |
903 } | |
904 | |
905 void NativeWidgetMus::ReleaseCapture() { | |
906 if (content_) | |
907 content_->ReleaseCapture(); | |
908 } | |
909 | |
910 bool NativeWidgetMus::HasCapture() const { | |
911 return content_ && content_->HasCapture(); | |
912 } | |
913 | |
914 ui::InputMethod* NativeWidgetMus::GetInputMethod() { | |
915 return window_tree_host_ ? window_tree_host_->GetInputMethod() : nullptr; | |
916 } | |
917 | |
918 void NativeWidgetMus::CenterWindow(const gfx::Size& size) { | |
919 if (is_parallel_widget_in_window_manager()) | |
920 return; | |
921 // TODO(beng): clear user-placed property and set preferred size property. | |
922 window_->SetSharedProperty<gfx::Size>( | |
923 ui::mojom::WindowManager::kPreferredSize_Property, size); | |
924 | |
925 gfx::Rect bounds = display::Screen::GetScreen() | |
926 ->GetDisplayNearestWindow(content_) | |
927 .work_area(); | |
928 bounds.ClampToCenteredSize(size); | |
929 window_->SetBounds(bounds); | |
930 } | |
931 | |
932 void NativeWidgetMus::GetWindowPlacement( | |
933 gfx::Rect* bounds, | |
934 ui::WindowShowState* maximized) const { | |
935 NOTIMPLEMENTED(); | |
936 } | |
937 | |
938 bool NativeWidgetMus::SetWindowTitle(const base::string16& title) { | |
939 if (!window_ || is_parallel_widget_in_window_manager()) | |
940 return false; | |
941 const char* kWindowTitle_Property = | |
942 ui::mojom::WindowManager::kWindowTitle_Property; | |
943 const base::string16 current_title = | |
944 window_->HasSharedProperty(kWindowTitle_Property) | |
945 ? window_->GetSharedProperty<base::string16>(kWindowTitle_Property) | |
946 : base::string16(); | |
947 if (current_title == title) | |
948 return false; | |
949 window_->SetSharedProperty<base::string16>(kWindowTitle_Property, title); | |
950 return true; | |
951 } | |
952 | |
953 void NativeWidgetMus::SetWindowIcons(const gfx::ImageSkia& window_icon, | |
954 const gfx::ImageSkia& app_icon) { | |
955 if (is_parallel_widget_in_window_manager()) | |
956 return; | |
957 | |
958 SetIconProperty(window_, ui::mojom::WindowManager::kWindowIcon_Property, | |
959 window_icon); | |
960 SetIconProperty(window_, ui::mojom::WindowManager::kAppIcon_Property, | |
961 app_icon); | |
962 } | |
963 | |
964 void NativeWidgetMus::InitModalType(ui::ModalType modal_type) { | |
965 if (modal_type != ui::MODAL_TYPE_NONE) | |
966 window_->SetModal(); | |
967 } | |
968 | |
969 gfx::Rect NativeWidgetMus::GetWindowBoundsInScreen() const { | |
970 if (!window_) | |
971 return gfx::Rect(); | |
972 | |
973 // Correct for the origin of the display. | |
974 const int64_t window_display_id = window_->GetRoot()->display_id(); | |
975 for (display::Display display : | |
976 display::Screen::GetScreen()->GetAllDisplays()) { | |
977 if (display.id() == window_display_id) { | |
978 gfx::Point display_origin = display.bounds().origin(); | |
979 gfx::Rect bounds_in_screen = window_->GetBoundsInRoot(); | |
980 bounds_in_screen.Offset(display_origin.x(), display_origin.y()); | |
981 return bounds_in_screen; | |
982 } | |
983 } | |
984 // Unknown display, assume primary display at 0,0. | |
985 return window_->GetBoundsInRoot(); | |
986 } | |
987 | |
988 gfx::Rect NativeWidgetMus::GetClientAreaBoundsInScreen() const { | |
989 // View-to-screen coordinate system transformations depend on this returning | |
990 // the full window bounds, for example View::ConvertPointToScreen(). | |
991 return GetWindowBoundsInScreen(); | |
992 } | |
993 | |
994 gfx::Rect NativeWidgetMus::GetRestoredBounds() const { | |
995 // Restored bounds should only be relevant if the window is minimized, | |
996 // maximized, fullscreen or docked. However, in some places the code expects | |
997 // GetRestoredBounds() to return the current window bounds if the window is | |
998 // not in either state. | |
999 if (IsMinimized() || IsMaximized() || IsFullscreen()) { | |
1000 const char* kRestoreBounds_Property = | |
1001 ui::mojom::WindowManager::kRestoreBounds_Property; | |
1002 if (window_->HasSharedProperty(kRestoreBounds_Property)) | |
1003 return window_->GetSharedProperty<gfx::Rect>(kRestoreBounds_Property); | |
1004 } | |
1005 return GetWindowBoundsInScreen(); | |
1006 } | |
1007 | |
1008 std::string NativeWidgetMus::GetWorkspace() const { | |
1009 return std::string(); | |
1010 } | |
1011 | |
1012 void NativeWidgetMus::SetBounds(const gfx::Rect& bounds_in_screen) { | |
1013 if (!(window_ && window_tree_host_)) | |
1014 return; | |
1015 | |
1016 // TODO(jamescook): Needs something like aura::ScreenPositionClient so higher | |
1017 // level code can move windows between displays. crbug.com/645291 | |
1018 gfx::Point origin(bounds_in_screen.origin()); | |
1019 const gfx::Point display_origin = display::Screen::GetScreen() | |
1020 ->GetDisplayMatching(bounds_in_screen) | |
1021 .bounds() | |
1022 .origin(); | |
1023 origin.Offset(-display_origin.x(), -display_origin.y()); | |
1024 | |
1025 gfx::Size size(bounds_in_screen.size()); | |
1026 const gfx::Size min_size = GetMinimumSize(); | |
1027 const gfx::Size max_size = GetMaximumSize(); | |
1028 if (!max_size.IsEmpty()) | |
1029 size.SetToMin(max_size); | |
1030 size.SetToMax(min_size); | |
1031 window_->SetBounds(gfx::Rect(origin, size)); | |
1032 // Observer on |window_tree_host_| expected to synchronously update bounds. | |
1033 DCHECK_EQ(gfx::ConvertRectToPixel(ScaleFactorForDisplay(content_), | |
1034 window_->bounds()) | |
1035 .ToString(), | |
1036 window_tree_host_->GetBoundsInPixels().ToString()); | |
1037 } | |
1038 | |
1039 void NativeWidgetMus::SetSize(const gfx::Size& size) { | |
1040 if (!window_tree_host_) | |
1041 return; | |
1042 | |
1043 gfx::Rect bounds = window_tree_host_->GetBoundsInPixels(); | |
1044 SetBounds(gfx::Rect(bounds.origin(), size)); | |
1045 } | |
1046 | |
1047 void NativeWidgetMus::StackAbove(gfx::NativeView native_view) { | |
1048 NOTIMPLEMENTED(); | |
1049 } | |
1050 | |
1051 void NativeWidgetMus::StackAtTop() { | |
1052 NOTIMPLEMENTED(); | |
1053 } | |
1054 | |
1055 void NativeWidgetMus::SetShape(std::unique_ptr<SkRegion> shape) { | |
1056 NOTIMPLEMENTED(); | |
1057 } | |
1058 | |
1059 void NativeWidgetMus::Close() { | |
1060 Hide(); | |
1061 if (!close_widget_factory_.HasWeakPtrs()) { | |
1062 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
1063 FROM_HERE, base::Bind(&NativeWidgetMus::CloseNow, | |
1064 close_widget_factory_.GetWeakPtr())); | |
1065 } | |
1066 } | |
1067 | |
1068 void NativeWidgetMus::CloseNow() { | |
1069 // Depending upon ownership |window_| may have been destroyed. | |
1070 if (window_) | |
1071 window_->Destroy(); | |
1072 } | |
1073 | |
1074 void NativeWidgetMus::Show() { | |
1075 ShowWithWindowState(ui::SHOW_STATE_NORMAL); | |
1076 } | |
1077 | |
1078 void NativeWidgetMus::Hide() { | |
1079 if (!(window_ && window_tree_host_)) | |
1080 return; | |
1081 | |
1082 // NOTE: |window_tree_host_| and |window_| visibility is updated in | |
1083 // OnMusWindowVisibilityChanged(). | |
1084 window_->SetVisible(false); | |
1085 } | |
1086 | |
1087 void NativeWidgetMus::ShowMaximizedWithBounds( | |
1088 const gfx::Rect& restored_bounds) { | |
1089 if (!window_) | |
1090 return; | |
1091 | |
1092 window_->SetSharedProperty<gfx::Rect>( | |
1093 ui::mojom::WindowManager::kRestoreBounds_Property, restored_bounds); | |
1094 ShowWithWindowState(ui::SHOW_STATE_MAXIMIZED); | |
1095 } | |
1096 | |
1097 void NativeWidgetMus::ShowWithWindowState(ui::WindowShowState state) { | |
1098 if (!(window_ && window_tree_host_)) | |
1099 return; | |
1100 | |
1101 // Matches NativeWidgetAura. | |
1102 switch (state) { | |
1103 case ui::SHOW_STATE_MAXIMIZED: | |
1104 SetShowState(ui::mojom::ShowState::MAXIMIZED); | |
1105 break; | |
1106 case ui::SHOW_STATE_FULLSCREEN: | |
1107 SetShowState(ui::mojom::ShowState::FULLSCREEN); | |
1108 break; | |
1109 case ui::SHOW_STATE_DOCKED: | |
1110 SetShowState(ui::mojom::ShowState::DOCKED); | |
1111 break; | |
1112 default: | |
1113 break; | |
1114 } | |
1115 | |
1116 // NOTE: |window_tree_host_| and |window_| visibility is updated in | |
1117 // OnMusWindowVisibilityChanged(). | |
1118 window_->SetVisible(true); | |
1119 if (native_widget_delegate_->CanActivate()) { | |
1120 if (state != ui::SHOW_STATE_INACTIVE) | |
1121 Activate(); | |
1122 GetWidget()->SetInitialFocus(state); | |
1123 } | |
1124 | |
1125 // Matches NativeWidgetAura. | |
1126 if (state == ui::SHOW_STATE_MINIMIZED) | |
1127 Minimize(); | |
1128 } | |
1129 | |
1130 bool NativeWidgetMus::IsVisible() const { | |
1131 // TODO(beng): this should probably be wired thru PlatformWindow. | |
1132 return window_ && window_->visible(); | |
1133 } | |
1134 | |
1135 void NativeWidgetMus::Activate() { | |
1136 if (!window_) | |
1137 return; | |
1138 | |
1139 static_cast<aura::client::ActivationClient*>(focus_client_.get()) | |
1140 ->ActivateWindow(content_); | |
1141 } | |
1142 | |
1143 void NativeWidgetMus::Deactivate() { | |
1144 if (IsActive()) | |
1145 window_->window_tree()->ClearFocus(); | |
1146 } | |
1147 | |
1148 bool NativeWidgetMus::IsActive() const { | |
1149 ui::Window* focused = | |
1150 window_ ? window_->window_tree()->GetFocusedWindow() : nullptr; | |
1151 return focused && window_->Contains(focused); | |
1152 } | |
1153 | |
1154 void NativeWidgetMus::SetAlwaysOnTop(bool always_on_top) { | |
1155 if (window_ && !is_parallel_widget_in_window_manager()) { | |
1156 window_->SetSharedProperty<bool>( | |
1157 ui::mojom::WindowManager::kAlwaysOnTop_Property, always_on_top); | |
1158 } | |
1159 } | |
1160 | |
1161 bool NativeWidgetMus::IsAlwaysOnTop() const { | |
1162 return window_ && | |
1163 window_->HasSharedProperty( | |
1164 ui::mojom::WindowManager::kAlwaysOnTop_Property) && | |
1165 window_->GetSharedProperty<bool>( | |
1166 ui::mojom::WindowManager::kAlwaysOnTop_Property); | |
1167 } | |
1168 | |
1169 void NativeWidgetMus::SetVisibleOnAllWorkspaces(bool always_visible) { | |
1170 // Not needed for chromeos. | |
1171 } | |
1172 | |
1173 bool NativeWidgetMus::IsVisibleOnAllWorkspaces() const { | |
1174 return false; | |
1175 } | |
1176 | |
1177 void NativeWidgetMus::Maximize() { | |
1178 SetShowState(ui::mojom::ShowState::MAXIMIZED); | |
1179 } | |
1180 | |
1181 void NativeWidgetMus::Minimize() { | |
1182 SetShowState(ui::mojom::ShowState::MINIMIZED); | |
1183 } | |
1184 | |
1185 bool NativeWidgetMus::IsMaximized() const { | |
1186 return GetShowState(window_) == ui::mojom::ShowState::MAXIMIZED; | |
1187 } | |
1188 | |
1189 bool NativeWidgetMus::IsMinimized() const { | |
1190 return GetShowState(window_) == ui::mojom::ShowState::MINIMIZED; | |
1191 } | |
1192 | |
1193 void NativeWidgetMus::Restore() { | |
1194 SetShowState(ui::mojom::ShowState::NORMAL); | |
1195 } | |
1196 | |
1197 void NativeWidgetMus::SetFullscreen(bool fullscreen) { | |
1198 if (IsFullscreen() == fullscreen) | |
1199 return; | |
1200 if (fullscreen) { | |
1201 show_state_before_fullscreen_ = GetShowState(window_); | |
1202 SetShowState(ui::mojom::ShowState::FULLSCREEN); | |
1203 } else { | |
1204 switch (show_state_before_fullscreen_) { | |
1205 case ui::mojom::ShowState::MAXIMIZED: | |
1206 Maximize(); | |
1207 break; | |
1208 case ui::mojom::ShowState::MINIMIZED: | |
1209 Minimize(); | |
1210 break; | |
1211 case ui::mojom::ShowState::DEFAULT: | |
1212 case ui::mojom::ShowState::NORMAL: | |
1213 case ui::mojom::ShowState::INACTIVE: | |
1214 case ui::mojom::ShowState::FULLSCREEN: | |
1215 case ui::mojom::ShowState::DOCKED: | |
1216 // TODO(sad): This may not be sufficient. | |
1217 Restore(); | |
1218 break; | |
1219 } | |
1220 } | |
1221 } | |
1222 | |
1223 bool NativeWidgetMus::IsFullscreen() const { | |
1224 return GetShowState(window_) == ui::mojom::ShowState::FULLSCREEN; | |
1225 } | |
1226 | |
1227 void NativeWidgetMus::SetOpacity(float opacity) { | |
1228 if (window_) | |
1229 window_->SetOpacity(opacity); | |
1230 } | |
1231 | |
1232 void NativeWidgetMus::FlashFrame(bool flash_frame) { | |
1233 NOTIMPLEMENTED(); | |
1234 } | |
1235 | |
1236 void NativeWidgetMus::RunShellDrag(View* view, | |
1237 const ui::OSExchangeData& data, | |
1238 const gfx::Point& location, | |
1239 int drag_operations, | |
1240 ui::DragDropTypes::DragEventSource source) { | |
1241 if (window_) | |
1242 views::RunShellDrag(content_, data, location, drag_operations, source); | |
1243 } | |
1244 | |
1245 void NativeWidgetMus::SchedulePaintInRect(const gfx::Rect& rect) { | |
1246 if (content_) | |
1247 content_->SchedulePaintInRect(rect); | |
1248 } | |
1249 | |
1250 void NativeWidgetMus::SetCursor(gfx::NativeCursor cursor) { | |
1251 if (!window_) | |
1252 return; | |
1253 | |
1254 // TODO(erg): In aura, our incoming cursor is really two | |
1255 // parts. cursor.native_type() is an integer for standard cursors and is all | |
1256 // we support right now. If native_type() == kCursorCustom, than we should | |
1257 // also send an image, but as the cursor code is currently written, the image | |
1258 // is in a platform native format that's already uploaded to the window | |
1259 // server. | |
1260 ui::mojom::Cursor new_cursor = ui::mojom::Cursor(cursor.native_type()); | |
1261 if (last_cursor_ != new_cursor) | |
1262 window_->SetPredefinedCursor(new_cursor); | |
1263 } | |
1264 | |
1265 bool NativeWidgetMus::IsMouseEventsEnabled() const { | |
1266 NOTIMPLEMENTED(); | |
1267 return true; | |
1268 } | |
1269 | |
1270 void NativeWidgetMus::ClearNativeFocus() { | |
1271 if (!IsActive()) | |
1272 return; | |
1273 ui::Window* focused = | |
1274 window_ ? window_->window_tree()->GetFocusedWindow() : nullptr; | |
1275 if (focused && window_->Contains(focused) && focused != window_) | |
1276 window_->SetFocus(); | |
1277 // Move aura-focus back to |content_|, so that the Widget still receives | |
1278 // events correctly. | |
1279 aura::client::GetFocusClient(content_)->ResetFocusWithinActiveWindow( | |
1280 content_); | |
1281 } | |
1282 | |
1283 gfx::Rect NativeWidgetMus::GetWorkAreaBoundsInScreen() const { | |
1284 NOTIMPLEMENTED(); | |
1285 return gfx::Rect(); | |
1286 } | |
1287 | |
1288 Widget::MoveLoopResult NativeWidgetMus::RunMoveLoop( | |
1289 const gfx::Vector2d& drag_offset, | |
1290 Widget::MoveLoopSource source, | |
1291 Widget::MoveLoopEscapeBehavior escape_behavior) { | |
1292 ReleaseCapture(); | |
1293 | |
1294 base::MessageLoopForUI* loop = base::MessageLoopForUI::current(); | |
1295 base::MessageLoop::ScopedNestableTaskAllower allow_nested(loop); | |
1296 base::RunLoop run_loop; | |
1297 | |
1298 ui::mojom::MoveLoopSource mus_source = | |
1299 source == Widget::MOVE_LOOP_SOURCE_MOUSE | |
1300 ? ui::mojom::MoveLoopSource::MOUSE | |
1301 : ui::mojom::MoveLoopSource::TOUCH; | |
1302 | |
1303 bool success = false; | |
1304 gfx::Point cursor_location = | |
1305 display::Screen::GetScreen()->GetCursorScreenPoint(); | |
1306 window_->PerformWindowMove( | |
1307 mus_source, cursor_location, | |
1308 base::Bind(OnMoveLoopEnd, &success, run_loop.QuitClosure())); | |
1309 | |
1310 run_loop.Run(); | |
1311 | |
1312 return success ? Widget::MOVE_LOOP_SUCCESSFUL : Widget::MOVE_LOOP_CANCELED; | |
1313 } | |
1314 | |
1315 void NativeWidgetMus::EndMoveLoop() { | |
1316 window_->CancelWindowMove(); | |
1317 } | |
1318 | |
1319 void NativeWidgetMus::SetVisibilityChangedAnimationsEnabled(bool value) { | |
1320 NOTIMPLEMENTED(); | |
1321 } | |
1322 | |
1323 void NativeWidgetMus::SetVisibilityAnimationDuration( | |
1324 const base::TimeDelta& duration) { | |
1325 NOTIMPLEMENTED(); | |
1326 } | |
1327 | |
1328 void NativeWidgetMus::SetVisibilityAnimationTransition( | |
1329 Widget::VisibilityTransition transition) { | |
1330 NOTIMPLEMENTED(); | |
1331 } | |
1332 | |
1333 bool NativeWidgetMus::IsTranslucentWindowOpacitySupported() const { | |
1334 NOTIMPLEMENTED(); | |
1335 return true; | |
1336 } | |
1337 | |
1338 void NativeWidgetMus::OnSizeConstraintsChanged() { | |
1339 if (!window_ || is_parallel_widget_in_window_manager()) | |
1340 return; | |
1341 | |
1342 int32_t behavior = ui::mojom::kResizeBehaviorNone; | |
1343 if (GetWidget()->widget_delegate()) | |
1344 behavior = GetWidget()->widget_delegate()->GetResizeBehavior(); | |
1345 window_->SetSharedProperty<PrimitiveType>( | |
1346 ui::mojom::WindowManager::kResizeBehavior_Property, behavior); | |
1347 } | |
1348 | |
1349 void NativeWidgetMus::RepostNativeEvent(gfx::NativeEvent native_event) { | |
1350 NOTIMPLEMENTED(); | |
1351 } | |
1352 | |
1353 std::string NativeWidgetMus::GetName() const { | |
1354 return window_->GetName(); | |
1355 } | |
1356 | |
1357 //////////////////////////////////////////////////////////////////////////////// | |
1358 // NativeWidgetMus, aura::WindowDelegate implementation: | |
1359 | |
1360 gfx::Size NativeWidgetMus::GetMinimumSize() const { | |
1361 return native_widget_delegate_->GetMinimumSize(); | |
1362 } | |
1363 | |
1364 gfx::Size NativeWidgetMus::GetMaximumSize() const { | |
1365 return native_widget_delegate_->GetMaximumSize(); | |
1366 } | |
1367 | |
1368 void NativeWidgetMus::OnBoundsChanged(const gfx::Rect& old_bounds, | |
1369 const gfx::Rect& new_bounds) { | |
1370 // This is handled in OnHost{Resized,Moved}() like DesktopNativeWidgetAura | |
1371 // instead of here like in NativeWidgetAura. | |
1372 } | |
1373 | |
1374 gfx::NativeCursor NativeWidgetMus::GetCursor(const gfx::Point& point) { | |
1375 return gfx::NativeCursor(); | |
1376 } | |
1377 | |
1378 int NativeWidgetMus::GetNonClientComponent(const gfx::Point& point) const { | |
1379 return native_widget_delegate_->GetNonClientComponent(point); | |
1380 } | |
1381 | |
1382 bool NativeWidgetMus::ShouldDescendIntoChildForEventHandling( | |
1383 aura::Window* child, | |
1384 const gfx::Point& location) { | |
1385 views::WidgetDelegate* widget_delegate = GetWidget()->widget_delegate(); | |
1386 return !widget_delegate || | |
1387 widget_delegate->ShouldDescendIntoChildForEventHandling(child, location); | |
1388 } | |
1389 | |
1390 bool NativeWidgetMus::CanFocus() { | |
1391 return true; | |
1392 } | |
1393 | |
1394 void NativeWidgetMus::OnCaptureLost() { | |
1395 native_widget_delegate_->OnMouseCaptureLost(); | |
1396 } | |
1397 | |
1398 void NativeWidgetMus::OnPaint(const ui::PaintContext& context) { | |
1399 native_widget_delegate_->OnNativeWidgetPaint(context); | |
1400 } | |
1401 | |
1402 void NativeWidgetMus::OnDeviceScaleFactorChanged(float device_scale_factor) { | |
1403 } | |
1404 | |
1405 void NativeWidgetMus::OnWindowDestroying(aura::Window* window) { | |
1406 } | |
1407 | |
1408 void NativeWidgetMus::OnWindowDestroyed(aura::Window* window) { | |
1409 // Cleanup happens in OnPlatformWindowClosed(). | |
1410 } | |
1411 | |
1412 void NativeWidgetMus::OnWindowTargetVisibilityChanged(bool visible) { | |
1413 } | |
1414 | |
1415 bool NativeWidgetMus::HasHitTestMask() const { | |
1416 return native_widget_delegate_->HasHitTestMask(); | |
1417 } | |
1418 | |
1419 void NativeWidgetMus::GetHitTestMask(gfx::Path* mask) const { | |
1420 native_widget_delegate_->GetHitTestMask(mask); | |
1421 } | |
1422 | |
1423 void NativeWidgetMus::SetShowState(ui::mojom::ShowState show_state) { | |
1424 if (!window_) | |
1425 return; | |
1426 window_->SetSharedProperty<PrimitiveType>( | |
1427 ui::mojom::WindowManager::kShowState_Property, | |
1428 static_cast<PrimitiveType>(show_state)); | |
1429 } | |
1430 | |
1431 void NativeWidgetMus::OnKeyEvent(ui::KeyEvent* event) { | |
1432 if (event->is_char()) { | |
1433 // If a ui::InputMethod object is attached to the root window, character | |
1434 // events are handled inside the object and are not passed to this function. | |
1435 // If such object is not attached, character events might be sent (e.g. on | |
1436 // Windows). In this case, we just skip these. | |
1437 return; | |
1438 } | |
1439 // Renderer may send a key event back to us if the key event wasn't handled, | |
1440 // and the window may be invisible by that time. | |
1441 if (!content_->IsVisible()) | |
1442 return; | |
1443 | |
1444 native_widget_delegate_->OnKeyEvent(event); | |
1445 } | |
1446 | |
1447 void NativeWidgetMus::OnMouseEvent(ui::MouseEvent* event) { | |
1448 DCHECK(content_->IsVisible()); | |
1449 | |
1450 if (tooltip_manager_.get()) | |
1451 tooltip_manager_->UpdateTooltip(); | |
1452 TooltipManagerAura::UpdateTooltipManagerForCapture(GetWidget()); | |
1453 | |
1454 native_widget_delegate_->OnMouseEvent(event); | |
1455 // WARNING: we may have been deleted. | |
1456 } | |
1457 | |
1458 void NativeWidgetMus::OnScrollEvent(ui::ScrollEvent* event) { | |
1459 if (event->type() == ui::ET_SCROLL) { | |
1460 native_widget_delegate_->OnScrollEvent(event); | |
1461 if (event->handled()) | |
1462 return; | |
1463 | |
1464 // Convert unprocessed scroll events into wheel events. | |
1465 ui::MouseWheelEvent mwe(*event->AsScrollEvent()); | |
1466 native_widget_delegate_->OnMouseEvent(&mwe); | |
1467 if (mwe.handled()) | |
1468 event->SetHandled(); | |
1469 } else { | |
1470 native_widget_delegate_->OnScrollEvent(event); | |
1471 } | |
1472 } | |
1473 | |
1474 void NativeWidgetMus::OnGestureEvent(ui::GestureEvent* event) { | |
1475 native_widget_delegate_->OnGestureEvent(event); | |
1476 } | |
1477 | |
1478 void NativeWidgetMus::OnHostResized(const aura::WindowTreeHost* host) { | |
1479 native_widget_delegate_->OnNativeWidgetSizeChanged( | |
1480 host->window()->bounds().size()); | |
1481 UpdateClientArea(); | |
1482 UpdateHitTestMask(); | |
1483 } | |
1484 | |
1485 void NativeWidgetMus::OnHostMovedInPixels( | |
1486 const aura::WindowTreeHost* host, | |
1487 const gfx::Point& new_origin_in_pixels) { | |
1488 native_widget_delegate_->OnNativeWidgetMove(); | |
1489 } | |
1490 | |
1491 void NativeWidgetMus::OnHostCloseRequested(const aura::WindowTreeHost* host) { | |
1492 GetWidget()->Close(); | |
1493 } | |
1494 | |
1495 //////////////////////////////////////////////////////////////////////////////// | |
1496 // NativeWidgetMus, aura::WindowDragDropDelegate implementation: | |
1497 | |
1498 void NativeWidgetMus::OnDragEntered(const ui::DropTargetEvent& event) { | |
1499 DCHECK(drop_helper_); | |
1500 last_drop_operation_ = drop_helper_->OnDragOver( | |
1501 event.data(), event.location(), event.source_operations()); | |
1502 } | |
1503 | |
1504 int NativeWidgetMus::OnDragUpdated(const ui::DropTargetEvent& event) { | |
1505 DCHECK(drop_helper_); | |
1506 last_drop_operation_ = drop_helper_->OnDragOver( | |
1507 event.data(), event.location(), event.source_operations()); | |
1508 return last_drop_operation_; | |
1509 } | |
1510 | |
1511 void NativeWidgetMus::OnDragExited() { | |
1512 DCHECK(drop_helper_); | |
1513 drop_helper_->OnDragExit(); | |
1514 } | |
1515 | |
1516 int NativeWidgetMus::OnPerformDrop(const ui::DropTargetEvent& event) { | |
1517 DCHECK(drop_helper_); | |
1518 return drop_helper_->OnDrop(event.data(), event.location(), | |
1519 last_drop_operation_); | |
1520 } | |
1521 | |
1522 //////////////////////////////////////////////////////////////////////////////// | |
1523 // NativeWidgetMus, ui::InputEventHandler implementation: | |
1524 | |
1525 void NativeWidgetMus::OnWindowInputEvent( | |
1526 ui::Window* view, | |
1527 const ui::Event& event_in, | |
1528 std::unique_ptr<base::Callback<void(EventResult)>>* ack_callback) { | |
1529 std::unique_ptr<ui::Event> event = ui::Event::Clone(event_in); | |
1530 | |
1531 if (event->IsKeyEvent()) { | |
1532 input_method_->DispatchKeyEvent(event->AsKeyEvent(), | |
1533 std::move(*ack_callback)); | |
1534 return; | |
1535 } | |
1536 | |
1537 // Take ownership of the callback, indicating that we will handle it. | |
1538 EventAckHandler ack_handler(std::move(*ack_callback)); | |
1539 | |
1540 // TODO(markdittmer): This should be this->OnEvent(event.get()), but that | |
1541 // can't happen until IME is refactored out of in WindowTreeHostMus. | |
1542 platform_window_delegate()->DispatchEvent(event.get()); | |
1543 // NOTE: |this| may be deleted. | |
1544 | |
1545 ack_handler.set_handled(event->handled()); | |
1546 // |ack_handler| acks the event on destruction if necessary. | |
1547 } | |
1548 | |
1549 void NativeWidgetMus::OnMusWindowVisibilityChanging(ui::Window* window, | |
1550 bool visible) { | |
1551 if (window == window_) | |
1552 native_widget_delegate_->OnNativeWidgetVisibilityChanging(visible); | |
1553 } | |
1554 | |
1555 void NativeWidgetMus::OnMusWindowVisibilityChanged(ui::Window* window, | |
1556 bool visible) { | |
1557 if (window != window_) | |
1558 return; | |
1559 | |
1560 if (visible) { | |
1561 window_tree_host_->Show(); | |
1562 GetNativeWindow()->Show(); | |
1563 } else { | |
1564 window_tree_host_->Hide(); | |
1565 GetNativeWindow()->Hide(); | |
1566 } | |
1567 native_widget_delegate_->OnNativeWidgetVisibilityChanged(visible); | |
1568 } | |
1569 | |
1570 void NativeWidgetMus::UpdateHitTestMask() { | |
1571 // The window manager (or other underlay window provider) is not allowed to | |
1572 // set a hit test mask, as that could interfere with a client app mask. | |
1573 if (is_parallel_widget_in_window_manager()) | |
1574 return; | |
1575 | |
1576 if (!native_widget_delegate_->HasHitTestMask()) { | |
1577 window_->ClearHitTestMask(); | |
1578 return; | |
1579 } | |
1580 | |
1581 gfx::Path mask_path; | |
1582 native_widget_delegate_->GetHitTestMask(&mask_path); | |
1583 // TODO(jamescook): Use the full path for the mask. | |
1584 gfx::Rect mask_rect = | |
1585 gfx::ToEnclosingRect(gfx::SkRectToRectF(mask_path.getBounds())); | |
1586 window_->SetHitTestMask(mask_rect); | |
1587 } | |
1588 | |
1589 } // namespace views | |
OLD | NEW |