diff options
Diffstat (limited to 'chromium/ui/aura')
62 files changed, 1610 insertions, 514 deletions
diff --git a/chromium/ui/aura/BUILD.gn b/chromium/ui/aura/BUILD.gn index b02ca41ac97..5250b58d048 100644 --- a/chromium/ui/aura/BUILD.gn +++ b/chromium/ui/aura/BUILD.gn @@ -38,6 +38,7 @@ jumbo_component("aura") { "local/window_port_local.h", "mus/capture_synchronizer.h", "mus/capture_synchronizer_delegate.h", + "mus/client_side_window_move_handler.h", "mus/client_surface_embedder.h", "mus/drag_drop_controller_host.h", "mus/drag_drop_controller_mus.h", @@ -79,6 +80,7 @@ jumbo_component("aura") { "window_event_dispatcher.h", "window_event_dispatcher_observer.h", "window_observer.h", + "window_occlusion_change_builder.h", "window_occlusion_tracker.h", "window_port.h", "window_targeter.h", @@ -114,6 +116,7 @@ jumbo_component("aura") { "mouse_location_manager.cc", "mouse_location_manager.h", "mus/capture_synchronizer.cc", + "mus/client_side_window_move_handler.cc", "mus/client_surface_embedder.cc", "mus/drag_drop_controller_mus.cc", "mus/embed_root.cc", @@ -123,6 +126,8 @@ jumbo_component("aura") { "mus/in_flight_change.cc", "mus/input_method_mus.cc", "mus/mus_context_factory.cc", + "mus/mus_lsi_allocator.cc", + "mus/mus_lsi_allocator.h", "mus/mus_mouse_location_updater.cc", "mus/os_exchange_data_provider_mus.cc", "mus/property_converter.cc", @@ -146,6 +151,7 @@ jumbo_component("aura") { "window_delegate.cc", "window_event_dispatcher.cc", "window_observer.cc", + "window_occlusion_change_builder.cc", "window_occlusion_tracker.cc", "window_port.cc", "window_port_for_shutdown.cc", @@ -159,6 +165,7 @@ jumbo_component("aura") { friend = [ ":aura_interactive_ui_tests", ":aura_unittests", + ":test_support", ] defines = [ "AURA_IMPLEMENTATION" ] @@ -184,6 +191,7 @@ jumbo_component("aura") { "//services/ws/public/mojom", "//skia", "//ui/base", + "//ui/base/clipboard", "//ui/base/ime", "//ui/display", "//ui/events", @@ -297,8 +305,8 @@ jumbo_static_library("test_support") { ":aura", "//services/ws/common", - # Must be public as headers include ui_features.h. - "//ui/base:ui_features", + # Must be public as headers include buildflags.h. + "//ui/base:buildflags", ] deps = [ "//base/test:test_support", @@ -379,7 +387,6 @@ executable("demo") { test("aura_unittests") { sources = [ "../compositor_extra/shadow_unittest.cc", - "//ui/aura_extra/window_occlusion_impl_unittest_win.cc", "gestures/gesture_recognizer_unittest.cc", "mouse_location_manager_unittest.cc", "mus/drag_drop_controller_mus_unittest.cc", @@ -395,6 +402,7 @@ test("aura_unittests") { "test/aura_test_suite.h", "test/run_all_unittests.cc", "window_event_dispatcher_unittest.cc", + "window_occlusion_change_builder_unittest.cc", "window_occlusion_tracker_unittest.cc", "window_targeter_unittest.cc", "window_tree_host_unittest.cc", @@ -417,7 +425,9 @@ test("aura_unittests") { "//skia", "//testing/gtest", "//ui/aura_extra", + "//ui/aura_extra:tests", "//ui/base:test_support", + "//ui/base/clipboard:clipboard_types", "//ui/compositor:test_support", "//ui/compositor_extra", "//ui/display:test_support", diff --git a/chromium/ui/aura/client/aura_constants.cc b/chromium/ui/aura/client/aura_constants.cc index eaa411d6119..afc117d0bf2 100644 --- a/chromium/ui/aura/client/aura_constants.cc +++ b/chromium/ui/aura/client/aura_constants.cc @@ -14,6 +14,7 @@ DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, base::UnguessableToken*) DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, base::string16*) DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, ui::ModalType) DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, gfx::ImageSkia*) +DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, gfx::NativeViewAccessible); DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, gfx::Rect*) DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, gfx::Size*) DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, gfx::SizeF*) @@ -26,6 +27,7 @@ DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, int32_t) DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, int64_t) DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, aura::client::FocusClient*) DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, aura::Window*) +DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, std::vector<aura::Window*>*) namespace aura { namespace client { @@ -50,11 +52,17 @@ DEFINE_UI_CLASS_PROPERTY_KEY(bool, kCreatedByUserGesture, false); DEFINE_UI_CLASS_PROPERTY_KEY(bool, kDrawAttentionKey, false); DEFINE_UI_CLASS_PROPERTY_KEY(FocusClient*, kFocusClientKey, nullptr); DEFINE_UI_CLASS_PROPERTY_KEY(Window*, kHostWindowKey, nullptr); +DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::Size, kMaximumSize, nullptr); DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::Size, kMinimumSize, nullptr); -DEFINE_UI_CLASS_PROPERTY_KEY(bool, kMirroringEnabledKey, false); +DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(std::vector<Window*>, + kMirrorWindowList, + nullptr); DEFINE_UI_CLASS_PROPERTY_KEY(Window*, kChildModalParentKey, nullptr); DEFINE_UI_CLASS_PROPERTY_KEY(ui::ModalType, kModalKey, ui::MODAL_TYPE_NONE); DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(std::string, kNameKey, nullptr); +DEFINE_UI_CLASS_PROPERTY_KEY(gfx::NativeViewAccessible, + kParentNativeViewAccessibleKey, + nullptr); DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::Size, kPreferredSize, nullptr); DEFINE_UI_CLASS_PROPERTY_KEY( ui::WindowShowState, kPreMinimizedShowStateKey, ui::SHOW_STATE_DEFAULT); diff --git a/chromium/ui/aura/client/aura_constants.h b/chromium/ui/aura/client/aura_constants.h index 8692e29d58d..b142ac2cdc0 100644 --- a/chromium/ui/aura/client/aura_constants.h +++ b/chromium/ui/aura/client/aura_constants.h @@ -6,6 +6,7 @@ #define UI_AURA_CLIENT_AURA_CONSTANTS_H_ #include <string> +#include <vector> #include "base/strings/string16.h" #include "third_party/skia/include/core/SkColor.h" @@ -85,12 +86,16 @@ AURA_EXPORT extern const WindowProperty<FocusClient*>* const kFocusClientKey; // WebContentsViews find the windows that should constrain NPAPI plugins. AURA_EXPORT extern const WindowProperty<Window*>* const kHostWindowKey; +// A property key to store the maximum size of the window. +AURA_EXPORT extern const WindowProperty<gfx::Size*>* const kMaximumSize; + // A property key to store the minimum size of the window. AURA_EXPORT extern const WindowProperty<gfx::Size*>* const kMinimumSize; -// A property key to indicate that a window is being "mirrored" and its contents -// should render regardless of its actual visibility state. -AURA_EXPORT extern const WindowProperty<bool>* const kMirroringEnabledKey; +// A property key to store a list of windows showing a mirror of the window this +// property is set on. +AURA_EXPORT extern const WindowProperty<std::vector<Window*>*>* const + kMirrorWindowList; // The modal parent of a child modal window. AURA_EXPORT extern const WindowProperty<Window*>* const kChildModalParentKey; @@ -101,6 +106,12 @@ AURA_EXPORT extern const WindowProperty<ui::ModalType>* const kModalKey; // A property key to store the name of the window; mostly used for debugging. AURA_EXPORT extern const WindowProperty<std::string*>* const kNameKey; +// A property key to store the accessible parent of a native view. This is +// used to allow WebContents to access their accessible parents for use in +// walking up the accessibility tree via platform APIs. +AURA_EXPORT extern const aura::WindowProperty<gfx::NativeViewAccessible>* const + kParentNativeViewAccessibleKey; + // A property key to store the preferred size of the window. AURA_EXPORT extern const WindowProperty<gfx::Size*>* const kPreferredSize; diff --git a/chromium/ui/aura/client/drag_drop_delegate.cc b/chromium/ui/aura/client/drag_drop_delegate.cc index 361a6f023fe..c273606c994 100644 --- a/chromium/ui/aura/client/drag_drop_delegate.cc +++ b/chromium/ui/aura/client/drag_drop_delegate.cc @@ -4,17 +4,15 @@ #include "ui/aura/client/drag_drop_delegate.h" -#include "ui/aura/window.h" #include "ui/base/class_property.h" -DEFINE_UI_CLASS_PROPERTY_TYPE(aura::client::DragDropDelegate*) +DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, + aura::client::DragDropDelegate*) namespace aura { namespace client { -DEFINE_LOCAL_UI_CLASS_PROPERTY_KEY(DragDropDelegate*, - kDragDropDelegateKey, - nullptr); +DEFINE_UI_CLASS_PROPERTY_KEY(DragDropDelegate*, kDragDropDelegateKey, nullptr); void SetDragDropDelegate(Window* window, DragDropDelegate* delegate) { window->SetProperty(kDragDropDelegateKey, delegate); diff --git a/chromium/ui/aura/client/drag_drop_delegate.h b/chromium/ui/aura/client/drag_drop_delegate.h index dde7f32ec73..03104337852 100644 --- a/chromium/ui/aura/client/drag_drop_delegate.h +++ b/chromium/ui/aura/client/drag_drop_delegate.h @@ -6,6 +6,7 @@ #define UI_AURA_CLIENT_DRAG_DROP_DELEGATE_H_ #include "ui/aura/aura_export.h" +#include "ui/aura/window.h" namespace ui { class DropTargetEvent; @@ -45,6 +46,9 @@ AURA_EXPORT void SetDragDropDelegate(Window* window, DragDropDelegate* delegate); AURA_EXPORT DragDropDelegate* GetDragDropDelegate(Window* window); +AURA_EXPORT extern const WindowProperty<DragDropDelegate*>* const + kDragDropDelegateKey; + } // namespace client } // namespace aura diff --git a/chromium/ui/aura/client/window_types.h b/chromium/ui/aura/client/window_types.h index 42789226fd1..261fc3ff9df 100644 --- a/chromium/ui/aura/client/window_types.h +++ b/chromium/ui/aura/client/window_types.h @@ -22,9 +22,6 @@ enum WindowType { // A window intended as a control. Not laid out by the shell. WINDOW_TYPE_CONTROL, - // Always on top windows aligned to bottom right of screen. - WINDOW_TYPE_PANEL, - WINDOW_TYPE_MENU, WINDOW_TYPE_TOOLTIP, diff --git a/chromium/ui/aura/demo/demo_main.cc b/chromium/ui/aura/demo/demo_main.cc index ce82f5b72d3..0282ea55ca1 100644 --- a/chromium/ui/aura/demo/demo_main.cc +++ b/chromium/ui/aura/demo/demo_main.cc @@ -92,7 +92,7 @@ class DemoWindowDelegate : public aura::WindowDelegate { void OnWindowDestroyed(aura::Window* window) override {} void OnWindowTargetVisibilityChanged(bool visible) override {} bool HasHitTestMask() const override { return false; } - void GetHitTestMask(gfx::Path* mask) const override {} + void GetHitTestMask(SkPath* mask) const override {} private: SkColor color_; diff --git a/chromium/ui/aura/env.h b/chromium/ui/aura/env.h index bf5499700d8..03cd3df8e16 100644 --- a/chromium/ui/aura/env.h +++ b/chromium/ui/aura/env.h @@ -73,7 +73,7 @@ class AURA_EXPORT Env : public ui::EventTarget, public base::SupportsUserData { public: enum class Mode { - // Classic aura. + // Classic aura, or ash under SingleProcessMash. LOCAL, // Aura with a backend of mus. diff --git a/chromium/ui/aura/mus/client_side_window_move_handler.cc b/chromium/ui/aura/mus/client_side_window_move_handler.cc new file mode 100644 index 00000000000..bc37be5fbdb --- /dev/null +++ b/chromium/ui/aura/mus/client_side_window_move_handler.cc @@ -0,0 +1,115 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/aura/mus/client_side_window_move_handler.h" + +#include "base/bind.h" +#include "ui/aura/client/screen_position_client.h" +#include "ui/aura/env.h" +#include "ui/aura/mus/window_tree_host_mus.h" +#include "ui/aura/window.h" +#include "ui/aura/window_delegate.h" +#include "ui/base/hit_test.h" +#include "ui/events/event.h" +#include "ui/events/gestures/gesture_recognizer.h" + +namespace aura { + +namespace { + +void WindowMoveEnded(Window* window, bool success) { + window->env()->gesture_recognizer()->CancelActiveTouches(window); +} + +} // namespace + +ClientSideWindowMoveHandler::ClientSideWindowMoveHandler(Env* env) : env_(env) { + env_->AddPreTargetHandler(this); +} + +ClientSideWindowMoveHandler::~ClientSideWindowMoveHandler() { + env_->RemovePreTargetHandler(this); +} + +void ClientSideWindowMoveHandler::MaybeSetupLastTarget( + ui::LocatedEvent* event) { + last_target_.RemoveAll(); + Window* window = static_cast<Window*>(event->target()); + if (!window || !window->delegate()) + return; + int component = window->delegate()->GetNonClientComponent(event->location()); + + // TODO(mukai): add the support of window resizing components like HTTOP. + if (component != HTCAPTION) + return; + + last_target_.Add(window); + last_location_ = event->location(); +} + +void ClientSideWindowMoveHandler::MaybePerformWindowMove( + ui::LocatedEvent* event, + ws::mojom::MoveLoopSource source) { + Window* target = static_cast<Window*>(event->target()); + if (!target || !last_target_.Contains(target) || !target->delegate()) + return; + + gfx::Point screen_location = last_location_; + aura::client::GetScreenPositionClient(target->GetRootWindow()) + ->ConvertPointToScreen(target, &screen_location); + WindowTreeHostMus::ForWindow(target)->PerformWindowMove( + target, source, screen_location, + base::BindOnce(&WindowMoveEnded, target)); + + // Clear |last_target_| so that event->target() won't match with + // |last_target_| anymore. + last_target_.RemoveAll(); + event->SetHandled(); +} + +void ClientSideWindowMoveHandler::OnMouseEvent(ui::MouseEvent* event) { + // The logic here should be aligned with ash::WmToplevelWindowEventHandler. + // TODO(mukai): create a common class in ash/public/cpp to share the logic. + if (event->handled()) + return; + if ((event->flags() & + (ui::EF_MIDDLE_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON)) != 0) { + return; + } + switch (event->type()) { + case ui::ET_MOUSE_PRESSED: + MaybeSetupLastTarget(event); + break; + + case ui::ET_MOUSE_DRAGGED: + MaybePerformWindowMove(event, ws::mojom::MoveLoopSource::MOUSE); + break; + + default: + // Do nothing. + break; + } +} + +void ClientSideWindowMoveHandler::OnGestureEvent(ui::GestureEvent* event) { + // The logic here should be aligned with ash::WmToplevelWindowEventHandler. + // TODO(mukai): create a common class in ash/public/cpp to share the logic. + if (event->handled()) + return; + switch (event->type()) { + case ui::ET_GESTURE_TAP_DOWN: + MaybeSetupLastTarget(event); + return; + + case ui::ET_GESTURE_SCROLL_UPDATE: + MaybePerformWindowMove(event, ws::mojom::MoveLoopSource::TOUCH); + break; + + default: + // Do nothing. + break; + } +} + +} // namespace aura diff --git a/chromium/ui/aura/mus/client_side_window_move_handler.h b/chromium/ui/aura/mus/client_side_window_move_handler.h new file mode 100644 index 00000000000..c1cbb410470 --- /dev/null +++ b/chromium/ui/aura/mus/client_side_window_move_handler.h @@ -0,0 +1,49 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_AURA_MUS_CLIENT_SIDE_WINDOW_MOVE_HANDLER_H_ +#define UI_AURA_MUS_CLIENT_SIDE_WINDOW_MOVE_HANDLER_H_ + +#include "services/ws/public/mojom/window_tree_constants.mojom.h" +#include "ui/aura/window_tracker.h" +#include "ui/events/event_handler.h" + +namespace ui { +class LocatedEvent; +} + +namespace aura { + +class Env; + +// ClientSideWindowMoveHandler handles mouse/gesture events and performs the +// window move session when the event is located on draggable area. +class ClientSideWindowMoveHandler : public ui::EventHandler { + public: + explicit ClientSideWindowMoveHandler(Env* env); + ~ClientSideWindowMoveHandler() override; + + private: + // Setup |last_target_| and |last_location_| for |event|, or clear them when + // the event will not involve window move. + void MaybeSetupLastTarget(ui::LocatedEvent* event); + + // Conduct the window move. + void MaybePerformWindowMove(ui::LocatedEvent* event, + ws::mojom::MoveLoopSource source); + + // ui::EventHandler: + void OnMouseEvent(ui::MouseEvent* event) override; + void OnGestureEvent(ui::GestureEvent* event) override; + + Env* env_; + WindowTracker last_target_; + gfx::Point last_location_; + + DISALLOW_COPY_AND_ASSIGN(ClientSideWindowMoveHandler); +}; + +} // namespace aura + +#endif // UI_AURA_MUS_CLIENT_SIDE_WINDOW_MOVE_HANDLER_H_ diff --git a/chromium/ui/aura/mus/client_surface_embedder.cc b/chromium/ui/aura/mus/client_surface_embedder.cc index 5c33f34c7fa..d00bdcf1612 100644 --- a/chromium/ui/aura/mus/client_surface_embedder.cc +++ b/chromium/ui/aura/mus/client_surface_embedder.cc @@ -20,6 +20,7 @@ ClientSurfaceEmbedder::ClientSurfaceEmbedder( std::make_unique<ui::Layer>(ui::LAYER_TEXTURED))), inject_gutter_(inject_gutter), client_area_insets_(client_area_insets) { + surface_layer_owner_->layer()->set_name("ClientSurfaceEmbedder"); surface_layer_owner_->layer()->SetMasksToBounds(true); // The frame provided by the parent window->layer() needs to show through // the surface layer. diff --git a/chromium/ui/aura/mus/drag_drop_controller_mus.cc b/chromium/ui/aura/mus/drag_drop_controller_mus.cc index 9670df44ac9..719abb1d058 100644 --- a/chromium/ui/aura/mus/drag_drop_controller_mus.cc +++ b/chromium/ui/aura/mus/drag_drop_controller_mus.cc @@ -75,17 +75,19 @@ void DragDropControllerMus::OnDragDropStart( uint32_t DragDropControllerMus::OnDragEnter(WindowMus* window, uint32_t event_flags, - const gfx::Point& screen_location, + const gfx::PointF& location_in_root, + const gfx::PointF& location, uint32_t effect_bitmask) { - return HandleDragEnterOrOver(window, event_flags, screen_location, + return HandleDragEnterOrOver(window, event_flags, location_in_root, location, effect_bitmask, true); } uint32_t DragDropControllerMus::OnDragOver(WindowMus* window, uint32_t event_flags, - const gfx::Point& screen_location, + const gfx::PointF& location_in_root, + const gfx::PointF& location, uint32_t effect_bitmask) { - return HandleDragEnterOrOver(window, event_flags, screen_location, + return HandleDragEnterOrOver(window, event_flags, location_in_root, location, effect_bitmask, false); } @@ -101,7 +103,8 @@ void DragDropControllerMus::OnDragLeave(WindowMus* window) { uint32_t DragDropControllerMus::OnCompleteDrop( WindowMus* window, uint32_t event_flags, - const gfx::Point& screen_location, + const gfx::PointF& location_in_root, + const gfx::PointF& location, uint32_t effect_bitmask) { if (drop_target_window_tracker_.windows().empty()) return ws::mojom::kDropEffectNone; @@ -109,8 +112,9 @@ uint32_t DragDropControllerMus::OnCompleteDrop( DCHECK(window); Window* current_target = drop_target_window_tracker_.Pop(); DCHECK_EQ(window->GetWindow(), current_target); - std::unique_ptr<ui::DropTargetEvent> event = CreateDropTargetEvent( - window->GetWindow(), event_flags, screen_location, effect_bitmask); + std::unique_ptr<ui::DropTargetEvent> event = + CreateDropTargetEvent(window->GetWindow(), event_flags, location_in_root, + location, effect_bitmask); return client::GetDragDropDelegate(current_target)->OnPerformDrop(*event); } @@ -193,7 +197,8 @@ void DragDropControllerMus::RemoveObserver( uint32_t DragDropControllerMus::HandleDragEnterOrOver( WindowMus* window, uint32_t event_flags, - const gfx::Point& screen_location, + const gfx::PointF& location_in_root, + const gfx::PointF& location, uint32_t effect_bitmask, bool is_enter) { client::DragDropDelegate* drag_drop_delegate = @@ -207,28 +212,26 @@ uint32_t DragDropControllerMus::HandleDragEnterOrOver( } drop_target_window_tracker_.Add(window->GetWindow()); - std::unique_ptr<ui::DropTargetEvent> event = CreateDropTargetEvent( - window->GetWindow(), event_flags, screen_location, effect_bitmask); + std::unique_ptr<ui::DropTargetEvent> event = + CreateDropTargetEvent(window->GetWindow(), event_flags, location_in_root, + location, effect_bitmask); if (is_enter) drag_drop_delegate->OnDragEntered(*event); return drag_drop_delegate->OnDragUpdated(*event); } std::unique_ptr<ui::DropTargetEvent> -DragDropControllerMus::CreateDropTargetEvent(Window* window, - uint32_t event_flags, - const gfx::Point& screen_location, - uint32_t effect_bitmask) { - DCHECK(window->GetHost()); - gfx::Point root_location = screen_location; - window->GetHost()->ConvertScreenInPixelsToDIP(&root_location); - gfx::PointF location(root_location); - Window::ConvertPointToTarget(window->GetRootWindow(), window, &location); +DragDropControllerMus::CreateDropTargetEvent( + Window* window, + uint32_t event_flags, + const gfx::PointF& location_in_root, + const gfx::PointF& location, + uint32_t effect_bitmask) { std::unique_ptr<ui::DropTargetEvent> event = std::make_unique<ui::DropTargetEvent>( current_drag_state_ ? current_drag_state_->drag_data : *(os_exchange_data_.get()), - location, gfx::PointF(root_location), effect_bitmask); + location, location_in_root, effect_bitmask); event->set_flags(event_flags); ui::Event::DispatcherApi(event.get()).set_target(window); return event; diff --git a/chromium/ui/aura/mus/drag_drop_controller_mus.h b/chromium/ui/aura/mus/drag_drop_controller_mus.h index 0bcb808a73f..cc95f6089d4 100644 --- a/chromium/ui/aura/mus/drag_drop_controller_mus.h +++ b/chromium/ui/aura/mus/drag_drop_controller_mus.h @@ -17,6 +17,10 @@ #include "ui/aura/window_tracker.h" #include "ui/base/dragdrop/drag_drop_types.h" +namespace gfx { +class PointF; +} + namespace ws { namespace mojom { class WindowTree; @@ -51,16 +55,19 @@ class AURA_EXPORT DragDropControllerMus : public client::DragDropClient { void OnDragDropStart(std::map<std::string, std::vector<uint8_t>> data); uint32_t OnDragEnter(WindowMus* window, uint32_t event_flags, - const gfx::Point& screen_location, + const gfx::PointF& location_in_root, + const gfx::PointF& location, uint32_t effect_bitmask); uint32_t OnDragOver(WindowMus* window, uint32_t event_flags, - const gfx::Point& screen_location, + const gfx::PointF& location_in_root, + const gfx::PointF& location, uint32_t effect_bitmask); void OnDragLeave(WindowMus* window); uint32_t OnCompleteDrop(WindowMus* window, uint32_t event_flags, - const gfx::Point& screen_location, + const gfx::PointF& location_in_root, + const gfx::PointF& location, uint32_t effect_bitmask); void OnPerformDragDropCompleted(uint32_t action_taken); void OnDragDropDone(); @@ -83,14 +90,16 @@ class AURA_EXPORT DragDropControllerMus : public client::DragDropClient { // Called from OnDragEnter() and OnDragOver(). uint32_t HandleDragEnterOrOver(WindowMus* window, uint32_t event_flags, - const gfx::Point& screen_location, + const gfx::PointF& location_in_root, + const gfx::PointF& location, uint32_t effect_bitmask, bool is_enter); std::unique_ptr<ui::DropTargetEvent> CreateDropTargetEvent( Window* window, uint32_t event_flags, - const gfx::Point& screen_location, + const gfx::PointF& location_in_root, + const gfx::PointF& location, uint32_t effect_bitmask); DragDropControllerHost* drag_drop_controller_host_; diff --git a/chromium/ui/aura/mus/drag_drop_controller_mus_unittest.cc b/chromium/ui/aura/mus/drag_drop_controller_mus_unittest.cc index 753d7c9d3ba..a48bd08f7ad 100644 --- a/chromium/ui/aura/mus/drag_drop_controller_mus_unittest.cc +++ b/chromium/ui/aura/mus/drag_drop_controller_mus_unittest.cc @@ -64,9 +64,10 @@ class DragDropControllerMusTest : public test::AuraMusClientTestBase { private: void DragMoveAndDrop() { WindowMus* const window_mus = WindowMus::Get(window_.get()); - controller_->OnDragEnter(window_mus, 0, gfx::Point(5, 20), 0); - controller_->OnDragOver(window_mus, 0, gfx::Point(5, 20), 0); - controller_->OnCompleteDrop(window_mus, 0, gfx::Point(5, 20), 0); + const gfx::PointF point(5, 20); + controller_->OnDragEnter(window_mus, 0, point, point, 0); + controller_->OnDragOver(window_mus, 0, point, point, 0); + controller_->OnCompleteDrop(window_mus, 0, point, point, 0); controller_->OnPerformDragDropCompleted(0); } diff --git a/chromium/ui/aura/mus/focus_synchronizer_unittest.cc b/chromium/ui/aura/mus/focus_synchronizer_unittest.cc index 08eb3467486..83feb7dfe39 100644 --- a/chromium/ui/aura/mus/focus_synchronizer_unittest.cc +++ b/chromium/ui/aura/mus/focus_synchronizer_unittest.cc @@ -24,8 +24,10 @@ class TestFocusRules : public wm::BaseFocusRules { ~TestFocusRules() override = default; // wm::BaseFocusRules overrides: - bool SupportsChildActivation(Window* window) const override { return true; } - bool CanActivateWindow(Window* window) const override { return true; } + bool SupportsChildActivation(const Window* window) const override { + return true; + } + bool CanActivateWindow(const Window* window) const override { return true; } private: DISALLOW_COPY_AND_ASSIGN(TestFocusRules); diff --git a/chromium/ui/aura/mus/in_flight_change.cc b/chromium/ui/aura/mus/in_flight_change.cc index fe5ed3153b7..9d6333fdef3 100644 --- a/chromium/ui/aura/mus/in_flight_change.cc +++ b/chromium/ui/aura/mus/in_flight_change.cc @@ -145,7 +145,10 @@ void CrashInFlightChange::SetRevertValueFrom(const InFlightChange& change) { } void CrashInFlightChange::ChangeFailed() { - CHECK(false) << "change failed, type=" << static_cast<int>(change_type()); + // TODO(crbug.com/912228): remove LOG(). Used to figure out why this is being + // hit. + LOG(ERROR) << "change failed, type=" << static_cast<int>(change_type()); + CHECK(false); } void CrashInFlightChange::Revert() { @@ -250,7 +253,7 @@ void InFlightPropertyChange::Revert() { // InFlightCursorChange ---------------------------------------------------- InFlightCursorChange::InFlightCursorChange(WindowMus* window, - const ui::CursorData& revert_value) + const ui::Cursor& revert_value) : InFlightChange(window, ChangeType::CURSOR), revert_cursor_(revert_value) {} diff --git a/chromium/ui/aura/mus/in_flight_change.h b/chromium/ui/aura/mus/in_flight_change.h index bfb8761a3b7..1d6d0f630bd 100644 --- a/chromium/ui/aura/mus/in_flight_change.h +++ b/chromium/ui/aura/mus/in_flight_change.h @@ -16,7 +16,7 @@ #include "base/optional.h" #include "components/viz/common/surfaces/local_surface_id.h" #include "ui/aura/window_observer.h" -#include "ui/base/cursor/cursor_data.h" +#include "ui/base/cursor/cursor.h" #include "ui/base/ui_base_types.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/transform.h" @@ -296,7 +296,7 @@ class InFlightPropertyChange : public InFlightChange { class InFlightCursorChange : public InFlightChange { public: - InFlightCursorChange(WindowMus* window, const ui::CursorData& revert_value); + InFlightCursorChange(WindowMus* window, const ui::Cursor& revert_value); ~InFlightCursorChange() override; // InFlightChange: @@ -304,7 +304,7 @@ class InFlightCursorChange : public InFlightChange { void Revert() override; private: - ui::CursorData revert_cursor_; + ui::Cursor revert_cursor_; DISALLOW_COPY_AND_ASSIGN(InFlightCursorChange); }; diff --git a/chromium/ui/aura/mus/input_method_mus.cc b/chromium/ui/aura/mus/input_method_mus.cc index 9a1d3c19ebe..589fc814538 100644 --- a/chromium/ui/aura/mus/input_method_mus.cc +++ b/chromium/ui/aura/mus/input_method_mus.cc @@ -102,8 +102,13 @@ void InputMethodMus::OnTextInputTypeChanged(const ui::TextInputClient* client) { UpdateTextInputType(); - if (input_method_) - input_method_->OnTextInputTypeChanged(client->GetTextInputType()); + if (!input_method_) + return; + + auto text_input_state = ws::mojom::TextInputState::New( + client->GetTextInputType(), client->GetTextInputMode(), + client->GetTextDirection(), client->GetTextInputFlags()); + input_method_->OnTextInputStateChanged(std::move(text_input_state)); } void InputMethodMus::OnCaretBoundsChanged(const ui::TextInputClient* client) { @@ -188,18 +193,15 @@ void InputMethodMus::OnDidChangeFocusedClient( std::make_unique<TextInputClientImpl>(focused, delegate()); if (ime_driver_) { - ws::mojom::StartSessionDetailsPtr details = - ws::mojom::StartSessionDetails::New(); - details->client = - text_input_client_->CreateInterfacePtrAndBind().PassInterface(); - details->input_method_request = MakeRequest(&input_method_ptr_); - input_method_ = input_method_ptr_.get(); - details->text_input_type = focused->GetTextInputType(); - details->text_input_mode = focused->GetTextInputMode(); - details->text_direction = focused->GetTextDirection(); - details->text_input_flags = focused->GetTextInputFlags(); + ws::mojom::SessionDetailsPtr details = ws::mojom::SessionDetails::New(); + details->state = ws::mojom::TextInputState::New( + focused->GetTextInputType(), focused->GetTextInputMode(), + focused->GetTextDirection(), focused->GetTextInputFlags()); details->caret_bounds = focused->GetCaretBounds(); - ime_driver_->StartSession(std::move(details)); + ime_driver_->StartSession(MakeRequest(&input_method_ptr_), + text_input_client_->CreateInterfacePtrAndBind(), + std::move(details)); + input_method_ = input_method_ptr_.get(); } } diff --git a/chromium/ui/aura/mus/input_method_mus_unittest.cc b/chromium/ui/aura/mus/input_method_mus_unittest.cc index b70f26395ba..7657e3d1080 100644 --- a/chromium/ui/aura/mus/input_method_mus_unittest.cc +++ b/chromium/ui/aura/mus/input_method_mus_unittest.cc @@ -56,8 +56,9 @@ class TestInputMethod : public ws::mojom::InputMethod { } // ui::ime::InputMethod: - void OnTextInputTypeChanged(ui::TextInputType text_input_type) override { - was_on_text_input_type_changed_called_ = true; + void OnTextInputStateChanged( + ws::mojom::TextInputStatePtr text_input_state) override { + was_on_text_input_state_changed_called_ = true; } void OnCaretBoundsChanged(const gfx::Rect& caret_bounds) override { was_on_caret_bounds_changed_called_ = true; @@ -71,8 +72,8 @@ class TestInputMethod : public ws::mojom::InputMethod { was_show_virtual_keyboard_if_enabled_called_ = true; } - bool was_on_text_input_type_changed_called() { - return was_on_text_input_type_changed_called_; + bool was_on_text_input_state_changed_called() { + return was_on_text_input_state_changed_called_; } bool was_on_caret_bounds_changed_called() { @@ -88,7 +89,7 @@ class TestInputMethod : public ws::mojom::InputMethod { } private: - bool was_on_text_input_type_changed_called_ = false; + bool was_on_text_input_state_changed_called_ = false; bool was_on_caret_bounds_changed_called_ = false; bool was_cancel_composition_called_ = false; bool was_show_virtual_keyboard_if_enabled_called_ = false; @@ -294,7 +295,7 @@ TEST_F(InputMethodMusTest, ChangeTextInputTypeFromUnfocusedClient) { InputMethodMusTestApi::CallOnTextInputTypeChanged(&input_method_mus, &unfocused_input_client); - EXPECT_FALSE(test_input_method.was_on_text_input_type_changed_called()); + EXPECT_FALSE(test_input_method.was_on_text_input_state_changed_called()); } // Calling OnCaretBoundsChanged from unfocused client should diff --git a/chromium/ui/aura/mus/mus_context_factory.cc b/chromium/ui/aura/mus/mus_context_factory.cc index eef0df5d05a..eff69071a56 100644 --- a/chromium/ui/aura/mus/mus_context_factory.cc +++ b/chromium/ui/aura/mus/mus_context_factory.cc @@ -39,7 +39,12 @@ void MusContextFactory::OnEstablishedGpuChannel( WindowTreeHost* host = WindowTreeHost::GetForAcceleratedWidget(compositor->widget()); WindowPortMus* window_port = WindowPortMus::Get(host->window()); - DCHECK(window_port); + // There should always be a WindowPortMus for WindowTreeHost::window(). If + // there isn't, it likely means we got the wrong WindowTreeHost. + // + // TODO(sky): make Compositor extend SupportsUserData so that this code + // doesn't need to use GetForAcceleratedWidget(). + CHECK(window_port); scoped_refptr<viz::ContextProvider> context_provider = gpu_->CreateContextProvider(gpu_channel); diff --git a/chromium/ui/aura/mus/mus_lsi_allocator.cc b/chromium/ui/aura/mus/mus_lsi_allocator.cc new file mode 100644 index 00000000000..4c6da346761 --- /dev/null +++ b/chromium/ui/aura/mus/mus_lsi_allocator.cc @@ -0,0 +1,115 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/aura/mus/mus_lsi_allocator.h" + +#include <utility> + +#include "components/viz/common/surfaces/scoped_surface_id_allocator.h" +#include "components/viz/common/surfaces/surface_id.h" +#include "ui/aura/mus/client_surface_embedder.h" +#include "ui/aura/mus/window_port_mus.h" +#include "ui/aura/mus/window_tree_client.h" + +namespace aura { + +ParentAllocator::ParentAllocator(MusLsiAllocatorType type, + WindowPortMus* window, + WindowTreeClient* window_tree_client) + : MusLsiAllocator(type), + window_(window), + window_tree_client_(window_tree_client) { + DCHECK(window_); + DCHECK(window_tree_client_); + if (type == MusLsiAllocatorType::kEmbed) { + client_surface_embedder_ = std::make_unique<ClientSurfaceEmbedder>( + GetWindow(), /* inject_gutter */ false, gfx::Insets()); + } +} + +ParentAllocator::~ParentAllocator() = default; + +void ParentAllocator::AllocateLocalSurfaceId() { + last_surface_size_in_pixels_ = window_->GetSizeInPixels(); + parent_local_surface_id_allocator_.GenerateId(); + Update(/* send_bounds_change */ true); +} + +viz::ScopedSurfaceIdAllocator ParentAllocator::GetSurfaceIdAllocator( + base::OnceClosure allocation_task) { + return viz::ScopedSurfaceIdAllocator(&parent_local_surface_id_allocator_, + std::move(allocation_task)); +} + +void ParentAllocator::InvalidateLocalSurfaceId() { + parent_local_surface_id_allocator_.Invalidate(); +} + +void ParentAllocator::UpdateLocalSurfaceIdFromEmbeddedClient( + const viz::LocalSurfaceIdAllocation& + embedded_client_local_surface_id_allocation) { + parent_local_surface_id_allocator_.UpdateFromChild( + embedded_client_local_surface_id_allocation); + // Ensure there is a valid value. + if (!GetLocalSurfaceIdAllocation().IsValid()) + parent_local_surface_id_allocator_.GenerateId(); + Update(/* send_bounds_change */ true); +} + +void ParentAllocator::OnDeviceScaleFactorChanged() { + parent_local_surface_id_allocator_.GenerateId(); + Update(/* send_bounds_change */ true); +} + +void ParentAllocator::OnDidChangeBounds(const gfx::Size& size_in_pixels, + bool from_server) { + if (last_surface_size_in_pixels_ == size_in_pixels && + parent_local_surface_id_allocator_.HasValidLocalSurfaceIdAllocation()) { + return; + } + + last_surface_size_in_pixels_ = size_in_pixels; + parent_local_surface_id_allocator_.GenerateId(); + // If |from_server| is true, then WindowPortMus sends a bound change. + Update(/* send_bounds_change */ from_server); +} + +const viz::LocalSurfaceIdAllocation& +ParentAllocator::GetLocalSurfaceIdAllocation() { + return parent_local_surface_id_allocator_ + .GetCurrentLocalSurfaceIdAllocation(); +} + +aura::Window* ParentAllocator::GetWindow() { + return static_cast<WindowMus*>(window_)->GetWindow(); +} + +void ParentAllocator::Update(bool send_bounds_change) { + // If not in a bounds change, then need to update server of new + // LocalSurfaceId. + if (send_bounds_change) { + const gfx::Rect& bounds = GetWindow()->bounds(); + window_tree_client_->OnWindowMusBoundsChanged(window_, bounds, bounds); + } + if (GetWindow()->IsEmbeddingClient() && client_surface_embedder_) { + viz::SurfaceId surface_id(GetWindow()->GetFrameSinkId(), + GetLocalSurfaceIdAllocation().local_surface_id()); + client_surface_embedder_->SetSurfaceId(surface_id); + client_surface_embedder_->UpdateSizeAndGutters(); + } +} + +void ParentAllocator::OnFrameSinkIdChanged() { + Update(/* send_bounds_change */ false); +} + +// static +std::unique_ptr<MusLsiAllocator> MusLsiAllocator::CreateAllocator( + MusLsiAllocatorType type, + WindowPortMus* window, + WindowTreeClient* window_tree_client) { + return std::make_unique<ParentAllocator>(type, window, window_tree_client); +} + +} // namespace aura diff --git a/chromium/ui/aura/mus/mus_lsi_allocator.h b/chromium/ui/aura/mus/mus_lsi_allocator.h new file mode 100644 index 00000000000..73dc6e50c77 --- /dev/null +++ b/chromium/ui/aura/mus/mus_lsi_allocator.h @@ -0,0 +1,119 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_AURA_MUS_MUS_LSI_ALLOCATOR_H_ +#define UI_AURA_MUS_MUS_LSI_ALLOCATOR_H_ + +#include <memory> + +#include "base/callback_forward.h" +#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" +#include "ui/gfx/geometry/size.h" + +namespace gfx { +class Size; +} + +namespace viz { +class LocalSurfaceIdAllocation; +class ScopedSurfaceIdAllocator; +} // namespace viz + +namespace aura { + +class ClientSurfaceEmbedder; +class Window; +class WindowPortMus; +class WindowTreeClient; + +enum class MusLsiAllocatorType { + // The allocator was created by a window that has an embedding in it. This + // is the embedder side, *not* the embedding side. + kEmbed, + + // A local window that has a FrameSinkId associated with it. + kLocal, +}; + +// MusLsiAllocator is used by WindowPortMus to handle management of +// LocalSurfaceIdAllocation, and associated data. +class MusLsiAllocator { + public: + virtual ~MusLsiAllocator() {} + + static std::unique_ptr<MusLsiAllocator> CreateAllocator( + MusLsiAllocatorType type, + WindowPortMus* window, + WindowTreeClient* window_tree_client); + + MusLsiAllocatorType type() const { return type_; } + + virtual void AllocateLocalSurfaceId() = 0; + virtual viz::ScopedSurfaceIdAllocator GetSurfaceIdAllocator( + base::OnceClosure allocation_task) = 0; + virtual void InvalidateLocalSurfaceId() = 0; + virtual void UpdateLocalSurfaceIdFromEmbeddedClient( + const viz::LocalSurfaceIdAllocation& + embedded_client_local_surface_id_allocation) = 0; + virtual void OnDeviceScaleFactorChanged() = 0; + virtual void OnDidChangeBounds(const gfx::Size& size_in_pixels, + bool from_server) = 0; + virtual const viz::LocalSurfaceIdAllocation& + GetLocalSurfaceIdAllocation() = 0; + virtual void OnFrameSinkIdChanged() = 0; + + protected: + explicit MusLsiAllocator(MusLsiAllocatorType type) : type_(type) {} + + private: + const MusLsiAllocatorType type_; +}; + +// ParentAllocator is used for kEmbed and kLocal types of allocators. It uses +// a ParentLocalSurfaceIdAllocator to generate a LocalSurfaceIdAllocation. +// Additionally ParenAllocator may creates a ClientSurfaceEmbedder| to handle +// associating the FrameSinkId with Viz. +// +// This is an implementation detail and only public for tests to poke at. +class ParentAllocator : public MusLsiAllocator { + public: + ParentAllocator(MusLsiAllocatorType type, + WindowPortMus* window, + WindowTreeClient* window_tree_client); + ~ParentAllocator() override; + + // MusLsiAllocator: + void AllocateLocalSurfaceId() override; + viz::ScopedSurfaceIdAllocator GetSurfaceIdAllocator( + base::OnceClosure allocation_task) override; + void InvalidateLocalSurfaceId() override; + void UpdateLocalSurfaceIdFromEmbeddedClient( + const viz::LocalSurfaceIdAllocation& + embedded_client_local_surface_id_allocation) override; + void OnDeviceScaleFactorChanged() override; + void OnDidChangeBounds(const gfx::Size& size_in_pixels, + bool from_server) override; + const viz::LocalSurfaceIdAllocation& GetLocalSurfaceIdAllocation() override; + void OnFrameSinkIdChanged() override; + + private: + friend class WindowPortMusTestHelper; + + Window* GetWindow(); + + void Update(bool in_bounds_change); + + WindowPortMus* window_; + WindowTreeClient* window_tree_client_; + viz::ParentLocalSurfaceIdAllocator parent_local_surface_id_allocator_; + std::unique_ptr<ClientSurfaceEmbedder> client_surface_embedder_; + + // Last size (in pixels) that a LocalSurfaceId was generated for. + gfx::Size last_surface_size_in_pixels_; + + DISALLOW_COPY_AND_ASSIGN(ParentAllocator); +}; +} // namespace aura + +#endif // UI_AURA_MUS_MUS_LSI_ALLOCATOR_H_ diff --git a/chromium/ui/aura/mus/os_exchange_data_provider_mus.cc b/chromium/ui/aura/mus/os_exchange_data_provider_mus.cc index f8e327cd09b..587516a4f86 100644 --- a/chromium/ui/aura/mus/os_exchange_data_provider_mus.cc +++ b/chromium/ui/aura/mus/os_exchange_data_provider_mus.cc @@ -15,6 +15,8 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "net/base/filename_util.h" +#include "ui/base/clipboard/clipboard_constants.h" +#include "ui/base/clipboard/clipboard_format_type.h" #include "ui/base/dragdrop/file_info.h" #include "ui/base/mojo/clipboard.mojom.h" #include "url/gurl.h" @@ -87,8 +89,7 @@ void OSExchangeDataProviderMus::SetString(const base::string16& data) { if (HasString()) return; - mime_data_[ui::Clipboard::kMimeTypeText] = - FromString(base::UTF16ToUTF8(data)); + mime_data_[ui::kMimeTypeText] = FromString(base::UTF16ToUTF8(data)); } void OSExchangeDataProviderMus::SetURL(const GURL& url, @@ -98,10 +99,10 @@ void OSExchangeDataProviderMus::SetURL(const GURL& url, AddString16ToVector(spec, &data); AddString16ToVector(base::ASCIIToUTF16("\n"), &data); AddString16ToVector(title, &data); - mime_data_[ui::Clipboard::kMimeTypeMozillaURL] = std::move(data); + mime_data_[ui::kMimeTypeMozillaURL] = std::move(data); - if (!base::ContainsKey(mime_data_, ui::Clipboard::kMimeTypeText)) - mime_data_[ui::Clipboard::kMimeTypeText] = FromString(url.spec()); + if (!base::ContainsKey(mime_data_, ui::kMimeTypeText)) + mime_data_[ui::kMimeTypeText] = FromString(url.spec()); } void OSExchangeDataProviderMus::SetFilename(const base::FilePath& path) { @@ -120,11 +121,11 @@ void OSExchangeDataProviderMus::SetFilenames( } std::string joined_data = base::JoinString(paths, "\n"); - mime_data_[ui::Clipboard::kMimeTypeURIList] = FromString(joined_data); + mime_data_[ui::kMimeTypeURIList] = FromString(joined_data); } void OSExchangeDataProviderMus::SetPickledData( - const ui::Clipboard::FormatType& format, + const ui::ClipboardFormatType& format, const base::Pickle& pickle) { const unsigned char* bytes = reinterpret_cast<const unsigned char*>(pickle.data()); @@ -134,7 +135,7 @@ void OSExchangeDataProviderMus::SetPickledData( } bool OSExchangeDataProviderMus::GetString(base::string16* data) const { - auto it = mime_data_.find(ui::Clipboard::kMimeTypeText); + auto it = mime_data_.find(ui::kMimeTypeText); if (it != mime_data_.end()) *data = base::UTF8ToUTF16(ToString(it->second)); return it != mime_data_.end(); @@ -144,7 +145,7 @@ bool OSExchangeDataProviderMus::GetURLAndTitle( ui::OSExchangeData::FilenameToURLPolicy policy, GURL* url, base::string16* title) const { - auto it = mime_data_.find(ui::Clipboard::kMimeTypeMozillaURL); + auto it = mime_data_.find(ui::kMimeTypeMozillaURL); if (it == mime_data_.end()) { title->clear(); return GetPlainTextURL(url) || @@ -177,7 +178,7 @@ bool OSExchangeDataProviderMus::GetFilename(base::FilePath* path) const { bool OSExchangeDataProviderMus::GetFilenames( std::vector<ui::FileInfo>* file_names) const { - auto it = mime_data_.find(ui::Clipboard::kMimeTypeURIList); + auto it = mime_data_.find(ui::kMimeTypeURIList); if (it == mime_data_.end()) return false; @@ -193,7 +194,7 @@ bool OSExchangeDataProviderMus::GetFilenames( } bool OSExchangeDataProviderMus::GetPickledData( - const ui::Clipboard::FormatType& format, + const ui::ClipboardFormatType& format, base::Pickle* data) const { auto it = mime_data_.find(format.Serialize()); if (it == mime_data_.end()) @@ -207,15 +208,15 @@ bool OSExchangeDataProviderMus::GetPickledData( } bool OSExchangeDataProviderMus::HasString() const { - return base::ContainsKey(mime_data_, ui::Clipboard::kMimeTypeText); + return base::ContainsKey(mime_data_, ui::kMimeTypeText); } bool OSExchangeDataProviderMus::HasURL( ui::OSExchangeData::FilenameToURLPolicy policy) const { - if (base::ContainsKey(mime_data_, ui::Clipboard::kMimeTypeMozillaURL)) + if (base::ContainsKey(mime_data_, ui::kMimeTypeMozillaURL)) return true; - auto it = mime_data_.find(ui::Clipboard::kMimeTypeURIList); + auto it = mime_data_.find(ui::kMimeTypeURIList); if (it == mime_data_.end()) return false; @@ -230,7 +231,7 @@ bool OSExchangeDataProviderMus::HasURL( } bool OSExchangeDataProviderMus::HasFile() const { - auto it = mime_data_.find(ui::Clipboard::kMimeTypeURIList); + auto it = mime_data_.find(ui::kMimeTypeURIList); if (it == mime_data_.end()) return false; @@ -245,7 +246,7 @@ bool OSExchangeDataProviderMus::HasFile() const { } bool OSExchangeDataProviderMus::HasCustomFormat( - const ui::Clipboard::FormatType& format) const { + const ui::ClipboardFormatType& format) const { return base::ContainsKey(mime_data_, format.Serialize()); } @@ -281,12 +282,12 @@ void OSExchangeDataProviderMus::SetHtml(const base::string16& html, bytes.push_back(0xFF); bytes.push_back(0xFE); AddString16ToVector(html, &bytes); - mime_data_[ui::Clipboard::kMimeTypeHTML] = bytes; + mime_data_[ui::kMimeTypeHTML] = bytes; } bool OSExchangeDataProviderMus::GetHtml(base::string16* html, GURL* base_url) const { - auto it = mime_data_.find(ui::Clipboard::kMimeTypeHTML); + auto it = mime_data_.find(ui::kMimeTypeHTML); if (it == mime_data_.end()) return false; @@ -313,7 +314,7 @@ bool OSExchangeDataProviderMus::GetHtml(base::string16* html, } bool OSExchangeDataProviderMus::HasHtml() const { - return base::ContainsKey(mime_data_, ui::Clipboard::kMimeTypeHTML); + return base::ContainsKey(mime_data_, ui::kMimeTypeHTML); } #endif diff --git a/chromium/ui/aura/mus/os_exchange_data_provider_mus.h b/chromium/ui/aura/mus/os_exchange_data_provider_mus.h index 27a541950dd..ce1b44a0d70 100644 --- a/chromium/ui/aura/mus/os_exchange_data_provider_mus.h +++ b/chromium/ui/aura/mus/os_exchange_data_provider_mus.h @@ -46,7 +46,7 @@ class AURA_EXPORT OSExchangeDataProviderMus void SetURL(const GURL& url, const base::string16& title) override; void SetFilename(const base::FilePath& path) override; void SetFilenames(const std::vector<ui::FileInfo>& file_names) override; - void SetPickledData(const ui::Clipboard::FormatType& format, + void SetPickledData(const ui::ClipboardFormatType& format, const base::Pickle& data) override; bool GetString(base::string16* data) const override; @@ -55,13 +55,13 @@ class AURA_EXPORT OSExchangeDataProviderMus base::string16* title) const override; bool GetFilename(base::FilePath* path) const override; bool GetFilenames(std::vector<ui::FileInfo>* file_names) const override; - bool GetPickledData(const ui::Clipboard::FormatType& format, + bool GetPickledData(const ui::ClipboardFormatType& format, base::Pickle* data) const override; bool HasString() const override; bool HasURL(ui::OSExchangeData::FilenameToURLPolicy policy) const override; bool HasFile() const override; - bool HasCustomFormat(const ui::Clipboard::FormatType& format) const override; + bool HasCustomFormat(const ui::ClipboardFormatType& format) const override; // Provider doesn't have a consistent interface between operating systems; // this wasn't seen as a problem when there was a single Provider subclass diff --git a/chromium/ui/aura/mus/os_exchange_data_provider_mus_unittest.cc b/chromium/ui/aura/mus/os_exchange_data_provider_mus_unittest.cc index 225a515a754..4eea746aefc 100644 --- a/chromium/ui/aura/mus/os_exchange_data_provider_mus_unittest.cc +++ b/chromium/ui/aura/mus/os_exchange_data_provider_mus_unittest.cc @@ -14,12 +14,12 @@ #include "net/base/filename_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" +#include "ui/base/clipboard/clipboard_format_type.h" #include "ui/base/dragdrop/os_exchange_data.h" #include "ui/base/dragdrop/os_exchange_data_provider_factory.h" #include "ui/events/platform/platform_event_source.h" #include "url/gurl.h" -using ui::Clipboard; using ui::OSExchangeData; namespace aura { @@ -171,8 +171,8 @@ TEST_F(OSExchangeDataProviderMusTest, TestFileToURLConversion) { } TEST_F(OSExchangeDataProviderMusTest, TestPickledData) { - const Clipboard::FormatType kTestFormat = - Clipboard::GetFormatType("application/vnd.chromium.test"); + const ui::ClipboardFormatType kTestFormat = + ui::ClipboardFormatType::GetType("application/vnd.chromium.test"); base::Pickle saved_pickle; saved_pickle.WriteInt(1); diff --git a/chromium/ui/aura/mus/property_converter.cc b/chromium/ui/aura/mus/property_converter.cc index 86b43b087af..0f1422424fe 100644 --- a/chromium/ui/aura/mus/property_converter.cc +++ b/chromium/ui/aura/mus/property_converter.cc @@ -91,12 +91,16 @@ PropertyConverter::PropertyConverter() { ws::mojom::WindowManager::kRestoreBounds_Property); RegisterSizeProperty(client::kPreferredSize, ws::mojom::WindowManager::kPreferredSize_Property); + RegisterSizeProperty(client::kMaximumSize, + ws::mojom::WindowManager::kMaximumSize_Property); RegisterSizeProperty(client::kMinimumSize, ws::mojom::WindowManager::kMinimumSize_Property); RegisterStringProperty(client::kNameKey, ws::mojom::WindowManager::kName_Property); RegisterString16Property(client::kTitleKey, ws::mojom::WindowManager::kWindowTitle_Property); + RegisterSizeFProperty(client::kAspectRatio, + ws::mojom::WindowManager::kAspectRatio_Property); RegisterPrimitiveProperty( client::kWindowCornerRadiusKey, ws::mojom::WindowManager::kWindowCornerRadius_Property, @@ -138,6 +142,11 @@ const void* PropertyConverter::GetPropertyKeyFromTransportName( return size_property.first->name; } + for (const auto& size_f_property : size_f_properties_) { + if (size_f_property.second == transport_name) + return size_f_property.first->name; + } + for (const auto& string_property : string_properties_) { if (string_property.second == transport_name) return string_property.first->name; @@ -201,6 +210,12 @@ bool PropertyConverter::ConvertPropertyForTransport( return true; } + auto* size_f_key = static_cast<const WindowProperty<gfx::SizeF*>*>(key); + if (size_f_properties_.count(size_f_key) > 0) { + *transport_value = GetArray(window, size_f_key); + return true; + } + auto* string_key = static_cast<const WindowProperty<std::string*>*>(key); if (string_properties_.count(string_key) > 0) { *transport_value = GetArray(window, string_key); @@ -254,6 +269,10 @@ std::string PropertyConverter::GetTransportNameForPropertyKey(const void* key) { if (size_properties_.count(size_key) > 0) return size_properties_[size_key]; + auto* size_f_key = static_cast<const WindowProperty<gfx::SizeF*>*>(key); + if (size_f_properties_.count(size_f_key) > 0) + return size_f_properties_[size_f_key]; + auto* string_key = static_cast<const WindowProperty<std::string*>*>(key); if (string_properties_.count(string_key) > 0) return string_properties_[string_key]; @@ -335,6 +354,18 @@ void PropertyConverter::SetPropertyFromTransportValue( } } + for (const auto& size_f_property : size_f_properties_) { + if (size_f_property.second == transport_name) { + if (data->size() != 8u) { + DVLOG(2) << "Property size mismatch (gfx::Size): " << transport_name; + return; + } + const gfx::SizeF value = mojo::ConvertTo<gfx::SizeF>(*data); + window->SetProperty(size_f_property.first, new gfx::SizeF(value)); + return; + } + } + for (const auto& string_property : string_properties_) { if (string_property.second == transport_name) { // TODO(msw): Validate the data somehow, before trying to convert? @@ -436,6 +467,15 @@ void PropertyConverter::RegisterSizeProperty( transport_names_.insert(transport_name); } +void PropertyConverter::RegisterSizeFProperty( + const WindowProperty<gfx::SizeF*>* property, + const char* transport_name) { + DCHECK(!IsTransportNameRegistered(transport_name)) + << "Property already registered: " << transport_name; + size_f_properties_[property] = transport_name; + transport_names_.insert(transport_name); +} + void PropertyConverter::RegisterStringProperty( const WindowProperty<std::string*>* property, const char* transport_name) { diff --git a/chromium/ui/aura/mus/property_converter.h b/chromium/ui/aura/mus/property_converter.h index 82650db1321..099feeafb9e 100644 --- a/chromium/ui/aura/mus/property_converter.h +++ b/chromium/ui/aura/mus/property_converter.h @@ -112,6 +112,8 @@ class AURA_EXPORT PropertyConverter { const char* transport_name); void RegisterSizeProperty(const WindowProperty<gfx::Size*>* property, const char* transport_name); + void RegisterSizeFProperty(const WindowProperty<gfx::SizeF*>* property, + const char* transport_name); void RegisterStringProperty(const WindowProperty<std::string*>* property, const char* transport_name); void RegisterString16Property(const WindowProperty<base::string16*>* property, @@ -165,6 +167,7 @@ class AURA_EXPORT PropertyConverter { image_properties_; std::map<const WindowProperty<gfx::Rect*>*, const char*> rect_properties_; std::map<const WindowProperty<gfx::Size*>*, const char*> size_properties_; + std::map<const WindowProperty<gfx::SizeF*>*, const char*> size_f_properties_; std::map<const WindowProperty<std::string*>*, const char*> string_properties_; std::map<const WindowProperty<base::string16*>*, const char*> string16_properties_; diff --git a/chromium/ui/aura/mus/property_utils.cc b/chromium/ui/aura/mus/property_utils.cc index d261320a22c..7f00f7fa06f 100644 --- a/chromium/ui/aura/mus/property_utils.cc +++ b/chromium/ui/aura/mus/property_utils.cc @@ -18,8 +18,6 @@ client::WindowType UiWindowTypeToWindowType(ws::mojom::WindowType type) { switch (type) { case ws::mojom::WindowType::WINDOW: return client::WINDOW_TYPE_NORMAL; - case ws::mojom::WindowType::PANEL: - return client::WINDOW_TYPE_PANEL; case ws::mojom::WindowType::CONTROL: return client::WINDOW_TYPE_CONTROL; case ws::mojom::WindowType::WINDOW_FRAMELESS: diff --git a/chromium/ui/aura/mus/text_input_client_impl.cc b/chromium/ui/aura/mus/text_input_client_impl.cc index 3d8a041f2ee..86dd35db082 100644 --- a/chromium/ui/aura/mus/text_input_client_impl.cc +++ b/chromium/ui/aura/mus/text_input_client_impl.cc @@ -90,4 +90,8 @@ void TextInputClientImpl::DispatchKeyEventPostIME( key_event->WillHandleAsync().Run(handled); } +void TextInputClientImpl::EnsureCaretNotInRect(const gfx::Rect& rect) { + text_input_client_->EnsureCaretNotInRect(rect); +} + } // namespace aura diff --git a/chromium/ui/aura/mus/text_input_client_impl.h b/chromium/ui/aura/mus/text_input_client_impl.h index 5d50c815023..12a21a9623a 100644 --- a/chromium/ui/aura/mus/text_input_client_impl.h +++ b/chromium/ui/aura/mus/text_input_client_impl.h @@ -36,6 +36,7 @@ class TextInputClientImpl : public ws::mojom::TextInputClient { void DispatchKeyEventPostIME( std::unique_ptr<ui::Event> event, DispatchKeyEventPostIMECallback callback) override; + void EnsureCaretNotInRect(const gfx::Rect& rect) override; ui::TextInputClient* text_input_client_; mojo::Binding<ws::mojom::TextInputClient> binding_; diff --git a/chromium/ui/aura/mus/window_mus.h b/chromium/ui/aura/mus/window_mus.h index 11ca0ae9419..9562f0ff81d 100644 --- a/chromium/ui/aura/mus/window_mus.h +++ b/chromium/ui/aura/mus/window_mus.h @@ -11,9 +11,9 @@ #include <vector> #include "components/viz/common/surfaces/local_surface_id_allocation.h" -#include "services/ws/public/mojom/cursor/cursor.mojom.h" #include "ui/aura/aura_export.h" #include "ui/aura/mus/mus_types.h" +#include "ui/base/mojo/cursor.mojom.h" namespace gfx { class Rect; @@ -28,7 +28,6 @@ enum class OrderDirection; namespace viz { class FrameSinkId; -class LocalSurfaceId; } namespace aura { @@ -82,19 +81,15 @@ class AURA_EXPORT WindowMus { virtual void ReorderFromServer(WindowMus* child, WindowMus* relative, ws::mojom::OrderDirection) = 0; - virtual void SetBoundsFromServer( - const gfx::Rect& bounds, - const base::Optional<viz::LocalSurfaceId>& local_surface_id) = 0; + virtual void SetBoundsFromServer(const gfx::Rect& bounds) = 0; virtual void SetTransformFromServer(const gfx::Transform& transform) = 0; virtual void SetVisibleFromServer(bool visible) = 0; virtual void SetOpacityFromServer(float opacity) = 0; - virtual void SetCursorFromServer(const ui::CursorData& cursor) = 0; + virtual void SetCursorFromServer(const ui::Cursor& cursor) = 0; virtual void SetPropertyFromServer(const std::string& property_name, const std::vector<uint8_t>* data) = 0; virtual void SetFrameSinkIdFromServer( const viz::FrameSinkId& frame_sink_id) = 0; - virtual const viz::LocalSurfaceId& GetOrAllocateLocalSurfaceId( - const gfx::Size& new_size) = 0; // The window was deleted on the server side. DestroyFromServer() should // result in deleting |this|. virtual void DestroyFromServer() = 0; @@ -110,6 +105,9 @@ class AURA_EXPORT WindowMus { virtual const viz::LocalSurfaceIdAllocation& GetLocalSurfaceIdAllocation() = 0; + // Returns true if the window has a LocalSurfaceId. + virtual bool HasLocalSurfaceId() = 0; + // Called in the rare case when WindowTreeClient needs to change state and // can't go through one of the SetFooFromServer() functions above. Generally // because it needs to call another function that as a side effect changes the @@ -127,8 +125,6 @@ class AURA_EXPORT WindowMus { virtual void NotifyEmbeddedAppDisconnected() = 0; - virtual bool HasLocalLayerTreeFrameSink() = 0; - virtual float GetDeviceScaleFactor() = 0; private: diff --git a/chromium/ui/aura/mus/window_port_mus.cc b/chromium/ui/aura/mus/window_port_mus.cc index e970a5d30dc..88fd879d6e8 100644 --- a/chromium/ui/aura/mus/window_port_mus.cc +++ b/chromium/ui/aura/mus/window_port_mus.cc @@ -9,17 +9,20 @@ #include "base/auto_reset.h" #include "base/bind.h" #include "base/callback.h" +#include "base/no_destructor.h" #include "cc/mojo_embedder/async_layer_tree_frame_sink.h" #include "components/viz/client/hit_test_data_provider_draw_quad.h" #include "components/viz/client/local_surface_id_provider.h" #include "components/viz/common/features.h" #include "components/viz/common/surfaces/local_surface_id_allocation.h" +#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" #include "components/viz/host/host_frame_sink_manager.h" #include "services/ws/public/mojom/window_tree_constants.mojom.h" #include "ui/aura/client/aura_constants.h" +#include "ui/aura/client/drag_drop_delegate.h" #include "ui/aura/client/transient_window_client.h" #include "ui/aura/env.h" -#include "ui/aura/mus/client_surface_embedder.h" +#include "ui/aura/mus/mus_lsi_allocator.h" #include "ui/aura/mus/property_converter.h" #include "ui/aura/mus/property_utils.h" #include "ui/aura/mus/window_tree_client.h" @@ -96,7 +99,7 @@ WindowPortMus::WindowPortMus(WindowTreeClient* client, weak_ptr_factory_(this) {} WindowPortMus::~WindowPortMus() { - client_surface_embedder_.reset(); + allocator_.reset(); // DESTROY is only scheduled from DestroyFromServer(), meaning if DESTROY is // present then the server originated the change. @@ -124,7 +127,7 @@ void WindowPortMus::SetImeVisibility(bool visible, window_tree_client_->SetImeVisibility(this, visible, std::move(state)); } -void WindowPortMus::SetCursor(const ui::CursorData& cursor) { +void WindowPortMus::SetCursor(const ui::Cursor& cursor) { if (cursor_.IsSameAs(cursor)) return; @@ -202,8 +205,6 @@ WindowPortMus::RequestLayerTreeFrameSink( std::make_unique<viz::HitTestDataProviderDrawQuad>( /* should_ask_for_child_regions */ false, root_accepts_events); } - params.local_surface_id_provider = - std::make_unique<viz::DefaultLocalSurfaceIdProvider>(); params.enable_surface_synchronization = true; params.client_name = kMus; @@ -224,6 +225,22 @@ viz::FrameSinkId WindowPortMus::GenerateFrameSinkIdFromServerId() const { return viz::FrameSinkId(kClientSelfId, server_id()); } +gfx::Size WindowPortMus::GetSizeInPixels() { + return GetSizeInPixels(window_->bounds().size()); +} + +gfx::Size WindowPortMus::GetSizeInPixels(const gfx::Size& size) { + return gfx::ScaleToCeiledSize(size, GetDeviceScaleFactor()); +} + +void WindowPortMus::SetAllocator(std::unique_ptr<MusLsiAllocator> allocator) { + allocator_ = std::move(allocator); + // This triggers allocating a LocalSurfaceId *and* notifying the server. + // TODO: investigate making allocation match that of WindowPortLocal, this may + // be called earlier than WindowPortLocal allocates the id. + allocator_->AllocateLocalSurfaceId(); +} + WindowPortMus::ServerChangeIdType WindowPortMus::ScheduleChange( const ServerChangeType type, const ServerChangeData& data) { @@ -319,6 +336,9 @@ bool WindowPortMus::PrepareForEmbed() { return false; has_embedding_ = true; + DCHECK(!allocator_.get()); + SetAllocator(MusLsiAllocator::CreateAllocator(MusLsiAllocatorType::kEmbed, + this, window_tree_client_)); return true; } @@ -327,8 +347,10 @@ void WindowPortMus::OnEmbedAck( base::WeakPtr<WindowPortMus> window, ws::mojom::WindowTree::EmbedCallback real_callback, bool result) { - if (window && !result) + if (window && !result) { window->has_embedding_ = false; + window->allocator_.reset(); + } std::move(real_callback).Run(window && result); } @@ -370,18 +392,15 @@ void WindowPortMus::ReorderFromServer(WindowMus* child, window_->StackChildAbove(child->GetWindow(), relative->GetWindow()); } -void WindowPortMus::SetBoundsFromServer( - const gfx::Rect& bounds, - const base::Optional<viz::LocalSurfaceId>& local_surface_id) { +void WindowPortMus::SetBoundsFromServer(const gfx::Rect& bounds) { + // Changes to TOP_LEVEL and EMBED are routed through WindowTreeHostMus. + DCHECK(window_mus_type() != WindowMusType::TOP_LEVEL && + window_mus_type() != WindowMusType::EMBED); ServerChangeData data; data.bounds_in_dip = bounds; ScopedServerChange change(this, ServerChangeType::BOUNDS, data); - last_surface_size_in_pixels_ = - gfx::ConvertSizeToPixel(GetDeviceScaleFactor(), bounds.size()); - if (local_surface_id) - parent_local_surface_id_allocator_.Reset(*local_surface_id); - else - parent_local_surface_id_allocator_.Invalidate(); + // XXX this seems like the wrong place to cache size. + last_surface_size_in_pixels_ = GetSizeInPixels(bounds.size()); window_->SetBounds(bounds); } @@ -406,7 +425,7 @@ void WindowPortMus::SetOpacityFromServer(float opacity) { window_->layer()->SetOpacity(opacity); } -void WindowPortMus::SetCursorFromServer(const ui::CursorData& cursor) { +void WindowPortMus::SetCursorFromServer(const ui::Cursor& cursor) { // As this does nothing more than set the cursor we don't need to use // ServerChange. cursor_ = cursor; @@ -424,37 +443,11 @@ void WindowPortMus::SetPropertyFromServer( void WindowPortMus::SetFrameSinkIdFromServer( const viz::FrameSinkId& frame_sink_id) { + // Only called if this window is embedding another window. + DCHECK(has_embedding_); embed_frame_sink_id_ = frame_sink_id; window_->SetEmbedFrameSinkId(embed_frame_sink_id_); - // We may not have allocated a LocalSurfaceId. Call OnWindowMusBoundsChanged() - // to trigger updating the LocalSurfaceId *and* notifying the server. - window_tree_client_->OnWindowMusBoundsChanged(this, window_->bounds(), - window_->bounds()); -} - -const viz::LocalSurfaceId& WindowPortMus::GetOrAllocateLocalSurfaceId( - const gfx::Size& surface_size_in_pixels) { - if (last_surface_size_in_pixels_ != surface_size_in_pixels || - !GetLocalSurfaceIdAllocation().IsValid()) { - parent_local_surface_id_allocator_.GenerateId(); - last_surface_size_in_pixels_ = surface_size_in_pixels; - } - - const viz::LocalSurfaceId& current_local_surface_id = - parent_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation() - .local_surface_id(); - - // If the FrameSinkId is available, then immediately embed the SurfaceId. - // The newly generated frame by the embedder will block in the display - // compositor until the child submits a corresponding CompositorFrame or a - // deadline hits. - if (window_->IsEmbeddingClient()) - UpdatePrimarySurfaceId(); - - if (local_layer_tree_frame_sink_) - local_layer_tree_frame_sink_->SetLocalSurfaceId(current_local_surface_id); - - return current_local_surface_id; + allocator_->OnFrameSinkIdChanged(); } void WindowPortMus::DestroyFromServer() { @@ -513,41 +506,52 @@ WindowPortMus::ChangeSource WindowPortMus::OnTransientChildRemoved( } void WindowPortMus::AllocateLocalSurfaceId() { - parent_local_surface_id_allocator_.GenerateId(); - UpdatePrimarySurfaceId(); - if (local_layer_tree_frame_sink_) { - local_layer_tree_frame_sink_->SetLocalSurfaceId( - GetLocalSurfaceIdAllocation().local_surface_id()); + // This API does not make sense for EMBED. + DCHECK_NE(window_mus_type(), WindowMusType::EMBED); + if (!allocator_ && window_mus_type() == WindowMusType::LOCAL) { + SetAllocator(MusLsiAllocator::CreateAllocator(MusLsiAllocatorType::kLocal, + this, window_tree_client_)); + } else if (allocator_) { + allocator_->AllocateLocalSurfaceId(); } } viz::ScopedSurfaceIdAllocator WindowPortMus::GetSurfaceIdAllocator( base::OnceCallback<void()> allocation_task) { - return viz::ScopedSurfaceIdAllocator(&parent_local_surface_id_allocator_, - std::move(allocation_task)); + // This API does not make sense for EMBED. + DCHECK_NE(window_mus_type(), WindowMusType::EMBED); + return allocator_ + ? allocator_->GetSurfaceIdAllocator(std::move(allocation_task)) + : viz::ScopedSurfaceIdAllocator(std::move(allocation_task)); } void WindowPortMus::InvalidateLocalSurfaceId() { - parent_local_surface_id_allocator_.Invalidate(); + // This API does not make sense for EMBED. + DCHECK_NE(window_mus_type(), WindowMusType::EMBED); + if (allocator_) + allocator_->InvalidateLocalSurfaceId(); } void WindowPortMus::UpdateLocalSurfaceIdFromEmbeddedClient( const viz::LocalSurfaceIdAllocation& embedded_client_local_surface_id_allocation) { - parent_local_surface_id_allocator_.UpdateFromChild( - embedded_client_local_surface_id_allocation); - UpdatePrimarySurfaceId(); - - // OnWindowMusBoundsChanged() triggers notifying the server of the new - // LocalSurfaceId. - window_tree_client_->OnWindowMusBoundsChanged(this, window_->bounds(), - window_->bounds()); + // This API does not make sense for EMBED. + DCHECK_NE(window_mus_type(), WindowMusType::EMBED); + if (allocator_) { + allocator_->UpdateLocalSurfaceIdFromEmbeddedClient( + embedded_client_local_surface_id_allocation); + } } const viz::LocalSurfaceIdAllocation& WindowPortMus::GetLocalSurfaceIdAllocation() { - return parent_local_surface_id_allocator_ - .GetCurrentLocalSurfaceIdAllocation(); + static base::NoDestructor<viz::LocalSurfaceIdAllocation> empty_allocation; + return allocator_ ? allocator_->GetLocalSurfaceIdAllocation() + : *empty_allocation; +} + +bool WindowPortMus::HasLocalSurfaceId() { + return allocator_.get() != nullptr; } std::unique_ptr<WindowMusChangeData> @@ -578,14 +582,11 @@ void WindowPortMus::PrepareForDestroy() { void WindowPortMus::NotifyEmbeddedAppDisconnected() { has_embedding_ = false; + allocator_ = nullptr; for (WindowObserver& observer : *GetObservers(window_)) observer.OnEmbeddedAppDisconnected(window_); } -bool WindowPortMus::HasLocalLayerTreeFrameSink() { - return !!local_layer_tree_frame_sink_; -} - float WindowPortMus::GetDeviceScaleFactor() { return window_->layer()->device_scale_factor(); } @@ -597,13 +598,8 @@ void WindowPortMus::OnPreInit(Window* window) { void WindowPortMus::OnDeviceScaleFactorChanged(float old_device_scale_factor, float new_device_scale_factor) { - if (!window_->IsRootWindow() && GetLocalSurfaceIdAllocation().IsValid() && - local_layer_tree_frame_sink_) { - parent_local_surface_id_allocator_.GenerateId(); - local_layer_tree_frame_sink_->SetLocalSurfaceId( - parent_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation() - .local_surface_id()); - } + if (allocator_) + allocator_->OnDeviceScaleFactorChanged(); if (window_->delegate()) { window_->delegate()->OnDeviceScaleFactorChanged(old_device_scale_factor, @@ -645,10 +641,12 @@ void WindowPortMus::OnDidChangeBounds(const gfx::Rect& old_bounds, const gfx::Rect& new_bounds) { ServerChangeData change_data; change_data.bounds_in_dip = new_bounds; - if (!RemoveChangeByTypeAndData(ServerChangeType::BOUNDS, change_data)) + const bool from_server = + RemoveChangeByTypeAndData(ServerChangeType::BOUNDS, change_data); + if (allocator_) + allocator_->OnDidChangeBounds(GetSizeInPixels(), from_server); + if (!from_server) window_tree_client_->OnWindowMusBoundsChanged(this, old_bounds, new_bounds); - if (client_surface_embedder_) - client_surface_embedder_->UpdateSizeAndGutters(); } void WindowPortMus::OnDidChangeTransform(const gfx::Transform& old_transform, @@ -680,6 +678,11 @@ void WindowPortMus::OnPropertyChanged(const void* key, if (!window_) return; + if (key == client::kDragDropDelegateKey) { + SetCanAcceptDrops(window_->GetProperty(client::kDragDropDelegateKey) != + nullptr); + } + ServerChangeData change_data; change_data.property_name = GetPropertyConverter()->GetTransportNameForPropertyKey(key); @@ -693,23 +696,9 @@ void WindowPortMus::OnPropertyChanged(const void* key, std::unique_ptr<cc::LayerTreeFrameSink> WindowPortMus::CreateLayerTreeFrameSink() { - DCHECK_EQ(window_mus_type(), WindowMusType::LOCAL); - DCHECK(!local_layer_tree_frame_sink_); - - // TODO(sky): this needs to supply a RasterContextProvider. - auto client_layer_tree_frame_sink = RequestLayerTreeFrameSink( - nullptr, nullptr, - window_->env()->context_factory()->GetGpuMemoryBufferManager()); - local_layer_tree_frame_sink_ = client_layer_tree_frame_sink->GetWeakPtr(); - embed_frame_sink_id_ = GenerateFrameSinkIdFromServerId(); - window_->SetEmbedFrameSinkId(embed_frame_sink_id_); - - gfx::Size size_in_pixel = - gfx::ConvertSizeToPixel(GetDeviceScaleFactor(), window_->bounds().size()); - // Make sure |local_surface_id_| and |last_surface_size_in_pixels_| are - // correct for the new created |local_layer_tree_frame_sink_|. - GetOrAllocateLocalSurfaceId(size_in_pixel); - return client_layer_tree_frame_sink; + // This function should not be called for WindowPortMus. + NOTIMPLEMENTED(); + return nullptr; } void WindowPortMus::OnEventTargetingPolicyChanged() { @@ -725,6 +714,14 @@ void WindowPortMus::RegisterFrameSinkId(const viz::FrameSinkId& frame_sink_id) { return; window_tree_client_->RegisterFrameSinkId(this, frame_sink_id); + // This api only makes sense for local windows. + DCHECK_EQ(window_mus_type(), WindowMusType::LOCAL); + if (allocator_) { + DCHECK_EQ(MusLsiAllocatorType::kLocal, allocator_->type()); + } else { + SetAllocator(MusLsiAllocator::CreateAllocator(MusLsiAllocatorType::kLocal, + this, window_tree_client_)); + } } void WindowPortMus::UnregisterFrameSinkId( @@ -744,26 +741,6 @@ void WindowPortMus::TrackOcclusionState() { window_tree_client_->TrackOcclusionState(this); } -void WindowPortMus::UpdatePrimarySurfaceId() { - if (window_mus_type() != WindowMusType::LOCAL) - return; - - if (!window_->IsEmbeddingClient() || !GetLocalSurfaceIdAllocation().IsValid()) - return; - - primary_surface_id_ = - viz::SurfaceId(window_->GetFrameSinkId(), - GetLocalSurfaceIdAllocation().local_surface_id()); - - if (!client_surface_embedder_) { - client_surface_embedder_ = std::make_unique<ClientSurfaceEmbedder>( - window_, /* inject_gutter */ false, gfx::Insets()); - } - - client_surface_embedder_->SetSurfaceId(primary_surface_id_); - client_surface_embedder_->UpdateSizeAndGutters(); -} - void WindowPortMus::SetOcclusionStateFromServer( ws::mojom::OcclusionState occlusion_state) { const Window::OcclusionState new_state = diff --git a/chromium/ui/aura/mus/window_port_mus.h b/chromium/ui/aura/mus/window_port_mus.h index 14f60e525f5..adf78045962 100644 --- a/chromium/ui/aura/mus/window_port_mus.h +++ b/chromium/ui/aura/mus/window_port_mus.h @@ -15,9 +15,7 @@ #include "base/memory/weak_ptr.h" #include "base/optional.h" #include "base/time/time.h" -#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" #include "components/viz/common/surfaces/surface_info.h" -#include "services/ws/public/mojom/cursor/cursor.mojom.h" #include "services/ws/public/mojom/window_tree.mojom.h" #include "services/ws/public/mojom/window_tree_constants.mojom.h" #include "ui/aura/aura_export.h" @@ -25,6 +23,7 @@ #include "ui/aura/mus/window_mus.h" #include "ui/aura/window.h" #include "ui/aura/window_port.h" +#include "ui/base/mojo/cursor.mojom.h" #include "ui/gfx/geometry/rect.h" #include "ui/platform_window/mojo/text_input_state.mojom.h" @@ -45,7 +44,7 @@ class RasterContextProvider; namespace aura { -class ClientSurfaceEmbedder; +class MusLsiAllocator; class PropertyConverter; class WindowTreeClient; class WindowTreeClientTestApi; @@ -67,10 +66,6 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus { Window* window() { return window_; } const Window* window() const { return window_; } - ClientSurfaceEmbedder* client_surface_embedder() const { - return client_surface_embedder_.get(); - } - const viz::SurfaceId& PrimarySurfaceIdForTesting() const { return primary_surface_id_; } @@ -78,8 +73,8 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus { void SetTextInputState(ui::mojom::TextInputStatePtr state); void SetImeVisibility(bool visible, ui::mojom::TextInputStatePtr state); - const ui::CursorData& cursor() const { return cursor_; } - void SetCursor(const ui::CursorData& cursor); + const ui::Cursor& cursor() const { return cursor_; } + void SetCursor(const ui::Cursor& cursor); // Sets the EventTargetingPolicy, default is TARGET_AND_DESCENDANTS. void SetEventTargetingPolicy(ws::mojom::EventTargetingPolicy policy); @@ -107,6 +102,9 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus { viz::FrameSinkId GenerateFrameSinkIdFromServerId() const; + gfx::Size GetSizeInPixels(); + gfx::Size GetSizeInPixels(const gfx::Size& size); + private: friend class WindowPortMusTestHelper; friend class WindowTreeClient; @@ -212,6 +210,8 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus { // and needs to consider ancestors' visibility as well. class VisibilityTracker; + void SetAllocator(std::unique_ptr<MusLsiAllocator> allocator); + // Creates and adds a ServerChange to |server_changes_|. Returns the id // assigned to the ServerChange. ServerChangeIdType ScheduleChange(const ServerChangeType type, @@ -220,7 +220,7 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus { // Removes a ServerChange by id. void RemoveChangeById(ServerChangeIdType change_id); - // If there is a schedule change matching |type| and |data| it is removed and + // If there is a scheduled change matching |type| and |data| it is removed and // true is returned. If no matching change is scheduled returns false. bool RemoveChangeByTypeAndData(const ServerChangeType type, const ServerChangeData& data); @@ -247,19 +247,15 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus { void ReorderFromServer(WindowMus* child, WindowMus* relative, ws::mojom::OrderDirection) override; - void SetBoundsFromServer( - const gfx::Rect& bounds, - const base::Optional<viz::LocalSurfaceId>& local_surface_id) override; + void SetBoundsFromServer(const gfx::Rect& bounds) override; void SetTransformFromServer(const gfx::Transform& transform) override; void SetVisibleFromServer(bool visible) override; void SetOpacityFromServer(float opacity) override; - void SetCursorFromServer(const ui::CursorData& cursor) override; + void SetCursorFromServer(const ui::Cursor& cursor) override; void SetPropertyFromServer( const std::string& property_name, const std::vector<uint8_t>* property_data) override; void SetFrameSinkIdFromServer(const viz::FrameSinkId& frame_sink_id) override; - const viz::LocalSurfaceId& GetOrAllocateLocalSurfaceId( - const gfx::Size& surface_size_in_pixels) override; void UpdateLocalSurfaceIdFromEmbeddedClient( const viz::LocalSurfaceIdAllocation& embedded_client_local_surface_id_allocation) override; @@ -268,13 +264,13 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus { void RemoveTransientChildFromServer(WindowMus* child) override; ChangeSource OnTransientChildAdded(WindowMus* child) override; ChangeSource OnTransientChildRemoved(WindowMus* child) override; + bool HasLocalSurfaceId() override; std::unique_ptr<WindowMusChangeData> PrepareForServerBoundsChange( const gfx::Rect& bounds) override; std::unique_ptr<WindowMusChangeData> PrepareForServerVisibilityChange( bool value) override; void PrepareForDestroy() override; void NotifyEmbeddedAppDisconnected() override; - bool HasLocalLayerTreeFrameSink() override; float GetDeviceScaleFactor() override; // WindowPort: @@ -306,8 +302,6 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus { void UnregisterFrameSinkId(const viz::FrameSinkId& frame_sink_id) override; void TrackOcclusionState() override; - void UpdatePrimarySurfaceId(); - // Called by WindowTreeClient to update window occlusion state. void SetOcclusionStateFromServer(ws::mojom::OcclusionState occlusion_state); @@ -323,21 +317,19 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus { Window* window_ = nullptr; - // Used when this window is embedding a client. - std::unique_ptr<ClientSurfaceEmbedder> client_surface_embedder_; - ServerChangeIdType next_server_change_id_ = 0; ServerChanges server_changes_; viz::SurfaceId primary_surface_id_; - // TODO(sad, fsamuel): For 'mash' mode, where the embedder is responsible for - // allocating the LocalSurfaceIds, this should use a - // ChildLocalSurfaceIdAllocator instead. - viz::ParentLocalSurfaceIdAllocator parent_local_surface_id_allocator_; - gfx::Size last_surface_size_in_pixels_; + // Manages allocation of LocalSurfaceIds. Only created if this window needs + // allocated LocalSurfaceIds. + std::unique_ptr<MusLsiAllocator> allocator_; + + // This is set the first time an id is generated. + base::Optional<gfx::Size> last_surface_size_in_pixels_; - ui::CursorData cursor_; + ui::Cursor cursor_; // Set if this class calls SetEmbedFrameSinkId() on the associated window. viz::FrameSinkId embed_frame_sink_id_; diff --git a/chromium/ui/aura/mus/window_port_mus_unittest.cc b/chromium/ui/aura/mus/window_port_mus_unittest.cc index 161ec145b66..649a715d459 100644 --- a/chromium/ui/aura/mus/window_port_mus_unittest.cc +++ b/chromium/ui/aura/mus/window_port_mus_unittest.cc @@ -7,7 +7,9 @@ #include "base/optional.h" #include "base/run_loop.h" #include "cc/mojo_embedder/async_layer_tree_frame_sink.h" +#include "components/viz/common/surfaces/child_local_surface_id_allocator.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/aura/client/drag_drop_delegate.h" #include "ui/aura/mus/client_surface_embedder.h" #include "ui/aura/test/aura_mus_test_base.h" #include "ui/aura/test/aura_test_base.h" @@ -90,16 +92,18 @@ TEST_F(WindowPortMusTest, ClientSurfaceEmbedderUpdatesLayer) { Window window(nullptr); window.Init(ui::LAYER_NOT_DRAWN); window.SetBounds(gfx::Rect(300, 300)); - window.SetEmbedFrameSinkId(viz::FrameSinkId(0, 1)); + WindowPortMusTestHelper(&window).SimulateEmbedding(); // Allocate a new LocalSurfaceId. The ui::Layer should be updated. window.AllocateLocalSurfaceId(); - auto* window_mus = WindowPortMus::Get(&window); viz::LocalSurfaceId local_surface_id = window.GetLocalSurfaceIdAllocation().local_surface_id(); + ClientSurfaceEmbedder* client_surface_embedder = + WindowPortMusTestHelper(&window).GetClientSurfaceEmbedder(); + ASSERT_TRUE(client_surface_embedder); viz::SurfaceId primary_surface_id = - window_mus->client_surface_embedder()->GetSurfaceIdForTesting(); + client_surface_embedder->GetSurfaceIdForTesting(); EXPECT_EQ(local_surface_id, primary_surface_id.local_surface_id()); } @@ -110,7 +114,7 @@ TEST_F(WindowPortMusTest, window.set_owned_by_parent(false); window.SetBounds(gfx::Rect(300, 300)); // Simulate an embedding. - window.SetEmbedFrameSinkId(viz::FrameSinkId(0, 1)); + WindowPortMusTestHelper(&window).SimulateEmbedding(); root_window()->AddChild(&window); // AckAllChanges() so that can verify a bounds change happens from @@ -132,18 +136,20 @@ TEST_F(WindowPortMusTest, parent_allocator->GetCurrentLocalSurfaceIdAllocation()); // Updating the LocalSurfaceId should propagate to the ClientSurfaceEmbedder. - auto* window_mus = WindowPortMus::Get(&window); - ASSERT_TRUE(window_mus); - ASSERT_TRUE(window_mus->client_surface_embedder()); - EXPECT_EQ(updated_id, window_mus->client_surface_embedder() - ->GetSurfaceIdForTesting() - .local_surface_id()); + ClientSurfaceEmbedder* client_surface_embedder = + WindowPortMusTestHelper(&window).GetClientSurfaceEmbedder(); + ASSERT_TRUE(client_surface_embedder); + EXPECT_EQ( + updated_id, + client_surface_embedder->GetSurfaceIdForTesting().local_surface_id()); // The server is notified of a bounds change, so that it sees the new // LocalSurfaceId. ASSERT_EQ(1u, window_tree()->GetChangeCountForType(WindowTreeChangeType::BOUNDS)); ASSERT_TRUE(window_tree()->last_local_surface_id()); + auto* window_mus = WindowPortMus::Get(&window); + ASSERT_TRUE(window_mus); EXPECT_EQ(window_mus->server_id(), window_tree()->window_id()); EXPECT_EQ(updated_id, *(window_tree()->last_local_surface_id())); } @@ -201,4 +207,87 @@ TEST_F(WindowPortMusTest, LocalOcclusionStateFromVisibility) { EXPECT_EQ(Window::OcclusionState::HIDDEN, window.occlusion_state()); } +TEST_F(WindowPortMusTest, PrepareForEmbed) { + Window window(nullptr); + window.Init(ui::LAYER_NOT_DRAWN); + window.set_owned_by_parent(false); + window.SetBounds(gfx::Rect(400, 300)); + + WindowPortMusTestHelper helper(&window); + helper.SimulateEmbedding(); + ClientSurfaceEmbedder* client_surface_embedder = + WindowPortMusTestHelper(&window).GetClientSurfaceEmbedder(); + ASSERT_TRUE(client_surface_embedder); + EXPECT_TRUE(client_surface_embedder->HasPrimarySurfaceId()); +} + +class TestDragDropDelegate : public client::DragDropDelegate { + public: + TestDragDropDelegate() = default; + ~TestDragDropDelegate() override = default; + + // client::DragDropDelegate: + void OnDragEntered(const ui::DropTargetEvent& event) override {} + int OnDragUpdated(const ui::DropTargetEvent& event) override { return 0; } + void OnDragExited() override {} + int OnPerformDrop(const ui::DropTargetEvent& event) override { return 0; } + + private: + DISALLOW_COPY_AND_ASSIGN(TestDragDropDelegate); +}; + +TEST_F(WindowPortMusTest, CanAcceptDrops) { + TestDragDropDelegate test_delegate; + + Window window(nullptr); + window.Init(ui::LAYER_NOT_DRAWN); + window.set_owned_by_parent(false); + window.SetBounds(gfx::Rect(400, 300)); + + EXPECT_EQ(0u, window_tree()->get_and_clear_accepts_drops_count()); + + // Setting the DragDropDelegate should implicitly call + // SetCanAcceptDrops(true). + client::SetDragDropDelegate(&window, &test_delegate); + EXPECT_EQ(1u, window_tree()->get_and_clear_accepts_drops_count()); + EXPECT_TRUE(window_tree()->last_accepts_drops()); + + // And removing the DragDropDelegate should implicitly call + // SetCanAcceptDrops(false). + client::SetDragDropDelegate(&window, nullptr); + EXPECT_EQ(1u, window_tree()->get_and_clear_accepts_drops_count()); + EXPECT_FALSE(window_tree()->last_accepts_drops()); +} + +TEST_F(WindowPortMusTest, RegisterFrameSinkId) { + Window window(nullptr); + window.Init(ui::LAYER_NOT_DRAWN); + window.set_owned_by_parent(false); + window.SetBounds(gfx::Rect(400, 300)); + + root_window()->AddChild(&window); + window_tree()->AckAllChanges(); + window.SetEmbedFrameSinkId(viz::FrameSinkId(0, 1)); + + // Setting a FrameSinkId should trigger generating LocalSurfaceIds. + ASSERT_EQ(1u, + window_tree()->GetChangeCountForType(WindowTreeChangeType::BOUNDS)); + ASSERT_TRUE(window_tree()->last_local_surface_id()); + EXPECT_EQ(window_tree()->last_local_surface_id(), + window.GetLocalSurfaceIdAllocation().local_surface_id()); + auto local_surface_id = + window.GetLocalSurfaceIdAllocation().local_surface_id(); + window_tree()->AckAllChanges(); + + // Changing the bounds should trigger a new LocalSurfaceId. + window.SetBounds(gfx::Rect(400, 310)); + ASSERT_EQ(1u, + window_tree()->GetChangeCountForType(WindowTreeChangeType::BOUNDS)); + ASSERT_TRUE(window_tree()->last_local_surface_id()); + EXPECT_EQ(window_tree()->last_local_surface_id(), + window.GetLocalSurfaceIdAllocation().local_surface_id()); + EXPECT_NE(local_surface_id, + window.GetLocalSurfaceIdAllocation().local_surface_id()); +} + } // namespace aura diff --git a/chromium/ui/aura/mus/window_tree_client.cc b/chromium/ui/aura/mus/window_tree_client.cc index a0dbdb0bb41..47c1a76c3c4 100644 --- a/chromium/ui/aura/mus/window_tree_client.cc +++ b/chromium/ui/aura/mus/window_tree_client.cc @@ -34,6 +34,7 @@ #include "ui/aura/env.h" #include "ui/aura/env_input_state_controller.h" #include "ui/aura/mus/capture_synchronizer.h" +#include "ui/aura/mus/client_side_window_move_handler.h" #include "ui/aura/mus/drag_drop_controller_mus.h" #include "ui/aura/mus/embed_root.h" #include "ui/aura/mus/embed_root_delegate.h" @@ -234,8 +235,8 @@ void WindowTreeClient::SetCanFocus(Window* window, bool can_focus) { } void WindowTreeClient::SetCursor(WindowMus* window, - const ui::CursorData& old_cursor, - const ui::CursorData& new_cursor) { + const ui::Cursor& old_cursor, + const ui::Cursor& new_cursor) { DCHECK(tree_); const uint32_t change_id = ScheduleInFlightChange( @@ -283,11 +284,6 @@ void WindowTreeClient::RegisterFrameSinkId( WindowMus* window, const viz::FrameSinkId& frame_sink_id) { tree_->AttachFrameSinkId(window->server_id(), frame_sink_id); - - // Call OnWindowMusBoundsChanged() to force allocation of a LocalSurfaceId as - // well as notifying the server of the LocalSurfaceId. - const gfx::Rect bounds = window->GetWindow()->bounds(); - OnWindowMusBoundsChanged(window, bounds, bounds); } void WindowTreeClient::UnregisterFrameSinkId(WindowMus* window) { @@ -527,7 +523,7 @@ WindowMus* WindowTreeClient::NewWindowFromWindowData( SetWindowType(window, GetWindowTypeFromProperties(properties)); window->Init(ui::LAYER_NOT_DRAWN); SetLocalPropertiesFromServerProperties(window_mus, window_data); - window_mus->SetBoundsFromServer(window_data.bounds, base::nullopt); + window_mus->SetBoundsFromServer(window_data.bounds); if (parent) parent->AddChildFromServer(window_port_mus_ptr); if (window_data.visible) @@ -557,6 +553,8 @@ void WindowTreeClient::WindowTreeConnectionEstablished( Env::GetInstance()->SetGestureRecognizer( std::make_unique<GestureRecognizerImplMus>(this)); gesture_synchronizer_ = std::make_unique<GestureSynchronizer>(tree_); + client_side_window_move_handler_ = + std::make_unique<ClientSideWindowMoveHandler>(Env::GetInstance()); } void WindowTreeClient::OnConnectionLost() { @@ -640,7 +638,7 @@ void WindowTreeClient::SetWindowBoundsFromServer( return; } - window->SetBoundsFromServer(revert_bounds, local_surface_id); + window->SetBoundsFromServer(revert_bounds); } void WindowTreeClient::SetWindowTransformFromServer( @@ -681,12 +679,10 @@ void WindowTreeClient::ScheduleInFlightBoundsChange( this, window, old_bounds, window->GetLocalSurfaceIdAllocation().local_surface_id())); base::Optional<viz::LocalSurfaceId> local_surface_id; - if (window->GetWindow()->IsEmbeddingClient() || - window->HasLocalLayerTreeFrameSink()) { - // Do not use ConvertRectToPixel, enclosing rects cause problems. - const gfx::Size size = gfx::ScaleToCeiledSize( - new_bounds.size(), window->GetDeviceScaleFactor()); - local_surface_id = window->GetOrAllocateLocalSurfaceId(size); + if (window->HasLocalSurfaceId()) { + local_surface_id = window->GetLocalSurfaceIdAllocation().local_surface_id(); + DCHECK(local_surface_id); + DCHECK(local_surface_id->is_valid()); // |window_tree_host| may be null if this is called during creation of // the window associated with the WindowTreeHostMus, or if there is an // embedding. @@ -1368,7 +1364,7 @@ void WindowTreeClient::OnWindowFocused(ws::Id focused_window_id) { } void WindowTreeClient::OnWindowCursorChanged(ws::Id window_id, - ui::CursorData cursor) { + ui::Cursor cursor) { WindowMus* window = GetWindowByServerId(window_id); if (!window) return; @@ -1387,20 +1383,24 @@ void WindowTreeClient::OnDragDropStart( void WindowTreeClient::OnDragEnter(ws::Id window_id, uint32_t key_state, - const gfx::Point& position, + const gfx::PointF& location_in_root, + const gfx::PointF& location, uint32_t effect_bitmask, OnDragEnterCallback callback) { std::move(callback).Run(drag_drop_controller_->OnDragEnter( - GetWindowByServerId(window_id), key_state, position, effect_bitmask)); + GetWindowByServerId(window_id), key_state, location_in_root, location, + effect_bitmask)); } void WindowTreeClient::OnDragOver(ws::Id window_id, uint32_t key_state, - const gfx::Point& position, + const gfx::PointF& location_in_root, + const gfx::PointF& location, uint32_t effect_bitmask, OnDragOverCallback callback) { std::move(callback).Run(drag_drop_controller_->OnDragOver( - GetWindowByServerId(window_id), key_state, position, effect_bitmask)); + GetWindowByServerId(window_id), key_state, location_in_root, location, + effect_bitmask)); } void WindowTreeClient::OnDragLeave(ws::Id window_id) { @@ -1413,11 +1413,13 @@ void WindowTreeClient::OnDragDropDone() { void WindowTreeClient::OnCompleteDrop(ws::Id window_id, uint32_t key_state, - const gfx::Point& position, + const gfx::PointF& location_in_root, + const gfx::PointF& location, uint32_t effect_bitmask, OnCompleteDropCallback callback) { std::move(callback).Run(drag_drop_controller_->OnCompleteDrop( - GetWindowByServerId(window_id), key_state, position, effect_bitmask)); + GetWindowByServerId(window_id), key_state, location_in_root, location, + effect_bitmask)); } void WindowTreeClient::OnPerformDragDropCompleted(uint32_t change_id, @@ -1468,8 +1470,7 @@ void WindowTreeClient::OnChangeCompleted(uint32_t change_id, bool success) { // is deleted, but still we want to invoke the finished callback. if (change_id == current_move_loop_change_) { current_move_loop_change_ = 0; - on_current_move_finished_.Run(success); - on_current_move_finished_.Reset(); + std::move(on_current_move_finished_).Run(success); for (auto& observer : observers_) observer.OnWindowMoveEnded(success); } @@ -1500,15 +1501,17 @@ void WindowTreeClient::GetScreenProviderObserver( screen_provider_observer_binding_.Bind(std::move(observer)); } -void WindowTreeClient::OnOcclusionStateChanged( - ws::Id window_id, - ws::mojom::OcclusionState occlusion_state) { - WindowMus* window = GetWindowByServerId(window_id); - if (!window) - return; +void WindowTreeClient::OnOcclusionStatesChanged( + const base::flat_map<ws::Id, ws::mojom::OcclusionState>& + occlusion_changes) { + for (const auto& change : occlusion_changes) { + WindowMus* window = GetWindowByServerId(change.first); + if (!window) + continue; - WindowPortMus::Get(window->GetWindow()) - ->SetOcclusionStateFromServer(occlusion_state); + WindowPortMus::Get(window->GetWindow()) + ->SetOcclusionStateFromServer(change.second); + } } void WindowTreeClient::OnDisplaysChanged( @@ -1534,6 +1537,11 @@ void WindowTreeClient::RequestClose(ws::Id window_id) { void WindowTreeClient::OnWindowTreeHostBoundsWillChange( WindowTreeHostMus* window_tree_host, const gfx::Rect& bounds_in_pixels) { + // The only other type of window that may hit this code path is EMBED. Clients + // are not allowed to change the bounds of EMBED windows (only the server). + // LOCAL and OTHER types don't have a WindowTreeHost. + DCHECK_EQ(WindowMusType::TOP_LEVEL, + WindowMus::Get(window_tree_host->window())->window_mus_type()); gfx::Rect old_bounds = window_tree_host->GetBoundsInPixels(); gfx::Rect new_bounds = bounds_in_pixels; const float device_scale_factor = window_tree_host->device_scale_factor(); @@ -1590,9 +1598,9 @@ void WindowTreeClient::OnWindowTreeHostPerformWindowMove( WindowTreeHostMus* window_tree_host, ws::mojom::MoveLoopSource source, const gfx::Point& cursor_location, - const base::Callback<void(bool)>& callback) { + base::OnceCallback<void(bool)> callback) { DCHECK(on_current_move_finished_.is_null()); - on_current_move_finished_ = callback; + on_current_move_finished_ = std::move(callback); WindowMus* window_mus = WindowMus::Get(window_tree_host->window()); current_move_loop_change_ = ScheduleInFlightChange( diff --git a/chromium/ui/aura/mus/window_tree_client.h b/chromium/ui/aura/mus/window_tree_client.h index 186f8e5c173..c25d30f3995 100644 --- a/chromium/ui/aura/mus/window_tree_client.h +++ b/chromium/ui/aura/mus/window_tree_client.h @@ -58,6 +58,7 @@ class Gpu; namespace aura { class CaptureSynchronizer; +class ClientSideWindowMoveHandler; class DragDropControllerMus; class EmbedRoot; class EmbedRootDelegate; @@ -135,8 +136,8 @@ class AURA_EXPORT WindowTreeClient void SetEventTargetingPolicy(WindowMus* window, ws::mojom::EventTargetingPolicy policy); void SetCursor(WindowMus* window, - const ui::CursorData& old_cursor, - const ui::CursorData& new_cursor); + const ui::Cursor& old_cursor, + const ui::Cursor& new_cursor); void SetWindowTextInputState(WindowMus* window, ui::mojom::TextInputStatePtr state); void SetImeVisibility(WindowMus* window, @@ -220,6 +221,7 @@ class AURA_EXPORT WindowTreeClient friend class InFlightPropertyChange; friend class InFlightTransformChange; friend class InFlightVisibleChange; + friend class ParentAllocator; // For OnWindowMusBoundsChanged(). friend class TopmostWindowTracker; friend class WindowPortMus; friend class WindowTreeClientTestApi; @@ -431,23 +433,26 @@ class AURA_EXPORT WindowTreeClient bool matches_event_observer) override; void OnObservedInputEvent(std::unique_ptr<ui::Event> event) override; void OnWindowFocused(ws::Id focused_window_id) override; - void OnWindowCursorChanged(ws::Id window_id, ui::CursorData cursor) override; + void OnWindowCursorChanged(ws::Id window_id, ui::Cursor cursor) override; void OnDragDropStart(const base::flat_map<std::string, std::vector<uint8_t>>& mime_data) override; void OnDragEnter(ws::Id window_id, uint32_t event_flags, - const gfx::Point& position, + const gfx::PointF& location_in_root, + const gfx::PointF& location, uint32_t effect_bitmask, OnDragEnterCallback callback) override; void OnDragOver(ws::Id window_id, uint32_t event_flags, - const gfx::Point& position, + const gfx::PointF& location_in_root, + const gfx::PointF& location, uint32_t effect_bitmask, OnDragOverCallback callback) override; void OnDragLeave(ws::Id window_id) override; void OnCompleteDrop(ws::Id window_id, uint32_t event_flags, - const gfx::Point& position, + const gfx::PointF& location_in_root, + const gfx::PointF& location, uint32_t effect_bitmask, OnCompleteDropCallback callback) override; void OnPerformDragDropCompleted(uint32_t change_id, @@ -459,9 +464,9 @@ class AURA_EXPORT WindowTreeClient void RequestClose(ws::Id window_id) override; void GetScreenProviderObserver( ws::mojom::ScreenProviderObserverAssociatedRequest observer) override; - void OnOcclusionStateChanged( - ws::Id window_id, - ws::mojom::OcclusionState occlusion_state) override; + void OnOcclusionStatesChanged( + const base::flat_map<ws::Id, ws::mojom::OcclusionState>& + occlusion_changes) override; // ws::mojom::ScreenProviderObserver: void OnDisplaysChanged(std::vector<ws::mojom::WsDisplayPtr> ws_displays, @@ -488,7 +493,7 @@ class AURA_EXPORT WindowTreeClient WindowTreeHostMus* window_tree_host, ws::mojom::MoveLoopSource mus_source, const gfx::Point& cursor_location, - const base::Callback<void(bool)>& callback) override; + base::OnceCallback<void(bool)> callback) override; void OnWindowTreeHostCancelWindowMove( WindowTreeHostMus* window_tree_host) override; std::unique_ptr<WindowPortMus> CreateWindowPortForTopLevel( @@ -541,6 +546,8 @@ class AURA_EXPORT WindowTreeClient std::unique_ptr<GestureSynchronizer> gesture_synchronizer_; + std::unique_ptr<ClientSideWindowMoveHandler> client_side_window_move_handler_; + mojo::Binding<ws::mojom::WindowTreeClient> binding_; ws::mojom::WindowTreePtr tree_ptr_; // Typically this is the value contained in |tree_ptr_|, but tests may @@ -568,7 +575,7 @@ class AURA_EXPORT WindowTreeClient // Callback executed when a move loop initiated by PerformWindowMove() is // completed. - base::Callback<void(bool)> on_current_move_finished_; + base::OnceCallback<void(bool)> on_current_move_finished_; std::unique_ptr<DragDropControllerMus> drag_drop_controller_; diff --git a/chromium/ui/aura/mus/window_tree_client_unittest.cc b/chromium/ui/aura/mus/window_tree_client_unittest.cc index 03c3b55880c..e120e0677f0 100644 --- a/chromium/ui/aura/mus/window_tree_client_unittest.cc +++ b/chromium/ui/aura/mus/window_tree_client_unittest.cc @@ -8,8 +8,8 @@ #include "base/command_line.h" #include "base/logging.h" -#include "base/macros.h" #include "base/memory/ptr_util.h" +#include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "cc/base/switches.h" @@ -255,6 +255,9 @@ TEST_F(WindowTreeClientTest, SetBoundsFailedLocalSurfaceId) { Window window(nullptr); window.Init(ui::LAYER_NOT_DRAWN); WindowPortMusTestHelper(&window).SimulateEmbedding(); + // SimulateEmbedding() generates a bounds change. + ASSERT_TRUE( + window_tree()->AckSingleChangeOfType(WindowTreeChangeType::BOUNDS, true)); const gfx::Rect original_bounds(window.bounds()); const viz::LocalSurfaceId original_local_surface_id( @@ -265,14 +268,19 @@ TEST_F(WindowTreeClientTest, SetBoundsFailedLocalSurfaceId) { EXPECT_EQ(new_bounds, window.bounds()); WindowMus* window_mus = WindowMus::Get(&window); ASSERT_NE(nullptr, window_mus); - EXPECT_TRUE(window_mus->GetLocalSurfaceIdAllocation().IsValid()); + ASSERT_TRUE(window_mus->GetLocalSurfaceIdAllocation().IsValid()); + const viz::LocalSurfaceId new_surface_id = + window_mus->GetLocalSurfaceIdAllocation().local_surface_id(); // Reverting the change should also revert the viz::LocalSurfaceId. ASSERT_TRUE(window_tree()->AckSingleChangeOfType(WindowTreeChangeType::BOUNDS, false)); EXPECT_EQ(original_bounds, window.bounds()); - EXPECT_EQ(original_local_surface_id, + // Whenever the bounds changes a new LocalSurfaceId needs to be allocated. + EXPECT_NE(new_surface_id, window.GetLocalSurfaceIdAllocation().local_surface_id()); + EXPECT_EQ(1u, + window_tree()->GetChangeCountForType(WindowTreeChangeType::BOUNDS)); } INSTANTIATE_TEST_CASE_P(/* no prefix */, @@ -283,14 +291,15 @@ INSTANTIATE_TEST_CASE_P(/* no prefix */, TEST_P(WindowTreeClientTestSurfaceSync, ClientSurfaceEmbedderCreated) { Window window(nullptr); window.Init(ui::LAYER_NOT_DRAWN); - WindowPortMusTestHelper(&window).SimulateEmbedding(); - WindowPortMus* window_port_mus = WindowPortMus::Get(&window); - ASSERT_NE(nullptr, window_port_mus); + WindowPortMusTestHelper window_test_helper(&window); + + // A ClientSurfaceEmbedder is only created once there is an embedding. + ClientSurfaceEmbedder* client_surface_embedder = + window_test_helper.GetClientSurfaceEmbedder(); + EXPECT_EQ(nullptr, client_surface_embedder); + window_test_helper.SimulateEmbedding(); - // A ClientSurfaceEmbedder is only created once there is bounds and a - // FrameSinkId. - EXPECT_EQ(nullptr, window_port_mus->client_surface_embedder()); gfx::Rect new_bounds(gfx::Rect(0, 0, 100, 100)); ASSERT_NE(new_bounds, window.bounds()); window.SetBounds(new_bounds); @@ -298,8 +307,7 @@ TEST_P(WindowTreeClientTestSurfaceSync, ClientSurfaceEmbedderCreated) { EXPECT_TRUE(WindowMus::Get(&window)->GetLocalSurfaceIdAllocation().IsValid()); // Once the bounds have been set, the ClientSurfaceEmbedder should be created. - ClientSurfaceEmbedder* client_surface_embedder = - window_port_mus->client_surface_embedder(); + client_surface_embedder = window_test_helper.GetClientSurfaceEmbedder(); ASSERT_NE(nullptr, client_surface_embedder); EXPECT_EQ(nullptr, client_surface_embedder->BottomGutterForTesting()); @@ -462,8 +470,7 @@ TEST_F(WindowTreeClientTest, FocusFromServer) { // Simulates a bounds change, and while the bounds change is in flight the // server replies with a new bounds and the original bounds change fails. -// The server bounds change takes hold along with the associated -// viz::LocalSurfaceId. +// The server bounds change takes hold. TEST_F(WindowTreeClientTest, SetBoundsFailedWithPendingChange) { aura::Window root_window(nullptr); root_window.Init(ui::LAYER_NOT_DRAWN); @@ -492,15 +499,12 @@ TEST_F(WindowTreeClientTest, SetBoundsFailedWithPendingChange) { ASSERT_TRUE(window_tree()->AckSingleChangeOfType(WindowTreeChangeType::BOUNDS, false)); EXPECT_EQ(server_changed_bounds, root_window.bounds()); - EXPECT_EQ(server_changed_local_surface_id, - root_window_mus->GetLocalSurfaceIdAllocation().local_surface_id()); // Simulate server changing back to original bounds. Should take immediately. window_tree_client()->OnWindowBoundsChanged(server_id(&root_window), server_changed_bounds, original_bounds, base::nullopt); EXPECT_EQ(original_bounds, root_window.bounds()); - EXPECT_FALSE(root_window_mus->GetLocalSurfaceIdAllocation().IsValid()); } TEST_F(WindowTreeClientTest, TwoInFlightBoundsChangesBothCanceled) { @@ -2307,7 +2311,7 @@ TEST_F(WindowTreeClientTest, ModalTypeSuccess) { // MODAL_TYPE_NONE, and make sure it succeeds each time. ui::ModalType kModalTypes[] = {ui::MODAL_TYPE_WINDOW, ui::MODAL_TYPE_SYSTEM, ui::MODAL_TYPE_NONE}; - for (size_t i = 0; i < arraysize(kModalTypes); i++) { + for (size_t i = 0; i < base::size(kModalTypes); i++) { window.SetProperty(client::kModalKey, kModalTypes[i]); // Ack change as succeeding. ASSERT_TRUE(window_tree()->AckSingleChangeOfType( @@ -2585,8 +2589,8 @@ TEST_F(WindowTreeClientTest, PerformWindowMove) { WindowTreeHostMus* host_mus = static_cast<WindowTreeHostMus*>(host()); host_mus->PerformWindowMove( - ws::mojom::MoveLoopSource::MOUSE, gfx::Point(), - base::Bind(&OnWindowMoveDone, &call_count, &last_result)); + host_mus->window(), ws::mojom::MoveLoopSource::MOUSE, gfx::Point(), + base::BindOnce(&OnWindowMoveDone, &call_count, &last_result)); EXPECT_EQ(0, call_count); window_tree()->AckAllChanges(); @@ -2594,8 +2598,8 @@ TEST_F(WindowTreeClientTest, PerformWindowMove) { EXPECT_TRUE(last_result); host_mus->PerformWindowMove( - ws::mojom::MoveLoopSource::MOUSE, gfx::Point(), - base::Bind(&OnWindowMoveDone, &call_count, &last_result)); + host_mus->window(), ws::mojom::MoveLoopSource::MOUSE, gfx::Point(), + base::BindOnce(&OnWindowMoveDone, &call_count, &last_result)); window_tree()->AckAllChangesOfType(WindowTreeChangeType::OTHER, false); EXPECT_EQ(2, call_count); EXPECT_FALSE(last_result); @@ -2611,8 +2615,8 @@ TEST_F(WindowTreeClientTest, PerformWindowMoveDoneAfterDelete) { window_tree()->AckAllChanges(); host_mus->PerformWindowMove( - ws::mojom::MoveLoopSource::MOUSE, gfx::Point(), - base::Bind(&OnWindowMoveDone, &call_count, &last_result)); + host_mus->window(), ws::mojom::MoveLoopSource::MOUSE, gfx::Point(), + base::BindOnce(&OnWindowMoveDone, &call_count, &last_result)); EXPECT_EQ(0, call_count); host_mus.reset(); @@ -2622,6 +2626,32 @@ TEST_F(WindowTreeClientTest, PerformWindowMoveDoneAfterDelete) { EXPECT_TRUE(last_result); } +TEST_F(WindowTreeClientTest, PerformWindowMoveTransferEvents) { + int call_count = 0; + bool last_result = false; + + aura::Window* window = CreateNormalWindow(10, host()->window(), nullptr); + WindowTreeHostMus* host_mus = static_cast<WindowTreeHostMus*>(host()); + window->SetCapture(); + host_mus->PerformWindowMove( + window, ws::mojom::MoveLoopSource::TOUCH, gfx::Point(), + base::BindOnce(&OnWindowMoveDone, &call_count, &last_result)); + EXPECT_EQ(0, call_count); + EXPECT_EQ(WindowPortMus::Get(window)->server_id(), + window_tree()->last_transfer_current()); + EXPECT_EQ(WindowPortMus::Get(host_mus->window())->server_id(), + window_tree()->last_transfer_new()); + EXPECT_FALSE(window->HasCapture()); + + window_tree()->AckAllChanges(); + EXPECT_EQ(1, call_count); + EXPECT_TRUE(last_result); + EXPECT_EQ(WindowPortMus::Get(host_mus->window())->server_id(), + window_tree()->last_transfer_current()); + EXPECT_EQ(WindowPortMus::Get(window)->server_id(), + window_tree()->last_transfer_new()); +} + // Verifies occlusion state from server is applied to underlying window. TEST_F(WindowTreeClientTest, OcclusionStateFromServer) { struct { @@ -2666,8 +2696,8 @@ TEST_F(WindowTreeClientTest, OcclusionStateFromServer) { window.Hide(); } - window_tree_client()->OnOcclusionStateChanged( - server_id(&window), test.changed_state_from_server); + window_tree_client()->OnOcclusionStatesChanged( + {{server_id(&window), test.changed_state_from_server}}); EXPECT_EQ(test.expected_state, window.occlusion_state()) << test.name; } } diff --git a/chromium/ui/aura/mus/window_tree_host_mus.cc b/chromium/ui/aura/mus/window_tree_host_mus.cc index b6c7b101fa6..527e13ec0a6 100644 --- a/chromium/ui/aura/mus/window_tree_host_mus.cc +++ b/chromium/ui/aura/mus/window_tree_host_mus.cc @@ -4,6 +4,8 @@ #include "ui/aura/mus/window_tree_host_mus.h" +#include <limits> + #include "ui/aura/env.h" #include "ui/aura/mus/input_method_mus.h" #include "ui/aura/mus/window_port_mus.h" @@ -12,13 +14,17 @@ #include "ui/aura/mus/window_tree_host_mus_init_params.h" #include "ui/aura/window.h" #include "ui/aura/window_event_dispatcher.h" +#include "ui/aura/window_tracker.h" #include "ui/aura/window_tree_host_observer.h" #include "ui/base/class_property.h" +#include "ui/base/hit_test.h" #include "ui/base/ui_base_features.h" #include "ui/base/ui_base_switches_util.h" #include "ui/display/display.h" #include "ui/display/screen.h" #include "ui/events/event.h" +#include "ui/events/gestures/gesture_recognizer.h" +#include "ui/events/gestures/gesture_recognizer_observer.h" #include "ui/platform_window/stub/stub_window.h" DEFINE_UI_CLASS_PROPERTY_TYPE(aura::WindowTreeHostMus*); @@ -30,7 +36,66 @@ namespace { DEFINE_UI_CLASS_PROPERTY_KEY( WindowTreeHostMus*, kWindowTreeHostMusKey, nullptr); -static uint32_t accelerated_widget_count = 1; +// Start at the max and decrease as in SingleProcessMash these values must not +// overlap with values assigned by Ozone's PlatformWindow (which starts at 1 +// and increases). +uint32_t next_accelerated_widget_id = std::numeric_limits<uint32_t>::max(); + +// ScopedTouchTransferController controls the transfer of touch events for +// window move loop. It transfers touches before the window move starts, and +// then transfers them back to the original window when the window move ends. +// However this transferring back to the original shouldn't happen if the client +// wants to continue the dragging on another window (like attaching the dragged +// tab to another window). +class ScopedTouchTransferController : public ui::GestureRecognizerObserver { + public: + ScopedTouchTransferController(Window* source, Window* dest) + : tracker_({source, dest}), + gesture_recognizer_(source->env()->gesture_recognizer()) { + gesture_recognizer_->TransferEventsTo( + source, dest, ui::TransferTouchesBehavior::kDontCancel); + gesture_recognizer_->AddObserver(this); + } + ~ScopedTouchTransferController() override { + gesture_recognizer_->RemoveObserver(this); + if (tracker_.windows().size() == 2) { + Window* source = tracker_.Pop(); + Window* dest = tracker_.Pop(); + gesture_recognizer_->TransferEventsTo( + dest, source, ui::TransferTouchesBehavior::kDontCancel); + } + } + + private: + // ui::GestureRecognizerObserver: + void OnActiveTouchesCanceledExcept( + ui::GestureConsumer* not_cancelled) override {} + void OnEventsTransferred( + ui::GestureConsumer* current_consumer, + ui::GestureConsumer* new_consumer, + ui::TransferTouchesBehavior transfer_touches_behavior) override { + if (tracker_.windows().size() <= 1) + return; + Window* dest = tracker_.windows()[1]; + if (current_consumer == dest) + tracker_.Remove(dest); + } + void OnActiveTouchesCanceled(ui::GestureConsumer* consumer) override {} + + WindowTracker tracker_; + + ui::GestureRecognizer* gesture_recognizer_; + + DISALLOW_COPY_AND_ASSIGN(ScopedTouchTransferController); +}; + +void OnPerformWindowMoveDone( + std::unique_ptr<ScopedTouchTransferController> controller, + base::OnceCallback<void(bool)> callback, + bool success) { + controller.reset(); + std::move(callback).Run(success); +} } // namespace @@ -57,20 +122,20 @@ WindowTreeHostMus::WindowTreeHostMus(WindowTreeHostMusInitParams init_params) // In other cases, let a valid FrameSinkId be selected by // context_factory_private(). const bool force_software_compositor = false; - const bool external_begin_frames_enabled = false; + ui::ExternalBeginFrameClient* external_begin_frame_client = nullptr; const bool are_events_in_pixels = false; CreateCompositor(window_mus->GenerateFrameSinkIdFromServerId(), - force_software_compositor, external_begin_frames_enabled, + force_software_compositor, external_begin_frame_client, are_events_in_pixels); gfx::AcceleratedWidget accelerated_widget; // We need accelerated widget numbers to be different for each window and // fit in the smallest sizeof(AcceleratedWidget) uint32_t has this property. #if defined(OS_WIN) || defined(OS_ANDROID) accelerated_widget = - reinterpret_cast<gfx::AcceleratedWidget>(accelerated_widget_count++); + reinterpret_cast<gfx::AcceleratedWidget>(next_accelerated_widget_id--); #else accelerated_widget = - static_cast<gfx::AcceleratedWidget>(accelerated_widget_count++); + static_cast<gfx::AcceleratedWidget>(next_accelerated_widget_id--); #endif OnAcceleratedWidgetAvailable(accelerated_widget); @@ -150,11 +215,21 @@ void WindowTreeHostMus::StackAtTop() { } void WindowTreeHostMus::PerformWindowMove( + Window* content_window, ws::mojom::MoveLoopSource mus_source, const gfx::Point& cursor_location, - const base::Callback<void(bool)>& callback) { + base::OnceCallback<void(bool)> callback) { + DCHECK(window()->Contains(content_window)); + std::unique_ptr<ScopedTouchTransferController> scoped_controller; + if (content_window != window()) { + scoped_controller = std::make_unique<ScopedTouchTransferController>( + content_window, window()); + } + content_window->ReleaseCapture(); delegate_->OnWindowTreeHostPerformWindowMove( - this, mus_source, cursor_location, callback); + this, mus_source, cursor_location, + base::BindOnce(&OnPerformWindowMoveDone, std::move(scoped_controller), + std::move(callback))); } void WindowTreeHostMus::CancelWindowMove() { diff --git a/chromium/ui/aura/mus/window_tree_host_mus.h b/chromium/ui/aura/mus/window_tree_host_mus.h index c8c9b9f9507..8a6d69592f9 100644 --- a/chromium/ui/aura/mus/window_tree_host_mus.h +++ b/chromium/ui/aura/mus/window_tree_host_mus.h @@ -70,9 +70,10 @@ class AURA_EXPORT WindowTreeHostMus : public WindowTreeHostPlatform, // Tells the window manager to take control of moving the window. Returns // true if the move wasn't canceled. - void PerformWindowMove(ws::mojom::MoveLoopSource mus_source, + void PerformWindowMove(Window* window, + ws::mojom::MoveLoopSource mus_source, const gfx::Point& cursor_location, - const base::Callback<void(bool)>& callback); + base::OnceCallback<void(bool)> callback); // Tells the window manager to abort any current move initiated by // PerformWindowMove(). diff --git a/chromium/ui/aura/mus/window_tree_host_mus_delegate.h b/chromium/ui/aura/mus/window_tree_host_mus_delegate.h index 0c17643cca5..399f55ef35e 100644 --- a/chromium/ui/aura/mus/window_tree_host_mus_delegate.h +++ b/chromium/ui/aura/mus/window_tree_host_mus_delegate.h @@ -60,7 +60,7 @@ class AURA_EXPORT WindowTreeHostMusDelegate { WindowTreeHostMus* window_tree_host, ws::mojom::MoveLoopSource mus_source, const gfx::Point& cursor_location, - const base::Callback<void(bool)>& callback) = 0; + base::OnceCallback<void(bool)> callback) = 0; // Called to cancel a move loop. virtual void OnWindowTreeHostCancelWindowMove( diff --git a/chromium/ui/aura/native_window_occlusion_tracker_win.cc b/chromium/ui/aura/native_window_occlusion_tracker_win.cc index b0372b96bb5..a6442f0a1c7 100644 --- a/chromium/ui/aura/native_window_occlusion_tracker_win.cc +++ b/chromium/ui/aura/native_window_occlusion_tracker_win.cc @@ -168,17 +168,20 @@ bool NativeWindowOcclusionTrackerWin::IsWindowVisibleAndFullyOpaque( void NativeWindowOcclusionTrackerWin::UpdateOcclusionState( const base::flat_map<HWND, Window::OcclusionState>& root_window_hwnds_occlusion_state) { + num_visible_root_windows_ = 0; for (const auto& root_window_pair : root_window_hwnds_occlusion_state) { auto it = hwnd_root_window_map_.find(root_window_pair.first); // The window was destroyed while processing occlusion. if (it == hwnd_root_window_map_.end()) continue; - Window* root_window = it->second; // Check Window::IsVisible here, on the UI thread, because it can't be // checked on the occlusion calculation thread. + bool root_window_hidden = !it->second->IsVisible(); it->second->GetHost()->SetNativeWindowOcclusionState( - !root_window->IsVisible() ? Window::OcclusionState::HIDDEN - : root_window_pair.second); + root_window_hidden ? Window::OcclusionState::HIDDEN + : root_window_pair.second); + if (!root_window_hidden) + num_visible_root_windows_++; } } @@ -223,9 +226,12 @@ void NativeWindowOcclusionTrackerWin::WindowOcclusionCalculator:: HandleVisibilityChanged(bool visible) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // May have gone from having no visible windows to having one, in - // which case we need to register event hooks. - if (visible) + // which case we need to register event hooks, and make sure that an + // occlusion calculation is scheduled. + if (visible) { MaybeRegisterEventHooks(); + ScheduleOcclusionCalculationIfNeeded(); + } } void NativeWindowOcclusionTrackerWin::WindowOcclusionCalculator:: diff --git a/chromium/ui/aura/native_window_occlusion_tracker_win.h b/chromium/ui/aura/native_window_occlusion_tracker_win.h index 477e77ab0d0..238e4bf9338 100644 --- a/chromium/ui/aura/native_window_occlusion_tracker_win.h +++ b/chromium/ui/aura/native_window_occlusion_tracker_win.h @@ -207,6 +207,9 @@ class AURA_EXPORT NativeWindowOcclusionTrackerWin : public WindowObserver { // |root_window_hwnds_occlusion_state_|. base::flat_map<HWND, Window*> hwnd_root_window_map_; + // This is set by UpdateOcclusionState. It is currently only used by tests. + int num_visible_root_windows_ = 0; + std::unique_ptr<WindowOcclusionCalculator> occlusion_calculator_; DISALLOW_COPY_AND_ASSIGN(NativeWindowOcclusionTrackerWin); diff --git a/chromium/ui/aura/native_window_occlusion_tracker_win_interactive_test.cc b/chromium/ui/aura/native_window_occlusion_tracker_win_interactive_test.cc index 674a2a90d76..e66f1369dc7 100644 --- a/chromium/ui/aura/native_window_occlusion_tracker_win_interactive_test.cc +++ b/chromium/ui/aura/native_window_occlusion_tracker_win_interactive_test.cc @@ -48,16 +48,20 @@ class MockWindowTreeHostObserver : public WindowTreeHostObserver { // WindowTreeHostObserver: void OnOcclusionStateChanged(WindowTreeHost* host, Window::OcclusionState new_state) override { - EXPECT_NE(new_state, Window::OcclusionState::UNKNOWN); // Should only get notified when the occlusion state changes. EXPECT_NE(new_state, cur_state_); cur_state_ = new_state; - if (cur_state_ == expectation_) { + if (expectation_ != Window::OcclusionState::UNKNOWN && + cur_state_ == expectation_) { EXPECT_FALSE(quit_closure_.is_null()); std::move(quit_closure_).Run(); } } + void set_quit_closure(base::OnceClosure quit_closure) { + quit_closure_ = std::move(quit_closure); + } + void set_expectation(Window::OcclusionState expectation) { expectation_ = expectation; } @@ -163,6 +167,11 @@ class NativeWindowOcclusionTrackerTest : public test::AuraTestBase { window->env()->GetWindowOcclusionTracker()->Track(window); } + int GetNumVisibleRootWindows() { + return NativeWindowOcclusionTrackerWin::GetOrCreateInstance() + ->num_visible_root_windows_; + } + private: base::test::ScopedFeatureList scoped_feature_list_; std::unique_ptr<TestNativeWindow> native_win_; @@ -200,12 +209,60 @@ TEST_F(NativeWindowOcclusionTrackerTest, SimpleHidden) { MockWindowTreeHostObserver observer(run_loop.QuitClosure()); CreateTrackedAuraWindowWithBounds(&observer, gfx::Rect(0, 0, 100, 100)); CreateNativeWindowWithBounds(gfx::Rect(200, 0, 100, 100)); - // Minimize the tracked aura window and check that its occlusion state + // Iconify the tracked aura window and check that its occlusion state // is HIDDEN. - ::ShowWindow(host()->GetAcceleratedWidget(), SW_MINIMIZE); + CloseWindow(host()->GetAcceleratedWidget()); observer.set_expectation(Window::OcclusionState::HIDDEN); run_loop.Run(); EXPECT_FALSE(observer.is_expecting_call()); } +// Test that minimizing and restoring an app window results in the occlusion +// tracker re-registering for win events and detecting that a native window +// occludes the app window. +TEST_F(NativeWindowOcclusionTrackerTest, OcclusionAfterVisibilityToggle) { + base::RunLoop run_loop; + MockWindowTreeHostObserver observer(run_loop.QuitClosure()); + CreateTrackedAuraWindowWithBounds(&observer, gfx::Rect(0, 0, 100, 100)); + observer.set_expectation(Window::OcclusionState::VISIBLE); + run_loop.Run(); + + base::RunLoop run_loop2; + observer.set_expectation(Window::OcclusionState::HIDDEN); + observer.set_quit_closure(run_loop2.QuitClosure()); + // host()->window()->Hide() is needed to generate OnWindowVisibilityChanged + // notifications. + host()->window()->Hide(); + // This makes the window iconic. + ::CloseWindow(host()->GetAcceleratedWidget()); + run_loop2.Run(); + // HIDDEN state is set synchronously by OnWindowVsiblityChanged notification, + // before occlusion is calculated, so the above expectation will be met w/o an + // occlusion calculation. + // Loop until an occlusion calculation has run with no non-hidden app windows. + + do { + // Need to pump events in order for UpdateOcclusionState to get called, and + // update the number of non hidden root windows. When that number is 0, + // occlusion has been calculated with no visible root windows. + base::RunLoop().RunUntilIdle(); + } while (GetNumVisibleRootWindows() != 0); + + base::RunLoop run_loop3; + observer.set_expectation(Window::OcclusionState::VISIBLE); + observer.set_quit_closure(run_loop3.QuitClosure()); + host()->window()->Show(); + // This opens the window made iconic above. + OpenIcon(host()->GetAcceleratedWidget()); + run_loop3.Run(); + + // Open a native window that occludes the visible app window. + base::RunLoop run_loop4; + observer.set_expectation(Window::OcclusionState::OCCLUDED); + observer.set_quit_closure(run_loop4.QuitClosure()); + CreateNativeWindowWithBounds(gfx::Rect(0, 0, 100, 100)); + run_loop4.Run(); + EXPECT_FALSE(observer.is_expecting_call()); +} + } // namespace aura diff --git a/chromium/ui/aura/test/ui_controls_factory_ozone.cc b/chromium/ui/aura/test/ui_controls_factory_ozone.cc index 2c6070f7207..f2bd4f979df 100644 --- a/chromium/ui/aura/test/ui_controls_factory_ozone.cc +++ b/chromium/ui/aura/test/ui_controls_factory_ozone.cc @@ -16,10 +16,12 @@ #include "ui/aura/mus/window_tree_client.h" #include "ui/aura/test/aura_test_utils.h" #include "ui/aura/test/env_test_helper.h" +#include "ui/aura/test/mus/window_tree_client_test_api.h" #include "ui/aura/test/ui_controls_factory_aura.h" #include "ui/aura/window_tree_host.h" #include "ui/base/test/ui_controls_aura.h" #include "ui/display/display.h" +#include "ui/display/display_observer.h" #include "ui/display/screen.h" #include "ui/events/event_utils.h" #include "ui/events/test/events_test_utils.h" @@ -28,18 +30,16 @@ namespace aura { namespace test { namespace { -// Callback from Window Service with the result of posting an event. |result| -// is true if event successfully processed and |closure| is an optional closure -// to run when done (used in client code to wait for ack). -void OnWindowServiceProcessedEvent(base::OnceClosure closure, bool result) { - DCHECK(result); - if (closure) - std::move(closure).Run(); -} - -class UIControlsOzone : public ui_controls::UIControlsAura { +class UIControlsOzone : public ui_controls::UIControlsAura, + display::DisplayObserver { public: - UIControlsOzone(WindowTreeHost* host) : host_(host) {} + UIControlsOzone(WindowTreeHost* host) : host_(host) { + MaybeInitializeEventInjector(); + display::Screen::GetScreen()->AddObserver(this); + } + ~UIControlsOzone() override { + display::Screen::GetScreen()->RemoveObserver(this); + } private: // ui_controls::UIControlsAura: @@ -60,40 +60,43 @@ class UIControlsOzone : public ui_controls::UIControlsAura { bool command, base::OnceClosure closure) override { int flags = button_down_mask_; + int64_t display_id = + display::Screen::GetScreen()->GetDisplayNearestWindow(window).id(); if (control) { flags |= ui::EF_CONTROL_DOWN; - PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, flags, + PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, flags, display_id, base::OnceClosure()); } if (shift) { flags |= ui::EF_SHIFT_DOWN; - PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SHIFT, flags, + PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SHIFT, flags, display_id, base::OnceClosure()); } if (alt) { flags |= ui::EF_ALT_DOWN; - PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_MENU, flags, + PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_MENU, flags, display_id, base::OnceClosure()); } if (command) { flags |= ui::EF_COMMAND_DOWN; - PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_LWIN, flags, + PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_LWIN, flags, display_id, base::OnceClosure()); } - PostKeyEvent(ui::ET_KEY_PRESSED, key, flags, base::OnceClosure()); + PostKeyEvent(ui::ET_KEY_PRESSED, key, flags, display_id, + base::OnceClosure()); const bool has_modifier = control || shift || alt || command; // Pass the real closure to the last generated KeyEvent. - PostKeyEvent(ui::ET_KEY_RELEASED, key, flags, + PostKeyEvent(ui::ET_KEY_RELEASED, key, flags, display_id, has_modifier ? base::OnceClosure() : std::move(closure)); if (alt) { flags &= ~ui::EF_ALT_DOWN; - PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_MENU, flags, + PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_MENU, flags, display_id, (shift || control || command) ? base::OnceClosure() : std::move(closure)); } @@ -101,19 +104,19 @@ class UIControlsOzone : public ui_controls::UIControlsAura { if (shift) { flags &= ~ui::EF_SHIFT_DOWN; PostKeyEvent( - ui::ET_KEY_RELEASED, ui::VKEY_SHIFT, flags, + ui::ET_KEY_RELEASED, ui::VKEY_SHIFT, flags, display_id, (control || command) ? base::OnceClosure() : std::move(closure)); } if (control) { flags &= ~ui::EF_CONTROL_DOWN; - PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL, flags, + PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL, flags, display_id, command ? base::OnceClosure() : std::move(closure)); } if (command) { flags &= ~ui::EF_COMMAND_DOWN; - PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_LWIN, flags, + PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_LWIN, flags, display_id, std::move(closure)); } @@ -127,9 +130,11 @@ class UIControlsOzone : public ui_controls::UIControlsAura { long screen_y, base::OnceClosure closure) override { gfx::Point host_location(screen_x, screen_y); - if (!ScreenDIPToHostPixels(&host_location)) + int64_t display_id = display::kInvalidDisplayId; + if (!ScreenDIPToHostPixels(&host_location, &display_id)) return false; last_mouse_location_ = host_location; + last_mouse_display_id_ = display_id; ui::EventType event_type; @@ -138,7 +143,7 @@ class UIControlsOzone : public ui_controls::UIControlsAura { else event_type = ui::ET_MOUSE_MOVED; - PostMouseEvent(event_type, host_location, button_down_mask_, 0, + PostMouseEvent(event_type, host_location, button_down_mask_, 0, display_id, std::move(closure)); return true; @@ -154,11 +159,13 @@ class UIControlsOzone : public ui_controls::UIControlsAura { base::OnceClosure closure, int accelerator_state) override { gfx::Point host_location; + int64_t display_id = display::kInvalidDisplayId; if (last_mouse_location_.has_value()) { host_location = last_mouse_location_.value(); + display_id = last_mouse_display_id_; } else { host_location = host_->window()->env()->last_mouse_location(); - if (!ScreenDIPToHostPixels(&host_location)) + if (!ScreenDIPToHostPixels(&host_location, &display_id)) return false; } @@ -194,14 +201,14 @@ class UIControlsOzone : public ui_controls::UIControlsAura { button_down_mask_ |= flag; // Pass the real closure to the last generated MouseEvent. PostMouseEvent(ui::ET_MOUSE_PRESSED, host_location, - button_down_mask_ | flag, changed_button_flag, + button_down_mask_ | flag, changed_button_flag, display_id, (button_state & ui_controls::UP) ? base::OnceClosure() : std::move(closure)); } if (button_state & ui_controls::UP) { button_down_mask_ &= ~flag; PostMouseEvent(ui::ET_MOUSE_RELEASED, host_location, - button_down_mask_ | flag, changed_button_flag, + button_down_mask_ | flag, changed_button_flag, display_id, std::move(closure)); } @@ -222,37 +229,42 @@ class UIControlsOzone : public ui_controls::UIControlsAura { base::OnceClosure task) override { DCHECK_NE(0, action); gfx::Point host_location(x, y); - if (!ScreenDIPToHostPixels(&host_location)) + int64_t display_id = display::kInvalidDisplayId; + if (!ScreenDIPToHostPixels(&host_location, &display_id)) return false; bool has_move = action & ui_controls::MOVE; bool has_release = action & ui_controls::RELEASE; - ui::PointerDetails details(ui::EventPointerType::POINTER_TYPE_TOUCH, id, - 1.0f, 1.0f, 0.0f); if (action & ui_controls::PRESS) { - ui::TouchEvent event(ui::ET_TOUCH_PRESSED, host_location, - base::TimeTicks::Now(), details); - SendEventToSink(&event, (has_move || has_release) ? base::OnceClosure() - : std::move(task)); + PostTouchEvent( + ui::ET_TOUCH_PRESSED, host_location, id, display_id, + (has_move || has_release) ? base::OnceClosure() : std::move(task)); } if (has_move) { - ui::TouchEvent event(ui::ET_TOUCH_MOVED, host_location, - base::TimeTicks::Now(), details); - SendEventToSink(&event, - has_release ? base::OnceClosure() : std::move(task)); + PostTouchEvent(ui::ET_TOUCH_MOVED, host_location, id, display_id, + has_release ? base::OnceClosure() : std::move(task)); } if (has_release) { - ui::TouchEvent event(ui::ET_TOUCH_RELEASED, host_location, - base::TimeTicks::Now(), details); - SendEventToSink(&event, std::move(task)); + PostTouchEvent(ui::ET_TOUCH_RELEASED, host_location, id, display_id, + std::move(task)); } return true; } #endif - void SendEventToSink(ui::Event* event, base::OnceClosure closure) { - if (host_->window()->env()->mode() == aura::Env::Mode::MUS) { - GetEventInjector()->InjectEvent( - host_->GetDisplayId(), ui::Event::Clone(*event), + // display::DisplayObserver: + void OnDisplayRemoved(const display::Display& old_display) override { + if (last_mouse_display_id_ == old_display.id()) { + last_mouse_display_id_ = display::kInvalidDisplayId; + last_mouse_location_.reset(); + } + } + + void SendEventToSink(ui::Event* event, + int64_t display_id, + base::OnceClosure closure) { + if (event_injector_) { + event_injector_->InjectEvent( + display_id, ui::Event::Clone(*event), base::BindOnce(&OnWindowServiceProcessedEvent, std::move(closure))); return; } @@ -271,40 +283,44 @@ class UIControlsOzone : public ui_controls::UIControlsAura { void PostKeyEvent(ui::EventType type, ui::KeyboardCode key_code, int flags, + int64_t display_id, base::OnceClosure closure) { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&UIControlsOzone::PostKeyEventTask, base::Unretained(this), type, key_code, flags, - std::move(closure))); + display_id, std::move(closure))); } void PostKeyEventTask(ui::EventType type, ui::KeyboardCode key_code, int flags, + int64_t display_id, base::OnceClosure closure) { // Do not rewrite injected events. See crbug.com/136465. flags |= ui::EF_FINAL; ui::KeyEvent key_event(type, key_code, flags); - SendEventToSink(&key_event, std::move(closure)); + SendEventToSink(&key_event, display_id, std::move(closure)); } void PostMouseEvent(ui::EventType type, const gfx::Point& host_location, int flags, int changed_button_flags, + int64_t display_id, base::OnceClosure closure) { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&UIControlsOzone::PostMouseEventTask, base::Unretained(this), type, host_location, flags, - changed_button_flags, std::move(closure))); + changed_button_flags, display_id, std::move(closure))); } void PostMouseEventTask(ui::EventType type, const gfx::Point& host_location, int flags, int changed_button_flags, + int64_t display_id, base::OnceClosure closure) { ui::MouseEvent mouse_event(type, host_location, host_location, ui::EventTimeForNow(), flags, @@ -313,33 +329,57 @@ class UIControlsOzone : public ui_controls::UIControlsAura { // This hack is necessary to set the repeat count for clicks. ui::MouseEvent mouse_event2(&mouse_event); - SendEventToSink(&mouse_event2, std::move(closure)); + SendEventToSink(&mouse_event2, display_id, std::move(closure)); } - // Returns the ws::mojom::EventInjector, which is used to send events - // to the Window Service for dispatch. - ws::mojom::EventInjector* GetEventInjector() { - DCHECK_EQ(aura::Env::Mode::MUS, host_->window()->env()->mode()); - if (!event_injector_) { - DCHECK(aura::test::EnvTestHelper().GetWindowTreeClient()); - aura::test::EnvTestHelper() - .GetWindowTreeClient() - ->connector() - ->BindInterface(ws::mojom::kServiceName, &event_injector_); - } - return event_injector_.get(); + void PostTouchEvent(ui::EventType type, + const gfx::Point& host_location, + int id, + int64_t display_id, + base::OnceClosure closure) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&UIControlsOzone::PostTouchEventTask, + base::Unretained(this), type, host_location, + id, display_id, std::move(closure))); } - bool ScreenDIPToHostPixels(gfx::Point* location) { + void PostTouchEventTask(ui::EventType type, + const gfx::Point& host_location, + int id, + int64_t display_id, + base::OnceClosure closure) { + ui::PointerDetails details(ui::EventPointerType::POINTER_TYPE_TOUCH, id, + 1.0f, 1.0f, 0.0f); + ui::TouchEvent touch_event(type, host_location, ui::EventTimeForNow(), + details); + SendEventToSink(&touch_event, display_id, std::move(closure)); + } + + // Initializes EventInjector when Mus. Otherwise do nothing. + void MaybeInitializeEventInjector() { + if (host_->window()->env()->mode() != Env::Mode::MUS) + return; + + DCHECK(aura::test::EnvTestHelper().GetWindowTreeClient()); + aura::test::EnvTestHelper() + .GetWindowTreeClient() + ->connector() + ->BindInterface(ws::mojom::kServiceName, &event_injector_); + } + + bool ScreenDIPToHostPixels(gfx::Point* location, int64_t* display_id) { // The location needs to be in display's coordinate. - display::Display display; - if (!display::Screen::GetScreen()->GetDisplayWithDisplayId( - host_->GetDisplayId(), &display)) { - LOG(ERROR) << "Failed to find the display for " << host_->GetDisplayId(); + display::Display display = + display::Screen::GetScreen()->GetDisplayNearestPoint(*location); + if (!display.is_valid()) { + LOG(ERROR) << "Failed to find the display for " << location->ToString(); return false; } + *display_id = display.id(); *location -= display.bounds().OffsetFromOrigin(); - host_->ConvertDIPToPixels(location); + *location = + gfx::ScaleToFlooredPoint(*location, display.device_scale_factor(), + display.device_scale_factor()); return true; } @@ -351,6 +391,11 @@ class UIControlsOzone : public ui_controls::UIControlsAura { // is updated asynchronously with mus. base::Optional<gfx::Point> last_mouse_location_; + // The display ID where the last SendMouseEventsNotifyWhenDone occurred. This + // is used along with |last_mouse_location_| to send the mouse event to the + // event injector. Not used when Mus is not enabled. + int64_t last_mouse_display_id_ = display::kInvalidDisplayId; + // Mask of the mouse buttons currently down. This is static as it needs to // track the state globally for all displays. A UIControlsOzone instance is // created for each display host. @@ -368,5 +413,20 @@ ui_controls::UIControlsAura* CreateUIControlsAura(WindowTreeHost* host) { return new UIControlsOzone(host); } +void OnWindowServiceProcessedEvent(base::OnceClosure closure, bool result) { + DCHECK(result); + if (closure) { + // There can be several mojo calls are queued in the window tree client, + // which may change the order of the operations unexpectedly. Do not call + // WaitForAllChangesToComplete() here, since some in-flight changes might + // not be resolved by just waiting (like window-dragging will not finish + // until it's cancelled or the mouse or touch is released). + // See also: https://crbug.com/916177 + WindowTreeClientTestApi(EnvTestHelper().GetWindowTreeClient()) + .FlushForTesting(); + std::move(closure).Run(); + } +} + } // namespace test } // namespace aura diff --git a/chromium/ui/aura/window.cc b/chromium/ui/aura/window.cc index ef148894298..972e0c5bd07 100644 --- a/chromium/ui/aura/window.cc +++ b/chromium/ui/aura/window.cc @@ -20,6 +20,7 @@ #include "base/strings/stringprintf.h" #include "cc/trees/layer_tree_frame_sink.h" #include "services/ws/public/mojom/window_tree_constants.mojom.h" +#include "third_party/skia/include/core/SkPath.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/client/capture_client.h" #include "ui/aura/client/cursor_client.h" @@ -48,7 +49,6 @@ #include "ui/events/event_target_iterator.h" #include "ui/events/keycodes/dom/dom_code.h" #include "ui/gfx/canvas.h" -#include "ui/gfx/path.h" #include "ui/gfx/scoped_canvas.h" namespace aura { @@ -317,9 +317,9 @@ std::unique_ptr<WindowTargeter> Window::SetEventTargeter( } void Window::SetBounds(const gfx::Rect& new_bounds) { - if (parent_ && parent_->layout_manager()) + if (parent_ && parent_->layout_manager()) { parent_->layout_manager()->SetChildBounds(this, new_bounds); - else { + } else { // Ensure we don't go smaller than our minimum bounds. gfx::Rect final_bounds(new_bounds); if (delegate_) { @@ -690,21 +690,6 @@ bool Window::CanFocus() const { return parent_->CanFocus(); } -bool Window::CanReceiveEvents() const { - // TODO(sky): this may want to delegate to the WindowPort as for mus there - // isn't a point in descending into windows owned by the client. - if (IsRootWindow()) - return IsVisible(); - - // The client may forbid certain windows from receiving events at a given - // point in time. - client::EventClient* client = client::GetEventClient(GetRootWindow()); - if (client && !client->CanProcessEventsWithinSubtree(this)) - return false; - - return parent_ && IsVisible() && parent_->CanReceiveEvents(); -} - void Window::SetCapture() { if (!IsVisible()) return; @@ -831,7 +816,7 @@ bool Window::HitTest(const gfx::Point& local_point) { if (!delegate_ || !delegate_->HasHitTestMask()) return local_bounds.Contains(local_point); - gfx::Path mask; + SkPath mask; delegate_->GetHitTestMask(&mask); SkRegion clip_region; @@ -893,6 +878,9 @@ void Window::SetOcclusionInfo(OcclusionState occlusion_state, occluded_region_ = occluded_region; if (delegate_) delegate_->OnWindowOcclusionChanged(occlusion_state, occluded_region); + + for (WindowObserver& observer : observers_) + observer.OnWindowOcclusionChanged(this); } } @@ -1058,7 +1046,7 @@ void Window::NotifyWindowHierarchyChangeAtReceiver( void Window::NotifyWindowVisibilityChanged(aura::Window* target, bool visible) { if (!NotifyWindowVisibilityChangedDown(target, visible)) - return; // |this| has been deleted. + return; // |this| has been deleted. NotifyWindowVisibilityChangedUp(target, visible); } @@ -1077,7 +1065,7 @@ bool Window::NotifyWindowVisibilityChangedAtReceiver(aura::Window* target, bool Window::NotifyWindowVisibilityChangedDown(aura::Window* target, bool visible) { if (!NotifyWindowVisibilityChangedAtReceiver(target, visible)) - return false; // |this| was deleted. + return false; // |this| was deleted. WindowTracker this_tracker; this_tracker.Add(this); diff --git a/chromium/ui/aura/window.h b/chromium/ui/aura/window.h index 010edc94e27..7fbb0d6677e 100644 --- a/chromium/ui/aura/window.h +++ b/chromium/ui/aura/window.h @@ -356,9 +356,6 @@ class AURA_EXPORT Window : public ui::LayerDelegate, // Returns true if the Window can be focused. bool CanFocus() const; - // Returns true if the Window can receive events. - bool CanReceiveEvents() const; - // Does a capture on the window. This does nothing if the window isn't showing // (VISIBILITY_SHOWN) or isn't contained in a valid window hierarchy. void SetCapture(); @@ -479,10 +476,10 @@ class AURA_EXPORT Window : public ui::LayerDelegate, int64_t old_value, std::unique_ptr<ui::PropertyData> data) override; private: + friend class DefaultWindowOcclusionChangeBuilder; friend class HitTestDataProviderAura; friend class LayoutManager; friend class PropertyConverter; - friend class WindowOcclusionTracker; friend class WindowPort; friend class WindowPortForShutdown; friend class WindowPortMus; @@ -663,7 +660,7 @@ class AURA_EXPORT Window : public ui::LayerDelegate, // Makes the window pass all events through to any windows behind it. ws::mojom::EventTargetingPolicy event_targeting_policy_; - base::ObserverList<WindowObserver, true> observers_; + base::ReentrantObserverList<WindowObserver, true> observers_; DISALLOW_COPY_AND_ASSIGN(Window); }; diff --git a/chromium/ui/aura/window_delegate.h b/chromium/ui/aura/window_delegate.h index 8107a0d3b41..e25e9850990 100644 --- a/chromium/ui/aura/window_delegate.h +++ b/chromium/ui/aura/window_delegate.h @@ -13,8 +13,9 @@ #include "ui/events/event_handler.h" #include "ui/gfx/native_widget_types.h" +class SkPath; + namespace gfx { -class Path; class Point; class Rect; class Size; @@ -101,7 +102,7 @@ class AURA_EXPORT WindowDelegate : public ui::EventHandler { // Called from Window::HitTest to retrieve hit test mask when HasHitTestMask // above returns true. - virtual void GetHitTestMask(gfx::Path* mask) const = 0; + virtual void GetHitTestMask(SkPath* mask) const = 0; // Returns whether the window wants to receive and handle double tap gesture // events. Defaults to false. diff --git a/chromium/ui/aura/window_event_dispatcher.cc b/chromium/ui/aura/window_event_dispatcher.cc index f22e6d1f000..f95080f10c3 100644 --- a/chromium/ui/aura/window_event_dispatcher.cc +++ b/chromium/ui/aura/window_event_dispatcher.cc @@ -34,6 +34,7 @@ #include "ui/events/event_utils.h" #include "ui/events/gestures/gesture_recognizer.h" #include "ui/events/gestures/gesture_types.h" +#include "ui/events/platform/platform_event_source.h" typedef ui::EventDispatchDetails DispatchDetails; @@ -866,6 +867,11 @@ ui::EventDispatchDetails WindowEventDispatcher::DispatchHeldEvents() { } void WindowEventDispatcher::PostSynthesizeMouseMove() { + // No one should care where the real mouse is when this flag is on. So there + // is no need to send a synthetic mouse move here. + if (ui::PlatformEventSource::ShouldIgnoreNativePlatformEvents()) + return; + if (synthesize_mouse_move_ || in_shutdown_) return; synthesize_mouse_move_ = true; diff --git a/chromium/ui/aura/window_event_dispatcher_unittest.cc b/chromium/ui/aura/window_event_dispatcher_unittest.cc index 1e4680488c6..9475308e47b 100644 --- a/chromium/ui/aura/window_event_dispatcher_unittest.cc +++ b/chromium/ui/aura/window_event_dispatcher_unittest.cc @@ -139,8 +139,11 @@ TEST_P(WindowEventDispatcherTest, OnHostMouseEvent) { ui::EF_LEFT_MOUSE_BUTTON); DispatchEventUsingWindowDispatcher(&event1); - // Event was tested for non-client area for the target window. - EXPECT_EQ(1, delegate1->non_client_count()); + // Event was tested for non-client area for the target window. The expected + // value is 2 when mode is MUS, since ClientSideWindowMoveHandler also invokes + // it. + EXPECT_EQ((Env::GetInstance()->mode() == Env::Mode::MUS) ? 2 : 1, + delegate1->non_client_count()); EXPECT_EQ(0, delegate2->non_client_count()); // The non-client component test was in local coordinates. EXPECT_EQ(gfx::Point(1, 1), delegate1->non_client_location()); diff --git a/chromium/ui/aura/window_observer.h b/chromium/ui/aura/window_observer.h index 1da8e5fbacf..57e351893f9 100644 --- a/chromium/ui/aura/window_observer.h +++ b/chromium/ui/aura/window_observer.h @@ -174,6 +174,9 @@ class AURA_EXPORT WindowObserver : public base::CheckedObserver { // embedded). virtual void OnEmbeddedAppDisconnected(Window* window) {} + // Called when the occlusion state of |window| changes. + virtual void OnWindowOcclusionChanged(Window* window) {} + protected: ~WindowObserver() override; }; diff --git a/chromium/ui/aura/window_occlusion_change_builder.cc b/chromium/ui/aura/window_occlusion_change_builder.cc new file mode 100644 index 00000000000..23724a72745 --- /dev/null +++ b/chromium/ui/aura/window_occlusion_change_builder.cc @@ -0,0 +1,67 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/aura/window_occlusion_change_builder.h" + +#include "base/containers/flat_map.h" +#include "base/logging.h" +#include "base/macros.h" +#include "third_party/skia/include/core/SkRegion.h" +#include "ui/aura/window_tracker.h" + +namespace aura { + +// Provide updating of occlusion info on aura::Window. +class DefaultWindowOcclusionChangeBuilder + : public WindowOcclusionChangeBuilder { + public: + DefaultWindowOcclusionChangeBuilder() = default; + ~DefaultWindowOcclusionChangeBuilder() override { + while (!windows_.windows().empty()) { + Window* window = windows_.Pop(); + auto it = changes_.find(window); + if (it == changes_.end()) + continue; + + window->SetOcclusionInfo(it->second.occlusion_state, + it->second.occluded_region); + } + changes_.clear(); + } + + private: + struct OcclusionData { + Window::OcclusionState occlusion_state; + SkRegion occluded_region; + }; + + // WindowOcclusionChangeBuilder: + void Add(Window* window, + Window::OcclusionState occlusion_state, + SkRegion occluded_region) override { + // Change back to UNKNOWN is not allowed. + DCHECK_NE(occlusion_state, Window::OcclusionState::UNKNOWN); + + windows_.Add(window); + changes_[window] = {occlusion_state, occluded_region}; + } + + // Tracks live windows that has a change. This is needed in addition to the + // keys in |changes_| because the window tree may change while changes are + // accumulated or being applied. + WindowTracker windows_; + + // Stores the accumulated occlusion changes. + base::flat_map<Window*, OcclusionData> changes_; + + DISALLOW_COPY_AND_ASSIGN(DefaultWindowOcclusionChangeBuilder); +}; + +// static +std::unique_ptr<WindowOcclusionChangeBuilder> +WindowOcclusionChangeBuilder::Create() { + return std::make_unique<DefaultWindowOcclusionChangeBuilder>(); +} + +} // namespace aura diff --git a/chromium/ui/aura/window_occlusion_change_builder.h b/chromium/ui/aura/window_occlusion_change_builder.h new file mode 100644 index 00000000000..05cd323b4db --- /dev/null +++ b/chromium/ui/aura/window_occlusion_change_builder.h @@ -0,0 +1,36 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_AURA_WINDOW_OCCLUSION_CHANGE_BUILDER_H_ +#define UI_AURA_WINDOW_OCCLUSION_CHANGE_BUILDER_H_ + +#include <memory> + +#include "ui/aura/aura_export.h" +#include "ui/aura/window.h" + +class SkRegion; + +namespace aura { + +// Interface for WindowOcclusionTracker to update window occlusion info. +class AURA_EXPORT WindowOcclusionChangeBuilder { + public: + virtual ~WindowOcclusionChangeBuilder() = default; + + // Add an occlusion info change for |window|. + // Note that setting Window::OcclusionState::UNKNOWN to a window is not + // allowed. + virtual void Add(Window* window, + Window::OcclusionState occlusion_state, + SkRegion occluded_region) = 0; + + // Factory to create the default implementation that updates occlusion info + // on aura::Window. + static std::unique_ptr<WindowOcclusionChangeBuilder> Create(); +}; + +} // namespace aura + +#endif // UI_AURA_WINDOW_OCCLUSION_CHANGE_BUILDER_H_ diff --git a/chromium/ui/aura/window_occlusion_change_builder_unittest.cc b/chromium/ui/aura/window_occlusion_change_builder_unittest.cc new file mode 100644 index 00000000000..b972d5066f0 --- /dev/null +++ b/chromium/ui/aura/window_occlusion_change_builder_unittest.cc @@ -0,0 +1,170 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/aura/window_occlusion_change_builder.h" + +#include <memory> + +#include "third_party/skia/include/core/SkRegion.h" +#include "ui/aura/test/aura_test_base.h" +#include "ui/aura/test/test_window_delegate.h" +#include "ui/aura/test/test_windows.h" + +namespace aura { + +namespace { + +// A delegate that remembers the occlusion info of its window. +class OcclusionTrackWindowDelegate : public test::TestWindowDelegate { + public: + OcclusionTrackWindowDelegate() = default; + ~OcclusionTrackWindowDelegate() override = default; + + bool occlusion_change_count() const { return occlusion_change_count_; } + Window::OcclusionState last_occlusion_state() const { + return last_occlusion_state_; + } + const SkRegion& last_occluded_region() const { return last_occluded_region_; } + + private: + // test::TestWindowDelegate: + void OnWindowOcclusionChanged(Window::OcclusionState occlusion_state, + const SkRegion& occluded_region) override { + ++occlusion_change_count_; + last_occlusion_state_ = occlusion_state; + last_occluded_region_ = occluded_region; + } + + int occlusion_change_count_ = 0; + Window::OcclusionState last_occlusion_state_ = + Window::OcclusionState::UNKNOWN; + SkRegion last_occluded_region_; + + DISALLOW_COPY_AND_ASSIGN(OcclusionTrackWindowDelegate); +}; + +} // namespace + +class WindowOcclusionChangeBuilderTest : public test::AuraTestBase { + public: + WindowOcclusionChangeBuilderTest() = default; + ~WindowOcclusionChangeBuilderTest() override = default; + + std::unique_ptr<Window> CreateTestWindow( + OcclusionTrackWindowDelegate* delegate) { + auto window = std::make_unique<Window>(delegate); + window->set_owned_by_parent(false); + window->SetType(client::WINDOW_TYPE_NORMAL); + window->Init(ui::LAYER_TEXTURED); + window->Show(); + + root_window()->AddChild(window.get()); + return window; + } + + private: + DISALLOW_COPY_AND_ASSIGN(WindowOcclusionChangeBuilderTest); +}; + +// Test that window occlusion info is updated after commit. +TEST_F(WindowOcclusionChangeBuilderTest, SingleWindow) { + SkRegion region; + region.setRect(1, 2, 3, 4); + + for (const auto state : + {Window::OcclusionState::VISIBLE, Window::OcclusionState::OCCLUDED, + Window::OcclusionState::HIDDEN}) { + OcclusionTrackWindowDelegate delegate; + auto window = CreateTestWindow(&delegate); + + auto builder = WindowOcclusionChangeBuilder::Create(); + builder->Add(window.get(), state, region); + + // Change should not be applied before Commit call. + EXPECT_EQ(0, delegate.occlusion_change_count()); + + // All changes are committed when builder is released. + builder.reset(); + + EXPECT_EQ(1, delegate.occlusion_change_count()); + EXPECT_EQ(state, delegate.last_occlusion_state()); + EXPECT_EQ(region, delegate.last_occluded_region()); + } +} + +// Test updating multiple windows. +TEST_F(WindowOcclusionChangeBuilderTest, MultipleWindow) { + auto builder = WindowOcclusionChangeBuilder::Create(); + + OcclusionTrackWindowDelegate delegate1; + auto window1 = CreateTestWindow(&delegate1); + const Window::OcclusionState state1 = Window::OcclusionState::VISIBLE; + SkRegion region1; + region1.setRect(1, 2, 3, 4); + builder->Add(window1.get(), state1, region1); + + OcclusionTrackWindowDelegate delegate2; + auto window2 = CreateTestWindow(&delegate2); + const Window::OcclusionState state2 = Window::OcclusionState::OCCLUDED; + SkRegion region2; + region2.setRect(5, 6, 7, 8); + builder->Add(window2.get(), state2, region2); + + // Changes should not be applied before Commit call. + EXPECT_EQ(0, delegate1.occlusion_change_count()); + EXPECT_EQ(0, delegate2.occlusion_change_count()); + + // All changes are committed when builder is released. + builder.reset(); + + EXPECT_EQ(1, delegate1.occlusion_change_count()); + EXPECT_EQ(state1, delegate1.last_occlusion_state()); + EXPECT_EQ(region1, delegate1.last_occluded_region()); + + EXPECT_EQ(1, delegate2.occlusion_change_count()); + EXPECT_EQ(state2, delegate2.last_occlusion_state()); + EXPECT_EQ(region2, delegate2.last_occluded_region()); +} + +// Tests that the last change wins when there are multiple changes on the same +// window. +TEST_F(WindowOcclusionChangeBuilderTest, MultipleChanges) { + OcclusionTrackWindowDelegate delegate; + auto window = CreateTestWindow(&delegate); + + auto builder = WindowOcclusionChangeBuilder::Create(); + builder->Add(window.get(), Window::OcclusionState::VISIBLE, SkRegion()); + builder->Add(window.get(), Window::OcclusionState::HIDDEN, SkRegion()); + + SkRegion region; + region.setRect(1, 2, 3, 4); + builder->Add(window.get(), Window::OcclusionState::OCCLUDED, region); + + // All changes are committed when builder is released. + builder.reset(); + + EXPECT_EQ(1, delegate.occlusion_change_count()); + EXPECT_EQ(Window::OcclusionState::OCCLUDED, delegate.last_occlusion_state()); + EXPECT_EQ(region, delegate.last_occluded_region()); +} + +// Test that occlusion info is not updated if window is destroyed before commit. +TEST_F(WindowOcclusionChangeBuilderTest, DestroyBeforeCommit) { + OcclusionTrackWindowDelegate delegate; + auto window = CreateTestWindow(&delegate); + + auto builder = WindowOcclusionChangeBuilder::Create(); + builder->Add(window.get(), Window::OcclusionState::VISIBLE, SkRegion()); + + // Destroy window before applying the changes. + window.reset(); + + // All changes are committed when builder is released. + builder.reset(); + + // Occlusion info is not updated. + EXPECT_EQ(0, delegate.occlusion_change_count()); +} + +} // namespace aura diff --git a/chromium/ui/aura/window_occlusion_tracker.cc b/chromium/ui/aura/window_occlusion_tracker.cc index f7e4fbbb004..1af23f7573a 100644 --- a/chromium/ui/aura/window_occlusion_tracker.cc +++ b/chromium/ui/aura/window_occlusion_tracker.cc @@ -11,7 +11,7 @@ #include "third_party/skia/include/core/SkRect.h" #include "third_party/skia/include/core/SkRegion.h" #include "ui/aura/env.h" -#include "ui/aura/window_tracker.h" +#include "ui/aura/window_occlusion_change_builder.h" #include "ui/aura/window_tree_host.h" #include "ui/gfx/geometry/safe_integer_conversions.h" #include "ui/gfx/transform.h" @@ -126,7 +126,9 @@ void WindowOcclusionTracker::Track(Window* window) { DCHECK(window != window->GetRootWindow()); auto insert_result = tracked_windows_.insert({window, {}}); - DCHECK(insert_result.second); + if (!insert_result.second) + return; + if (!window_observer_.IsObserving(window)) window_observer_.Add(window); if (window->GetRootWindow()) @@ -194,31 +196,28 @@ void WindowOcclusionTracker::MaybeComputeOcclusion() { ++num_times_occlusion_recomputed_; ++num_times_occlusion_recomputed_in_current_step_; - // Call Window::SetOcclusionInfo() on tracked windows. A WindowDelegate may - // change the window tree in response to this. - WindowTracker tracked_windows_list; - for (const auto& tracked_window : tracked_windows_) - tracked_windows_list.Add(tracked_window.first); - - while (!tracked_windows_list.windows().empty()) { - Window* window = tracked_windows_list.Pop(); - auto it = tracked_windows_.find(window); - if (it != tracked_windows_.end() && - it->second.occlusion_state != Window::OcclusionState::UNKNOWN) { - // Fallback to VISIBLE/HIDDEN if the maximum number of times that - // occlusion can be recomputed was exceeded. - if (exceeded_max_num_times_occlusion_recomputed) { - if (window->IsVisible()) { - it->second.occlusion_state = Window::OcclusionState::VISIBLE; - } else { - it->second.occlusion_state = Window::OcclusionState::HIDDEN; - } - it->second.occluded_region = SkRegion(); + std::unique_ptr<WindowOcclusionChangeBuilder> change_builder = + occlusion_change_builder_factory_ + ? occlusion_change_builder_factory_.Run() + : WindowOcclusionChangeBuilder::Create(); + for (auto& it : tracked_windows_) { + Window* window = it.first; + if (it.second.occlusion_state == Window::OcclusionState::UNKNOWN) + continue; + + // Fallback to VISIBLE/HIDDEN if the maximum number of times that + // occlusion can be recomputed was exceeded. + if (exceeded_max_num_times_occlusion_recomputed) { + if (window->IsVisible()) { + it.second.occlusion_state = Window::OcclusionState::VISIBLE; + } else { + it.second.occlusion_state = Window::OcclusionState::HIDDEN; } - - window->SetOcclusionInfo(it->second.occlusion_state, - it->second.occluded_region); + it.second.occluded_region = SkRegion(); } + + change_builder->Add(window, it.second.occlusion_state, + it.second.occluded_region); } } diff --git a/chromium/ui/aura/window_occlusion_tracker.h b/chromium/ui/aura/window_occlusion_tracker.h index 6258792f8f0..02e78322c2b 100644 --- a/chromium/ui/aura/window_occlusion_tracker.h +++ b/chromium/ui/aura/window_occlusion_tracker.h @@ -33,6 +33,7 @@ class WindowOcclusionTrackerTestApi; } class Env; +class WindowOcclusionChangeBuilder; // Notifies tracked Windows when their occlusion state change. // @@ -73,7 +74,7 @@ class AURA_EXPORT WindowOcclusionTracker : public ui::LayerAnimationObserver, // temporary until it is finished. // Note that this is intended to be used by window manager and not by mus // client process. - class AURA_EXPORT ScopedExclude : public aura::WindowObserver { + class AURA_EXPORT ScopedExclude : public WindowObserver { public: explicit ScopedExclude(Window* window); ~ScopedExclude() override; @@ -100,6 +101,14 @@ class AURA_EXPORT WindowOcclusionTracker : public ui::LayerAnimationObserver, window_has_content_callback_ = std::move(callback); } + // Set the factory to create WindowOcclusionChangeBuilder. + using OcclusionChangeBuilderFactory = + base::RepeatingCallback<std::unique_ptr<WindowOcclusionChangeBuilder>()>; + void set_occlusion_change_builder_factory( + OcclusionChangeBuilderFactory factory) { + occlusion_change_builder_factory_ = std::move(factory); + } + private: friend class test::WindowOcclusionTrackerTestApi; friend class Env; @@ -269,12 +278,13 @@ class AURA_EXPORT WindowOcclusionTracker : public ui::LayerAnimationObserver, Window* new_root) override; void OnWindowLayerRecreated(Window* window) override; - // Windows whose occlusion data is tracked. - base::flat_map<Window*, OcclusionData> tracked_windows_; // WindowTreeHostObserver void OnOcclusionStateChanged(WindowTreeHost* host, Window::OcclusionState new_state) override; + // Windows whose occlusion data is tracked. + base::flat_map<Window*, OcclusionData> tracked_windows_; + // Windows whose bounds or transform are animated. // // To reduce the overhead of the WindowOcclusionTracker, windows in this set @@ -308,6 +318,9 @@ class AURA_EXPORT WindowOcclusionTracker : public ui::LayerAnimationObserver, // Callback to be invoked for additional window has content check. WindowHasContentCallback window_has_content_callback_; + // Optional factory to create occlusion change builder. + OcclusionChangeBuilderFactory occlusion_change_builder_factory_; + DISALLOW_COPY_AND_ASSIGN(WindowOcclusionTracker); }; diff --git a/chromium/ui/aura/window_port.cc b/chromium/ui/aura/window_port.cc index 80f9c4bcd14..2922baf1a7f 100644 --- a/chromium/ui/aura/window_port.cc +++ b/chromium/ui/aura/window_port.cc @@ -16,7 +16,7 @@ WindowPort* WindowPort::Get(Window* window) { } // static -base::ObserverList<WindowObserver, true>* WindowPort::GetObservers( +base::ReentrantObserverList<WindowObserver, true>* WindowPort::GetObservers( Window* window) { return &(window->observers_); } diff --git a/chromium/ui/aura/window_port.h b/chromium/ui/aura/window_port.h index 4c4073afa92..d07c84d6e9a 100644 --- a/chromium/ui/aura/window_port.h +++ b/chromium/ui/aura/window_port.h @@ -148,7 +148,8 @@ class AURA_EXPORT WindowPort { static WindowPort* Get(Window* window); // Returns the ObserverList of a Window. - static base::ObserverList<WindowObserver, true>* GetObservers(Window* window); + static base::ReentrantObserverList<WindowObserver, true>* GetObservers( + Window* window); private: const Type type_; diff --git a/chromium/ui/aura/window_targeter.cc b/chromium/ui/aura/window_targeter.cc index 14665e38eaf..0e182f2d8e9 100644 --- a/chromium/ui/aura/window_targeter.cc +++ b/chromium/ui/aura/window_targeter.cc @@ -29,6 +29,21 @@ bool AreInsetsEmptyOrPositive(const gfx::Insets& insets) { insets.bottom() >= 0; } +void UpdateMusIfNecessary(aura::Window* window, + const gfx::Insets& mouse_extend, + const gfx::Insets& touch_extend) { + if (!window || window->env()->mode() != Env::Mode::MUS) + return; + + // Negative insets are used solely to extend the hit-test region of child + // windows, which is not needed by code using MUS (negative insets are only + // used in the server). + if (AreInsetsEmptyOrPositive(mouse_extend) && + AreInsetsEmptyOrPositive(touch_extend)) { + WindowPortMus::Get(window)->SetHitTestInsets(mouse_extend, touch_extend); + } +} + } // namespace WindowTargeter::WindowTargeter() {} @@ -224,6 +239,9 @@ Window* WindowTargeter::FindTargetForKeyEvent(Window* window) { } void WindowTargeter::OnInstalled(Window* window) { + // Needs to clear the existing insets when uninstalled. + if (!window) + aura::UpdateMusIfNecessary(window_, gfx::Insets(), gfx::Insets()); window_ = window; UpdateMusIfNecessary(); } @@ -334,16 +352,7 @@ bool WindowTargeter::ShouldUseExtendedBounds(const aura::Window* w) const { // TODO: this function should go away once https://crbug.com/879308 is fixed. void WindowTargeter::UpdateMusIfNecessary() { - if (!window_ || window_->env()->mode() != Env::Mode::MUS) - return; - - // Negative insets are used solely to extend the hit-test region of child - // windows, which is not needed by code using MUS (negative insets are only - // used in the server). - if (AreInsetsEmptyOrPositive(mouse_extend_) && - AreInsetsEmptyOrPositive(touch_extend_)) { - WindowPortMus::Get(window_)->SetHitTestInsets(mouse_extend_, touch_extend_); - } + aura::UpdateMusIfNecessary(window_, mouse_extend_, touch_extend_); } Window* WindowTargeter::FindTargetForNonKeyEvent(Window* root_window, diff --git a/chromium/ui/aura/window_tree_host.cc b/chromium/ui/aura/window_tree_host.cc index 89ed4c6bb9b..08ffa5e729b 100644 --- a/chromium/ui/aura/window_tree_host.cc +++ b/chromium/ui/aura/window_tree_host.cc @@ -139,6 +139,10 @@ ui::EventSink* WindowTreeHost::event_sink() { return dispatcher_.get(); } +base::WeakPtr<WindowTreeHost> WindowTreeHost::GetWeakPtr() { + return weak_factory_.GetWeakPtr(); +} + gfx::Transform WindowTreeHost::GetRootTransform() const { gfx::Transform transform; transform.Scale(device_scale_factor_, device_scale_factor_); @@ -274,6 +278,10 @@ ui::EventDispatchDetails WindowTreeHost::DispatchKeyEventPostIME( return dispatch_details; } +ui::EventSink* WindowTreeHost::GetEventSink() { + return dispatcher_.get(); +} + int64_t WindowTreeHost::GetDisplayId() { return display::Screen::GetScreen()->GetDisplayNearestWindow(window()).id(); } @@ -379,28 +387,26 @@ void WindowTreeHost::DestroyDispatcher() { //window()->RemoveOrDestroyChildren(); } -void WindowTreeHost::CreateCompositor(const viz::FrameSinkId& frame_sink_id, - bool force_software_compositor, - bool external_begin_frames_enabled, - bool are_events_in_pixels, - const char* trace_environment_name) { +void WindowTreeHost::CreateCompositor( + const viz::FrameSinkId& frame_sink_id, + bool force_software_compositor, + ui::ExternalBeginFrameClient* external_begin_frame_client, + bool are_events_in_pixels, + const char* trace_environment_name) { DCHECK(window()->env()); Env* env = window()->env(); ui::ContextFactory* context_factory = env->context_factory(); DCHECK(context_factory); ui::ContextFactoryPrivate* context_factory_private = env->context_factory_private(); - bool enable_surface_synchronization = - env->mode() == aura::Env::Mode::MUS || - features::IsSurfaceSynchronizationEnabled(); compositor_ = std::make_unique<ui::Compositor>( (!context_factory_private || frame_sink_id.is_valid()) ? frame_sink_id : context_factory_private->AllocateFrameSinkId(), context_factory, context_factory_private, - base::ThreadTaskRunnerHandle::Get(), enable_surface_synchronization, - ui::IsPixelCanvasRecordingEnabled(), external_begin_frames_enabled, - force_software_compositor, trace_environment_name); + base::ThreadTaskRunnerHandle::Get(), ui::IsPixelCanvasRecordingEnabled(), + external_begin_frame_client, force_software_compositor, + trace_environment_name); #if defined(OS_CHROMEOS) compositor_->AddObserver(this); #endif @@ -495,10 +501,6 @@ void WindowTreeHost::OnHostLostWindowCapture() { capture_window->ReleaseCapture(); } -ui::EventSink* WindowTreeHost::GetEventSink() { - return dispatcher_.get(); -} - void WindowTreeHost::OnDisplayMetricsChanged(const display::Display& display, uint32_t metrics) { if (metrics & DisplayObserver::DISPLAY_METRIC_COLOR_SPACE) { @@ -546,11 +548,6 @@ void WindowTreeHost::OnCompositingDidCommit(ui::Compositor* compositor) { base::TimeTicks::Now() - synchronization_start_time_); } -void WindowTreeHost::OnCompositingStarted(ui::Compositor* compositor, - base::TimeTicks start_time) {} - -void WindowTreeHost::OnCompositingEnded(ui::Compositor* compositor) {} - void WindowTreeHost::OnCompositingChildResizing(ui::Compositor* compositor) { if (!window()->env()->throttle_input_on_resize() || holding_pointer_moves_) return; diff --git a/chromium/ui/aura/window_tree_host.h b/chromium/ui/aura/window_tree_host.h index e89644f9776..7730ef6a58a 100644 --- a/chromium/ui/aura/window_tree_host.h +++ b/chromium/ui/aura/window_tree_host.h @@ -85,6 +85,7 @@ class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate, Window* window() { return window_; } const Window* window() const { return window_; } + // TODO(msw): Remove this, callers should use GetEventSink(). ui::EventSink* event_sink(); WindowEventDispatcher* dispatcher() { @@ -95,6 +96,8 @@ class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate, ui::Compositor* compositor() { return compositor_.get(); } + base::WeakPtr<WindowTreeHost> GetWeakPtr(); + // Gets/Sets the root window's transform. virtual gfx::Transform GetRootTransform() const; virtual void SetRootTransform(const gfx::Transform& transform); @@ -177,6 +180,9 @@ class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate, ui::KeyEvent* event, base::OnceCallback<void(bool)> ack_callback) final; + // Overridden from ui::EventSource: + ui::EventSink* GetEventSink() override; + // Returns the id of the display. Default implementation queries Screen. virtual int64_t GetDisplayId(); @@ -262,7 +268,7 @@ class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate, void CreateCompositor( const viz::FrameSinkId& frame_sink_id = viz::FrameSinkId(), bool force_software_compositor = false, - bool external_begin_frames_enabled = false, + ui::ExternalBeginFrameClient* external_begin_frame_client = nullptr, bool are_events_in_pixels = true, const char* trace_environment_name = nullptr); @@ -298,9 +304,6 @@ class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate, // Hides the WindowTreeHost. virtual void HideImpl() = 0; - // Overridden from ui::EventSource: - ui::EventSink* GetEventSink() override; - // display::DisplayObserver implementation. void OnDisplayMetricsChanged(const display::Display& display, uint32_t metrics) override; @@ -333,9 +336,6 @@ class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate, // Overrided from CompositorObserver: void OnCompositingDidCommit(ui::Compositor* compositor) override; - void OnCompositingStarted(ui::Compositor* compositor, - base::TimeTicks start_time) override; - void OnCompositingEnded(ui::Compositor* compositor) override; void OnCompositingChildResizing(ui::Compositor* compositor) override; void OnCompositingShuttingDown(ui::Compositor* compositor) override; diff --git a/chromium/ui/aura/window_tree_host_platform.cc b/chromium/ui/aura/window_tree_host_platform.cc index a116ba0b96c..99159327dd4 100644 --- a/chromium/ui/aura/window_tree_host_platform.cc +++ b/chromium/ui/aura/window_tree_host_platform.cc @@ -59,7 +59,7 @@ WindowTreeHostPlatform::WindowTreeHostPlatform( bounds_ = properties.bounds; CreateCompositor(viz::FrameSinkId(), /* force_software_compositor */ false, - /* external_begin_frames_enabled */ false, + /* external_begin_frames_enabled */ nullptr, /* are_events_in_pixels */ true, trace_environment_name); CreateAndSetPlatformWindow(std::move(properties)); } diff --git a/chromium/ui/aura/window_unittest.cc b/chromium/ui/aura/window_unittest.cc index c5cfcd400ac..a7c15069e3f 100644 --- a/chromium/ui/aura/window_unittest.cc +++ b/chromium/ui/aura/window_unittest.cc @@ -3255,6 +3255,11 @@ TEST_P(WindowTest, RootWindowUsesCompositorFrameSinkId) { } TEST_P(WindowTest, LocalSurfaceIdChanges) { + // This uses Window::CreateLayerTreeFrameSink(), which is not wired up in + // Mus. At this time it is only used for LOCAL, so it's not wired up for MUS. + if (GetParam() == Env::Mode::MUS) + return; + Window window(nullptr); window.Init(ui::LAYER_NOT_DRAWN); window.SetBounds(gfx::Rect(300, 300)); |