diff options
Diffstat (limited to 'Userland/Services/WindowServer')
-rw-r--r-- | Userland/Services/WindowServer/Overlays.cpp | 72 | ||||
-rw-r--r-- | Userland/Services/WindowServer/Overlays.h | 14 | ||||
-rw-r--r-- | Userland/Services/WindowServer/WindowManager.cpp | 14 | ||||
-rw-r--r-- | Userland/Services/WindowServer/WindowManager.h | 1 |
4 files changed, 97 insertions, 4 deletions
diff --git a/Userland/Services/WindowServer/Overlays.cpp b/Userland/Services/WindowServer/Overlays.cpp index 58234e0851..6a2a0869c7 100644 --- a/Userland/Services/WindowServer/Overlays.cpp +++ b/Userland/Services/WindowServer/Overlays.cpp @@ -5,6 +5,7 @@ */ #include "Overlays.h" +#include "Animation.h" #include "Compositor.h" #include "WindowManager.h" #include <LibGfx/StylePainter.h> @@ -230,16 +231,78 @@ WindowGeometryOverlay::WindowGeometryOverlay(Window& window) update_rect(); } +void WindowGeometryOverlay::set_actual_rect() +{ + if (!m_move_into_overlay_rect_animation.animation) { + set_rect(m_ideal_overlay_rect); + return; + } + + auto const& starting_rect = m_move_into_overlay_rect_animation.starting_rect.value(); + m_move_into_overlay_rect_animation.current_rect = starting_rect.interpolated_to(starting_rect.centered_within(m_move_into_overlay_rect_animation.tile_overlay_rect_at_start), m_move_into_overlay_rect_animation.progress); + set_rect(m_move_into_overlay_rect_animation.current_rect); +} + +void WindowGeometryOverlay::start_or_stop_move_to_tile_overlay_animation(TileWindowOverlay* tile_window_overlay) +{ + if (!tile_window_overlay) { + if (m_move_into_overlay_rect_animation.animation) + m_move_into_overlay_rect_animation.animation->stop(); + m_move_into_overlay_rect_animation = {}; + return; + } + + auto tile_overlay_rect = tile_window_overlay->tiled_frame_rect(); + if (m_move_into_overlay_rect_animation.tile_overlay_rect_at_start != tile_overlay_rect || !m_move_into_overlay_rect_animation.starting_rect.has_value()) { + if (!m_move_into_overlay_rect_animation.starting_rect.has_value()) { + // The tile overlay was just started on one location, we want to move the geometry overlay from the center of the window to the center of the tile overlay, + m_move_into_overlay_rect_animation.starting_rect = m_ideal_overlay_rect; + m_move_into_overlay_rect_animation.current_rect = m_ideal_overlay_rect; + } else if (m_ideal_overlay_rect.size() != m_move_into_overlay_rect_animation.starting_rect.value().size()) { + // The geometry label size was changed. This normally would only happen when the text changes while moving the window around. + // But because the tile overlay is visible, we don't update the geometry label with the window rect, but instead we show the prospective tile size. + // So, the only case where the geometry label size can change is if the tile overlay rectangle was changed (e.g. from Left to Top). + // In this case we want just update the rectangle size at where the geometry label was last rendered. We then restart the animation, + // which causes it to move to the center of the new tile overlay rectangle. + m_move_into_overlay_rect_animation.starting_rect = m_ideal_overlay_rect.centered_within(m_move_into_overlay_rect_animation.current_rect); + m_move_into_overlay_rect_animation.current_rect = m_move_into_overlay_rect_animation.starting_rect.value(); + } else { + // The geometry label size didn't change, but the tile overlay rectangle was changed (e.g. from Left to Top). + // In this case we restart the animation by starting where we last rendered the geometry label, + // causing it to move to the center of the new tile overlay rectangle. + m_move_into_overlay_rect_animation.starting_rect = m_move_into_overlay_rect_animation.current_rect; + } + + m_move_into_overlay_rect_animation.tile_overlay_rect_at_start = tile_overlay_rect; + m_move_into_overlay_rect_animation.progress = 0.0f; + + if (m_move_into_overlay_rect_animation.animation) { + m_move_into_overlay_rect_animation.animation->stop(); + } else { + m_move_into_overlay_rect_animation.animation = Animation::create(); + m_move_into_overlay_rect_animation.animation->set_duration(150); + } + + m_move_into_overlay_rect_animation.animation->on_update = [this](float progress, Gfx::Painter&, Screen&, Gfx::DisjointIntRectSet&) { + m_move_into_overlay_rect_animation.progress = progress; + set_actual_rect(); + }; + m_move_into_overlay_rect_animation.animation->start(); + } +} + void WindowGeometryOverlay::update_rect() { if (auto* window = m_window.ptr()) { auto& wm = WindowManager::the(); + auto* tile_window_overlay = wm.get_tile_window_overlay(*window); + auto geometry_rect = tile_window_overlay ? tile_window_overlay->tiled_frame_rect() : window->rect(); if (!window->size_increment().is_empty()) { int width_steps = (window->width() - window->base_size().width()) / window->size_increment().width(); int height_steps = (window->height() - window->base_size().height()) / window->size_increment().height(); - m_label = DeprecatedString::formatted("{} ({}x{})", window->rect(), width_steps, height_steps); + m_label = DeprecatedString::formatted("{} ({}x{})", geometry_rect, width_steps, height_steps); } else { - m_label = window->rect().to_deprecated_string(); + m_label = geometry_rect.to_deprecated_string(); } m_label_rect = Gfx::IntRect { 0, 0, static_cast<int>(ceilf(wm.font().width(m_label))) + 16, wm.font().pixel_size_rounded_up() + 10 }; @@ -254,8 +317,11 @@ void WindowGeometryOverlay::update_rect() if (rect.bottom() > desktop_rect.bottom()) rect.set_bottom_without_resize(desktop_rect.bottom()); - set_rect(rect); + m_ideal_overlay_rect = rect; + set_actual_rect(); invalidate_content(); // needed in case the rectangle itself doesn't change. But the contents did. + + start_or_stop_move_to_tile_overlay_animation(tile_window_overlay); } else { set_enabled(false); } diff --git a/Userland/Services/WindowServer/Overlays.h b/Userland/Services/WindowServer/Overlays.h index bde7becd74..69a0b1c11f 100644 --- a/Userland/Services/WindowServer/Overlays.h +++ b/Userland/Services/WindowServer/Overlays.h @@ -17,7 +17,9 @@ namespace WindowServer { +class Animation; class Screen; +class TileWindowOverlay; class Window; class WindowStack; @@ -145,12 +147,24 @@ public: virtual ZOrder zorder() const override { return ZOrder::WindowGeometry; } virtual void render_overlay_bitmap(Gfx::Painter&) override; + void set_actual_rect(); + void start_or_stop_move_to_tile_overlay_animation(TileWindowOverlay*); + private: void update_rect(); WeakPtr<Window> m_window; DeprecatedString m_label; Gfx::IntRect m_label_rect; + Gfx::IntRect m_ideal_overlay_rect; + + struct { + RefPtr<Animation> animation; + float progress { 0.0f }; + Gfx::IntRect tile_overlay_rect_at_start; + Gfx::IntRect current_rect; + Optional<Gfx::IntRect> starting_rect; + } m_move_into_overlay_rect_animation; }; class DndOverlay : public BitmapOverlay { diff --git a/Userland/Services/WindowServer/WindowManager.cpp b/Userland/Services/WindowServer/WindowManager.cpp index b666a069e2..42808baadb 100644 --- a/Userland/Services/WindowServer/WindowManager.cpp +++ b/Userland/Services/WindowServer/WindowManager.cpp @@ -757,7 +757,11 @@ void WindowManager::start_tile_window_animation(Gfx::IntRect const& starting_rec void WindowManager::stop_tile_window_animation() { - m_tile_window_overlay = nullptr; + if (m_tile_window_overlay) { + if (m_geometry_overlay) + m_geometry_overlay->start_or_stop_move_to_tile_overlay_animation(nullptr); + m_tile_window_overlay = nullptr; + } m_tile_window_overlay_animation = nullptr; } @@ -776,9 +780,17 @@ void WindowManager::show_tile_window_overlay(Window& window, Screen const& curso if (m_tile_window_overlay->tiled_frame_rect() != tiled_frame_rect) { m_tile_window_overlay->set_tiled_frame_rect(tiled_frame_rect); start_tile_window_animation(m_tile_window_overlay->rect()); + if (m_geometry_overlay) + m_geometry_overlay->window_rect_changed(); } } } +TileWindowOverlay* WindowManager::get_tile_window_overlay(Window& window) const +{ + if (m_tile_window_overlay && m_tile_window_overlay->is_window(window)) + return m_tile_window_overlay.ptr(); + return nullptr; +} bool WindowManager::process_ongoing_window_move(MouseEvent& event) { diff --git a/Userland/Services/WindowServer/WindowManager.h b/Userland/Services/WindowServer/WindowManager.h index 217e7f61f9..101001ba18 100644 --- a/Userland/Services/WindowServer/WindowManager.h +++ b/Userland/Services/WindowServer/WindowManager.h @@ -340,6 +340,7 @@ public: u8 last_processed_buttons() { return m_last_processed_buttons; } + TileWindowOverlay* get_tile_window_overlay(Window&) const; void start_tile_window_animation(Gfx::IntRect const&); void stop_tile_window_animation(); |