1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777 |
- // Copyright (c) 2012 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.h"
- #include <stddef.h>
- #include <algorithm>
- #include <utility>
- #include "base/bind.h"
- #include "base/callback.h"
- #include "base/callback_helpers.h"
- #include "base/containers/adapters.h"
- #include "base/containers/contains.h"
- #include "base/logging.h"
- #include "base/memory/raw_ptr.h"
- #include "base/observer_list.h"
- #include "base/strings/string_number_conversions.h"
- #include "base/strings/string_util.h"
- #include "base/strings/stringprintf.h"
- #include "cc/mojo_embedder/async_layer_tree_frame_sink.h"
- #include "cc/trees/layer_tree_frame_sink.h"
- #include "components/viz/common/features.h"
- #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
- #include "components/viz/host/host_frame_sink_manager.h"
- #include "mojo/public/cpp/bindings/pending_receiver.h"
- #include "mojo/public/cpp/bindings/pending_remote.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"
- #include "ui/aura/client/event_client.h"
- #include "ui/aura/client/focus_client.h"
- #include "ui/aura/client/screen_position_client.h"
- #include "ui/aura/client/visibility_client.h"
- #include "ui/aura/client/window_stacking_client.h"
- #include "ui/aura/env.h"
- #include "ui/aura/layout_manager.h"
- #include "ui/aura/scoped_keyboard_hook.h"
- #include "ui/aura/window_delegate.h"
- #include "ui/aura/window_event_dispatcher.h"
- #include "ui/aura/window_observer.h"
- #include "ui/aura/window_occlusion_tracker.h"
- #include "ui/aura/window_targeter.h"
- #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"
- #include "ui/compositor/layer_animator.h"
- #include "ui/display/display.h"
- #include "ui/display/screen.h"
- #include "ui/events/event_target_iterator.h"
- #include "ui/events/keycodes/dom/dom_code.h"
- #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";
- class ScopedCursorHider {
- public:
- explicit ScopedCursorHider(Window* window)
- : window_(window), hid_cursor_(false) {
- if (!window_->IsRootWindow())
- return;
- const bool cursor_is_in_bounds = window_->GetBoundsInScreen().Contains(
- Env::GetInstance()->last_mouse_location());
- client::CursorClient* cursor_client = client::GetCursorClient(window_);
- if (cursor_is_in_bounds && cursor_client &&
- cursor_client->IsCursorVisible()) {
- cursor_client->HideCursor();
- hid_cursor_ = true;
- }
- }
- ScopedCursorHider(const ScopedCursorHider&) = delete;
- ScopedCursorHider& operator=(const ScopedCursorHider&) = delete;
- ~ScopedCursorHider() {
- if (!window_->IsRootWindow())
- return;
- // Update the device scale factor of the cursor client only when the last
- // mouse location is on this root window.
- if (hid_cursor_) {
- client::CursorClient* cursor_client = client::GetCursorClient(window_);
- if (cursor_client) {
- const display::Display& display =
- display::Screen::GetScreen()->GetDisplayNearestWindow(window_);
- cursor_client->SetDisplay(display);
- cursor_client->ShowCursor();
- }
- }
- }
- private:
- raw_ptr<Window> window_;
- bool hid_cursor_;
- };
- } // namespace
- Window::Window(WindowDelegate* delegate, client::WindowType type)
- : type_(type),
- delegate_(delegate),
- event_targeting_policy_(
- aura::EventTargetingPolicy::kTargetAndDescendants),
- restore_event_targeting_policy_(
- aura::EventTargetingPolicy::kTargetAndDescendants),
- // Don't notify newly added observers during notification. This causes
- // problems for code that adds an observer as part of an observer
- // notification (such as the workspace code).
- observers_(base::ObserverListPolicy::EXISTING_ONLY) {
- SetTargetHandler(delegate_);
- }
- Window::~Window() {
- is_destroying_ = true;
- WindowOcclusionTracker::ScopedPause pause_occlusion_tracking;
- if (layer()->owner() == this)
- layer()->CompleteAllAnimations();
- // Let the delegate know we're in the processing of destroying.
- if (delegate_)
- delegate_->OnWindowDestroying(this);
- for (WindowObserver& observer : observers_)
- observer.OnWindowDestroying(this);
- // While we are being destroyed, our target handler may also be in the
- // process of destruction or already destroyed, so do not forward any
- // input events at the ui::EP_TARGET phase.
- SetTargetHandler(nullptr);
- // TODO(beng): See comment in window_event_dispatcher.h. This shouldn't be
- // necessary but unfortunately is right now due to ordering
- // peculiarities. WED must be notified _after_ other observers
- // are notified of pending teardown but before the hierarchy
- // is actually torn down.
- WindowTreeHost* host = GetHost();
- if (host)
- host->dispatcher()->OnPostNotifiedWindowDestroying(this);
- // The window should have already had its state cleaned up in
- // WindowEventDispatcher::OnWindowHidden(), but there have been some crashes
- // involving windows being destroyed without being hidden first. See
- // crbug.com/342040. This should help us debug the issue. TODO(tdresser):
- // remove this once we determine why we have windows that are destroyed
- // without being hidden.
- bool window_incorrectly_cleaned_up = CleanupGestureState();
- CHECK(!window_incorrectly_cleaned_up);
- // Then destroy the children.
- RemoveOrDestroyChildren();
- // The window needs to be removed from the parent before calling the
- // WindowDestroyed callbacks of delegate and the observers.
- if (parent_)
- parent_->RemoveChild(this);
- if (delegate_)
- delegate_->OnWindowDestroyed(this);
- for (WindowObserver& observer : observers_) {
- RemoveObserver(&observer);
- observer.OnWindowDestroyed(this);
- }
- // Delete the LayoutManager before properties. This way if the LayoutManager
- // depends upon properties existing the properties are still valid.
- layout_manager_.reset();
- ClearProperties();
- // The layer will either be destroyed by |layer_owner_|'s dtor, or by whoever
- // acquired it.
- layer()->set_delegate(nullptr);
- DestroyLayer();
- // If SetEmbedFrameSinkId() was called by client code, then we assume client
- // code is taking care of invalidating.
- if (frame_sink_id_.is_valid() && !embeds_external_client_) {
- auto* context_factory = Env::GetInstance()->context_factory();
- auto* host_frame_sink_manager = context_factory->GetHostFrameSinkManager();
- host_frame_sink_manager->InvalidateFrameSinkId(frame_sink_id_);
- }
- }
- void Window::Init(ui::LayerType layer_type) {
- WindowOcclusionTracker::ScopedPause pause_occlusion_tracking;
- SetLayer(std::make_unique<ui::Layer>(layer_type));
- layer()->SetVisible(false);
- layer()->set_delegate(this);
- UpdateLayerName();
- layer()->SetFillsBoundsOpaquely(!transparent_);
- 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 {
- std::string* name = GetProperty(client::kNameKey);
- return name ? *name : base::EmptyString();
- }
- void Window::SetName(const std::string& name) {
- if (name == GetName())
- return;
- SetProperty(client::kNameKey, name);
- if (layer())
- UpdateLayerName();
- TriggerChangedCallback(client::kNameKey);
- }
- const std::u16string& Window::GetTitle() const {
- std::u16string* title = GetProperty(client::kTitleKey);
- return title ? *title : base::EmptyString16();
- }
- void Window::SetTitle(const std::u16string& title) {
- if (title == GetTitle())
- return;
- SetProperty(client::kTitleKey, title);
- for (WindowObserver& observer : observers_)
- 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) {
- layer()->SetFillsBoundsCompletely(fills_bounds);
- }
- Window* Window::GetRootWindow() {
- return const_cast<Window*>(
- static_cast<const Window*>(this)->GetRootWindow());
- }
- const Window* Window::GetRootWindow() const {
- return IsRootWindow() ? this : parent_ ? parent_->GetRootWindow() : nullptr;
- }
- WindowTreeHost* Window::GetHost() {
- return const_cast<WindowTreeHost*>(const_cast<const Window*>(this)->
- GetHost());
- }
- const WindowTreeHost* Window::GetHost() const {
- const Window* root_window = GetRootWindow();
- return root_window ? root_window->host_.get() : nullptr;
- }
- void Window::Show() {
- DCHECK_EQ(visible_, layer()->GetTargetVisibility());
- // It is not allowed that a window is visible but the layers alpha is fully
- // transparent since the window would still be considered to be active but
- // could not be seen.
- DCHECK(!visible_ || layer()->GetTargetOpacity() > 0.0f);
- SetVisibleInternal(true);
- }
- void Window::Hide() {
- // RootWindow::OnVisibilityChanged will call ReleaseCapture.
- SetVisibleInternal(false);
- }
- bool Window::IsVisible() const {
- // Layer visibility can be inconsistent with window visibility, for example
- // when a Window is hidden, we want this function to return false immediately
- // after, even though the client may decide to animate the hide effect (and
- // so the layer will be visible for some time after Hide() is called).
- 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.";
- return ScopedWindowCaptureRequest(this);
- }
- gfx::Rect Window::GetBoundsInRootWindow() const {
- if (!GetRootWindow())
- return bounds();
- gfx::Rect bounds_in_root(bounds().size());
- ConvertRectToTarget(this, GetRootWindow(), &bounds_in_root);
- 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();
- if (root) {
- aura::client::ScreenPositionClient* screen_position_client =
- aura::client::GetScreenPositionClient(root);
- if (screen_position_client) {
- gfx::Point origin = bounds.origin();
- screen_position_client->ConvertPointToScreen(root, &origin);
- bounds.set_origin(origin);
- }
- }
- 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_)
- observer.OnWindowTargetTransformChanging(this, transform);
- layer()->SetTransform(transform);
- }
- void Window::SetLayoutManager(LayoutManager* layout_manager) {
- if (layout_manager == layout_manager_.get())
- return;
- layout_manager_.reset(layout_manager);
- if (!layout_manager)
- return;
- // If we're changing to a new layout manager, ensure it is aware of all the
- // existing child windows.
- for (Windows::const_iterator it = children_.begin();
- it != children_.end();
- ++it)
- layout_manager_->OnWindowAddedToLayout(*it);
- }
- std::unique_ptr<WindowTargeter> Window::SetEventTargeter(
- std::unique_ptr<WindowTargeter> targeter) {
- std::unique_ptr<WindowTargeter> old_targeter = std::move(targeter_);
- if (old_targeter)
- old_targeter->OnInstalled(nullptr);
- targeter_ = std::move(targeter);
- if (targeter_)
- targeter_->OnInstalled(this);
- return old_targeter;
- }
- void Window::SetBounds(const gfx::Rect& new_bounds) {
- if (parent_ && parent_->layout_manager()) {
- parent_->layout_manager()->SetChildBounds(this, new_bounds);
- } else {
- // Ensure we don't go smaller than our minimum bounds.
- gfx::Rect final_bounds(new_bounds);
- if (delegate_) {
- const gfx::Size& min_size = delegate_->GetMinimumSize();
- final_bounds.set_width(std::max(min_size.width(), final_bounds.width()));
- final_bounds.set_height(std::max(min_size.height(),
- final_bounds.height()));
- }
- SetBoundsInternal(final_bounds);
- }
- }
- void Window::SetBoundsInScreen(const gfx::Rect& new_bounds_in_screen,
- const display::Display& dst_display) {
- aura::client::ScreenPositionClient* screen_position_client = nullptr;
- Window* root = GetRootWindow();
- if (root)
- screen_position_client = aura::client::GetScreenPositionClient(root);
- if (screen_position_client)
- screen_position_client->SetBounds(this, new_bounds_in_screen, dst_display);
- else
- SetBounds(new_bounds_in_screen);
- }
- gfx::Rect Window::GetTargetBounds() const {
- return layer() ? layer()->GetTargetBounds() : bounds();
- }
- void Window::ScheduleDraw() {
- layer()->ScheduleDraw();
- }
- void Window::SchedulePaintInRect(const gfx::Rect& rect) {
- layer()->SchedulePaint(rect);
- }
- void Window::StackChildAtTop(Window* child) {
- if (children_.size() <= 1 || child == children_.back())
- return; // In the front already.
- StackChildAbove(child, children_.back());
- }
- void Window::StackChildAbove(Window* child, Window* target) {
- StackChildRelativeTo(child, target, STACK_ABOVE);
- }
- void Window::StackChildAtBottom(Window* child) {
- if (children_.size() <= 1 || child == children_.front())
- return; // At the bottom already.
- StackChildBelow(child, children_.front());
- }
- void Window::StackChildBelow(Window* child, Window* target) {
- StackChildRelativeTo(child, target, STACK_BELOW);
- }
- void Window::AddChild(Window* child) {
- WindowOcclusionTracker::ScopedPause pause_occlusion_tracking;
- DCHECK(layer()) << "Parent has not been Init()ed yet.";
- DCHECK(child->layer()) << "Child has not been Init()ed yt.";
- WindowObserver::HierarchyChangeParams params;
- params.target = child;
- params.new_parent = this;
- params.old_parent = child->parent();
- params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
- NotifyWindowHierarchyChange(params);
- Window* old_root = child->GetRootWindow();
- DCHECK(!base::Contains(children_, child));
- if (child->parent())
- child->parent()->RemoveChildImpl(child, this);
- child->parent_ = this;
- layer()->Add(child->layer());
- children_.push_back(child);
- if (layout_manager_)
- layout_manager_->OnWindowAddedToLayout(child);
- for (WindowObserver& observer : observers_)
- observer.OnWindowAdded(child);
- child->OnParentChanged();
- Window* root_window = GetRootWindow();
- if (root_window && old_root != root_window) {
- root_window->GetHost()->dispatcher()->OnWindowAddedToRootWindow(child);
- child->NotifyAddedToRootWindow();
- }
- params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
- NotifyWindowHierarchyChange(params);
- }
- void Window::RemoveChild(Window* child) {
- WindowOcclusionTracker::ScopedPause pause_occlusion_tracking;
- WindowObserver::HierarchyChangeParams params;
- params.target = child;
- params.new_parent = nullptr;
- params.old_parent = this;
- params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
- NotifyWindowHierarchyChange(params);
- RemoveChildImpl(child, nullptr);
- params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
- NotifyWindowHierarchyChange(params);
- }
- bool Window::Contains(const Window* other) const {
- for (const Window* parent = other; parent; parent = parent->parent_) {
- if (parent == this)
- return true;
- }
- return false;
- }
- Window* Window::GetChildById(int id) {
- return const_cast<Window*>(const_cast<const Window*>(this)->GetChildById(id));
- }
- const Window* Window::GetChildById(int id) const {
- Windows::const_iterator i;
- for (i = children_.begin(); i != children_.end(); ++i) {
- if ((*i)->GetId() == id)
- return *i;
- const Window* result = (*i)->GetChildById(id);
- if (result)
- return result;
- }
- return nullptr;
- }
- // static
- void Window::ConvertPointToTarget(const Window* source,
- const Window* target,
- gfx::PointF* point) {
- if (!source)
- return;
- if (source->GetRootWindow() != target->GetRootWindow()) {
- client::ScreenPositionClient* source_client =
- client::GetScreenPositionClient(source->GetRootWindow());
- // |source_client| can be nullptr in tests.
- if (source_client)
- source_client->ConvertPointToScreen(source, point);
- client::ScreenPositionClient* target_client =
- client::GetScreenPositionClient(target->GetRootWindow());
- // |target_client| can be nullptr in tests.
- if (target_client)
- target_client->ConvertPointFromScreen(target, point);
- } else {
- ui::Layer::ConvertPointToLayer(source->layer(), target->layer(),
- /*use_target_transform=*/true, point);
- }
- }
- // static
- void Window::ConvertPointToTarget(const Window* source,
- const Window* target,
- gfx::Point* point) {
- gfx::PointF point_float(*point);
- ConvertPointToTarget(source, target, &point_float);
- *point = gfx::ToFlooredPoint(point_float);
- }
- // static
- void Window::ConvertRectToTarget(const Window* source,
- const Window* target,
- gfx::Rect* rect) {
- DCHECK(rect);
- gfx::Point origin = rect->origin();
- ConvertPointToTarget(source, target, &origin);
- rect->set_origin(origin);
- }
- // static
- void Window::ConvertNativePointToTargetHost(const Window* source,
- const Window* target,
- gfx::PointF* point) {
- if (!source || !target)
- return;
- if (source->GetHost() == target->GetHost())
- return;
- point->Offset(-target->GetHost()->GetBoundsInPixels().x(),
- -target->GetHost()->GetBoundsInPixels().y());
- }
- // static
- void Window::ConvertNativePointToTargetHost(const Window* source,
- const Window* target,
- gfx::Point* point) {
- gfx::PointF point_float(*point);
- ConvertNativePointToTargetHost(source, target, &point_float);
- *point = gfx::ToFlooredPoint(point_float);
- }
- void Window::MoveCursorTo(const gfx::Point& point_in_window) {
- Window* root_window = GetRootWindow();
- DCHECK(root_window);
- gfx::Point point_in_root(point_in_window);
- ConvertPointToTarget(this, root_window, &point_in_root);
- root_window->GetHost()->MoveCursorToLocationInDIP(point_in_root);
- }
- gfx::NativeCursor Window::GetCursor(const gfx::Point& point) const {
- return delegate_ ? delegate_->GetCursor(point) : gfx::kNullCursor;
- }
- void Window::AddObserver(WindowObserver* observer) {
- observers_.AddObserver(observer);
- }
- void Window::RemoveObserver(WindowObserver* observer) {
- observers_.RemoveObserver(observer);
- }
- bool Window::HasObserver(const WindowObserver* observer) const {
- return observers_.HasObserver(observer);
- }
- void Window::SetEventTargetingPolicy(EventTargetingPolicy policy) {
- // If the event targeting is blocked on the window, do not allow change event
- // targeting policy until all event targeting blockers are removed from the
- // window.
- if (event_targeting_blocker_count_ > 0) {
- restore_event_targeting_policy_ = policy;
- return;
- }
- #if DCHECK_IS_ON()
- const bool old_window_accepts_events =
- (event_targeting_policy_ == EventTargetingPolicy::kTargetOnly) ||
- (event_targeting_policy_ == EventTargetingPolicy::kTargetAndDescendants);
- const bool new_window_accepts_events =
- (policy == EventTargetingPolicy::kTargetOnly) ||
- (policy == EventTargetingPolicy::kTargetAndDescendants);
- if (new_window_accepts_events != old_window_accepts_events)
- DCHECK(!created_layer_tree_frame_sink_);
- #endif
- if (event_targeting_policy_ == policy)
- return;
- event_targeting_policy_ = policy;
- layer()->SetAcceptEvents(policy != EventTargetingPolicy::kNone);
- }
- bool Window::ContainsPointInRoot(const gfx::Point& point_in_root) const {
- const Window* root_window = GetRootWindow();
- if (!root_window)
- return false;
- gfx::Point local_point(point_in_root);
- ConvertPointToTarget(root_window, this, &local_point);
- return gfx::Rect(GetTargetBounds().size()).Contains(local_point);
- }
- bool Window::ContainsPoint(const gfx::Point& local_point) const {
- return gfx::Rect(bounds().size()).Contains(local_point);
- }
- Window* Window::GetEventHandlerForPoint(const gfx::Point& local_point) {
- if (!IsVisible())
- return nullptr;
- if (!HitTest(local_point))
- return nullptr;
- for (Window* child : base::Reversed(children_)) {
- if (child->event_targeting_policy_ == EventTargetingPolicy::kNone) {
- continue;
- }
- // The client may not allow events to be processed by certain subtrees.
- client::EventClient* client = client::GetEventClient(GetRootWindow());
- if (client && !client->GetCanProcessEventsWithinSubtree(child))
- continue;
- if (delegate_ && !delegate_->ShouldDescendIntoChildForEventHandling(
- child, local_point)) {
- continue;
- }
- gfx::Point point_in_child_coords(local_point);
- ConvertPointToTarget(this, child, &point_in_child_coords);
- Window* match = child->GetEventHandlerForPoint(point_in_child_coords);
- if (!match)
- continue;
- switch (child->event_targeting_policy_) {
- case EventTargetingPolicy::kTargetOnly:
- if (child->delegate_)
- return child;
- break;
- case EventTargetingPolicy::kTargetAndDescendants:
- return match;
- case EventTargetingPolicy::kDescendantsOnly:
- if (match != child)
- return match;
- break;
- case EventTargetingPolicy::kNone:
- NOTREACHED(); // This case is handled early on.
- }
- }
- return delegate_ ? this : nullptr;
- }
- Window* Window::GetToplevelWindow() {
- Window* topmost_window_with_delegate = nullptr;
- for (aura::Window* window = this; window != nullptr;
- window = window->parent()) {
- if (window->delegate())
- topmost_window_with_delegate = window;
- }
- return topmost_window_with_delegate;
- }
- void Window::Focus() {
- client::FocusClient* client = client::GetFocusClient(this);
- DCHECK(client);
- client->FocusWindow(this);
- }
- bool Window::HasFocus() const {
- client::FocusClient* client = client::GetFocusClient(this);
- return client && client->GetFocusedWindow() == this;
- }
- bool Window::CanFocus() const {
- if (IsRootWindow())
- return IsVisible();
- // NOTE: as part of focusing the window the ActivationClient may make the
- // window visible (by way of making a hidden ancestor visible). For this
- // reason we can't check visibility here and assume the client is doing it.
- if (!parent_ || (delegate_ && !delegate_->CanFocus()))
- return false;
- // The client may forbid certain windows from receiving focus at a given point
- // in time.
- client::EventClient* client = client::GetEventClient(GetRootWindow());
- if (client && !client->GetCanProcessEventsWithinSubtree(this))
- return false;
- return parent_->CanFocus();
- }
- void Window::SetCapture() {
- if (!IsVisible())
- return;
- Window* root_window = GetRootWindow();
- if (!root_window)
- return;
- client::CaptureClient* capture_client = client::GetCaptureClient(root_window);
- if (!capture_client)
- return;
- capture_client->SetCapture(this);
- }
- void Window::ReleaseCapture() {
- Window* root_window = GetRootWindow();
- if (!root_window)
- return;
- client::CaptureClient* capture_client = client::GetCaptureClient(root_window);
- if (!capture_client)
- return;
- capture_client->ReleaseCapture(this);
- }
- bool Window::HasCapture() {
- Window* root_window = GetRootWindow();
- if (!root_window)
- return false;
- client::CaptureClient* capture_client = client::GetCaptureClient(root_window);
- return capture_client && capture_client->GetCaptureWindow() == this;
- }
- std::unique_ptr<ScopedKeyboardHook> Window::CaptureSystemKeyEvents(
- absl::optional<base::flat_set<ui::DomCode>> dom_codes) {
- Window* root_window = GetRootWindow();
- if (!root_window)
- return nullptr;
- WindowTreeHost* host = root_window->GetHost();
- if (!host)
- return nullptr;
- return host->CaptureSystemKeyEvents(std::move(dom_codes));
- }
- // {Set,Get,Clear}Property are implemented in class_property.h.
- void Window::SetNativeWindowProperty(const char* key, void* value) {
- SetPropertyInternal(key, key, nullptr, reinterpret_cast<int64_t>(value), 0);
- }
- void* Window::GetNativeWindowProperty(const char* key) const {
- return reinterpret_cast<void*>(GetPropertyInternal(key, 0,
- /*search_parent=*/false));
- }
- void Window::OnDeviceScaleFactorChanged(float old_device_scale_factor,
- float new_device_scale_factor) {
- if (!IsRootWindow() && last_device_scale_factor_ != new_device_scale_factor &&
- IsEmbeddingExternalContent()) {
- last_device_scale_factor_ = new_device_scale_factor;
- parent_local_surface_id_allocator_->GenerateId();
- if (frame_sink_)
- frame_sink_->SetLocalSurfaceId(GetCurrentLocalSurfaceId());
- }
- ScopedCursorHider hider(this);
- if (delegate_) {
- delegate_->OnDeviceScaleFactorChanged(old_device_scale_factor,
- new_device_scale_factor);
- }
- }
- void Window::UpdateVisualState() {
- if (delegate_)
- delegate_->UpdateVisualState();
- }
- #if DCHECK_IS_ON()
- std::string Window::GetDebugInfo() const {
- std::string name = GetName();
- if (name.empty())
- name = "Unknown";
- std::string layer_state = "NoLayer";
- if (layer()) {
- layer_state = base::StringPrintf(
- "%s opacity=%.1f",
- layer()->GetTargetVisibility() ? "LayerVisible" : "LayerHidden",
- layer()->opacity());
- }
- return base::StringPrintf(
- "%s<%d> bounds=%s %s %s occlusion_state=%s", name.c_str(), GetId(),
- bounds().ToString().c_str(), visible_ ? "WindowVisible" : "WindowHidden",
- layer_state.c_str(),
- base::UTF16ToUTF8(OcclusionStateToString(occlusion_state_)).c_str());
- }
- std::string Window::GetWindowHierarchy(int depth) const {
- std::string hierarchy =
- base::StringPrintf("%*s%s\n", depth * 2, "", GetDebugInfo().c_str());
- for (Window* child : children_)
- hierarchy += child->GetWindowHierarchy(depth + 1);
- return hierarchy;
- }
- void Window::PrintWindowHierarchy(int depth) const {
- VLOG(0) << GetWindowHierarchy(depth);
- }
- #endif
- void Window::RemoveOrDestroyChildren() {
- while (!children_.empty()) {
- Window* child = children_[0];
- if (child->owned_by_parent_) {
- delete child;
- // Deleting the child so remove it from out children_ list.
- DCHECK(!base::Contains(children_, child));
- } else {
- // Even if we can't delete the child, we still need to remove it from the
- // parent so that relevant bookkeeping (parent_ back-pointers etc) are
- // updated.
- RemoveChild(child);
- }
- }
- }
- void Window::AfterPropertyChange(const void* key, int64_t old_value) {
- for (WindowObserver& observer : observers_)
- observer.OnWindowPropertyChanged(this, key, old_value);
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Window, private:
- void Window::SetEmbedFrameSinkIdImpl(const viz::FrameSinkId& frame_sink_id) {
- UnregisterFrameSinkId();
- DCHECK(frame_sink_id.is_valid());
- frame_sink_id_ = frame_sink_id;
- RegisterFrameSinkId();
- }
- bool Window::HitTest(const gfx::Point& local_point) {
- gfx::Rect local_bounds(bounds().size());
- if (!delegate_ || !delegate_->HasHitTestMask())
- return local_bounds.Contains(local_point);
- SkPath mask;
- delegate_->GetHitTestMask(&mask);
- SkRegion clip_region;
- clip_region.setRect({local_bounds.x(), local_bounds.y(), local_bounds.width(),
- local_bounds.height()});
- SkRegion mask_region;
- return mask_region.setPath(mask, clip_region) &&
- mask_region.contains(local_point.x(), local_point.y());
- }
- void Window::SetBoundsInternal(const gfx::Rect& new_bounds) {
- gfx::Rect old_bounds = GetTargetBounds();
- // Always need to set the layer's bounds -- even if it is to the same thing.
- // This may cause important side effects such as stopping animation.
- layer()->SetBounds(new_bounds);
- // If we are currently not the layer's delegate, we will not get bounds
- // changed notification from the layer (this typically happens after animating
- // hidden). We must notify ourselves.
- if (layer()->delegate() != this) {
- OnLayerBoundsChanged(old_bounds,
- ui::PropertyChangeReason::NOT_FROM_ANIMATION);
- }
- }
- void Window::SetVisibleInternal(bool visible) {
- if (visible == layer()->GetTargetVisibility())
- return; // No change.
- WindowOcclusionTracker::ScopedPause pause_occlusion_tracking;
- for (WindowObserver& observer : observers_)
- observer.OnWindowVisibilityChanging(this, visible);
- client::VisibilityClient* visibility_client =
- client::GetVisibilityClient(this);
- if (visibility_client)
- visibility_client->UpdateLayerVisibility(this, visible);
- else
- layer()->SetVisible(visible);
- visible_ = visible;
- SchedulePaint();
- if (parent_ && parent_->layout_manager_)
- parent_->layout_manager_->OnChildWindowVisibilityChanged(this, visible);
- if (delegate_)
- delegate_->OnWindowTargetVisibilityChanged(visible);
- NotifyWindowVisibilityChanged(this, visible);
- }
- void Window::SetOcclusionInfo(OcclusionState occlusion_state,
- const SkRegion& occluded_region) {
- if (occlusion_state == occlusion_state_ &&
- occluded_region_in_root_ == occluded_region) {
- return;
- }
- occlusion_state_ = occlusion_state;
- occluded_region_in_root_ = occluded_region;
- if (delegate_)
- delegate_->OnWindowOcclusionChanged(occlusion_state);
- for (WindowObserver& observer : observers_)
- observer.OnWindowOcclusionChanged(this);
- }
- void Window::SchedulePaint() {
- SchedulePaintInRect(gfx::Rect(0, 0, bounds().width(), bounds().height()));
- }
- void Window::Paint(const ui::PaintContext& context) {
- if (delegate_)
- delegate_->OnPaint(context);
- }
- void Window::RemoveChildImpl(Window* child, Window* new_parent) {
- if (layout_manager_)
- layout_manager_->OnWillRemoveWindowFromLayout(child);
- for (WindowObserver& observer : observers_)
- observer.OnWillRemoveWindow(child);
- Window* root_window = child->GetRootWindow();
- Window* new_root_window = new_parent ? new_parent->GetRootWindow() : nullptr;
- if (root_window && root_window != new_root_window)
- child->NotifyRemovingFromRootWindow(new_root_window);
- if (child->OwnsLayer())
- layer()->Remove(child->layer());
- child->parent_ = nullptr;
- auto i = std::find(children_.begin(), children_.end(), child);
- DCHECK(i != children_.end());
- children_.erase(i);
- child->OnParentChanged();
- if (layout_manager_)
- layout_manager_->OnWindowRemovedFromLayout(child);
- for (WindowObserver& observer : observers_)
- observer.OnWindowRemoved(child);
- }
- void Window::OnParentChanged() {
- for (WindowObserver& observer : observers_)
- observer.OnWindowParentChanged(this, parent_);
- }
- void Window::StackChildRelativeTo(Window* child,
- Window* target,
- StackDirection direction) {
- DCHECK_NE(child, target);
- DCHECK(child);
- DCHECK(target);
- DCHECK_EQ(this, child->parent());
- DCHECK_EQ(this, target->parent());
- WindowOcclusionTracker::ScopedPause pause_occlusion_tracking;
- client::WindowStackingClient* stacking_client =
- client::GetWindowStackingClient();
- if (stacking_client &&
- !stacking_client->AdjustStacking(&child, &target, &direction))
- return;
- const size_t child_i =
- std::find(children_.begin(), children_.end(), child) - children_.begin();
- const size_t target_i =
- std::find(children_.begin(), children_.end(), target) - children_.begin();
- DCHECK_LT(child_i, children_.size()) << "Child was not in list of children!";
- DCHECK_LT(target_i, children_.size())
- << "Target was not in list of children!";
- // Don't move the child if it is already in the right place.
- if ((direction == STACK_ABOVE && child_i == target_i + 1) ||
- (direction == STACK_BELOW && child_i + 1 == target_i))
- return;
- const size_t dest_i =
- direction == STACK_ABOVE ?
- (child_i < target_i ? target_i : target_i + 1) :
- (child_i < target_i ? target_i - 1 : target_i);
- children_.erase(children_.begin() + child_i);
- children_.insert(children_.begin() + dest_i, child);
- StackChildLayerRelativeTo(child, target, direction);
- child->OnStackingChanged();
- }
- void Window::StackChildLayerRelativeTo(Window* child,
- Window* target,
- StackDirection direction) {
- DCHECK(layer() && child->layer() && target->layer());
- if (direction == STACK_ABOVE)
- layer()->StackAbove(child->layer(), target->layer());
- else
- layer()->StackBelow(child->layer(), target->layer());
- }
- void Window::OnStackingChanged() {
- for (WindowObserver& observer : observers_)
- observer.OnWindowStackingChanged(this);
- }
- void Window::NotifyRemovingFromRootWindow(Window* new_root) {
- if (frame_sink_id_.is_valid())
- UnregisterFrameSinkId();
- for (WindowObserver& observer : observers_)
- observer.OnWindowRemovingFromRootWindow(this, new_root);
- for (Window::Windows::const_iterator it = children_.begin();
- it != children_.end(); ++it) {
- (*it)->NotifyRemovingFromRootWindow(new_root);
- }
- }
- void Window::NotifyAddedToRootWindow() {
- if (frame_sink_id_.is_valid())
- RegisterFrameSinkId();
- for (WindowObserver& observer : observers_)
- observer.OnWindowAddedToRootWindow(this);
- for (Window::Windows::const_iterator it = children_.begin();
- it != children_.end(); ++it) {
- (*it)->NotifyAddedToRootWindow();
- }
- }
- void Window::NotifyWindowHierarchyChange(
- const WindowObserver::HierarchyChangeParams& params) {
- params.target->NotifyWindowHierarchyChangeDown(params);
- switch (params.phase) {
- case WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING:
- if (params.old_parent)
- params.old_parent->NotifyWindowHierarchyChangeUp(params);
- break;
- case WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED:
- if (params.new_parent)
- params.new_parent->NotifyWindowHierarchyChangeUp(params);
- break;
- }
- }
- void Window::NotifyWindowHierarchyChangeDown(
- const WindowObserver::HierarchyChangeParams& params) {
- NotifyWindowHierarchyChangeAtReceiver(params);
- for (Window::Windows::const_iterator it = children_.begin();
- it != children_.end(); ++it) {
- (*it)->NotifyWindowHierarchyChangeDown(params);
- }
- }
- void Window::NotifyWindowHierarchyChangeUp(
- const WindowObserver::HierarchyChangeParams& params) {
- for (Window* window = this; window; window = window->parent())
- window->NotifyWindowHierarchyChangeAtReceiver(params);
- }
- void Window::NotifyWindowHierarchyChangeAtReceiver(
- const WindowObserver::HierarchyChangeParams& params) {
- WindowObserver::HierarchyChangeParams local_params = params;
- local_params.receiver = this;
- switch (params.phase) {
- case WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING:
- for (WindowObserver& observer : observers_)
- observer.OnWindowHierarchyChanging(local_params);
- break;
- case WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED:
- for (WindowObserver& observer : observers_)
- observer.OnWindowHierarchyChanged(local_params);
- break;
- }
- }
- void Window::NotifyWindowVisibilityChanged(aura::Window* target,
- bool visible) {
- if (!NotifyWindowVisibilityChangedDown(target, visible))
- return; // |this| has been deleted.
- NotifyWindowVisibilityChangedUp(target, visible);
- }
- bool Window::NotifyWindowVisibilityChangedAtReceiver(aura::Window* target,
- bool visible) {
- // |this| may be deleted during a call to OnWindowVisibilityChanged() on one
- // of the observers. We create an local observer for that. In that case we
- // exit without further access to any members.
- WindowTracker tracker;
- tracker.Add(this);
- for (WindowObserver& observer : observers_)
- observer.OnWindowVisibilityChanged(target, visible);
- return tracker.Contains(this);
- }
- bool Window::NotifyWindowVisibilityChangedDown(aura::Window* target,
- bool visible) {
- if (!NotifyWindowVisibilityChangedAtReceiver(target, visible))
- return false; // |this| was deleted.
- WindowTracker this_tracker;
- this_tracker.Add(this);
- // Copy |children_| in case iterating mutates |children_|, or destroys an
- // existing child.
- WindowTracker children(children_);
- while (!this_tracker.windows().empty() && !children.windows().empty())
- children.Pop()->NotifyWindowVisibilityChangedDown(target, visible);
- const bool this_still_valid = !this_tracker.windows().empty();
- return this_still_valid;
- }
- void Window::NotifyWindowVisibilityChangedUp(aura::Window* target,
- bool visible) {
- // Start with the parent as we already notified |this|
- // in NotifyWindowVisibilityChangedDown.
- for (Window* window = parent(); window; window = window->parent()) {
- bool ret = window->NotifyWindowVisibilityChangedAtReceiver(target, visible);
- DCHECK(ret);
- }
- }
- bool Window::CleanupGestureState() {
- // If it's in the process already, nothing has to be done. Reentrant can
- // happen through some event handlers for CancelActiveTouches().
- if (cleaning_up_gesture_state_)
- return false;
- cleaning_up_gesture_state_ = true;
- // Cancelling active touches may end up destroying this window. We use a
- // tracker to detect this.
- WindowTracker tracking_this({this});
- bool state_modified = false;
- Env* env = Env::GetInstance();
- state_modified |= env->gesture_recognizer()->CancelActiveTouches(this);
- state_modified |= env->gesture_recognizer()->CleanupStateForConsumer(this);
- if (!tracking_this.Contains(this))
- return state_modified;
- // Potentially event handlers for CancelActiveTouches() within
- // CleanupGestureState may change the window hierarchy (or reorder the
- // |children_|), and therefore iterating over |children_| is not safe. Use
- // WindowTracker to track the list of children.
- WindowTracker children(children_);
- while (!children.windows().empty()) {
- Window* child = children.Pop();
- state_modified |= child->CleanupGestureState();
- }
- cleaning_up_gesture_state_ = false;
- return state_modified;
- }
- std::unique_ptr<cc::LayerTreeFrameSink> Window::CreateLayerTreeFrameSink() {
- // Currently we don't have a need for both SetEmbedFrameSinkId() and
- // this function be called.
- DCHECK(!embeds_external_client_);
- auto* context_factory = Env::GetInstance()->context_factory();
- auto* host_frame_sink_manager = context_factory->GetHostFrameSinkManager();
- if (!frame_sink_id_.is_valid()) {
- auto frame_sink_id = context_factory->AllocateFrameSinkId();
- host_frame_sink_manager->RegisterFrameSinkId(
- frame_sink_id, this, viz::ReportFirstSurfaceActivation::kYes);
- SetEmbedFrameSinkIdImpl(frame_sink_id);
- }
- // For creating a async frame sink which connects to the viz display
- // compositor.
- mojo::PendingRemote<viz::mojom::CompositorFrameSink> sink_remote;
- mojo::PendingReceiver<viz::mojom::CompositorFrameSink> sink_receiver =
- sink_remote.InitWithNewPipeAndPassReceiver();
- mojo::PendingRemote<viz::mojom::CompositorFrameSinkClient> client_remote;
- mojo::PendingReceiver<viz::mojom::CompositorFrameSinkClient> client_receiver =
- client_remote.InitWithNewPipeAndPassReceiver();
- host_frame_sink_manager->CreateCompositorFrameSink(
- frame_sink_id_, std::move(sink_receiver), std::move(client_remote));
- cc::mojo_embedder::AsyncLayerTreeFrameSink::InitParams params;
- params.gpu_memory_buffer_manager =
- Env::GetInstance()->context_factory()->GetGpuMemoryBufferManager();
- params.pipes.compositor_frame_sink_remote = std::move(sink_remote);
- params.pipes.client_receiver = std::move(client_receiver);
- params.client_name = kExo;
- auto frame_sink =
- std::make_unique<cc::mojo_embedder::AsyncLayerTreeFrameSink>(
- nullptr /* context_provider */, nullptr /* worker_context_provider */,
- ¶ms);
- frame_sink_ = frame_sink->GetWeakPtr();
- AllocateLocalSurfaceId();
- DCHECK(GetLocalSurfaceId().is_valid());
- #if DCHECK_IS_ON()
- created_layer_tree_frame_sink_ = true;
- #endif
- return std::move(frame_sink);
- }
- 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_ =
- std::make_unique<viz::ParentLocalSurfaceIdAllocator>();
- }
- parent_local_surface_id_allocator_->GenerateId();
- UpdateLocalSurfaceId();
- }
- viz::ScopedSurfaceIdAllocator Window::GetSurfaceIdAllocator(
- base::OnceCallback<void()> allocation_task) {
- return viz::ScopedSurfaceIdAllocator(parent_local_surface_id_allocator_.get(),
- std::move(allocation_task));
- }
- const viz::LocalSurfaceId& Window::GetLocalSurfaceId() {
- if (!parent_local_surface_id_allocator_)
- AllocateLocalSurfaceId();
- return GetCurrentLocalSurfaceId();
- }
- void Window::InvalidateLocalSurfaceId() {
- if (!parent_local_surface_id_allocator_)
- return;
- parent_local_surface_id_allocator_->Invalidate();
- }
- void Window::UpdateLocalSurfaceIdFromEmbeddedClient(
- const absl::optional<viz::LocalSurfaceId>&
- embedded_client_local_surface_id) {
- if (embedded_client_local_surface_id) {
- parent_local_surface_id_allocator_->UpdateFromChild(
- *embedded_client_local_surface_id);
- UpdateLocalSurfaceId();
- } else {
- AllocateLocalSurfaceId();
- }
- }
- const viz::FrameSinkId& Window::GetFrameSinkId() const {
- if (IsRootWindow()) {
- DCHECK(host_);
- auto* compositor = host_->compositor();
- DCHECK(compositor);
- return compositor->frame_sink_id();
- }
- return frame_sink_id_;
- }
- void Window::SetEmbedFrameSinkId(const viz::FrameSinkId& frame_sink_id) {
- SetEmbedFrameSinkIdImpl(frame_sink_id);
- embeds_external_client_ = true;
- }
- void Window::TrackOcclusionState() {
- Env::GetInstance()->GetWindowOcclusionTracker()->Track(this);
- }
- bool Window::RequiresDoubleTapGestureEvents() const {
- return delegate_ && delegate_->RequiresDoubleTapGestureEvents();
- }
- // static
- 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(GetTransparent() || opaque_regions_for_occlusion.empty());
- if (opaque_regions_for_occlusion == opaque_regions_for_occlusion_)
- return;
- opaque_regions_for_occlusion_ = opaque_regions_for_occlusion;
- for (auto& observer : observers_)
- observer.OnWindowOpaqueRegionsForOcclusionChanged(this);
- }
- void Window::NotifyResizeLoopStarted() {
- for (auto& observer : observers_)
- observer.OnResizeLoopStarted(this);
- }
- void Window::NotifyResizeLoopEnded() {
- for (auto& observer : observers_)
- observer.OnResizeLoopEnded(this);
- }
- void Window::OnPaintLayer(const ui::PaintContext& context) {
- Paint(context);
- }
- void Window::OnLayerBoundsChanged(const gfx::Rect& old_bounds,
- ui::PropertyChangeReason reason) {
- WindowOcclusionTracker::ScopedPause pause_occlusion_tracking;
- bounds_ = layer()->bounds();
- if (!IsRootWindow() && old_bounds.size() != bounds_.size() &&
- IsEmbeddingExternalContent()) {
- parent_local_surface_id_allocator_->GenerateId();
- if (frame_sink_) {
- frame_sink_->SetLocalSurfaceId(GetCurrentLocalSurfaceId());
- }
- }
- if (layout_manager_)
- layout_manager_->OnWindowResized();
- if (delegate_)
- 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) {
- WindowOcclusionTracker::ScopedPause pause_occlusion_tracking;
- for (WindowObserver& observer : observers_)
- observer.OnWindowOpacitySet(this, reason);
- }
- void Window::OnLayerAlphaShapeChanged() {
- WindowOcclusionTracker::ScopedPause pause_occlusion_tracking;
- for (WindowObserver& observer : observers_)
- observer.OnWindowAlphaShapeSet(this);
- }
- void Window::OnLayerFillsBoundsOpaquelyChanged(
- ui::PropertyChangeReason reason) {
- // Let observers know that this window's transparent status has changed.
- // Transparent status can affect the occlusion computed for windows.
- WindowOcclusionTracker::ScopedPause pause_occlusion_tracking;
- // Non-transparent windows should not have opaque regions for occlusion set.
- if (!GetTransparent())
- DCHECK(opaque_regions_for_occlusion_.empty());
- for (WindowObserver& observer : observers_)
- observer.OnWindowTransparentChanged(this, reason);
- }
- void Window::OnLayerTransformed(const gfx::Transform& old_transform,
- ui::PropertyChangeReason reason) {
- WindowOcclusionTracker::ScopedPause pause_occlusion_tracking;
- for (WindowObserver& observer : observers_)
- observer.OnWindowTransformed(this, reason);
- }
- bool Window::CanAcceptEvent(const ui::Event& event) {
- // The client may forbid certain windows from receiving events at a given
- // point in time.
- client::EventClient* client = client::GetEventClient(GetRootWindow());
- if (client && !client->GetCanProcessEventsWithinSubtree(this))
- return false;
- // We need to make sure that a touch cancel event and any gesture events it
- // creates can always reach the window. This ensures that we receive a valid
- // touch / gesture stream.
- if (event.IsEndingEvent())
- return true;
- if (!IsVisible())
- return false;
- // The top-most window can always process an event.
- if (!parent_)
- return true;
- // For located events (i.e. mouse, touch etc.), an assumption is made that
- // windows that don't have a default event-handler cannot process the event
- // (see more in GetWindowForPoint()). This assumption is not made for key
- // events.
- return event.IsKeyEvent() || target_handler();
- }
- ui::EventTarget* Window::GetParentTarget() {
- if (IsRootWindow()) {
- return client::GetEventClient(this)
- ? client::GetEventClient(this)->GetToplevelEventTarget()
- : Env::GetInstance();
- }
- return parent_;
- }
- std::unique_ptr<ui::EventTargetIterator> Window::GetChildIterator() const {
- return std::make_unique<ui::EventTargetIteratorPtrImpl<Window>>(children());
- }
- ui::EventTargeter* Window::GetEventTargeter() {
- return targeter_.get();
- }
- void Window::ConvertEventToTarget(const ui::EventTarget* target,
- ui::LocatedEvent* event) const {
- event->ConvertLocationToTarget(this, static_cast<const Window*>(target));
- }
- gfx::PointF Window::GetScreenLocationF(const ui::LocatedEvent& event) const {
- DCHECK_EQ(this, event.target());
- gfx::PointF screen_location(event.root_location_f());
- const Window* root = GetRootWindow();
- auto* screen_position_client = aura::client::GetScreenPositionClient(root);
- if (screen_position_client)
- screen_position_client->ConvertPointToScreen(root, &screen_location);
- return screen_location;
- }
- std::unique_ptr<ui::Layer> Window::ReleaseLayer() {
- if (number_of_capture_requests_) {
- // Before we release our own layer, if this window was marked for capture,
- // we need to reset the SubtreeCaptureId on that layer as it will no longer
- // be associated with us.
- DCHECK(subtree_capture_id_.is_valid());
- if (layer())
- layer()->SetSubtreeCaptureId(viz::SubtreeCaptureId());
- }
- return LayerOwner::ReleaseLayer();
- }
- std::unique_ptr<ui::Layer> Window::RecreateLayer() {
- WindowOcclusionTracker::ScopedPause pause_occlusion_tracking;
- ui::LayerAnimator* const animator = layer()->GetAnimator();
- const bool was_animating_opacity =
- animator->IsAnimatingProperty(ui::LayerAnimationElement::OPACITY);
- const bool was_animating_transform =
- animator->IsAnimatingProperty(ui::LayerAnimationElement::TRANSFORM);
- std::unique_ptr<ui::Layer> old_layer = LayerOwner::RecreateLayer();
- // If a frame sink is attached to the window, then allocate a new surface
- // id when layers are recreated, so the old layer contents are not affected
- // by a frame sent to the frame sink.
- if (GetFrameSinkId().is_valid() && old_layer)
- AllocateLocalSurfaceId();
- // The old layer subtree must no longer be capturable.
- // Note that we don't need to worry about the newly recreated layer since
- // Window::SetLayer() will have taken care of it already.
- if (number_of_capture_requests_ && old_layer)
- old_layer->SetSubtreeCaptureId(viz::SubtreeCaptureId());
- // Observers are guaranteed to be notified when an opacity or transform
- // animation ends.
- if (was_animating_opacity) {
- for (WindowObserver& observer : observers_) {
- observer.OnWindowOpacitySet(this,
- ui::PropertyChangeReason::FROM_ANIMATION);
- }
- }
- if (was_animating_transform) {
- for (WindowObserver& observer : observers_) {
- observer.OnWindowTransformed(this,
- ui::PropertyChangeReason::FROM_ANIMATION);
- }
- }
- for (WindowObserver& observer : observers_)
- observer.OnWindowLayerRecreated(this);
- return old_layer;
- }
- void Window::SetLayer(std::unique_ptr<ui::Layer> alayer) {
- LayerOwner::SetLayer(std::move(alayer));
- if (number_of_capture_requests_) {
- // If this window was marked for capture before, then the new layer that we
- // own now should be given the current SubtreeCaptureId that we have.
- DCHECK(subtree_capture_id_.is_valid());
- if (layer())
- layer()->SetSubtreeCaptureId(subtree_capture_id_);
- }
- }
- void Window::OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) {
- DCHECK_EQ(surface_info.id().frame_sink_id(), GetFrameSinkId());
- layer()->SetShowSurface(surface_info.id(), bounds().size(), SK_ColorWHITE,
- cc::DeadlinePolicy::UseDefaultDeadline(),
- false /* stretch_content_to_fill_bounds */);
- }
- void Window::OnFrameTokenChanged(uint32_t frame_token,
- base::TimeTicks activation_time) {}
- void Window::UpdateLayerName() {
- DCHECK(layer());
- std::string layer_name(GetName());
- if (layer_name.empty())
- layer_name = "Unnamed Window";
- if (id_ != -1)
- layer_name += " " + base::NumberToString(id_);
- layer()->SetName(layer_name);
- }
- void Window::RegisterFrameSinkId() {
- DCHECK(frame_sink_id_.is_valid());
- if (registered_frame_sink_id_ || disable_frame_sink_id_registration_)
- return;
- if (auto* compositor = layer()->GetCompositor()) {
- compositor->AddChildFrameSink(frame_sink_id_);
- registered_frame_sink_id_ = true;
- }
- }
- void Window::UnregisterFrameSinkId() {
- if (!registered_frame_sink_id_)
- return;
- registered_frame_sink_id_ = false;
- if (auto* compositor = layer()->GetCompositor())
- compositor->RemoveChildFrameSink(frame_sink_id_);
- }
- void Window::UpdateLocalSurfaceId() {
- last_device_scale_factor_ = ui::GetScaleFactorForNativeView(this);
- if (frame_sink_) {
- frame_sink_->SetLocalSurfaceId(GetCurrentLocalSurfaceId());
- }
- }
- const viz::LocalSurfaceId& Window::GetCurrentLocalSurfaceId() const {
- return parent_local_surface_id_allocator_->GetCurrentLocalSurfaceId();
- }
- bool Window::IsEmbeddingExternalContent() const {
- return parent_local_surface_id_allocator_.get() != nullptr;
- }
- void Window::OnScopedWindowCaptureRequestAdded() {
- if (++number_of_capture_requests_ == 1) {
- DCHECK(!subtree_capture_id_.is_valid());
- DCHECK(!layer() || !layer()->GetSubtreeCaptureId().is_valid());
- subtree_capture_id_ =
- Env::GetInstance()->context_factory()->AllocateSubtreeCaptureId();
- if (layer())
- layer()->SetSubtreeCaptureId(subtree_capture_id_);
- }
- DCHECK(subtree_capture_id_.is_valid());
- }
- void Window::OnScopedWindowCaptureRequestRemoved() {
- DCHECK(subtree_capture_id_.is_valid());
- DCHECK(number_of_capture_requests_);
- --number_of_capture_requests_;
- DCHECK_GE(number_of_capture_requests_, 0);
- if (number_of_capture_requests_ == 0) {
- subtree_capture_id_ = viz::SubtreeCaptureId();
- if (layer())
- layer()->SetSubtreeCaptureId(subtree_capture_id_);
- }
- }
- 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().
- }
- 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
|