mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 06:27:45 +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
6 changed files with 46 additions and 4 deletions
|
@ -122,6 +122,20 @@ void Window::show()
|
||||||
|
|
||||||
m_window_id = s_window_id_allocator.allocate();
|
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(
|
WindowServerConnection::the().async_create_window(
|
||||||
m_window_id,
|
m_window_id,
|
||||||
m_rect_when_windowless,
|
m_rect_when_windowless,
|
||||||
|
@ -141,7 +155,8 @@ void Window::show()
|
||||||
m_resize_aspect_ratio,
|
m_resize_aspect_ratio,
|
||||||
(i32)m_window_type,
|
(i32)m_window_type,
|
||||||
m_title_when_windowless,
|
m_title_when_windowless,
|
||||||
parent_window ? parent_window->window_id() : 0);
|
parent_window ? parent_window->window_id() : 0,
|
||||||
|
launch_origin_rect);
|
||||||
m_visible = true;
|
m_visible = true;
|
||||||
|
|
||||||
apply_icon();
|
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 auto_position, bool has_alpha_channel, bool modal, bool minimizable, bool resizable,
|
||||||
bool fullscreen, bool frameless, bool accessory, float opacity, float alpha_hit_threshold,
|
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,
|
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;
|
Window* parent_window = nullptr;
|
||||||
if (parent_window_id) {
|
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);
|
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_has_alpha_channel(has_alpha_channel);
|
||||||
window->set_title(title);
|
window->set_title(title);
|
||||||
if (!fullscreen) {
|
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 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,
|
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&,
|
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 Messages::WindowServer::DestroyWindowResponse destroy_window(i32) override;
|
||||||
virtual void set_window_title(i32, String const&) override;
|
virtual void set_window_title(i32, String const&) override;
|
||||||
virtual Messages::WindowServer::GetWindowTitleResponse get_window_title(i32) override;
|
virtual Messages::WindowServer::GetWindowTitleResponse get_window_title(i32) override;
|
||||||
|
|
|
@ -365,6 +365,26 @@ void Window::start_minimize_animation()
|
||||||
m_animation->start();
|
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)
|
void Window::set_opacity(float opacity)
|
||||||
{
|
{
|
||||||
if (m_opacity == opacity)
|
if (m_opacity == opacity)
|
||||||
|
|
|
@ -259,6 +259,8 @@ public:
|
||||||
bool has_taskbar_rect() const { return m_have_taskbar_rect; };
|
bool has_taskbar_rect() const { return m_have_taskbar_rect; };
|
||||||
void start_minimize_animation();
|
void start_minimize_animation();
|
||||||
|
|
||||||
|
void start_launch_animation(Gfx::IntRect const&);
|
||||||
|
|
||||||
Gfx::IntRect tiled_rect(Screen*, WindowTileType) const;
|
Gfx::IntRect tiled_rect(Screen*, WindowTileType) const;
|
||||||
void recalculate_rect();
|
void recalculate_rect();
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,8 @@ endpoint WindowServer
|
||||||
Optional<Gfx::IntSize> resize_aspect_ratio,
|
Optional<Gfx::IntSize> resize_aspect_ratio,
|
||||||
i32 type,
|
i32 type,
|
||||||
[UTF8] String title,
|
[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)
|
destroy_window(i32 window_id) => (Vector<i32> destroyed_window_ids)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue