summaryrefslogtreecommitdiff
path: root/Userland/Services/WindowServer
diff options
context:
space:
mode:
Diffstat (limited to 'Userland/Services/WindowServer')
-rw-r--r--Userland/Services/WindowServer/Overlays.cpp72
-rw-r--r--Userland/Services/WindowServer/Overlays.h14
-rw-r--r--Userland/Services/WindowServer/WindowManager.cpp14
-rw-r--r--Userland/Services/WindowServer/WindowManager.h1
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();