Skip to content

Commit

Permalink
WindowServer: Move window geometry label into the tile overlay area
Browse files Browse the repository at this point in the history
This moves the window geometry overlay into the center of the
tile window overlay when it's visible or when it moves.
  • Loading branch information
tomuta authored and linusg committed Apr 13, 2023
1 parent fe54a0c commit 5a73691
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 4 deletions.
72 changes: 69 additions & 3 deletions Userland/Services/WindowServer/Overlays.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/

#include "Overlays.h"
#include "Animation.h"
#include "Compositor.h"
#include "WindowManager.h"
#include <LibGfx/StylePainter.h>
Expand Down Expand Up @@ -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 };

Expand All @@ -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);
}
Expand Down
14 changes: 14 additions & 0 deletions Userland/Services/WindowServer/Overlays.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@

namespace WindowServer {

class Animation;
class Screen;
class TileWindowOverlay;
class Window;
class WindowStack;

Expand Down Expand Up @@ -145,12 +147,24 @@ class WindowGeometryOverlay : public RectangularOverlay {
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 {
Expand Down
14 changes: 13 additions & 1 deletion Userland/Services/WindowServer/WindowManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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)
{
Expand Down
1 change: 1 addition & 0 deletions Userland/Services/WindowServer/WindowManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ class WindowManager : public Core::Object {

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();

Expand Down

0 comments on commit 5a73691

Please sign in to comment.