Skip to content

Commit

Permalink
wip wip wip!
Browse files Browse the repository at this point in the history
  • Loading branch information
mattkae committed Nov 3, 2024
1 parent 0fac119 commit fb5d53f
Show file tree
Hide file tree
Showing 7 changed files with 275 additions and 252 deletions.
80 changes: 49 additions & 31 deletions src/output.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,20 +60,17 @@ Output::Output(
{
}

std::shared_ptr<Workspace> const& Output::get_active_workspace() const
std::shared_ptr<Workspace> Output::active() const
{
for (auto& info : workspaces)
{
if (info->get_workspace() == active_workspace)
return info;
}
if (active_workspace.expired())
return nullptr;

throw std::runtime_error("get_active_workspace: unable to find the active workspace. We shouldn't be here!");
return active_workspace.lock();
}

std::shared_ptr<Container> Output::intersect(const MirPointerEvent* event)
{
if (get_active_workspace_num() < 0)
if (active_workspace.expired())
{
mir::log_error("Output::handle_pointer_event: unexpectedly trying to handle a pointer event when we lack workspaces");
return nullptr;
Expand Down Expand Up @@ -113,59 +110,80 @@ void Output::delete_container(std::shared_ptr<miracle::Container> const& contain
workspace->delete_container(container);
}

void Output::advise_new_workspace(int workspace)
void Output::advise_new_workspace(WorkspaceCreationData const&& data)
{
// Workspaces are always kept in sorted order
// Workspaces are always kept in sorted order with numbered workspaces in front, then named
// workspaces, and then spooky unmarked workspaces.
auto new_workspace = std::make_shared<Workspace>(
this, tools, workspace, config, window_controller, state, floating_window_manager);
this, tools, data.id, data.num, data.name, config, window_controller, state, floating_window_manager);
insert_sorted(workspaces, new_workspace, [](std::shared_ptr<Workspace> const& a, std::shared_ptr<Workspace> const& b)
{
return a->get_workspace() < b->get_workspace();
if (a->num() && b->num())
return a->num().value() < b->num().value();
else if (a->num())
return true;
else if (b->num())
return false;
else if (a->name() && b->name())
return a->name().value() < b->name().value();
else if (a->name())
return true;
else if (b->name())
return false;
else
return false;
});
}

void Output::advise_workspace_deleted(int workspace)
void Output::advise_workspace_deleted(uint32_t id)
{
for (auto it = workspaces.begin(); it != workspaces.end(); it++)
{
if (it->get()->get_workspace() == workspace)
if (it->get()->id() == id)
{
workspaces.erase(it);
return;
}
}
}

bool Output::advise_workspace_active(int key)
bool Output::advise_workspace_active(uint32_t id)
{
std::shared_ptr<Workspace> from = nullptr;
std::shared_ptr<Workspace> to = nullptr;
for (auto const& workspace : workspaces)
int from_index = -1;
int to_index = -1;
for (int i = 0; i < workspaces.size(); i++)
{
if (workspace->get_workspace() == active_workspace)
auto const& workspace = workspaces[i];
if (!active_workspace.expired() && workspace == active_workspace.lock())
{
from = workspace;
from_index = i;
}

if (workspace->get_workspace() == key)
if (workspace->id() == id)
{
if (active_workspace == key)
if (!active_workspace.expired() && active_workspace.lock()->id() == id)
return true;

to = workspace;
to_index = i;
}
}

if (!to)
{
mir::fatal_error("advise_workspace_active: switch to workspace that doesn't exist: %d", key);
mir::fatal_error("advise_workspace_active: switch to workspace that doesn't exist: %d", id);
return false;
}

if (!from)
{
to->show();
active_workspace = key;
active_workspace = to;

auto to_rectangle = get_workspace_rectangle(active_workspace);
auto to_rectangle = get_workspace_rectangle(to_index);
set_position(glm::vec2(
to_rectangle.top_left.x.as_int(),
to_rectangle.top_left.y.as_int()));
Expand All @@ -175,14 +193,14 @@ bool Output::advise_workspace_active(int key)

// Note: It is very important that [active_workspace] be modified before notifications
// are sent out.
active_workspace = key;
active_workspace = to;

auto from_src = get_workspace_rectangle(from->get_workspace());
auto from_src = get_workspace_rectangle(from_index);
from->transfer_pinned_windows_to(to);

// If 'from' is empty, we can delete the workspace. However, this means that from_src is now incorrect
if (from->is_empty())
workspace_manager.delete_workspace(from->get_workspace());
workspace_manager.delete_workspace(from->id());

// Show everyone so that we can animate over all workspaces
for (auto const& workspace : workspaces)
Expand All @@ -192,7 +210,7 @@ bool Output::advise_workspace_active(int key)
{ geom::X { position_offset.x }, geom::Y { position_offset.y } },
area.size
};
auto to_src = get_workspace_rectangle(to->get_workspace());
auto to_src = get_workspace_rectangle(to_index);
geom::Rectangle src {
{ geom::X { -from_src.top_left.x.as_int() }, geom::Y { from_src.top_left.y.as_int() } },
area.size
Expand Down Expand Up @@ -314,7 +332,7 @@ void Output::request_toggle_active_float()
void Output::add_immediately(miral::Window& window, AllocationHint hint)
{
auto& prev_info = window_controller.info_for(window);
WindowSpecification spec = window_helpers::copy_from(prev_info);
miral::WindowSpecification spec = window_helpers::copy_from(prev_info);

// If we are adding a window immediately, let's force it back into existence
if (spec.state() == mir_window_state_hidden)
Expand All @@ -331,21 +349,21 @@ void Output::graft(std::shared_ptr<Container> const& container)
get_active_workspace()->graft(container);
}

geom::Rectangle Output::get_workspace_rectangle(int workspace) const
geom::Rectangle Output::get_workspace_rectangle(size_t i) const
{
// TODO: Support vertical workspaces one day in the future
const size_t x = (workspace - 1) * area.size.width.as_int();
const size_t x = (i - 1) * area.size.width.as_int();
return geom::Rectangle {
geom::Point { geom::X { x }, geom::Y { 0 } },
geom::Size { area.size.width.as_int(), area.size.height.as_int() }
};
}

[[nodiscard]] Workspace const* Output::workspace(int key) const
[[nodiscard]] Workspace const* Output::workspace(uint32_t id) const
{
for (auto const& workspace : workspaces)
{
if (workspace->get_workspace() == key)
if (workspace->id() == id)
return workspace.get();
}

Expand Down
24 changes: 15 additions & 9 deletions src/output.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ class WindowManagerToolsWindowController;
class CompositorState;
class Animator;

struct WorkspaceCreationData
{
uint32_t id;
std::optional<int> num;
std::optional<std::string> name;
};

class Output
{
public:
Expand All @@ -60,9 +67,9 @@ class Output
[[nodiscard]] std::shared_ptr<Container> create_container(
miral::WindowInfo const& window_info, AllocationHint const& hint) const;
void delete_container(std::shared_ptr<miracle::Container> const& container);
void advise_new_workspace(int workspace);
void advise_workspace_deleted(int workspace);
bool advise_workspace_active(int workspace);
void advise_new_workspace(WorkspaceCreationData const&&);
void advise_workspace_deleted(uint32_t id);
bool advise_workspace_active(uint32_t id);
void advise_application_zone_create(miral::Zone const& application_zone);
void advise_application_zone_update(miral::Zone const& updated, miral::Zone const& original);
void advise_application_zone_delete(miral::Zone const& application_zone);
Expand All @@ -87,8 +94,7 @@ class Output
// Getters

[[nodiscard]] std::vector<miral::Window> collect_all_windows() const;
[[nodiscard]] int get_active_workspace_num() const { return active_workspace; }
[[nodiscard]] std::shared_ptr<Workspace> const& get_active_workspace() const;
[[nodiscard]] std::shared_ptr<Workspace> active() const;
[[nodiscard]] std::vector<std::shared_ptr<Workspace>> const& get_workspaces() const { return workspaces; }
[[nodiscard]] geom::Rectangle const& get_area() const { return area; }
[[nodiscard]] std::vector<miral::Zone> const& get_app_zones() const { return application_zone_list; }
Expand All @@ -97,9 +103,9 @@ class Output
[[nodiscard]] glm::mat4 get_transform() const;
/// Gets the relative position of the current rectangle (e.g. the active
/// rectangle with be at position (0, 0))
[[nodiscard]] geom::Rectangle get_workspace_rectangle(int workspace) const;
[[nodiscard]] Workspace const* workspace(int key) const;
nlohmann::json to_json() const;
[[nodiscard]] geom::Rectangle get_workspace_rectangle(size_t i) const;
[[nodiscard]] Workspace const* workspace(uint32_t id) const;
[[nodiscard]] nlohmann::json to_json() const;

private:
miral::Output output;
Expand All @@ -111,7 +117,7 @@ class Output
std::shared_ptr<Config> config;
WindowController& window_controller;
Animator& animator;
int active_workspace = -1;
std::weak_ptr<Workspace> active_workspace;
std::vector<std::shared_ptr<Workspace>> workspaces;
std::vector<miral::Zone> application_zone_list;
bool is_active_ = false;
Expand Down
29 changes: 11 additions & 18 deletions src/workspace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,25 +62,23 @@ class OutputTilingWindowTreeInterface : public TilingWindowTreeInterface
Workspace* workspace;
};

std::string get_name(std::shared_ptr<MiracleConfig> const& config, int workspace)
{
return config->get_workspace_config(workspace).name;
}

}

Workspace::Workspace(
miracle::Output* output,
miral::WindowManagerTools const& tools,
int workspace,
uint32_t id,
std::optional<int> num,
std::optional<std::string> name,
std::shared_ptr<Config> const& config,
WindowController& window_controller,
CompositorState const& state,
std::shared_ptr<MinimalWindowManager> const& floating_window_manager) :
output { output },
tools { tools },
workspace { workspace },
name { ::get_name(config, workspace) },
id_{ id },
num_{ num },
name_{ name },
window_controller { window_controller },
state { state },
config { config },
Expand All @@ -91,11 +89,6 @@ Workspace::Workspace(
{
}

int Workspace::get_workspace() const
{
return workspace;
}

void Workspace::set_area(mir::geometry::Rectangle const& area)
{
tree->set_area(area);
Expand All @@ -112,8 +105,8 @@ AllocationHint Workspace::allocate_position(
AllocationHint const& hint)
{
// If there's no ideal layout type, use the one provided by the workspace
auto layout = hint.container_type == ContainerType::none
? config->get_workspace_config(workspace).layout
auto layout = (hint.container_type == ContainerType::none && num_)
? config->get_workspace_config(num_.value()).layout
: hint.container_type;
switch (layout)
{
Expand Down Expand Up @@ -457,7 +450,7 @@ std::shared_ptr<ParentContainer> Workspace::get_layout_container()

nlohmann::json Workspace::to_json() const
{
bool is_focused = output->get_active_workspace_num() == workspace;
bool const is_focused = output->get_active_workspace().get() == this;

// Note: The reported workspace area appears to be the placement
// area of the root tree.
Expand All @@ -474,10 +467,10 @@ nlohmann::json Workspace::to_json() const
nodes.push_back(container->to_json());

return {
{ "num", workspace },
{ "num", num_ ? num_.value() : -1, },
{ "id", reinterpret_cast<std::uintptr_t>(this) },
{ "type", "workspace" },
{ "name", std::to_string(workspace) },
{ "name", "TODO!" },
{ "visible", output->is_active() && is_focused },
{ "focused", output->is_active() && is_focused },
{ "urgent", false },
Expand Down
16 changes: 10 additions & 6 deletions src/workspace.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,14 @@ class Workspace
Workspace(
Output* output,
miral::WindowManagerTools const& tools,
int workspace,
uint32_t id,
std::optional<int> num,
std::optional<std::string> name,
std::shared_ptr<Config> const& config,
WindowController& window_controller,
CompositorState const& state,
std::shared_ptr<MinimalWindowManager> const& floating_window_manager);

[[nodiscard]] int get_workspace() const;
void set_area(mir::geometry::Rectangle const&);
void recalculate_area();

Expand All @@ -80,16 +81,19 @@ class Workspace
[[nodiscard]] bool is_empty() const;
void graft(std::shared_ptr<Container> const&);
/// Converts a workspace to its corresponding index in the workspace array.
[[nodiscard]] uint32_t id() const { return id_; }
[[nodiscard]] std::optional<int> num() const { return num_; }
[[nodiscard]] nlohmann::json to_json() const;
[[nodiscard]] TilingWindowTree const* get_tree() const { return tree.get(); }
nlohmann::json to_json() const;
[[nodiscard]] std::string const& get_name() { return name; }
[[nodiscard]] std::optional<std::string> const& name() { return name_; }

private:
Output* output;
miral::WindowManagerTools tools;
uint32_t id_;
std::optional<int> num_;
std::optional<std::string> name_;
std::shared_ptr<TilingWindowTree> tree;
int workspace;
std::string name;
std::vector<std::shared_ptr<FloatingWindowContainer>> floating_windows;
std::vector<std::shared_ptr<FloatingTreeContainer>> floating_trees;
WindowController& window_controller;
Expand Down
Loading

0 comments on commit fb5d53f

Please sign in to comment.