/* * @Author: DI JUNKUN * @Date: 2026-10-12 * Copyright (c) 2026 by DI JUNKUN, All Rights Reserved. */ #ifndef _GALLERY_WINDOW_STATE_H_ #define _GALLERY_WINDOW_STATE_H_ #include #include #include #include namespace crossdesk::gallery { struct WindowState { bool wall_fullscreen = false; bool wall_maximized = false; // Store client dimensions in logical pixels, independent of the display DPI. std::optional wall_size; std::optional wall_position, connection_position; void Observe(bool wall, slint::PhysicalPosition position, slint::PhysicalSize size, float scale, bool fullscreen, bool maximized, float compact_height = 486, float compact_width = 640) { if (Restoring()) return; if (!wall) { connection_position = position; return; } if (!fullscreen && !maximized && IsUndersized(size, scale, compact_height, compact_width)) return; scale = std::max(scale, 1.0f); wall_fullscreen = fullscreen; wall_maximized = !fullscreen && maximized; if (!fullscreen && !maximized) { wall_size = slint::LogicalSize( slint::Size{size.width / scale, size.height / scale}); wall_position = position; } } bool RecoverUndersized(bool wall, slint::PhysicalPosition position, slint::PhysicalSize size, float scale, bool visible, bool minimized, bool fullscreen, bool maximized, float compact_height = 486, float compact_width = 640) { // Hidden/minimized/uninitialized windows can report temporary tiny bounds. // Leave those alone, and let an in-flight restoration retain its target. if (Restoring() || !visible || minimized || fullscreen || maximized || size.width == 0 || size.height == 0 || !IsUndersized(size, scale, compact_height, compact_width)) return false; if (wall) { wall_position = position; wall_fullscreen = false; wall_maximized = false; } else { connection_position = position; } // Keep the last valid logical size; only the current anchor is captured. BeginRestore(); return true; } slint::PhysicalSize RestoreSize(bool wall, float scale, float compact_height = 486, float compact_width = 640) const { const float width = wall && wall_size ? std::max(compact_width, wall_size->width) : compact_width; const float height = wall && wall_size ? std::max(compact_height, wall_size->height) : compact_height; scale = std::max(scale, 1.0f); return slint::PhysicalSize( slint::Size{uint32_t(std::lround(width * scale)), uint32_t(std::lround(height * scale))}); } void BeginRestore() { phase_ = Phase::Normal; target_.reset(); last_size_.reset(); matches_ = 0; } void PrepareForShow(slint::Window &window, bool wall, slint::PhysicalSize size, std::optional position, float initial_y_offset = 0) { const float scale = std::max(window.scale_factor(), 1.0f); // The actual display scale is resolved when the native window is created. // Give the backend logical geometry so its first visible frame is correct. window.set_size(slint::LogicalSize( slint::Size{size.width / scale, size.height / scale})); if (position) { (wall ? wall_position : connection_position) = position; window.set_position(slint::LogicalPosition(slint::Point{ position->x / scale, position->y / scale + initial_y_offset})); } } bool Restoring() const { return phase_ != Phase::Idle; } bool RestoringNormal() const { return phase_ == Phase::Normal; } // A set_size request can complete asynchronously, after layout constraints // and the backing scale have changed. Acknowledge observations on later // ticks. bool NormalSizeRestored(slint::PhysicalSize actual, slint::PhysicalSize target) { if (!RestoringNormal()) return false; if (target_ && SameSize(*target_, target) && SameSize(actual, target)) ++matches_; else matches_ = 0; target_ = target; if (matches_ < 2) return false; phase_ = Phase::Presentation; matches_ = 0; last_size_.reset(); return true; } bool FinishRestore(bool wall, slint::PhysicalSize actual, bool fullscreen, bool maximized) { if (phase_ != Phase::Presentation) return false; const bool want_fullscreen = wall && wall_fullscreen; const bool want_maximized = wall && !want_fullscreen && wall_maximized; const bool normal = !want_fullscreen && !want_maximized; if (normal && !fullscreen && !maximized && target_ && !SameSize(actual, *target_)) { // A late constraint/DPI update can invalidate an earlier acknowledgement. // Reissue the normal size instead of getting stuck or saving that size. BeginRestore(); return false; } const bool ready = fullscreen == want_fullscreen && (want_fullscreen || maximized == want_maximized) && (!normal || (target_ && SameSize(actual, *target_))); if (ready && last_size_ && SameSize(actual, *last_size_)) ++matches_; else matches_ = 0; last_size_ = actual; if (matches_ < 2) return false; phase_ = Phase::Idle; return true; } private: enum class Phase { Idle, Normal, Presentation }; Phase phase_ = Phase::Idle; std::optional target_, last_size_; int matches_ = 0; static bool IsUndersized(slint::PhysicalSize size, float scale, float compact_height, float compact_width) { scale = std::max(scale, 1.0f); return double(size.width) + 1 < compact_width * scale || double(size.height) + 1 < compact_height * scale; } static bool SameSize(slint::PhysicalSize a, slint::PhysicalSize b) { return std::abs(double(a.width) - b.width) <= 1 && std::abs(double(a.height) - b.height) <= 1; } }; } // namespace crossdesk::gallery #endif