From 248b9a54e00144569450c1fb52096fe9abd04af1 Mon Sep 17 00:00:00 2001 From: Scott Moreau Date: Tue, 13 Aug 2024 17:04:20 -0600 Subject: [PATCH] Add pin-view plugin --- metadata/meson.build | 1 + metadata/pin-view.xml | 8 ++ src/meson.build | 3 + src/pin-view.cpp | 166 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 178 insertions(+) create mode 100644 metadata/pin-view.xml create mode 100644 src/pin-view.cpp diff --git a/metadata/meson.build b/metadata/meson.build index 60d6457..e2c7e9a 100644 --- a/metadata/meson.build +++ b/metadata/meson.build @@ -13,6 +13,7 @@ install_data('join-views.xml', install_dir: wayfire.get_variable(pkgconfig: 'met install_data('keycolor.xml', install_dir: wayfire.get_variable(pkgconfig: 'metadatadir')) install_data('mag.xml', install_dir: wayfire.get_variable(pkgconfig: 'metadatadir')) install_data('obs.xml', install_dir: wayfire.get_variable(pkgconfig: 'metadatadir')) +install_data('pin-view.xml', install_dir: wayfire.get_variable(pkgconfig: 'metadatadir')) install_data('showrepaint.xml', install_dir: wayfire.get_variable(pkgconfig: 'metadatadir')) install_data('view-shot.xml', install_dir: wayfire.get_variable(pkgconfig: 'metadatadir')) install_data('water.xml', install_dir: wayfire.get_variable(pkgconfig: 'metadatadir')) diff --git a/metadata/pin-view.xml b/metadata/pin-view.xml new file mode 100644 index 0000000..f9dc2fa --- /dev/null +++ b/metadata/pin-view.xml @@ -0,0 +1,8 @@ + + + + <_short>Pin View + <_long>Set a view layer, role and workspace + Window Management + + diff --git a/src/meson.build b/src/meson.build index a824dc8..d09b4b8 100644 --- a/src/meson.build +++ b/src/meson.build @@ -66,6 +66,9 @@ if json.found() 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], + install: true, install_dir: join_paths(get_option('libdir'), 'wayfire')) endif showrepaint = shared_module('showrepaint', 'showrepaint.cpp', diff --git a/src/pin-view.cpp b/src/pin-view.cpp new file mode 100644 index 0000000..7f92dd1 --- /dev/null +++ b/src/pin-view.cpp @@ -0,0 +1,166 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 Scott Moreau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +namespace wf +{ +namespace pin_view +{ +class pin_view_data : public wf::custom_data_t +{ + public: + wf::scene::layer layer; + wf::view_role_t role; +}; +class wayfire_pin_view : public wf::plugin_interface_t +{ + wf::shared_data::ref_ptr_t ipc_repo; + + public: + void init() override + { + ipc_repo->register_method("pin-view/pin", ipc_pin_view); + ipc_repo->register_method("pin-view/unpin", ipc_unpin_view); + } + + wf::ipc::method_callback ipc_pin_view = [=] (nlohmann::json data) -> nlohmann::json + { + WFJSON_EXPECT_FIELD(data, "view-id", number_unsigned); + WFJSON_EXPECT_FIELD(data, "layer", string); + /* workspace x,y */ + WFJSON_OPTIONAL_FIELD(data, "x", number_unsigned); + WFJSON_OPTIONAL_FIELD(data, "y", number_unsigned); + + auto view = wf::ipc::find_view_by_id(data["view-id"]); + if (view) + { + 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}; + 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); + } + } else + { + view->role = wf::VIEW_ROLE_DESKTOP_ENVIRONMENT; + } + + wf::scene::layer layer; + if (data["layer"] == "background") + { + layer = wf::scene::layer::BACKGROUND; + } else if (data["layer"] == "bottom") + { + layer = wf::scene::layer::BOTTOM; + } else if (data["layer"] == "workspace") + { + layer = wf::scene::layer::WORKSPACE; + } else if (data["layer"] == "top") + { + layer = wf::scene::layer::TOP; + } else if (data["layer"] == "unmanaged") + { + layer = wf::scene::layer::UNMANAGED; + } else if (data["layer"] == "overlay") + { + layer = wf::scene::layer::OVERLAY; + } else if (data["layer"] == "lock") + { + layer = wf::scene::layer::LOCK; + } else + { + layer = wf::scene::layer::TOP; + } + + 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_ok(); + }; + + wf::ipc::method_callback ipc_unpin_view = [=] (nlohmann::json data) -> nlohmann::json + { + WFJSON_EXPECT_FIELD(data, "view-id", number_unsigned); + + auto view = wf::ipc::find_view_by_id(data["view-id"]); + if (view && view->get_data()) + { + 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()); + } else + { + LOGE("Failed to find view with given id. Perhaps it is not pinned."); + return wf::ipc::json_error("Failed to find view with given id. Perhaps it is not pinned."); + } + + return wf::ipc::json_ok(); + }; + + void fini() override + { + ipc_repo->unregister_method("pin-view/pin"); + ipc_repo->unregister_method("pin-view/unpin"); + } +}; +} +} + +DECLARE_WAYFIRE_PLUGIN(wf::pin_view::wayfire_pin_view);