#ifndef MIR_EXAMPLE_BASIC_WINDOW_MANAGER_H_
#define MIR_EXAMPLE_BASIC_WINDOW_MANAGER_H_
#include <map>
#include <mutex>
{
namespace examples
{
template<typename Info>
struct SurfaceTo
{
using type = std::map<std::weak_ptr<scene::Surface>, Info, std::owner_less<std::weak_ptr<scene::Surface>>>;
};
template<typename Info>
struct SessionTo
{
using type = std::map<std::weak_ptr<scene::Session>, Info, std::owner_less<std::weak_ptr<scene::Session>>>;
};
template<typename SessionInfo, typename SurfaceInfo>
class BasicWindowManagerToolsCopy
{
public:
virtual auto find_session(std::function<
bool(SessionInfo
const& info)>
const& predicate)
-> std::shared_ptr<scene::Session> = 0;
virtual auto info_for(std::weak_ptr<scene::Session>
const& session)
const -> SessionInfo& = 0;
virtual auto info_for(std::weak_ptr<scene::Surface>
const& surface)
const -> SurfaceInfo& = 0;
std::shared_ptr<scene::Session> const& focus,
std::shared_ptr<scene::Surface> const& surface) = 0;
virtual auto surface_at(geometry::Point cursor)
const -> std::shared_ptr<scene::Surface> = 0;
virtual void raise(
SurfaceSet const& surfaces) = 0;
virtual void forget(std::weak_ptr<scene::Surface>
const& surface) = 0;
};
template<typename WindowManagementPolicy, typename SessionInfo, typename SurfaceInfo>
class BasicWindowManagerCopy : public shell::WindowManager,
private BasicWindowManagerToolsCopy<SessionInfo, SurfaceInfo>
{
public:
template <typename... PolicyArgs>
shell::FocusController* focus_controller,
PolicyArgs&&... policy_args) :
focus_controller(focus_controller),
policy(this, std::forward<PolicyArgs>(policy_args)...)
{
}
private:
void add_session(std::shared_ptr<scene::Session> const& session) override
{
std::lock_guard<decltype(mutex)> lock(mutex);
session_info[session] = SessionInfo();
policy.handle_session_info_updated(session_info, displays);
}
void remove_session(std::shared_ptr<scene::Session> const& session) override
{
std::lock_guard<decltype(mutex)> lock(mutex);
session_info.erase(session);
policy.handle_session_info_updated(session_info, displays);
}
std::shared_ptr<scene::Session> const& session,
scene::SurfaceCreationParameters const& params,
std::function<
frontend::SurfaceId(std::shared_ptr<scene::Session>
const& session, scene::SurfaceCreationParameters
const& params)>
const& build)
override
{
std::lock_guard<decltype(mutex)> lock(mutex);
scene::SurfaceCreationParameters const placed_params = policy.handle_place_new_surface(session, params);
auto const result = build(session, placed_params);
auto const surface = session->surface(result);
surface_info.emplace(surface, SurfaceInfo{session, surface, placed_params});
policy.handle_new_surface(session, surface);
policy.generate_decorations_for(session, surface, surface_info, build);
return result;
}
void modify_surface(
std::shared_ptr<scene::Session> const& session,
std::shared_ptr<scene::Surface> const& surface,
shell::SurfaceSpecification const& modifications) override
{
std::lock_guard<decltype(mutex)> lock(mutex);
policy.handle_modify_surface(session, surface, modifications);
}
void remove_surface(
std::shared_ptr<scene::Session> const& session,
std::weak_ptr<scene::Surface> const& surface) override
{
std::lock_guard<decltype(mutex)> lock(mutex);
policy.handle_delete_surface(session, surface);
surface_info.erase(surface);
}
void forget(std::weak_ptr<scene::Surface> const& surface) override
{
surface_info.erase(surface);
}
void add_display(geometry::Rectangle const& area) override
{
std::lock_guard<decltype(mutex)> lock(mutex);
policy.handle_displays_updated(session_info, displays);
}
void remove_display(geometry::Rectangle const& area) override
{
std::lock_guard<decltype(mutex)> lock(mutex);
policy.handle_displays_updated(session_info, displays);
}
{
std::lock_guard<decltype(mutex)> lock(mutex);
return policy.handle_keyboard_event(event);
}
{
std::lock_guard<decltype(mutex)> lock(mutex);
return policy.handle_touch_event(event);
}
{
std::lock_guard<decltype(mutex)> lock(mutex);
cursor = {
return policy.handle_pointer_event(event);
}
int set_surface_attribute(
std::shared_ptr<scene::Session> const& ,
std::shared_ptr<scene::Surface> const& surface,
int value) override
{
std::lock_guard<decltype(mutex)> lock(mutex);
switch (attrib)
{
{
auto const state = policy.handle_set_state(surface,
MirSurfaceState(value));
return surface->configure(attrib, state);
}
default:
return surface->configure(attrib, value);
}
}
auto find_session(std::function<bool(SessionInfo const& info)> const& predicate)
-> std::shared_ptr<scene::Session> override
{
for(auto& info : session_info)
{
if (predicate(info.second))
{
return info.first.lock();
}
}
return std::shared_ptr<scene::Session>{};
}
auto info_for(std::weak_ptr<scene::Session> const& session) const -> SessionInfo& override
{
return const_cast<SessionInfo&>(session_info.at(session));
}
auto info_for(std::weak_ptr<scene::Surface> const& surface) const -> SurfaceInfo& override
{
return const_cast<SurfaceInfo&>(surface_info.at(surface));
}
std::shared_ptr<scene::Session> focused_session() const override
{
return focus_controller->focused_session();
}
std::shared_ptr<scene::Surface> focused_surface() const override
{
return focus_controller->focused_surface();
}
void focus_next_session() override
{
focus_controller->focus_next_session();
}
void set_focus_to(
std::shared_ptr<scene::Session> const& focus,
std::shared_ptr<scene::Surface> const& surface) override
{
focus_controller->set_focus_to(focus, surface);
}
auto surface_at(geometry::Point cursor) const -> std::shared_ptr<scene::Surface> override
{
return focus_controller->surface_at(cursor);
}
{
focus_controller->raise(surfaces);
}
auto active_display() -> geometry::Rectangle const override
{
geometry::Rectangle result;
if (auto const surface = focused_surface())
{
auto const surface_rect = surface->input_bounds();
int max_overlap_area = -1;
for (auto const& display : displays)
{
auto const intersection = surface_rect.intersection_with(display).size;
if (intersection.width.as_int()*intersection.height.as_int() > max_overlap_area)
{
max_overlap_area = intersection.width.as_int()*intersection.height.as_int();
result = display;
}
}
return result;
}
for (auto const& display : displays)
{
if (display.contains(cursor))
{
return display;
}
}
if (displays.size())
result = *displays.begin();
return result;
}
shell::FocusController* const focus_controller;
WindowManagementPolicy policy;
std::mutex mutex;
geometry::Rectangles displays;
geometry::Point cursor;
};
}
}
#endif