diff --git a/src/meson.build b/src/meson.build index d09b4b8..8989d63 100644 --- a/src/meson.build +++ b/src/meson.build @@ -67,7 +67,7 @@ obs = shared_module('obs', 'obs.cpp', dependencies: [wayfire, json], install: true, install_dir: join_paths(get_option('libdir'), 'wayfire')) pin_view = shared_module('pin-view', 'pin-view.cpp', - dependencies: [wayfire, json], + dependencies: [wayfire, json, wf_protos], install: true, install_dir: join_paths(get_option('libdir'), 'wayfire')) endif diff --git a/src/pin-view.cpp b/src/pin-view.cpp index 7f92dd1..6d5dc4e 100644 --- a/src/pin-view.cpp +++ b/src/pin-view.cpp @@ -34,8 +34,12 @@ #include #include #include +#include +#include #include #include +#include + namespace wf { namespace pin_view @@ -43,7 +47,8 @@ namespace pin_view class pin_view_data : public wf::custom_data_t { public: - wf::scene::layer layer; + wf::geometry_t geometry; + wf::point_t workspace; wf::view_role_t role; }; class wayfire_pin_view : public wf::plugin_interface_t @@ -68,35 +73,19 @@ class wayfire_pin_view : public wf::plugin_interface_t auto view = wf::ipc::find_view_by_id(data["view-id"]); if (view) { + auto output = view->get_output(); + output->connect(&on_workspace_changed); if (!view->get_data()) { pin_view_data pv_data; - pv_data.layer = *wf::get_view_layer(view); - pv_data.role = view->role; - view->store_data(std::make_unique(pv_data)); - } - - auto output = view->get_output(); - int x = 0, y = 0; - if (data.contains("x")) - { - x = data["x"].get(); - if (data.contains("y")) - { - y = data["y"].get(); - } - - auto og = output->get_relative_geometry(); - auto cws = output->wset()->get_current_workspace(); - wf::point_t nws{x, y}; + pv_data.role = view->role; if (auto toplevel = toplevel_cast(view)) { - auto vg = toplevel->get_geometry(); - toplevel->move(vg.x + (nws.x - cws.x) * og.width, vg.y + (nws.y - cws.y) * og.height); + pv_data.workspace = output->wset()->get_view_main_workspace(toplevel); + pv_data.geometry = toplevel->get_geometry(); } - } else - { - view->role = wf::VIEW_ROLE_DESKTOP_ENVIRONMENT; + + view->store_data(std::make_unique(pv_data)); } wf::scene::layer layer; @@ -126,10 +115,43 @@ class wayfire_pin_view : public wf::plugin_interface_t layer = wf::scene::layer::TOP; } + auto og = output->get_relative_geometry(); + int x = 0, y = 0; + if (data.contains("x")) + { + x = data["x"].get(); + if (data.contains("y")) + { + y = data["y"].get(); + } + + wf::point_t nws{x, y}; + if (auto toplevel = toplevel_cast(view)) + { + auto cws = output->wset()->get_view_main_workspace(toplevel); + auto vg = toplevel->get_geometry(); + toplevel->move(vg.x + (nws.x - cws.x) * og.width, vg.y + (nws.y - cws.y) * og.height); + } + } else + { + if (auto toplevel = toplevel_cast(view)) + { + wf::point_t nws = output->wset()->get_current_workspace(); + auto cws = output->wset()->get_view_main_workspace(toplevel); + auto vg = toplevel->get_geometry(); + toplevel->move(vg.x + (nws.x - cws.x) * og.width, vg.y + (nws.y - cws.y) * og.height); + toplevel->set_geometry(og); + } + + view->role = wf::VIEW_ROLE_DESKTOP_ENVIRONMENT; + wf::scene::readd_front(view->get_output()->node_for_layer(layer), view->get_root_node()); + return wf::ipc::json_ok(); + } + wf::scene::readd_front(output->node_for_layer(layer), view->get_root_node()); } else { - return wf::ipc::json_error("Failed to find view with given id. Maybe it was closed?"); + return wf::ipc::json_error("Failed to find view with given id."); } return wf::ipc::json_ok(); @@ -144,7 +166,19 @@ class wayfire_pin_view : public wf::plugin_interface_t { auto pvd = view->get_data(); view->role = pvd->role; - wf::scene::readd_front(view->get_output()->node_for_layer(pvd->layer), view->get_root_node()); + wf::scene::readd_front(view->get_output()->wset()->get_node(), view->get_root_node()); + if (auto toplevel = toplevel_cast(view)) + { + auto output = view->get_output(); + auto og = output->get_relative_geometry(); + auto cws = output->wset()->get_view_main_workspace(toplevel); + auto vg = toplevel->get_geometry(); + toplevel->move(vg.x + (pvd->workspace.x - cws.x) * og.width, + vg.y + (pvd->workspace.y - cws.y) * og.height); + toplevel->set_geometry(pvd->geometry); + } + + view->release_data(); } else { LOGE("Failed to find view with given id. Perhaps it is not pinned."); @@ -154,10 +188,41 @@ class wayfire_pin_view : public wf::plugin_interface_t return wf::ipc::json_ok(); }; + wf::signal::connection_t on_workspace_changed = + [=] (wf::workspace_changed_signal *ev) + { + auto nws = ev->new_viewport; + auto output = ev->output; + auto og = output->get_relative_geometry(); + for (auto & view : wf::get_core().get_all_views()) + { + if (!view->get_data()) + { + continue; + } + + if (auto toplevel = toplevel_cast(view)) + { + auto cws = output->wset()->get_view_main_workspace(toplevel); + auto vg = toplevel->get_geometry(); + toplevel->move(vg.x + (nws.x - cws.x) * og.width, vg.y + (nws.y - cws.y) * og.height); + } + } + }; + void fini() override { + for (auto & view : wf::get_core().get_all_views()) + { + if (view->get_data()) + { + view->release_data(); + } + } + ipc_repo->unregister_method("pin-view/pin"); ipc_repo->unregister_method("pin-view/unpin"); + on_workspace_changed.disconnect(); } }; }