mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-30 00:31:14 +00:00
WindowServer+LibGUI: Allow specifying a "launch origin" for new windows
The launch_origin_rect parameter to create_window() specifies where on screen the window was launched from. It's optional, but if you provide it, the new window will have a short wireframe animation from the origin to the initial window frame rect. GUI::Window looks for the "__libgui_launch_origin_rect" environment variable. Put your launch origin rect in there with the format "<x>,<y>,<width>,<height>" and the first GUI::Window shown by the app will use that as the launch origin rect. Also it looks pretty neat, although I'm sure we can improve it. :^)
This commit is contained in:
parent
75f870a93f
commit
6a132d8672
Notes:
sideshowbarker
2024-07-18 11:26:51 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/6a132d8672d
|
@ -122,6 +122,20 @@ void Window::show()
|
|||
|
||||
m_window_id = s_window_id_allocator.allocate();
|
||||
|
||||
Gfx::IntRect launch_origin_rect;
|
||||
if (auto* launch_origin_rect_string = getenv("__libgui_launch_origin_rect")) {
|
||||
auto parts = StringView(launch_origin_rect_string).split_view(',');
|
||||
if (parts.size() == 4) {
|
||||
launch_origin_rect = Gfx::IntRect {
|
||||
parts[0].to_int().value_or(0),
|
||||
parts[1].to_int().value_or(0),
|
||||
parts[2].to_int().value_or(0),
|
||||
parts[3].to_int().value_or(0),
|
||||
};
|
||||
}
|
||||
unsetenv("__libgui_launch_origin_rect");
|
||||
}
|
||||
|
||||
WindowServerConnection::the().async_create_window(
|
||||
m_window_id,
|
||||
m_rect_when_windowless,
|
||||
|
@ -141,7 +155,8 @@ void Window::show()
|
|||
m_resize_aspect_ratio,
|
||||
(i32)m_window_type,
|
||||
m_title_when_windowless,
|
||||
parent_window ? parent_window->window_id() : 0);
|
||||
parent_window ? parent_window->window_id() : 0,
|
||||
launch_origin_rect);
|
||||
m_visible = true;
|
||||
|
||||
apply_icon();
|
||||
|
|
|
@ -496,7 +496,8 @@ void ClientConnection::create_window(i32 window_id, Gfx::IntRect const& rect,
|
|||
bool auto_position, bool has_alpha_channel, bool modal, bool minimizable, bool resizable,
|
||||
bool fullscreen, bool frameless, bool accessory, float opacity, float alpha_hit_threshold,
|
||||
Gfx::IntSize const& base_size, Gfx::IntSize const& size_increment, Gfx::IntSize const& minimum_size,
|
||||
Optional<Gfx::IntSize> const& resize_aspect_ratio, i32 type, String const& title, i32 parent_window_id)
|
||||
Optional<Gfx::IntSize> const& resize_aspect_ratio, i32 type, String const& title, i32 parent_window_id,
|
||||
Gfx::IntRect const& launch_origin_rect)
|
||||
{
|
||||
Window* parent_window = nullptr;
|
||||
if (parent_window_id) {
|
||||
|
@ -519,6 +520,9 @@ void ClientConnection::create_window(i32 window_id, Gfx::IntRect const& rect,
|
|||
|
||||
auto window = Window::construct(*this, (WindowType)type, window_id, modal, minimizable, frameless, resizable, fullscreen, accessory, parent_window);
|
||||
|
||||
if (!launch_origin_rect.is_empty())
|
||||
window->start_launch_animation(launch_origin_rect);
|
||||
|
||||
window->set_has_alpha_channel(has_alpha_channel);
|
||||
window->set_title(title);
|
||||
if (!fullscreen) {
|
||||
|
|
|
@ -101,7 +101,7 @@ private:
|
|||
virtual void update_menu_item(i32, i32, i32, String const&, bool, bool, bool, bool, String const&) override;
|
||||
virtual void create_window(i32, Gfx::IntRect const&, bool, bool, bool,
|
||||
bool, bool, bool, bool, bool, float, float, Gfx::IntSize const&, Gfx::IntSize const&, Gfx::IntSize const&,
|
||||
Optional<Gfx::IntSize> const&, i32, String const&, i32) override;
|
||||
Optional<Gfx::IntSize> const&, i32, String const&, i32, Gfx::IntRect const&) override;
|
||||
virtual Messages::WindowServer::DestroyWindowResponse destroy_window(i32) override;
|
||||
virtual void set_window_title(i32, String const&) override;
|
||||
virtual Messages::WindowServer::GetWindowTitleResponse get_window_title(i32) override;
|
||||
|
|
|
@ -365,6 +365,26 @@ void Window::start_minimize_animation()
|
|||
m_animation->start();
|
||||
}
|
||||
|
||||
void Window::start_launch_animation(Gfx::IntRect const& launch_origin_rect)
|
||||
{
|
||||
m_animation = Animation::create();
|
||||
m_animation->set_length(150);
|
||||
m_animation->on_update = [this, launch_origin_rect](float progress, Gfx::Painter& painter, Screen& screen, Gfx::DisjointRectSet& flush_rects) {
|
||||
Gfx::PainterStateSaver saver(painter);
|
||||
painter.set_draw_op(Gfx::Painter::DrawOp::Invert);
|
||||
|
||||
auto rect = interpolate_rect(launch_origin_rect, frame().rect(), progress);
|
||||
|
||||
painter.draw_rect(rect, Color::Transparent); // Color doesn't matter, we draw inverted
|
||||
flush_rects.add(rect.intersected(screen.rect()));
|
||||
Compositor::the().invalidate_screen(rect);
|
||||
};
|
||||
m_animation->on_stop = [this] {
|
||||
m_animation = nullptr;
|
||||
};
|
||||
m_animation->start();
|
||||
}
|
||||
|
||||
void Window::set_opacity(float opacity)
|
||||
{
|
||||
if (m_opacity == opacity)
|
||||
|
|
|
@ -259,6 +259,8 @@ public:
|
|||
bool has_taskbar_rect() const { return m_have_taskbar_rect; };
|
||||
void start_minimize_animation();
|
||||
|
||||
void start_launch_animation(Gfx::IntRect const&);
|
||||
|
||||
Gfx::IntRect tiled_rect(Screen*, WindowTileType) const;
|
||||
void recalculate_rect();
|
||||
|
||||
|
|
|
@ -44,7 +44,8 @@ endpoint WindowServer
|
|||
Optional<Gfx::IntSize> resize_aspect_ratio,
|
||||
i32 type,
|
||||
[UTF8] String title,
|
||||
i32 parent_window_id) =|
|
||||
i32 parent_window_id,
|
||||
Gfx::IntRect launch_origin_rect) =|
|
||||
|
||||
destroy_window(i32 window_id) => (Vector<i32> destroyed_window_ids)
|
||||
|
||||
|
|
Loading…
Reference in a new issue