#pragma once #include "Layout.h" #include #include #include #include #include namespace msimeui { class Scene { public: struct PopupEntry { std::shared_ptr visual; std::function onClose; }; void SetRoot(std::shared_ptr root); void Attach(Window *window); void EnsureLayout(const SizeF &size); void Layout(const SizeF &size); void AddPopup(std::shared_ptr popup, std::function onClose = {}); void RemovePopup(Visual *popup, bool notify = true); void ClearPopups(bool notify = true); bool DismissPopupsForClick(const PointF &point, Visual *target); void RelayoutPopups(); void InvalidateMeasure(); void InvalidateMeasure(Visual *source); void InvalidateArrange(); void InvalidateArrange(Visual *source); void InvalidateVisual(); // Hosts call DeviceResources::BeginFrame before this, so the animation clock and the // next-frame deadline belong to this frame. void Render(DeviceResources &deviceResources); // When the scene rendered last needs its next frame: the earliest change of an animated // image it drew. Empty when nothing on screen animates. Hosts that render on demand // schedule one repaint for it (msimeui::Window does so itself). std::optional GetNextFrameDeadline() const; Visual *FindVisualAt(const PointF &point); Visual *FindFocusableAt(const PointF &point); bool OnMouseWheel(const POINT &point, short delta, WPARAM keyState); bool OnTimer(UINT_PTR timerId); private: std::shared_ptr root_; std::vector popups_; Window *window_ = nullptr; Visual *measureDirtySource_ = nullptr; Visual *arrangeDirtyRoot_ = nullptr; SizeF lastLayoutSize_ = {}; bool hasLastLayoutSize_ = false; bool measureDirty_ = true; bool arrangeDirty_ = true; std::optional nextFrameDeadline_; }; } // namespace msimeui