diff options
Diffstat (limited to 'chromium/ui/aura')
31 files changed, 578 insertions, 114 deletions
diff --git a/chromium/ui/aura/BUILD.gn b/chromium/ui/aura/BUILD.gn index f638d50067f..92de86a947a 100644 --- a/chromium/ui/aura/BUILD.gn +++ b/chromium/ui/aura/BUILD.gn @@ -123,6 +123,7 @@ component("aura") { "//ui/events", "//ui/events:dom_keyboard_layout", "//ui/events:events_base", + "//ui/events:keyboard_hook", "//ui/events/platform", "//ui/gfx", "//ui/gfx:gfx_switches", diff --git a/chromium/ui/aura/client/aura_constants.cc b/chromium/ui/aura/client/aura_constants.cc index e1d88b353f8..e63df4e16d9 100644 --- a/chromium/ui/aura/client/aura_constants.cc +++ b/chromium/ui/aura/client/aura_constants.cc @@ -6,6 +6,7 @@ #include "ui/base/class_property.h" #include "ui/gfx/geometry/rect.h" +#include "ui/gfx/image/image_skia.h" DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, bool) DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, base::TimeDelta) diff --git a/chromium/ui/aura/client/aura_constants.h b/chromium/ui/aura/client/aura_constants.h index c81a0263bee..7c486507e99 100644 --- a/chromium/ui/aura/client/aura_constants.h +++ b/chromium/ui/aura/client/aura_constants.h @@ -13,6 +13,10 @@ #include "ui/aura/window.h" #include "ui/base/ui_base_types.h" +namespace gfx { +class ImageSkia; +} + namespace ws { namespace mojom { enum class WindowType; diff --git a/chromium/ui/aura/client/cursor_client.h b/chromium/ui/aura/client/cursor_client.h index a39aeff5870..4d7c6361cf2 100644 --- a/chromium/ui/aura/client/cursor_client.h +++ b/chromium/ui/aura/client/cursor_client.h @@ -5,7 +5,6 @@ #ifndef UI_AURA_CLIENT_CURSOR_CLIENT_H_ #define UI_AURA_CLIENT_CURSOR_CLIENT_H_ -#include <string> #include "ui/aura/aura_export.h" #include "ui/base/cursor/cursor.h" diff --git a/chromium/ui/aura/client/drag_drop_client.h b/chromium/ui/aura/client/drag_drop_client.h index a6fa5efeb1d..14f959b948b 100644 --- a/chromium/ui/aura/client/drag_drop_client.h +++ b/chromium/ui/aura/client/drag_drop_client.h @@ -34,12 +34,13 @@ class AURA_EXPORT DragDropClient { // applied at the end of the drag drop session. |screen_location| is in // screen coordinates. At most one drag and drop operation is allowed. // It must not start drag operation while |IsDragDropInProgress| returns true. - virtual int StartDragAndDrop(std::unique_ptr<ui::OSExchangeData> data, - aura::Window* root_window, - aura::Window* source_window, - const gfx::Point& screen_location, - int operation, - ui::mojom::DragEventSource source) = 0; + virtual ui::mojom::DragOperation StartDragAndDrop( + std::unique_ptr<ui::OSExchangeData> data, + aura::Window* root_window, + aura::Window* source_window, + const gfx::Point& screen_location, + int allowed_operations, + ui::mojom::DragEventSource source) = 0; // Called when a drag and drop session is cancelled. virtual void DragCancel() = 0; diff --git a/chromium/ui/aura/client/drag_drop_delegate.h b/chromium/ui/aura/client/drag_drop_delegate.h index 009f91445bc..717ff6ed693 100644 --- a/chromium/ui/aura/client/drag_drop_delegate.h +++ b/chromium/ui/aura/client/drag_drop_delegate.h @@ -7,6 +7,7 @@ #include <memory> +#include "base/callback.h" #include "ui/aura/aura_export.h" #include "ui/aura/window.h" #include "ui/base/data_transfer_policy/data_transfer_endpoint.h" @@ -37,9 +38,15 @@ struct AURA_EXPORT DragUpdateInfo { // Delegate interface for drag and drop actions on aura::Window. class AURA_EXPORT DragDropDelegate { public: + using DropCallback = + base::OnceCallback<void(const ui::DropTargetEvent& event, + std::unique_ptr<ui::OSExchangeData> data, + ui::mojom::DragOperation& output_drag_op)>; + // OnDragEntered is invoked when the mouse enters this window during a drag & // drop session. This is immediately followed by an invocation of - // OnDragUpdated, and eventually one of OnDragExited or OnPerformDrop. + // OnDragUpdated, and eventually one of OnDragExited, OnPerformDrop, or + // GetDropCallback. virtual void OnDragEntered(const ui::DropTargetEvent& event) = 0; // Invoked during a drag and drop session while the mouse is over the window. @@ -57,10 +64,16 @@ class AURA_EXPORT DragDropDelegate { // also stored in the DropTargetEvent. Implementor of this function should be // aware of keeping the OSExchageData alive until it wants to access it // through the parameter or the stored reference in DropTargetEvent. + // TODO(crbug.com/1175682): Remove OnPerformDrop and switch to GetDropCallback + // instead. virtual ui::mojom::DragOperation OnPerformDrop( const ui::DropTargetEvent& event, std::unique_ptr<ui::OSExchangeData> data) = 0; + // Invoked during a drag and drop session when the user release the mouse, but + // the drop is held because of the DataTransferPolicyController. + virtual DropCallback GetDropCallback(const ui::DropTargetEvent& event) = 0; + protected: virtual ~DragDropDelegate() {} }; diff --git a/chromium/ui/aura/client/screen_position_client.h b/chromium/ui/aura/client/screen_position_client.h index f2d7a44a155..3db26868037 100644 --- a/chromium/ui/aura/client/screen_position_client.h +++ b/chromium/ui/aura/client/screen_position_client.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_AURA_SCREEN_POSITION_CLIENT_H_ -#define UI_AURA_SCREEN_POSITION_CLIENT_H_ +#ifndef UI_AURA_CLIENT_SCREEN_POSITION_CLIENT_H_ +#define UI_AURA_CLIENT_SCREEN_POSITION_CLIENT_H_ #include "ui/aura/aura_export.h" #include "ui/aura/window.h" @@ -68,4 +68,4 @@ AURA_EXPORT ScreenPositionClient* GetScreenPositionClient( } // namespace client } // namespace aura -#endif // UI_AURA_SCREEN_POSITION_CLIENT_H_ +#endif // UI_AURA_CLIENT_SCREEN_POSITION_CLIENT_H_ diff --git a/chromium/ui/aura/client/window_stacking_client.h b/chromium/ui/aura/client/window_stacking_client.h index 657e5997147..151efdd902e 100644 --- a/chromium/ui/aura/client/window_stacking_client.h +++ b/chromium/ui/aura/client/window_stacking_client.h @@ -5,7 +5,6 @@ #ifndef UI_AURA_CLIENT_WINDOW_STACKING_CLIENT_H_ #define UI_AURA_CLIENT_WINDOW_STACKING_CLIENT_H_ -#include <memory> #include "ui/aura/aura_export.h" #include "ui/aura/window.h" diff --git a/chromium/ui/aura/demo/demo_main.cc b/chromium/ui/aura/demo/demo_main.cc index 235f635a06e..eb0f97df230 100644 --- a/chromium/ui/aura/demo/demo_main.cc +++ b/chromium/ui/aura/demo/demo_main.cc @@ -116,8 +116,8 @@ class DemoWindowParentingClient : public aura::client::WindowParentingClient { aura::Window* GetDefaultParent(aura::Window* window, const gfx::Rect& bounds) override { if (!capture_client_) { - capture_client_.reset( - new aura::client::DefaultCaptureClient(window_->GetRootWindow())); + capture_client_ = std::make_unique<aura::client::DefaultCaptureClient>( + window_->GetRootWindow()); } return window_; } @@ -192,7 +192,7 @@ int DemoMain() { gfx::Rect window1_bounds(100, 100, 400, 400); DemoWindowDelegate window_delegate1(SK_ColorBLUE); aura::Window window1(&window_delegate1); - window1.set_id(1); + window1.SetId(1); window1.Init(ui::LAYER_TEXTURED); window1.SetBounds(window1_bounds); window1.Show(); @@ -201,7 +201,7 @@ int DemoMain() { gfx::Rect window2_bounds(200, 200, 350, 350); DemoWindowDelegate window_delegate2(SK_ColorRED); aura::Window window2(&window_delegate2); - window2.set_id(2); + window2.SetId(2); window2.Init(ui::LAYER_TEXTURED); window2.SetBounds(window2_bounds); window2.Show(); @@ -210,7 +210,7 @@ int DemoMain() { gfx::Rect window3_bounds(10, 10, 50, 50); DemoWindowDelegate window_delegate3(SK_ColorGREEN); aura::Window window3(&window_delegate3); - window3.set_id(3); + window3.SetId(3); window3.Init(ui::LAYER_TEXTURED); window3.SetBounds(window3_bounds); window3.Show(); diff --git a/chromium/ui/aura/env.cc b/chromium/ui/aura/env.cc index 043a669ebea..12de7c4f947 100644 --- a/chromium/ui/aura/env.cc +++ b/chromium/ui/aura/env.cc @@ -34,10 +34,6 @@ #include "ui/base/x/x11_cursor_factory.h" #endif -#if defined(OS_WIN) || defined(USE_X11) -#include "ui/gfx/switches.h" -#endif - namespace aura { namespace { @@ -210,17 +206,13 @@ Env::Env() : env_controller_(std::make_unique<EnvInputStateController>(this)), gesture_recognizer_(std::make_unique<ui::GestureRecognizerImpl>()), input_state_lookup_(InputStateLookup::Create()) { -#if defined(OS_WIN) || defined(USE_X11) - if (!base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kHeadless)) { #if defined(USE_X11) - // In Ozone/X11, the cursor factory is initialized by the platform - // initialization code. - if (!features::IsUsingOzonePlatform()) - cursor_factory_ = std::make_unique<ui::X11CursorFactory>(); -#else - cursor_factory_ = std::make_unique<ui::WinCursorFactory>(); -#endif - } + // In Ozone/X11, the cursor factory is initialized by the platform + // initialization code. + if (!features::IsUsingOzonePlatform()) + cursor_factory_ = std::make_unique<ui::X11CursorFactory>(); +#elif defined(OS_WIN) + cursor_factory_ = std::make_unique<ui::WinCursorFactory>(); #endif } diff --git a/chromium/ui/aura/env.h b/chromium/ui/aura/env.h index 2baf5a54175..ff912bbe9f8 100644 --- a/chromium/ui/aura/env.h +++ b/chromium/ui/aura/env.h @@ -8,7 +8,6 @@ #include <memory> #include <set> -#include "base/callback_forward.h" #include "base/macros.h" #include "base/observer_list.h" #include "base/supports_user_data.h" diff --git a/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc b/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc index 40ad0466075..50e6c3177c2 100644 --- a/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc +++ b/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc @@ -41,8 +41,9 @@ namespace test { namespace { std::string WindowIDAsString(ui::GestureConsumer* consumer) { - return consumer ? base::NumberToString(static_cast<Window*>(consumer)->id()) - : "?"; + return consumer + ? base::NumberToString(static_cast<Window*>(consumer)->GetId()) + : "?"; } #define EXPECT_0_EVENTS(events) \ @@ -2214,7 +2215,7 @@ TEST_F(GestureRecognizerTest, GestureEventTouchLockSelectsCorrectWindow) { delegates[i] = new GestureEventConsumeDelegate(); windows[i] = CreateTestWindowWithDelegate( delegates[i], i, window_bounds[i], root_window()); - windows[i]->set_id(i); + windows[i]->SetId(i); ui::TouchEvent press(ui::ET_TOUCH_PRESSED, window_bounds[i].origin(), tes.Now(), ui::PointerDetails(ui::EventPointerType::kTouch, i)); diff --git a/chromium/ui/aura/native_window_occlusion_tracker_win.cc b/chromium/ui/aura/native_window_occlusion_tracker_win.cc index 57f85d3699f..70f7b9ccb50 100644 --- a/chromium/ui/aura/native_window_occlusion_tracker_win.cc +++ b/chromium/ui/aura/native_window_occlusion_tracker_win.cc @@ -799,7 +799,7 @@ bool NativeWindowOcclusionTrackerWin::WindowOcclusionCalculator:: (IsWindowOnCurrentVirtualDesktop(hwnd) == true); } -base::Optional<bool> NativeWindowOcclusionTrackerWin:: +absl::optional<bool> NativeWindowOcclusionTrackerWin:: WindowOcclusionCalculator::IsWindowOnCurrentVirtualDesktop(HWND hwnd) { if (!virtual_desktop_manager_) return true; @@ -809,7 +809,7 @@ base::Optional<bool> NativeWindowOcclusionTrackerWin:: hwnd, &on_current_desktop))) { return on_current_desktop; } - return base::nullopt; + return absl::nullopt; } } // namespace aura diff --git a/chromium/ui/aura/native_window_occlusion_tracker_win.h b/chromium/ui/aura/native_window_occlusion_tracker_win.h index b1a44a9989b..dc00150dbc8 100644 --- a/chromium/ui/aura/native_window_occlusion_tracker_win.h +++ b/chromium/ui/aura/native_window_occlusion_tracker_win.h @@ -18,7 +18,6 @@ #include "base/containers/flat_set.h" #include "base/memory/weak_ptr.h" #include "base/sequenced_task_runner.h" -#include "base/time/time.h" #include "base/timer/timer.h" #include "ui/aura/aura_export.h" #include "ui/aura/window.h" @@ -184,7 +183,7 @@ class AURA_EXPORT NativeWindowOcclusionTrackerWin // Returns true if |hwnd| is definitely on the current virtual desktop, // false if it's definitely not on the current virtual desktop, and nullopt // if we we can't tell for sure. - base::Optional<bool> IsWindowOnCurrentVirtualDesktop(HWND hwnd); + absl::optional<bool> IsWindowOnCurrentVirtualDesktop(HWND hwnd); static WindowOcclusionCalculator* instance_; diff --git a/chromium/ui/aura/scoped_simple_keyboard_hook.cc b/chromium/ui/aura/scoped_simple_keyboard_hook.cc index c39f0a1cf4c..2591d8701c0 100644 --- a/chromium/ui/aura/scoped_simple_keyboard_hook.cc +++ b/chromium/ui/aura/scoped_simple_keyboard_hook.cc @@ -12,7 +12,7 @@ namespace aura { ScopedSimpleKeyboardHook::ScopedSimpleKeyboardHook( - base::Optional<base::flat_set<ui::DomCode>> dom_codes) + absl::optional<base::flat_set<ui::DomCode>> dom_codes) : dom_codes_(std::move(dom_codes)) {} ScopedSimpleKeyboardHook::~ScopedSimpleKeyboardHook() = default; diff --git a/chromium/ui/aura/scoped_simple_keyboard_hook.h b/chromium/ui/aura/scoped_simple_keyboard_hook.h index 18d3c512265..f68499bfbd7 100644 --- a/chromium/ui/aura/scoped_simple_keyboard_hook.h +++ b/chromium/ui/aura/scoped_simple_keyboard_hook.h @@ -7,7 +7,7 @@ #include "base/containers/flat_set.h" #include "base/macros.h" -#include "base/optional.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/aura/scoped_keyboard_hook.h" namespace ui { @@ -24,14 +24,14 @@ namespace aura { class ScopedSimpleKeyboardHook : public ScopedKeyboardHook { public: explicit ScopedSimpleKeyboardHook( - base::Optional<base::flat_set<ui::DomCode>> dom_codes); + absl::optional<base::flat_set<ui::DomCode>> dom_codes); ~ScopedSimpleKeyboardHook() override; // ScopedKeyboardHook override. bool IsKeyLocked(ui::DomCode dom_code) override; private: - base::Optional<base::flat_set<ui::DomCode>> dom_codes_; + absl::optional<base::flat_set<ui::DomCode>> dom_codes_; DISALLOW_COPY_AND_ASSIGN(ScopedSimpleKeyboardHook); }; diff --git a/chromium/ui/aura/window.cc b/chromium/ui/aura/window.cc index 303a0290b53..aca9f1e5838 100644 --- a/chromium/ui/aura/window.cc +++ b/chromium/ui/aura/window.cc @@ -46,6 +46,8 @@ #include "ui/aura/window_tracker.h" #include "ui/aura/window_tree_host.h" #include "ui/base/layout.h" +#include "ui/base/metadata/base_type_conversion.h" +#include "ui/base/metadata/metadata_impl_macros.h" #include "ui/base/ui_base_features.h" #include "ui/compositor/compositor.h" #include "ui/compositor/layer.h" @@ -57,6 +59,66 @@ #include "ui/gfx/canvas.h" #include "ui/gfx/scoped_canvas.h" +DEFINE_ENUM_CONVERTERS( + aura::client::WindowType, + {aura::client::WINDOW_TYPE_UNKNOWN, u"WINDOW_TYPE_UNKNOWN"}, + {aura::client::WINDOW_TYPE_NORMAL, u"WINDOW_TYPE_NORMAL"}, + {aura::client::WINDOW_TYPE_POPUP, u"WINDOW_TYPE_POPUP"}, + {aura::client::WINDOW_TYPE_CONTROL, u"WINDOW_TYPE_CONTROL"}, + {aura::client::WINDOW_TYPE_MENU, u"WINDOW_TYPE_MENU"}, + {aura::client::WINDOW_TYPE_TOOLTIP, u"WINDOW_TYPE_TOOLTIP"}) + +DEFINE_ENUM_CONVERTERS(aura::Window::OcclusionState, + {aura::Window::OcclusionState::UNKNOWN, u"UNKNOWN"}, + {aura::Window::OcclusionState::VISIBLE, u"VISIBLE"}, + {aura::Window::OcclusionState::OCCLUDED, u"OCCLUDED"}, + {aura::Window::OcclusionState::HIDDEN, u"HIDDEN"}) + +namespace ui { +namespace metadata { + +template <> +struct TypeConverter<viz::SurfaceId> : public BaseTypeConverter<true> { + static std::u16string ToString(const viz::SurfaceId& source_value); + static absl::optional<viz::SurfaceId> FromString( + const std::u16string& source_value); + static ValidStrings GetValidStrings(); +}; + +// static +std::u16string TypeConverter<viz::SurfaceId>::ToString( + const viz::SurfaceId& source_value) { + return source_value.is_valid() ? base::UTF8ToUTF16(source_value.ToString()) + : u"<none>"; +} + +// static +absl::optional<viz::SurfaceId> TypeConverter<viz::SurfaceId>::FromString( + const std::u16string& source_value) { + return absl::nullopt; +} + +// static +ValidStrings TypeConverter<viz::SurfaceId>::GetValidStrings() { + return ValidStrings(); +} + +} // namespace metadata +} // namespace ui + +namespace { + +// This enum is used to construct a unique property changed callback key from +// the address of the `bounds_` field by using these values as an offset. +enum BoundsCallbackIndex : int { + kBoundsX, + kBoundsY, + kBoundsWidth, + kBoundsHeight, +}; + +} // namespace + namespace aura { namespace { static const char* kExo = "Exo"; @@ -198,10 +260,28 @@ void Window::Init(ui::LayerType layer_type) { Env::GetInstance()->NotifyWindowInitialized(this); } +int Window::GetId() const { + return id_; +} + +void Window::SetId(int id) { + if (id == id_) + return; + id_ = id; + TriggerChangedCallback(&id_); +} + +client::WindowType Window::GetType() const { + return type_; +} + void Window::SetType(client::WindowType type) { // Cannot change type after the window is initialized. DCHECK(!layer()); + if (type == type_) + return; type_ = type; + TriggerChangedCallback(&type_); } const std::string& Window::GetName() const { @@ -215,6 +295,7 @@ void Window::SetName(const std::string& name) { SetProperty(client::kNameKey, name); if (layer()) UpdateLayerName(); + TriggerChangedCallback(client::kNameKey); } const std::u16string& Window::GetTitle() const { @@ -230,12 +311,17 @@ void Window::SetTitle(const std::u16string& title) { observer.OnWindowTitleChanged(this); } +bool Window::GetTransparent() const { + return transparent_; +} + void Window::SetTransparent(bool transparent) { if (transparent == transparent_) return; transparent_ = transparent; if (layer()) layer()->SetFillsBoundsOpaquely(!transparent_); + TriggerChangedCallback(&transparent_); } void Window::SetFillsBoundsCompletely(bool fills_bounds) { @@ -267,12 +353,12 @@ void Window::Show() { // transparent since the window would still be considered to be active but // could not be seen. DCHECK(!visible_ || layer()->GetTargetOpacity() > 0.0f); - SetVisible(true); + SetVisibleInternal(true); } void Window::Hide() { // RootWindow::OnVisibilityChanged will call ReleaseCapture. - SetVisible(false); + SetVisibleInternal(false); } bool Window::IsVisible() const { @@ -283,6 +369,10 @@ bool Window::IsVisible() const { return visible_ ? layer()->IsDrawn() : false; } +Window::OcclusionState Window::GetOcclusionState() const { + return occlusion_state_; +} + ScopedWindowCaptureRequest Window::MakeWindowCapturable() { DCHECK(!IsRootWindow()) << "Root windows can already be captured using their " "FrameSinkId; no need to call this."; @@ -291,9 +381,6 @@ ScopedWindowCaptureRequest Window::MakeWindowCapturable() { } gfx::Rect Window::GetBoundsInRootWindow() const { - // TODO(beng): There may be a better way to handle this, and the existing code - // is likely wrong anyway in a multi-display world, but this will - // do for now. if (!GetRootWindow()) return bounds(); gfx::Rect bounds_in_root(bounds().size()); @@ -301,6 +388,21 @@ gfx::Rect Window::GetBoundsInRootWindow() const { return bounds_in_root; } +gfx::Rect Window::GetActualBoundsInRootWindow() const { + if (!GetRootWindow()) + return bounds(); + gfx::Rect bounds_in_root(bounds().size()); + gfx::PointF origin_f = gfx::PointF(bounds_in_root.origin()); + ui::Layer::ConvertPointToLayer(layer(), GetRootWindow()->layer(), + /*use_target_transform=*/false, &origin_f); + bounds_in_root.set_origin(gfx::ToFlooredPoint(origin_f)); + return bounds_in_root; +} + +const gfx::Transform& Window::transform() const { + return layer()->transform(); +} + gfx::Rect Window::GetBoundsInScreen() const { gfx::Rect bounds(GetBoundsInRootWindow()); const Window* root = GetRootWindow(); @@ -316,6 +418,17 @@ gfx::Rect Window::GetBoundsInScreen() const { return bounds; } +gfx::Rect Window::GetActualBoundsInScreen() const { + gfx::Rect bounds(GetActualBoundsInRootWindow()); + const Window* root = GetRootWindow(); + if (root) { + gfx::Point origin_in_screen = root->GetBoundsInScreen().origin(); + origin_in_screen += bounds.OffsetFromOrigin(); + bounds.set_origin(origin_in_screen); + } + return bounds; +} + void Window::SetTransform(const gfx::Transform& transform) { WindowOcclusionTracker::ScopedPause pause_occlusion_tracking; for (WindowObserver& observer : observers_) @@ -477,7 +590,7 @@ Window* Window::GetChildById(int id) { const Window* Window::GetChildById(int id) const { Windows::const_iterator i; for (i = children_.begin(); i != children_.end(); ++i) { - if ((*i)->id() == id) + if ((*i)->GetId() == id) return *i; const Window* result = (*i)->GetChildById(id); if (result) @@ -505,7 +618,8 @@ void Window::ConvertPointToTarget(const Window* source, if (target_client) target_client->ConvertPointFromScreen(target, point); } else { - ui::Layer::ConvertPointToLayer(source->layer(), target->layer(), point); + ui::Layer::ConvertPointToLayer(source->layer(), target->layer(), + /*use_target_transform=*/true, point); } } @@ -738,7 +852,7 @@ bool Window::HasCapture() { } std::unique_ptr<ScopedKeyboardHook> Window::CaptureSystemKeyEvents( - base::Optional<base::flat_set<ui::DomCode>> dom_codes) { + absl::optional<base::flat_set<ui::DomCode>> dom_codes) { Window* root_window = GetRootWindow(); if (!root_window) return nullptr; @@ -795,9 +909,10 @@ std::string Window::GetDebugInfo() const { layer()->opacity()); } return base::StringPrintf( - "%s<%d> bounds=%s %s %s occlusion_state=%s", name.c_str(), id(), + "%s<%d> bounds=%s %s %s occlusion_state=%s", name.c_str(), GetId(), bounds().ToString().c_str(), visible_ ? "WindowVisible" : "WindowHidden", - layer_state.c_str(), OcclusionStateToString(occlusion_state_)); + layer_state.c_str(), + base::UTF16ToUTF8(OcclusionStateToString(occlusion_state_)).c_str()); } std::string Window::GetWindowHierarchy(int depth) const { @@ -877,7 +992,7 @@ void Window::SetBoundsInternal(const gfx::Rect& new_bounds) { } } -void Window::SetVisible(bool visible) { +void Window::SetVisibleInternal(bool visible) { if (visible == layer()->GetTargetVisibility()) return; // No change. @@ -1201,6 +1316,10 @@ viz::SurfaceId Window::GetSurfaceId() { return viz::SurfaceId(GetFrameSinkId(), GetLocalSurfaceId()); } +viz::SurfaceId Window::GetSurfaceId() const { + return const_cast<Window*>(this)->GetSurfaceId(); +} + void Window::AllocateLocalSurfaceId() { if (!parent_local_surface_id_allocator_) { parent_local_surface_id_allocator_ = @@ -1229,7 +1348,7 @@ void Window::InvalidateLocalSurfaceId() { } void Window::UpdateLocalSurfaceIdFromEmbeddedClient( - const base::Optional<viz::LocalSurfaceId>& + const absl::optional<viz::LocalSurfaceId>& embedded_client_local_surface_id) { if (embedded_client_local_surface_id) { parent_local_surface_id_allocator_->UpdateFromChild( @@ -1264,27 +1383,14 @@ bool Window::RequiresDoubleTapGestureEvents() const { } // static -const char* Window::OcclusionStateToString(OcclusionState state) { -#define CASE_TYPE(t) \ - case t: \ - return #t - - switch (state) { - CASE_TYPE(OcclusionState::UNKNOWN); - CASE_TYPE(OcclusionState::VISIBLE); - CASE_TYPE(OcclusionState::OCCLUDED); - CASE_TYPE(OcclusionState::HIDDEN); - } -#undef CASE_TYPE - - NOTREACHED(); - return ""; +const std::u16string Window::OcclusionStateToString(OcclusionState state) { + return ui::metadata::TypeConverter<OcclusionState>::ToString(state); } void Window::SetOpaqueRegionsForOcclusion( const std::vector<gfx::Rect>& opaque_regions_for_occlusion) { // Only transparent windows should try to set opaque regions for occlusion. - DCHECK(transparent() || opaque_regions_for_occlusion.empty()); + DCHECK(GetTransparent() || opaque_regions_for_occlusion.empty()); if (opaque_regions_for_occlusion == opaque_regions_for_occlusion_) return; opaque_regions_for_occlusion_ = opaque_regions_for_occlusion; @@ -1326,6 +1432,16 @@ void Window::OnLayerBoundsChanged(const gfx::Rect& old_bounds, delegate_->OnBoundsChanged(old_bounds, bounds_); for (auto& observer : observers_) observer.OnWindowBoundsChanged(this, old_bounds, bounds_, reason); + + // Trigger the changed notification for each of the bounds "properties". + if (old_bounds.x() != bounds_.x()) + TriggerChangedCallback(&bounds_ + kBoundsX); + if (old_bounds.y() != bounds_.y()) + TriggerChangedCallback(&bounds_ + kBoundsY); + if (old_bounds.width() != bounds_.width()) + TriggerChangedCallback(&bounds_ + kBoundsWidth); + if (old_bounds.height() != bounds_.height()) + TriggerChangedCallback(&bounds_ + kBoundsHeight); } void Window::OnLayerOpacityChanged(ui::PropertyChangeReason reason) { @@ -1347,7 +1463,7 @@ void Window::OnLayerFillsBoundsOpaquelyChanged( WindowOcclusionTracker::ScopedPause pause_occlusion_tracking; // Non-transparent windows should not have opaque regions for occlusion set. - if (!transparent()) + if (!GetTransparent()) DCHECK(opaque_regions_for_occlusion_.empty()); for (WindowObserver& observer : observers_) @@ -1573,4 +1689,87 @@ void Window::OnScopedWindowCaptureRequestRemoved() { } } +int Window::GetHeight() const { + return bounds().height(); +} + +int Window::GetWidth() const { + return bounds().width(); +} + +int Window::GetX() const { + return bounds().x(); +} + +int Window::GetY() const { + return bounds().y(); +} + +void Window::SetHeight(int height) { + if (height == bounds().height()) + return; + // Bounds changed notification is done within OnLayerBoundsChanged. + // Here and below. + SetBounds({bounds().x(), bounds().y(), bounds().width(), height}); +} + +void Window::SetWidth(int width) { + if (width == bounds().width()) + return; + SetBounds({bounds().x(), bounds().y(), width, bounds().height()}); +} + +void Window::SetX(int x) { + if (x == bounds().x()) + return; + SetBounds({x, bounds().y(), bounds().width(), bounds().height()}); +} + +void Window::SetY(int y) { + if (y == bounds().y()) + return; + SetBounds({bounds().x(), y, bounds().width(), bounds().height()}); +} + +bool Window::GetCapture() const { + return const_cast<Window*>(this)->HasCapture(); +} + +bool Window::GetVisible() const { + return IsVisible(); +} + +void Window::SetVisible(bool visible) { + if (visible == IsVisible()) + return; + if (visible) + Show(); + else + Hide(); + // Changed notification is handled in SetVisibleInternal(). +} + +// Under Windows this macro is defined. +#undef GetClassName + +BEGIN_METADATA_BASE(Window) +ADD_READONLY_PROPERTY_METADATA(gfx::Rect, ActualBoundsInRootWindow) +ADD_READONLY_PROPERTY_METADATA(gfx::Rect, ActualBoundsInScreen) +ADD_READONLY_PROPERTY_METADATA(gfx::Rect, BoundsInRootWindow) +ADD_READONLY_PROPERTY_METADATA(gfx::Rect, BoundsInScreen) +ADD_READONLY_PROPERTY_METADATA(bool, Capture) +ADD_PROPERTY_METADATA(int, Height) +ADD_PROPERTY_METADATA(int, Width) +ADD_PROPERTY_METADATA(int, X) +ADD_PROPERTY_METADATA(int, Y) +ADD_READONLY_PROPERTY_METADATA(Window::OcclusionState, OcclusionState) +ADD_READONLY_PROPERTY_METADATA(viz::SurfaceId, SurfaceId) +ADD_PROPERTY_METADATA(int, Id) +ADD_PROPERTY_METADATA(std::string, Name) +ADD_PROPERTY_METADATA(std::u16string, Title) +ADD_PROPERTY_METADATA(bool, Transparent) +ADD_PROPERTY_METADATA(client::WindowType, Type) +ADD_PROPERTY_METADATA(bool, Visible) +END_METADATA + } // namespace aura diff --git a/chromium/ui/aura/window.h b/chromium/ui/aura/window.h index d3034469851..b79b13298f6 100644 --- a/chromium/ui/aura/window.h +++ b/chromium/ui/aura/window.h @@ -19,7 +19,6 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" -#include "base/optional.h" #include "base/time/time.h" #include "build/build_config.h" #include "components/viz/common/surfaces/frame_sink_id.h" @@ -27,14 +26,18 @@ #include "components/viz/common/surfaces/scoped_surface_id_allocator.h" #include "components/viz/common/surfaces/subtree_capture_id.h" #include "components/viz/host/host_frame_sink_client.h" +#include "third_party/abseil-cpp/absl/types/optional.h" +#include "third_party/skia/include/core/SkRegion.h" #include "ui/aura/aura_export.h" #include "ui/aura/client/window_types.h" #include "ui/aura/scoped_window_capture_request.h" #include "ui/aura/window_observer.h" #include "ui/base/class_property.h" +#include "ui/base/metadata/metadata_header_macros.h" #include "ui/compositor/layer_animator.h" #include "ui/compositor/layer_delegate.h" #include "ui/compositor/layer_owner.h" +#include "ui/compositor/layer_type.h" #include "ui/events/event_constants.h" #include "ui/events/event_target.h" #include "ui/events/event_targeter.h" @@ -65,6 +68,7 @@ class Layer; namespace viz { class ParentLocalSurfaceIdAllocator; +class SurfaceId; } namespace aura { @@ -106,8 +110,11 @@ class AURA_EXPORT Window : public ui::LayerDelegate, public ui::EventTarget, public ui::GestureConsumer, public ui::PropertyHandler, + public ui::metadata::MetaDataProvider, public viz::HostFrameSinkClient { public: + METADATA_HEADER_BASE(Window); + // Initial value of id() for newly created windows. static constexpr int kInitialId = -1; @@ -163,11 +170,11 @@ class AURA_EXPORT Window : public ui::LayerDelegate, // A type is used to identify a class of Windows and customize behavior such // as event handling and parenting. This field should only be consumed by the // shell -- Aura itself shouldn't contain type-specific logic. - client::WindowType type() const { return type_; } + client::WindowType GetType() const; void SetType(client::WindowType type); - int id() const { return id_; } - void set_id(int id) { id_ = id; } + int GetId() const; + void SetId(int id); const std::string& GetName() const; void SetName(const std::string& name); @@ -175,7 +182,7 @@ class AURA_EXPORT Window : public ui::LayerDelegate, const std::u16string& GetTitle() const; void SetTitle(const std::u16string& title); - bool transparent() const { return transparent_; } + bool GetTransparent() const; // Note: Setting a window transparent has significant performance impact, // especially on low-end Chrome OS devices. Please ensure you are not @@ -218,7 +225,7 @@ class AURA_EXPORT Window : public ui::LayerDelegate, // state of this window isn't tracked (Window::TrackOcclusionState) or // hasn't been computed yet. Is stale if called within the scope of a // WindowOcclusionTracker::ScopedPause. - OcclusionState occlusion_state() const { return occlusion_state_; } + OcclusionState GetOcclusionState() const; // Returns the currently occluded region in the root Window coordinates. This // will be empty unless the window is tracked and has a VISIBLE occlusion @@ -256,17 +263,33 @@ class AURA_EXPORT Window : public ui::LayerDelegate, return subtree_capture_id_; } - // Returns the window's bounds in root window's coordinates. + // Returns the window's bounds in root window's coordinates. The returned + // value is calculated using the target transform. The target transform is the + // end value of a transform animation. If there is no animation ongoing, the + // target transform is the same as the current transform. gfx::Rect GetBoundsInRootWindow() const; - // Returns the window's bounds in screen coordinates. + // Similar to `GetBoundsInRootWindow()` except that the returned value is + // calculated using the current transform. If there is no animation ongoing, + // this function returns the same value as `GetBoundsInRootWindow()`. + gfx::Rect GetActualBoundsInRootWindow() const; + + // Returns the window's bounds in screen coordinates. The returned + // value is calculated using the target transform. The target transform is the + // end value of a transform animation. If there is no animation ongoing, the + // target transform is the same as the current transform. // How the root window's coordinates is mapped to screen's coordinates // is platform dependent and defined in the implementation of the // |aura::client::ScreenPositionClient| interface. gfx::Rect GetBoundsInScreen() const; + // Similar to `GetBoundsInScreen()` except that the returned value is + // calculated using the current transform. If there is no animation ongoing, + // this function returns the same value as `GetBoundsInScreen()`. + gfx::Rect GetActualBoundsInScreen() const; + void SetTransform(const gfx::Transform& transform); - const gfx::Transform& transform() const { return layer()->transform(); } + const gfx::Transform& transform() const; // Assigns a LayoutManager to size and place child windows. // The Window takes ownership of the LayoutManager. @@ -330,7 +353,10 @@ class AURA_EXPORT Window : public ui::LayerDelegate, // Converts |point| from |source|'s coordinates to |target|'s. If |source| is // nullptr, the function returns without modifying |point|. |target| cannot be - // nullptr. + // nullptr. Use layers' target transform in coordinate conversions. The target + // transform is the end value of a transform animation. If there is no + // animation ongoing, the target transform is the same as the current + // transform. static void ConvertPointToTarget(const Window* source, const Window* target, gfx::PointF* point); @@ -407,7 +433,7 @@ class AURA_EXPORT Window : public ui::LayerDelegate, // intercepted. Returns a ScopedKeyboardHook instance which stops capturing // system key events when destroyed. std::unique_ptr<ScopedKeyboardHook> CaptureSystemKeyEvents( - base::Optional<base::flat_set<ui::DomCode>> codes); + absl::optional<base::flat_set<ui::DomCode>> codes); // NativeWidget::[GS]etNativeWindowProperty use strings as keys, and this is // difficult to change while retaining compatibility with other platforms. @@ -462,7 +488,7 @@ class AURA_EXPORT Window : public ui::LayerDelegate, // has allocated one. Also sets child sequence number component of the // viz::LocalSurfaceId allocator. void UpdateLocalSurfaceIdFromEmbeddedClient( - const base::Optional<viz::LocalSurfaceId>& local_surface_id); + const absl::optional<viz::LocalSurfaceId>& local_surface_id); // Returns the FrameSinkId. In LOCAL mode, this returns a valid FrameSinkId // only if a LayerTreeFrameSink has been created. In MUS mode, this always @@ -489,7 +515,7 @@ class AURA_EXPORT Window : public ui::LayerDelegate, bool RequiresDoubleTapGestureEvents() const override; // Returns |state| as a string. This is generally only useful for debugging. - static const char* OcclusionStateToString(OcclusionState state); + static const std::u16string OcclusionStateToString(OcclusionState state); // Sets the regions of this window to consider opaque when computing the // occlusion of underneath windows. Opaque regions can only be set for a @@ -552,9 +578,9 @@ class AURA_EXPORT Window : public ui::LayerDelegate, // Changes the bounds of the window without condition. void SetBoundsInternal(const gfx::Rect& new_bounds); - // Updates the visible state of the layer, but does not make visible-state - // specific changes. Called from Show()/Hide(). - void SetVisible(bool visible); + // Updates the visible state of the layer and the Window, but does not make + // visible-state specific changes. Called from Show()/Hide(). + void SetVisibleInternal(bool visible); // Updates the occlusion info of the window. void SetOcclusionInfo(OcclusionState occlusion_state, @@ -663,6 +689,27 @@ class AURA_EXPORT Window : public ui::LayerDelegate, // to make this non-root window capturable by the FrameSinkVideoCapturer. void OnScopedWindowCaptureRequestRemoved(); + // The following are intended for use by the metadata to access the internals + // of instances of this class. At some point they should be moved to the + // public section and code refactored to use them. + + // Break out the separate elements of the Window bounds. + int GetHeight() const; + int GetWidth() const; + int GetX() const; + int GetY() const; + void SetHeight(int height); + void SetWidth(int width); + void SetX(int x); + void SetY(int y); + + bool GetCapture() const; + + viz::SurfaceId GetSurfaceId() const; + + bool GetVisible() const; + void SetVisible(bool visible); + // Bounds of this window relative to the parent. This is cached as the bounds // of the Layer and Window are not necessarily the same. In particular bounds // of the Layer are relative to the first ancestor with a Layer, where as this diff --git a/chromium/ui/aura/window_event_dispatcher.cc b/chromium/ui/aura/window_event_dispatcher.cc index 9eddddd0499..11e99e357df 100644 --- a/chromium/ui/aura/window_event_dispatcher.cc +++ b/chromium/ui/aura/window_event_dispatcher.cc @@ -60,6 +60,8 @@ bool IsEventCandidateForHold(const ui::Event& event) { return true; if (event.type() == ui::ET_MOUSE_DRAGGED) return true; + if (event.type() == ui::ET_MOUSE_EXITED) + return false; if (event.IsMouseEvent() && (event.flags() & ui::EF_IS_SYNTHESIZED)) return true; return false; diff --git a/chromium/ui/aura/window_event_dispatcher_unittest.cc b/chromium/ui/aura/window_event_dispatcher_unittest.cc index 8b05ebc4c55..43445b5c0fa 100644 --- a/chromium/ui/aura/window_event_dispatcher_unittest.cc +++ b/chromium/ui/aura/window_event_dispatcher_unittest.cc @@ -296,10 +296,10 @@ class TestEventClient : public client::EventClient { client::SetEventClient(root_window_, this); Window* lock_window = test::CreateTestWindowWithBounds(root_window_->bounds(), root_window_); - lock_window->set_id(kLockWindowId); + lock_window->SetId(kLockWindowId); Window* non_lock_window = test::CreateTestWindowWithBounds(root_window_->bounds(), root_window_); - non_lock_window->set_id(kNonLockWindowId); + non_lock_window->SetId(kNonLockWindowId); } ~TestEventClient() override { client::SetEventClient(root_window_, NULL); } @@ -348,10 +348,10 @@ TEST_F(WindowEventDispatcherTest, GetCanProcessEventsWithinSubtree) { Window* w1 = test::CreateTestWindowWithBounds(gfx::Rect(10, 10, 20, 20), client.GetNonLockWindow()); - w1->set_id(1); + w1->SetId(1); Window* w2 = test::CreateTestWindowWithBounds(gfx::Rect(30, 30, 20, 20), client.GetNonLockWindow()); - w2->set_id(2); + w2->SetId(2); std::unique_ptr<Window> w3(test::CreateTestWindowWithDelegate( &d, 3, gfx::Rect(30, 30, 20, 20), client.GetLockWindow())); @@ -975,6 +975,35 @@ TEST_F(WindowEventDispatcherTest, DispatchMouseExitWhenHidingWindow) { window->RemovePreTargetHandler(&recorder); } +TEST_F(WindowEventDispatcherTest, HeldMovesDispatchMouseExitWhenHidingWindow) { + EventFilterRecorder recorder; + + test::TestWindowDelegate delegate; + std::unique_ptr<aura::Window> window(CreateTestWindowWithDelegate( + &delegate, 1, gfx::Rect(10, 10, 50, 50), root_window())); + window->Show(); + window->AddPreTargetHandler(&recorder); + + // Dispatch a mouse move event into the window. + const gfx::Point event_location(22, 33); + ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location, + ui::EventTimeForNow(), 0, 0); + DispatchEventUsingWindowDispatcher(&mouse); + EXPECT_FALSE(recorder.events().empty()); + recorder.Reset(); + + // Hide the window and verify a mouse exit event's location. + host()->dispatcher()->HoldPointerMoves(); + window->Hide(); + host()->dispatcher()->ReleasePointerMoves(); + EXPECT_FALSE(recorder.events().empty()); + EXPECT_EQ("MOUSE_EXITED", EventTypesToString(recorder.events())); + ASSERT_EQ(1u, recorder.mouse_locations().size()); + EXPECT_EQ(gfx::Point(12, 23).ToString(), + recorder.mouse_locations()[0].ToString()); + window->RemovePreTargetHandler(&recorder); +} + // Tests that a mouse-exit event is not synthesized during shutdown. TEST_F(WindowEventDispatcherTest, NoMouseExitInShutdown) { EventFilterRecorder recorder; diff --git a/chromium/ui/aura/window_observer.h b/chromium/ui/aura/window_observer.h index c2ce7a6d141..d893c9345b1 100644 --- a/chromium/ui/aura/window_observer.h +++ b/chromium/ui/aura/window_observer.h @@ -5,7 +5,6 @@ #ifndef UI_AURA_WINDOW_OBSERVER_H_ #define UI_AURA_WINDOW_OBSERVER_H_ -#include <string> #include "base/observer_list_types.h" #include "ui/aura/aura_export.h" diff --git a/chromium/ui/aura/window_occlusion_tracker.cc b/chromium/ui/aura/window_occlusion_tracker.cc index 07a1f10402a..c4c5f71dff7 100644 --- a/chromium/ui/aura/window_occlusion_tracker.cc +++ b/chromium/ui/aura/window_occlusion_tracker.cc @@ -14,6 +14,7 @@ #include "ui/aura/env.h" #include "ui/aura/window_occlusion_change_builder.h" #include "ui/aura/window_tree_host.h" +#include "ui/compositor/layer.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/skia_util.h" #include "ui/gfx/transform.h" @@ -260,7 +261,7 @@ bool WindowOcclusionTracker::OcclusionStatesMatch( const base::flat_map<Window*, OcclusionData>& tracked_windows) { for (const auto& tracked_window : tracked_windows) { if (tracked_window.second.occlusion_state != - tracked_window.first->occlusion_state()) + tracked_window.first->GetOcclusionState()) return false; } return true; @@ -345,7 +346,7 @@ void WindowOcclusionTracker::MaybeComputeOcclusion() { } // Sanity check: Occlusion states in |tracked_windows_| should match those - // returned by Window::occlusion_state(). + // returned by Window::GetOcclusionState(). DCHECK(OcclusionStatesMatch(tracked_windows_)); } @@ -449,7 +450,7 @@ bool WindowOcclusionTracker::VisibleWindowCanOccludeOtherWindows( : window->layer()->background_color(); combined_opacity *= SkColorGetA(color) / 255.f; } - return (!window->transparent() && WindowHasContent(window) && + return (!window->GetTransparent() && WindowHasContent(window) && combined_opacity == 1.0f && // For simplicity, a shaped window is not considered opaque. !WindowOrParentHasShape(window)) || @@ -655,7 +656,7 @@ bool WindowOcclusionTracker::WindowOrDescendantCanOccludeOtherWindows( WindowIsAnimated(window)) { return false; } - if ((!window->transparent() && WindowHasContent(window)) || + if ((!window->GetTransparent() && WindowHasContent(window)) || WindowHasOpaqueRegionsForOcclusion(window)) { return true; } diff --git a/chromium/ui/aura/window_occlusion_tracker.h b/chromium/ui/aura/window_occlusion_tracker.h index 70a6477489a..19bdb1d2a49 100644 --- a/chromium/ui/aura/window_occlusion_tracker.h +++ b/chromium/ui/aura/window_occlusion_tracker.h @@ -174,7 +174,7 @@ class AURA_EXPORT WindowOcclusionTracker : public ui::LayerAnimationObserver, ~WindowOcclusionTracker() override; // Returns true iff the occlusion states in |tracked_windows| match those - // returned by Window::occlusion_state(). + // returned by Window::GetOcclusionState(). static bool OcclusionStatesMatch( const base::flat_map<Window*, OcclusionData>& tracked_windows); diff --git a/chromium/ui/aura/window_occlusion_tracker_unittest.cc b/chromium/ui/aura/window_occlusion_tracker_unittest.cc index a8ecbcf2a62..63607894c63 100644 --- a/chromium/ui/aura/window_occlusion_tracker_unittest.cc +++ b/chromium/ui/aura/window_occlusion_tracker_unittest.cc @@ -19,6 +19,7 @@ #include "ui/aura/test/window_occlusion_tracker_test_api.h" #include "ui/aura/window_observer.h" #include "ui/base/ui_base_features.h" +#include "ui/compositor/layer.h" #include "ui/compositor/layer_animation_observer.h" #include "ui/compositor/layer_animation_sequence.h" #include "ui/compositor/layer_animator.h" @@ -2411,7 +2412,7 @@ TEST_F(WindowOcclusionTrackerTest, ScopedForceVisibleHiddenContainer) { EXPECT_FALSE(browser_delegate->is_expecting_call()); EXPECT_FALSE(webcontents_delegate->is_expecting_call()); - EXPECT_EQ(Window::OcclusionState::VISIBLE, webcontents->occlusion_state()); + EXPECT_EQ(Window::OcclusionState::VISIBLE, webcontents->GetOcclusionState()); EXPECT_TRUE(webcontents->TargetVisibility()); container_delegate->set_expectation(Window::OcclusionState::VISIBLE); diff --git a/chromium/ui/aura/window_targeter.cc b/chromium/ui/aura/window_targeter.cc index 46e718a7943..facae72bf56 100644 --- a/chromium/ui/aura/window_targeter.cc +++ b/chromium/ui/aura/window_targeter.cc @@ -14,6 +14,7 @@ #include "ui/aura/window_delegate.h" #include "ui/aura/window_event_dispatcher.h" #include "ui/aura/window_tree_host.h" +#include "ui/compositor/layer.h" #include "ui/display/display.h" #include "ui/display/screen.h" #include "ui/events/event_target.h" diff --git a/chromium/ui/aura/window_targeter_unittest.cc b/chromium/ui/aura/window_targeter_unittest.cc index f4e6b465f59..6dc411c5b95 100644 --- a/chromium/ui/aura/window_targeter_unittest.cc +++ b/chromium/ui/aura/window_targeter_unittest.cc @@ -11,6 +11,7 @@ #include "ui/aura/test/aura_test_base.h" #include "ui/aura/test/test_window_delegate.h" #include "ui/aura/window.h" +#include "ui/compositor/layer.h" #include "ui/display/display.h" #include "ui/display/screen.h" #include "ui/events/event_utils.h" @@ -217,7 +218,7 @@ class IdCheckingEventTargeter : public WindowTargeter { // WindowTargeter: bool SubtreeShouldBeExploredForEvent(Window* window, const ui::LocatedEvent& event) override { - return (window->id() == id_ && + return (window->GetId() == id_ && WindowTargeter::SubtreeShouldBeExploredForEvent(window, event)); } diff --git a/chromium/ui/aura/window_tree_host.cc b/chromium/ui/aura/window_tree_host.cc index 6faeee8d7eb..bcb66b25eb8 100644 --- a/chromium/ui/aura/window_tree_host.cc +++ b/chromium/ui/aura/window_tree_host.cc @@ -310,7 +310,7 @@ void WindowTreeHost::Hide() { } std::unique_ptr<ScopedKeyboardHook> WindowTreeHost::CaptureSystemKeyEvents( - base::Optional<base::flat_set<ui::DomCode>> dom_codes) { + absl::optional<base::flat_set<ui::DomCode>> dom_codes) { // TODO(joedow): Remove the simple hook class/logic once this flag is removed. if (!base::FeatureList::IsEnabled(features::kSystemKeyboardLock)) return std::make_unique<ScopedSimpleKeyboardHook>(std::move(dom_codes)); diff --git a/chromium/ui/aura/window_tree_host.h b/chromium/ui/aura/window_tree_host.h index 93c56f7ffbc..65644909583 100644 --- a/chromium/ui/aura/window_tree_host.h +++ b/chromium/ui/aura/window_tree_host.h @@ -15,9 +15,9 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" -#include "base/optional.h" #include "build/build_config.h" #include "components/viz/common/surfaces/frame_sink_id.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/aura/aura_export.h" #include "ui/aura/scoped_enable_unadjusted_mouse_events.h" #include "ui/aura/window.h" @@ -220,7 +220,7 @@ class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate, // intercepted. Returns a ScopedKeyboardHook instance which stops capturing // system key events when destroyed. std::unique_ptr<ScopedKeyboardHook> CaptureSystemKeyEvents( - base::Optional<base::flat_set<ui::DomCode>> codes); + absl::optional<base::flat_set<ui::DomCode>> codes); // Returns a map of KeyboardEvent code to KeyboardEvent key values. virtual base::flat_map<std::string, std::string> GetKeyboardLayoutMap() = 0; @@ -307,7 +307,7 @@ class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate, // Begins capturing system key events. Returns true if successful. virtual bool CaptureSystemKeyEventsImpl( - base::Optional<base::flat_set<ui::DomCode>> dom_codes) = 0; + absl::optional<base::flat_set<ui::DomCode>> dom_codes) = 0; // Stops capturing system keyboard events. virtual void ReleaseSystemKeyEventCapture() = 0; diff --git a/chromium/ui/aura/window_tree_host_platform.cc b/chromium/ui/aura/window_tree_host_platform.cc index 6025626d122..9b9a303a750 100644 --- a/chromium/ui/aura/window_tree_host_platform.cc +++ b/chromium/ui/aura/window_tree_host_platform.cc @@ -4,6 +4,7 @@ #include "ui/aura/window_tree_host_platform.h" +#include <memory> #include <utility> #include "base/bind.h" @@ -92,7 +93,7 @@ void WindowTreeHostPlatform::CreateAndSetPlatformWindow( #endif NOTREACHED(); #elif defined(OS_WIN) - platform_window_.reset(new ui::WinWindow(this, properties.bounds)); + platform_window_ = std::make_unique<ui::WinWindow>(this, properties.bounds); #else NOTIMPLEMENTED(); #endif @@ -150,7 +151,7 @@ void WindowTreeHostPlatform::ReleaseCapture() { } bool WindowTreeHostPlatform::CaptureSystemKeyEventsImpl( - base::Optional<base::flat_set<ui::DomCode>> dom_codes) { + absl::optional<base::flat_set<ui::DomCode>> dom_codes) { // Only one KeyboardHook should be active at a time, otherwise there will be // problems with event routing (i.e. which Hook takes precedence) and // destruction ordering. diff --git a/chromium/ui/aura/window_tree_host_platform.h b/chromium/ui/aura/window_tree_host_platform.h index 60d5129bdb9..dd2a8f40076 100644 --- a/chromium/ui/aura/window_tree_host_platform.h +++ b/chromium/ui/aura/window_tree_host_platform.h @@ -81,7 +81,7 @@ class AURA_EXPORT WindowTreeHostPlatform : public WindowTreeHost, // Overridden from aura::WindowTreeHost: bool CaptureSystemKeyEventsImpl( - base::Optional<base::flat_set<ui::DomCode>> dom_codes) override; + absl::optional<base::flat_set<ui::DomCode>> dom_codes) override; void ReleaseSystemKeyEventCapture() override; bool IsKeyLocked(ui::DomCode dom_code) override; base::flat_map<std::string, std::string> GetKeyboardLayoutMap() override; diff --git a/chromium/ui/aura/window_unittest.cc b/chromium/ui/aura/window_unittest.cc index a30c5ee18b0..69af357e341 100644 --- a/chromium/ui/aura/window_unittest.cc +++ b/chromium/ui/aura/window_unittest.cc @@ -39,6 +39,7 @@ #include "ui/aura/window_tree_host.h" #include "ui/base/class_property.h" #include "ui/base/hit_test.h" +#include "ui/compositor/compositor_observer.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_animation_observer.h" #include "ui/compositor/layer_animator.h" @@ -96,6 +97,72 @@ class DeletionTracker { DISALLOW_COPY_AND_ASSIGN(DeletionTracker); }; +// The helper class to wait for the animation completion and run callbacks. +class LayerTranslationAnimationNotifier : public ui::CompositorObserver { + public: + using AnimationCallback = + base::RepeatingCallback<void(const gfx::Transform&)>; + + LayerTranslationAnimationNotifier( + ui::Layer* animation_layer, + const gfx::Transform& initial_transform_, + const gfx::Transform& target_transform, + AnimationCallback animation_start_callback, + AnimationCallback animation_end_callback, + AnimationCallback animation_progress_callback) + : animation_layer_(animation_layer), + initial_transform_(initial_transform_), + target_transform_(target_transform), + animation_start_callback_(animation_start_callback), + animation_end_callback_(animation_end_callback), + animation_progress_callback_(animation_progress_callback) { + animation_layer_->GetCompositor()->AddObserver(this); + } + LayerTranslationAnimationNotifier(const LayerTranslationAnimationNotifier&) = + delete; + LayerTranslationAnimationNotifier& operator=( + const LayerTranslationAnimationNotifier&) = delete; + ~LayerTranslationAnimationNotifier() override { + animation_layer_->GetCompositor()->RemoveObserver(this); + } + + void WaitForAnimationCompletion() { run_loop_.Run(); } + + // ui::CompositorObserver: + void OnCompositingDidCommit(ui::Compositor* compositor) override { + const gfx::Transform current_transform = animation_layer_->transform(); + if (current_transform == initial_transform_) { + animation_start_callback_.Run(current_transform); + } else if (current_transform == target_transform_) { + animation_end_callback_.Run(current_transform); + run_loop_.Quit(); + } else { + animation_progress_callback_.Run(current_transform); + } + } + + private: + // The layer to be animated. + ui::Layer* const animation_layer_; + + // The initial transform. + gfx::Transform initial_transform_; + + // The target transform. + gfx::Transform target_transform_; + + // The callback to run at the start of the animation. + AnimationCallback animation_start_callback_; + + // The callback to run at the end of the animation. + AnimationCallback animation_end_callback_; + + // The callback to run during the progress of the animation. + AnimationCallback animation_progress_callback_; + + base::RunLoop run_loop_; +}; + class DeletionTestProperty { public: explicit DeletionTestProperty(DeletionTracker* tracker) : tracker_(tracker) {} @@ -793,13 +860,13 @@ TEST_F(WindowTest, StackChildBelow) { parent.Init(ui::LAYER_NOT_DRAWN); Window child1(nullptr); child1.Init(ui::LAYER_NOT_DRAWN); - child1.set_id(1); + child1.SetId(1); Window child2(nullptr); child2.Init(ui::LAYER_NOT_DRAWN); - child2.set_id(2); + child2.SetId(2); Window child3(nullptr); child3.Init(ui::LAYER_NOT_DRAWN); - child3.set_id(3); + child3.SetId(3); parent.AddChild(&child1); parent.AddChild(&child2); @@ -1968,7 +2035,7 @@ class WindowObserverTest : public WindowTest, void OnWindowVisibilityChanged(Window* window, bool visible) override { if (!visibility_info_) { - visibility_info_.reset(new VisibilityInfo); + visibility_info_ = std::make_unique<VisibilityInfo>(); visibility_info_->changed_count = 0; } visibility_info_->window_visible = window->IsVisible(); @@ -2425,7 +2492,7 @@ TEST_F(WindowTest, RecreateLayer) { // Set properties to non default values. gfx::Rect window_bounds(100, 100); Window w(new ColorTestWindowDelegate(SK_ColorWHITE)); - w.set_id(1); + w.SetId(1); w.Init(ui::LAYER_SOLID_COLOR); w.SetBounds(window_bounds); @@ -2699,7 +2766,7 @@ TEST_F(WindowTest, RootWindowAttachment) { observer.Clear(); // Test an indirect add/remove from the RootWindow. - w1.reset(new Window(nullptr)); + w1 = std::make_unique<Window>(nullptr); w1->Init(ui::LAYER_NOT_DRAWN); Window* w11 = new Window(nullptr); w11->Init(ui::LAYER_NOT_DRAWN); @@ -2720,7 +2787,7 @@ TEST_F(WindowTest, RootWindowAttachment) { observer.Clear(); // Test an indirect add/remove with nested observers. - w1.reset(new Window(nullptr)); + w1 = std::make_unique<Window>(nullptr); w1->Init(ui::LAYER_NOT_DRAWN); w11 = new Window(nullptr); w11->Init(ui::LAYER_NOT_DRAWN); @@ -3511,6 +3578,113 @@ TEST_F(WindowTest, CleanupGestureStateDeleteOtherWindows) { child2.reset(); } +class WindowActualScreenBoundsTest + : public WindowTest, + public testing::WithParamInterface< + /*is_target_transform_identical*/ bool> { + public: + WindowActualScreenBoundsTest() = default; + WindowActualScreenBoundsTest(const WindowActualScreenBoundsTest&) = delete; + WindowActualScreenBoundsTest& operator=(const WindowActualScreenBoundsTest&) = + delete; + ~WindowActualScreenBoundsTest() override = default; + + // WindowTest: + void SetUp() override { + WindowTest::SetUp(); + viewport_ = std::unique_ptr<Window>(CreateTestWindowWithBounds( + gfx::Rect(/*x=*/100, /*y=*/50, /*width=*/200, /*height=*/200), + root_window())); + child_ = std::unique_ptr<Window>(CreateTestWindowWithBounds( + gfx::Rect(/*x=*/0, /*y=*/0, /*width=*/100, /*height*/ 100), + viewport_.get())); + } + + void TearDown() override { + child_.reset(); + viewport_.reset(); + WindowTest::TearDown(); + } + + void OnTranslationAnimationStarted(const gfx::Transform& transform) const { + EXPECT_EQ("100,50 100x100", child_->GetActualBoundsInScreen().ToString()); + EXPECT_EQ("50,0 100x100", child_->GetBoundsInScreen().ToString()); + } + + void OnTranslationAnimationEnded(const gfx::Transform& transform) const { + EXPECT_EQ("50,0 100x100", child_->GetActualBoundsInScreen().ToString()); + EXPECT_EQ("50,0 100x100", child_->GetBoundsInScreen().ToString()); + } + + void OnTranslationAnimationProgressed(const gfx::Rect& child_initial_bounds, + const gfx::Transform& transform) const { + gfx::RectF current_screen_bounds(child_initial_bounds); + transform.TransformRect(¤t_screen_bounds); + EXPECT_EQ(gfx::ToEnclosedRect(current_screen_bounds), + child_->GetActualBoundsInScreen()); + } + + std::unique_ptr<Window> viewport_; + std::unique_ptr<Window> child_; +}; + +INSTANTIATE_TEST_SUITE_P(All, WindowActualScreenBoundsTest, testing::Bool()); + +// Verifies that the function to get the window's screen bounds works as +// expected during layer animation. +TEST_P(WindowActualScreenBoundsTest, VerifyWindowActualBoundsDuringAnimation) { + ui::ScopedAnimationDurationScaleMode test_duration_mode( + ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); + + auto* viewport_layer = viewport_->layer(); + gfx::Transform initial_transform; + gfx::Transform target_transform; + gfx::Rect child_initial_bounds; + if (GetParam()) { + // Test in the scenario where the target transform is identical. + + // Set the target bounds. + viewport_->SetBounds( + gfx::Rect(/*x=*/50, /*y=*/0, /*width=*/200, /*height=*/200)); + + // Set the transform to reverse the effect brought by bounds setting. + initial_transform.Translate(50, 50); + viewport_->layer()->SetTransform(initial_transform); + + // Trigger the translation animation. + ui::ScopedLayerAnimationSettings settings(viewport_layer->GetAnimator()); + viewport_layer->SetTransform(target_transform); + + // Calculate the child's initial screen bounds manually. + child_initial_bounds = + gfx::Rect(/*x=*/50, /*y=*/0, /*width=*/100, /*height=*/100); + } else { + // Test in the scenario where the target transform is non-identical. + + // Trigger the translation animation. + ui::ScopedLayerAnimationSettings settings(viewport_layer->GetAnimator()); + target_transform.Translate(-50, -50); + viewport_layer->SetTransform(target_transform); + + // Calculate the child's initial screen bounds manually. + child_initial_bounds = + gfx::Rect(/*x=*/100, /*y=*/50, /*width=*/100, /*height=*/100); + } + + LayerTranslationAnimationNotifier bounds_checker( + viewport_layer, initial_transform, target_transform, + base::BindRepeating( + &WindowActualScreenBoundsTest::OnTranslationAnimationStarted, + base::Unretained(this)), + base::BindRepeating( + &WindowActualScreenBoundsTest::OnTranslationAnimationEnded, + base::Unretained(this)), + base::BindRepeating( + &WindowActualScreenBoundsTest::OnTranslationAnimationProgressed, + base::Unretained(this), child_initial_bounds)); + bounds_checker.WaitForAnimationCompletion(); +} + } // namespace } // namespace test } // namespace aura |