mirror of
https://github.com/miracle-wm-org/miracle-wm.git
synced 2024-11-22 03:02:17 +03:00
feature: animation groundwork + window movement animation (#121)
This commit is contained in:
parent
57515dda03
commit
66ce46ee07
@ -37,27 +37,6 @@ AlignConsecutiveShortCaseStatements:
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCaseColons: false
|
||||
AlignConsecutiveTableGenBreakingDAGArgColons:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveTableGenCondOperatorColons:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveTableGenDefinitionColons:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: DontAlign
|
||||
AlignTrailingComments:
|
||||
@ -84,7 +63,6 @@ BitFieldColonSpacing: Both
|
||||
BreakAdjacentStringLiterals: true
|
||||
BreakAfterAttributes: Leave
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakAfterReturnType: None
|
||||
BreakArrays: true
|
||||
BreakBeforeBinaryOperators: All
|
||||
BreakBeforeConceptDeclarations: Always
|
||||
@ -92,10 +70,8 @@ BreakBeforeBraces: Allman
|
||||
BreakBeforeInlineASMColon: OnlyMultiline
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: AfterColon
|
||||
BreakFunctionDefinitionParameters: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakStringLiterals: true
|
||||
BreakTemplateDeclarations: MultiLine
|
||||
ColumnLimit: 0
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
@ -157,7 +133,6 @@ LambdaBodyIndentation: OuterScope
|
||||
LineEnding: DeriveLF
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MainIncludeChar: Quote
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: Inner
|
||||
ObjCBinPackProtocolList: Auto
|
||||
@ -171,7 +146,6 @@ PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakOpenParenthesis: 0
|
||||
PenaltyBreakScopeResolution: 500
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
@ -189,7 +163,6 @@ RequiresClausePosition: OwnLine
|
||||
RequiresExpressionIndentation: OuterScope
|
||||
SeparateDefinitionBlocks: Leave
|
||||
ShortNamespaceLines: 1
|
||||
SkipMacroDefinitionBody: false
|
||||
SortIncludes: CaseSensitive
|
||||
SortJavaStaticImport: Before
|
||||
SortUsingDeclarations: LexicographicNumeric
|
||||
@ -237,7 +210,6 @@ StatementAttributeLikeMacros:
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TableGenBreakInsideDAGArg: DontBreak
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
VerilogBreakBetweenInstancePorts: true
|
||||
|
@ -61,6 +61,7 @@ add_library(miracle-wm-implementation
|
||||
src/i3_command_executor.cpp
|
||||
src/surface_tracker.cpp
|
||||
src/window_tools_accessor.cpp
|
||||
src/animator.cpp
|
||||
)
|
||||
|
||||
add_executable(miracle-wm
|
||||
|
220
src/animator.cpp
Normal file
220
src/animator.cpp
Normal file
@ -0,0 +1,220 @@
|
||||
/**
|
||||
Copyright (C) 2024 Matthew Kosarek
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
|
||||
#include "animator.h"
|
||||
#include <mir/scene/surface.h>
|
||||
#include <mir/server_action_queue.h>
|
||||
#include <chrono>
|
||||
#define MIR_LOG_COMPONENT "animator"
|
||||
#include <mir/log.h>
|
||||
|
||||
using namespace miracle;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
Animation::Animation(
|
||||
miral::Window const& window,
|
||||
miracle::AnimationType animation_type,
|
||||
std::function<void(AnimationStepResult const&)> const& callback)
|
||||
: window{window},
|
||||
type{animation_type},
|
||||
callback{callback}
|
||||
{
|
||||
}
|
||||
|
||||
Animation& Animation::operator=(miracle::Animation const& other)
|
||||
{
|
||||
window = other.window;
|
||||
type = other.type;
|
||||
from = other.from;
|
||||
to = other.to;
|
||||
endtime_seconds = other.endtime_seconds;
|
||||
runtime_seconds = other.runtime_seconds;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Animation Animation::move_lerp(
|
||||
miral::Window const& window,
|
||||
mir::geometry::Rectangle const& _from,
|
||||
mir::geometry::Rectangle const& _to,
|
||||
std::function<void(AnimationStepResult const&)> const& callback)
|
||||
{
|
||||
Animation result(window, AnimationType::move_lerp, callback);
|
||||
result.from = _from;
|
||||
result.to = _to;
|
||||
result.endtime_seconds = 0.25f;
|
||||
return result;
|
||||
}
|
||||
|
||||
std::weak_ptr<mir::scene::Surface> Animation::get_surface() const
|
||||
{
|
||||
return window.operator std::weak_ptr<mir::scene::Surface>();
|
||||
}
|
||||
|
||||
AnimationStepResult Animation::step()
|
||||
{
|
||||
auto weak_surface = get_surface();
|
||||
if (weak_surface.expired())
|
||||
{
|
||||
return {
|
||||
window,
|
||||
true,
|
||||
glm::vec2(to.top_left.x.as_int(), to.top_left.y.as_int()),
|
||||
glm::vec2(to.size.width.as_int(), to.size.height.as_int()),
|
||||
glm::mat4(1.f),
|
||||
};
|
||||
}
|
||||
|
||||
runtime_seconds += timestep_seconds;
|
||||
if (runtime_seconds >= endtime_seconds)
|
||||
{
|
||||
return {
|
||||
window,
|
||||
true,
|
||||
glm::vec2(to.top_left.x.as_int(), to.top_left.y.as_int()),
|
||||
glm::vec2(to.size.width.as_int(), to.size.height.as_int()),
|
||||
glm::mat4(1.f),
|
||||
};
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case AnimationType::move_lerp:
|
||||
{
|
||||
// First, we begin lerping the position
|
||||
auto distance = to.top_left - from.top_left;
|
||||
float fraction = (runtime_seconds / endtime_seconds);
|
||||
float x = (float)distance.dx.as_int() * fraction;
|
||||
float y = (float)distance.dy.as_int() * fraction;
|
||||
|
||||
glm::vec2 position = {
|
||||
from.top_left.x.as_int() + x,
|
||||
from.top_left.y.as_int() + y
|
||||
};
|
||||
|
||||
return {
|
||||
window,
|
||||
false,
|
||||
position,
|
||||
glm::vec2(to.size.width.as_int(), to.size.height.as_int()),
|
||||
glm::mat4(1.f)
|
||||
};
|
||||
}
|
||||
default:
|
||||
return {
|
||||
window,
|
||||
false,
|
||||
glm::vec2(to.top_left.x.as_int(), to.top_left.y.as_int()),
|
||||
glm::vec2(to.size.width.as_int(), to.size.height.as_int()),
|
||||
glm::mat4(1.f)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Animator::Animator(
|
||||
std::shared_ptr<mir::ServerActionQueue> const& server_action_queue)
|
||||
: server_action_queue{server_action_queue},
|
||||
run_thread([&]() { run(); })
|
||||
{
|
||||
}
|
||||
|
||||
Animator::~Animator()
|
||||
{
|
||||
};
|
||||
|
||||
void Animator::animate_window_movement(
|
||||
miral::Window const& window,
|
||||
mir::geometry::Rectangle const& from,
|
||||
mir::geometry::Rectangle const& to,
|
||||
std::function<void(AnimationStepResult const&)> const& callback)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(processing_lock);
|
||||
for (auto it = queued_animations.begin(); it != queued_animations.end(); it++)
|
||||
{
|
||||
if (it->get_window() == window)
|
||||
{
|
||||
queued_animations.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
queued_animations.push_back(Animation::move_lerp(
|
||||
window,
|
||||
from,
|
||||
to,
|
||||
callback));
|
||||
cv.notify_one();
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct PendingUpdateData
|
||||
{
|
||||
AnimationStepResult result;
|
||||
std::function<void(miracle::AnimationStepResult const&)> callback;
|
||||
};
|
||||
}
|
||||
|
||||
void Animator::run()
|
||||
{
|
||||
// https://gist.github.com/mariobadr/673bbd5545242fcf9482
|
||||
using clock = std::chrono::high_resolution_clock;
|
||||
constexpr std::chrono::nanoseconds timestep(16ms);
|
||||
std::chrono::nanoseconds lag(0ns);
|
||||
auto time_start = clock::now();
|
||||
bool running = true;
|
||||
|
||||
while (running)
|
||||
{
|
||||
{
|
||||
std::unique_lock lock(processing_lock);
|
||||
if (queued_animations.empty())
|
||||
{
|
||||
cv.wait(lock);
|
||||
time_start = clock::now();
|
||||
}
|
||||
}
|
||||
|
||||
auto delta_time = clock::now() - time_start;
|
||||
time_start = clock::now();
|
||||
lag += std::chrono::duration_cast<std::chrono::nanoseconds>(delta_time);
|
||||
|
||||
while(lag >= timestep) {
|
||||
lag -= timestep;
|
||||
|
||||
std::vector<PendingUpdateData> update_data;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(processing_lock);
|
||||
for (auto it = queued_animations.begin(); it != queued_animations.end();)
|
||||
{
|
||||
auto& item = *it;
|
||||
auto result = item.step();
|
||||
|
||||
update_data.push_back({ result, item.get_callback() });
|
||||
if (result.should_erase)
|
||||
it = queued_animations.erase(it);
|
||||
else
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
server_action_queue->enqueue(this, [&, update_data]() {
|
||||
for (auto const& update_item : update_data)
|
||||
update_item.callback(update_item.result);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
109
src/animator.h
Normal file
109
src/animator.h
Normal file
@ -0,0 +1,109 @@
|
||||
/**
|
||||
Copyright (C) 2024 Matthew Kosarek
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
|
||||
#ifndef MIRACLEWM_ANIMATOR_H
|
||||
#define MIRACLEWM_ANIMATOR_H
|
||||
|
||||
#include <miral/window.h>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <glm/glm.hpp>
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <mir/geometry/rectangle.h>
|
||||
|
||||
namespace mir
|
||||
{
|
||||
class ServerActionQueue;
|
||||
}
|
||||
|
||||
namespace miracle
|
||||
{
|
||||
|
||||
enum class AnimationType
|
||||
{
|
||||
move_lerp
|
||||
};
|
||||
|
||||
struct AnimationStepResult
|
||||
{
|
||||
miral::Window window;
|
||||
bool should_erase = false;
|
||||
glm::vec2 position;
|
||||
glm::vec2 size;
|
||||
glm::mat4 transform;
|
||||
};
|
||||
|
||||
class Animation
|
||||
{
|
||||
public:
|
||||
static Animation move_lerp(
|
||||
miral::Window const& window,
|
||||
mir::geometry::Rectangle const& from,
|
||||
mir::geometry::Rectangle const& to,
|
||||
std::function<void(AnimationStepResult const&)> const& callback);
|
||||
Animation& operator=(Animation const& other);
|
||||
|
||||
AnimationStepResult step();
|
||||
miral::Window const& get_window() const { return window; }
|
||||
std::weak_ptr<mir::scene::Surface> get_surface() const;
|
||||
std::function<void(AnimationStepResult const&)> get_callback() const { return callback; }
|
||||
|
||||
private:
|
||||
Animation(
|
||||
miral::Window const& window,
|
||||
AnimationType animation_type,
|
||||
std::function<void(AnimationStepResult const&)> const& callback);
|
||||
|
||||
miral::Window window;
|
||||
AnimationType type;
|
||||
mir::geometry::Rectangle from;
|
||||
mir::geometry::Rectangle to;
|
||||
float endtime_seconds = 1.f;
|
||||
float runtime_seconds = 0.f;
|
||||
const float timestep_seconds = 0.016;
|
||||
std::function<void(AnimationStepResult const&)> callback;
|
||||
};
|
||||
|
||||
class Animator
|
||||
{
|
||||
public:
|
||||
/// This will take the MainLoop to schedule animation.
|
||||
explicit Animator(std::shared_ptr<mir::ServerActionQueue> const&);
|
||||
~Animator();
|
||||
|
||||
/// Queue an animation on a window from the provided point to the other
|
||||
/// point. It is assumed that the window has already been moved to the
|
||||
/// "to" position.
|
||||
void animate_window_movement(
|
||||
miral::Window const&,
|
||||
mir::geometry::Rectangle const& from,
|
||||
mir::geometry::Rectangle const& to,
|
||||
std::function<void(AnimationStepResult const&)> const& callback);
|
||||
|
||||
private:
|
||||
void run();
|
||||
std::shared_ptr<mir::ServerActionQueue> server_action_queue;
|
||||
std::vector<Animation> queued_animations;
|
||||
std::thread run_thread;
|
||||
std::mutex processing_lock;
|
||||
std::condition_variable cv;
|
||||
};
|
||||
|
||||
} // miracle
|
||||
|
||||
#endif // MIRACLEWM_ANIMATOR_H
|
@ -37,7 +37,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <miral/window_management_options.h>
|
||||
#include <miral/x11_support.h>
|
||||
#include <miroil/open_gl_context.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
using namespace miral;
|
||||
|
||||
|
@ -63,7 +63,8 @@ Policy::Policy(
|
||||
i3_command_executor(*this, workspace_manager, tools),
|
||||
surface_tracker{surface_tracker},
|
||||
ipc { std::make_shared<Ipc>(runner, workspace_manager, *this, server.the_main_loop(), i3_command_executor) },
|
||||
node_interface(tools)
|
||||
animator(server.the_main_loop()),
|
||||
node_interface(tools, animator)
|
||||
{
|
||||
workspace_observer_registrar.register_interest(ipc);
|
||||
|
||||
|
@ -26,6 +26,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "window_metadata.h"
|
||||
#include "workspace_manager.h"
|
||||
#include "surface_tracker.h"
|
||||
#include "animator.h"
|
||||
|
||||
#include <memory>
|
||||
#include <miral/external_client.h>
|
||||
@ -113,6 +114,7 @@ private:
|
||||
WorkspaceObserverRegistrar workspace_observer_registrar;
|
||||
WorkspaceManager workspace_manager;
|
||||
std::shared_ptr<Ipc> ipc;
|
||||
Animator animator;
|
||||
WindowManagerToolsTilingInterface node_interface;
|
||||
I3CommandExecutor i3_command_executor;
|
||||
SurfaceTracker& surface_tracker;
|
||||
|
@ -521,10 +521,10 @@ void Renderer::draw(mg::Renderable const& renderable, OutlineContext* context) c
|
||||
if (clip_area)
|
||||
{
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
auto clip_x = clip_area.value().top_left.x.as_int();
|
||||
glm::vec4 transformed_position = renderable.transformation() * glm::vec4(clip_area.value().top_left.x.as_int(), clip_area.value().top_left.y.as_int(), 0, 1);
|
||||
// The Y-coordinate is always relative to the top, so we make it relative to the bottom.
|
||||
auto clip_y = viewport.top_left.y.as_int() + viewport.size.height.as_int() - clip_area.value().top_left.y.as_int() - clip_area.value().size.height.as_int();
|
||||
glm::vec4 clip_pos(clip_x, clip_y, 0, 1);
|
||||
auto clip_y = viewport.top_left.y.as_int() + viewport.size.height.as_int() - transformed_position.y - clip_area.value().size.height.as_int();
|
||||
glm::vec4 clip_pos(transformed_position.x, clip_y, 0, 1);
|
||||
clip_pos = display_transform * clip_pos;
|
||||
|
||||
glScissor(
|
||||
|
@ -664,7 +664,7 @@ std::tuple<std::shared_ptr<ParentNode>, std::shared_ptr<ParentNode>> TilingWindo
|
||||
auto to_update = handle_remove(node);
|
||||
|
||||
// Note: When we remove moving_node from its initial position, there's a chance
|
||||
// that the target_lane was melted into another lane. Hence, we need to update it
|
||||
// that the target_lane was melted into another lane. Hence, we need to run it
|
||||
auto target_parent = to->get_parent().lock();
|
||||
auto index = target_parent->get_index_of_node(to);
|
||||
target_parent->graft_existing(node, index + 1);
|
||||
|
@ -19,12 +19,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "leaf_node.h"
|
||||
#include "window_helpers.h"
|
||||
#include "window_metadata.h"
|
||||
#include "animator.h"
|
||||
#include <mir/scene/surface.h>
|
||||
|
||||
using namespace miracle;
|
||||
|
||||
WindowManagerToolsTilingInterface::WindowManagerToolsTilingInterface(
|
||||
miral::WindowManagerTools const& tools) :
|
||||
tools { tools }
|
||||
miral::WindowManagerTools const& tools,
|
||||
Animator& animator) :
|
||||
tools { tools },
|
||||
animator { animator }
|
||||
{
|
||||
}
|
||||
|
||||
@ -34,21 +38,50 @@ bool WindowManagerToolsTilingInterface::is_fullscreen(miral::Window const& windo
|
||||
return window_helpers::is_window_fullscreen(info.state());
|
||||
}
|
||||
|
||||
void WindowManagerToolsTilingInterface::set_rectangle(miral::Window const& window, geom::Rectangle const& r)
|
||||
void WindowManagerToolsTilingInterface::set_rectangle(
|
||||
miral::Window const& window, geom::Rectangle const& r)
|
||||
{
|
||||
miral::WindowSpecification spec;
|
||||
spec.top_left() = r.top_left;
|
||||
spec.size() = r.size;
|
||||
tools.modify_window(window, spec);
|
||||
animator.animate_window_movement(
|
||||
window,
|
||||
geom::Rectangle(window.top_left(), window.size()),
|
||||
r,
|
||||
[this](miracle::AnimationStepResult const& result)
|
||||
{
|
||||
if (auto surface = result.window.operator std::shared_ptr<mir::scene::Surface>())
|
||||
{
|
||||
surface->set_transformation(result.transform);
|
||||
// Set the positions on the windows and the sub windows
|
||||
miral::WindowSpecification spec;
|
||||
spec.top_left() = mir::geometry::Point(
|
||||
result.position.x,
|
||||
result.position.y
|
||||
);
|
||||
spec.size() = mir::geometry::Size(
|
||||
result.size.x,
|
||||
result.size.y
|
||||
);
|
||||
tools.modify_window(result.window, spec);
|
||||
|
||||
auto& window_info = tools.info_for(window);
|
||||
for (auto const& child : window_info.children())
|
||||
{
|
||||
miral::WindowSpecification sub_spec;
|
||||
sub_spec.top_left() = r.top_left;
|
||||
sub_spec.size() = r.size;
|
||||
tools.modify_window(child, sub_spec);
|
||||
}
|
||||
auto& window_info = tools.info_for(result.window);
|
||||
mir::geometry::Rectangle new_rectangle(
|
||||
mir::geometry::Point(
|
||||
result.position.x,
|
||||
result.position.y),
|
||||
mir::geometry::Size(
|
||||
result.size.x,
|
||||
result.size.y));
|
||||
clip(result.window, new_rectangle);
|
||||
|
||||
for (auto const& child : window_info.children())
|
||||
{
|
||||
miral::WindowSpecification sub_spec;
|
||||
sub_spec.top_left() = spec.top_left();
|
||||
sub_spec.size() = spec.size();
|
||||
tools.modify_window(child, sub_spec);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
MirWindowState WindowManagerToolsTilingInterface::get_state(miral::Window const& window)
|
||||
@ -68,8 +101,8 @@ void WindowManagerToolsTilingInterface::change_state(miral::Window const& window
|
||||
|
||||
void WindowManagerToolsTilingInterface::clip(miral::Window const& window, geom::Rectangle const& r)
|
||||
{
|
||||
auto& window_info = tools.info_for(window);
|
||||
window_info.clip_area(r);
|
||||
// auto& window_info = tools.info_for(window);
|
||||
// window_info.clip_area(r);
|
||||
}
|
||||
|
||||
void WindowManagerToolsTilingInterface::noclip(miral::Window const& window)
|
||||
|
@ -23,10 +23,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace miracle
|
||||
{
|
||||
class Animator;
|
||||
|
||||
class WindowManagerToolsTilingInterface : public TilingInterface
|
||||
{
|
||||
public:
|
||||
explicit WindowManagerToolsTilingInterface(miral::WindowManagerTools const&);
|
||||
WindowManagerToolsTilingInterface(miral::WindowManagerTools const&, Animator& animator);
|
||||
bool is_fullscreen(miral::Window const&) override;
|
||||
void set_rectangle(miral::Window const&, geom::Rectangle const&) override;
|
||||
MirWindowState get_state(miral::Window const&) override;
|
||||
@ -41,6 +43,7 @@ public:
|
||||
|
||||
private:
|
||||
miral::WindowManagerTools tools;
|
||||
Animator& animator;
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user