From 20bdb9f11af714b5532930804992cb3894b1cccf Mon Sep 17 00:00:00 2001 From: Ilia Bozhinov Date: Thu, 30 Jul 2020 20:18:13 +0200 Subject: [PATCH 1/5] add wlr-workspaces integration plugin --- plugins/single_plugins/meson.build | 1 + plugins/single_plugins/wlr-workspaces.cpp | 126 ++++++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 plugins/single_plugins/wlr-workspaces.cpp diff --git a/plugins/single_plugins/meson.build b/plugins/single_plugins/meson.build index 614cecdc0..24a638816 100644 --- a/plugins/single_plugins/meson.build +++ b/plugins/single_plugins/meson.build @@ -2,6 +2,7 @@ plugins = [ 'move', 'resize', 'command', 'autostart', 'vswipe', 'grid', 'wrot', 'expo', 'switcher', 'fast-switcher', 'oswitch', 'place', 'invert', 'fisheye', 'zoom', 'alpha', 'idle', 'extra-gestures', 'preserve-output', + 'wlr-workspaces', ] all_include_dirs = [wayfire_api_inc, wayfire_conf_inc, plugins_common_inc, vswitch_inc, wobbly_inc] diff --git a/plugins/single_plugins/wlr-workspaces.cpp b/plugins/single_plugins/wlr-workspaces.cpp new file mode 100644 index 000000000..31a255e33 --- /dev/null +++ b/plugins/single_plugins/wlr-workspaces.cpp @@ -0,0 +1,126 @@ +#include +#include +#include +#include +#include + +extern "C" +{ +#include +} + +namespace wf +{ +/** + * The workspaces manager is stored in core, to allow for a single instance. + */ +class wlr_workspaces_manager : public custom_data_t +{ + public: + int refcount = 0; + wlr_workspace_manager_v1 *manager; + wlr_workspaces_manager() + { + manager = wlr_workspace_manager_v1_create(wf::get_core().display); + } +}; + +class wlr_workspaces_intergration : public plugin_interface_t +{ + public: + wlr_workspace_group_handle_v1 *group; + std::vector> workspaces; + + wf::wl_listener_wrapper on_commit; + + void init() override + { + /* Take ref to manager */ + auto manager = wf::get_core().get_data_safe(); + ++manager->refcount; + + /* Create group & workspaces */ + group = wlr_workspace_group_handle_v1_create(manager->manager); + + dimensions_t ws_dim = output->workspace->get_workspace_grid_size(); + workspaces.resize(ws_dim.height, + std::vector(ws_dim.width)); + for (int i = 0; i < ws_dim.height; i++) + { + for (int j = 0; j < ws_dim.width; j++) + { + workspaces[i][j] = wlr_workspace_handle_v1_create(group); + + std::string name = + output->to_string() + "workspace-" + + std::to_string(i * ws_dim.height + j); + wlr_workspace_handle_v1_set_name(workspaces[i][j], name.c_str()); + + wl_array coordinates; + wl_array_init(&coordinates); + *(int32_t*)wl_array_add(&coordinates, sizeof(int32_t)) = i; + *(int32_t*)wl_array_add(&coordinates, sizeof(int32_t)) = j; + wlr_workspace_handle_v1_set_coordinates( + workspaces[i][j], &coordinates); + wl_array_release(&coordinates); + } + } + + /* Initially, workspace 0,0 is active */ + wlr_workspace_handle_v1_set_active(workspaces[0][0], true); + output->connect_signal("workspace-changed", &on_current_workspace_changed); + + /* Listen for client requests */ + on_commit.set_callback([&] (void*) + { + point_t active_workspace = {0, 0}; + dimensions_t ws_dim = output->workspace->get_workspace_grid_size(); + + for (int i = 0; i < ws_dim.height; i++) + { + for (int j = 0; j < ws_dim.width; j++) + { + if (workspaces[i][j]->current & + WLR_WORKSPACE_HANDLE_V1_STATE_ACTIVE) + { + // workspaces in core are [column, row] + active_workspace = {j, i}; + } + } + } + + output->workspace->request_workspace(active_workspace); + }); + } + + signal_connection_t on_current_workspace_changed = [&] (signal_data_t *data) + { + auto ev = static_cast(data); + wlr_workspace_handle_v1_set_active( + workspaces[ev->old_viewport.x][ev->old_viewport.y], false); + wlr_workspace_handle_v1_set_active( + workspaces[ev->new_viewport.x][ev->new_viewport.y], true); + }; + + void fini() override + { + auto manager = wf::get_core().get_data(); + --manager->refcount; + + if (manager->refcount <= 0) + { + /** Make sure to clean up global data on shutdown */ + wf::get_core().erase_data(); + } + } + + /** Currently, we do not want to kill clients when unloading this plugin, so + * we disallow disabling it. */ + bool is_unloadable() override + { + return false; + } +}; +} + +DECLARE_WAYFIRE_PLUGIN(wf::wlr_workspaces_intergration); From c90c952828770bb2105dbc693452a32d8ea90987 Mon Sep 17 00:00:00 2001 From: Ilia Bozhinov Date: Thu, 30 Jul 2020 20:48:45 +0200 Subject: [PATCH 2/5] fixes to wlr-workspace plugin --- plugins/single_plugins/wlr-workspaces.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/plugins/single_plugins/wlr-workspaces.cpp b/plugins/single_plugins/wlr-workspaces.cpp index 31a255e33..2a08057e4 100644 --- a/plugins/single_plugins/wlr-workspaces.cpp +++ b/plugins/single_plugins/wlr-workspaces.cpp @@ -52,8 +52,8 @@ class wlr_workspaces_intergration : public plugin_interface_t workspaces[i][j] = wlr_workspace_handle_v1_create(group); std::string name = - output->to_string() + "workspace-" + - std::to_string(i * ws_dim.height + j); + output->to_string() + ":workspace-" + + std::to_string(i * ws_dim.width + j); wlr_workspace_handle_v1_set_name(workspaces[i][j], name.c_str()); wl_array coordinates; @@ -91,15 +91,16 @@ class wlr_workspaces_intergration : public plugin_interface_t output->workspace->request_workspace(active_workspace); }); + on_commit.connect(&manager->manager->events.commit); } signal_connection_t on_current_workspace_changed = [&] (signal_data_t *data) { auto ev = static_cast(data); wlr_workspace_handle_v1_set_active( - workspaces[ev->old_viewport.x][ev->old_viewport.y], false); + workspaces[ev->old_viewport.y][ev->old_viewport.x], false); wlr_workspace_handle_v1_set_active( - workspaces[ev->new_viewport.x][ev->new_viewport.y], true); + workspaces[ev->new_viewport.y][ev->new_viewport.x], true); }; void fini() override From 0b899d3542d9308f86c3a60715a6cb3201d309e1 Mon Sep 17 00:00:00 2001 From: Ilia Bozhinov Date: Fri, 21 May 2021 10:49:28 +0200 Subject: [PATCH 3/5] handle create/remove workspaces --- plugins/single_plugins/wlr-workspaces.cpp | 61 +++++++++++++++-------- 1 file changed, 40 insertions(+), 21 deletions(-) diff --git a/plugins/single_plugins/wlr-workspaces.cpp b/plugins/single_plugins/wlr-workspaces.cpp index 2a08057e4..f0e527c2f 100644 --- a/plugins/single_plugins/wlr-workspaces.cpp +++ b/plugins/single_plugins/wlr-workspaces.cpp @@ -6,7 +6,7 @@ extern "C" { -#include +#include } namespace wf @@ -14,60 +14,79 @@ namespace wf /** * The workspaces manager is stored in core, to allow for a single instance. */ -class wlr_workspaces_manager : public custom_data_t +class wlr_ext_workspaces_manager : public custom_data_t { public: int refcount = 0; - wlr_workspace_manager_v1 *manager; - wlr_workspaces_manager() + wlr_ext_workspace_manager_v1 *manager; + wlr_ext_workspaces_manager() { - manager = wlr_workspace_manager_v1_create(wf::get_core().display); + manager = wlr_ext_workspace_manager_v1_create(wf::get_core().display); } }; -class wlr_workspaces_intergration : public plugin_interface_t +class wlr_ext_workspaces_intergration : public plugin_interface_t { public: - wlr_workspace_group_handle_v1 *group; - std::vector> workspaces; + wlr_ext_workspace_group_handle_v1 *group; + std::vector> workspaces; + std::vector> on_ws_remove; wf::wl_listener_wrapper on_commit; + wf::wl_listener_wrapper on_ws_create; void init() override { /* Take ref to manager */ - auto manager = wf::get_core().get_data_safe(); + auto manager = wf::get_core().get_data_safe(); ++manager->refcount; /* Create group & workspaces */ - group = wlr_workspace_group_handle_v1_create(manager->manager); + group = wlr_ext_workspace_group_handle_v1_create(manager->manager); + on_ws_create.set_callback([&] (void *data) + { + auto ev = static_cast< + wlr_ext_workspace_group_handle_v1_create_workspace_event*>(data); + LOGD("Application requested creation of workspace ", ev->name); + }); + on_ws_create.connect(&group->events.create_workspace_request); dimensions_t ws_dim = output->workspace->get_workspace_grid_size(); workspaces.resize(ws_dim.height, - std::vector(ws_dim.width)); + std::vector(ws_dim.width)); + on_ws_remove.resize(ws_dim.height, + std::vector(ws_dim.width)); for (int i = 0; i < ws_dim.height; i++) { for (int j = 0; j < ws_dim.width; j++) { - workspaces[i][j] = wlr_workspace_handle_v1_create(group); + workspaces[i][j] = wlr_ext_workspace_handle_v1_create(group); std::string name = output->to_string() + ":workspace-" + std::to_string(i * ws_dim.width + j); - wlr_workspace_handle_v1_set_name(workspaces[i][j], name.c_str()); + wlr_ext_workspace_handle_v1_set_name(workspaces[i][j], name.c_str()); wl_array coordinates; wl_array_init(&coordinates); *(int32_t*)wl_array_add(&coordinates, sizeof(int32_t)) = i; *(int32_t*)wl_array_add(&coordinates, sizeof(int32_t)) = j; - wlr_workspace_handle_v1_set_coordinates( + wlr_ext_workspace_handle_v1_set_coordinates( workspaces[i][j], &coordinates); wl_array_release(&coordinates); + + on_ws_remove[i][j].set_callback([&] (void*) + { + LOGD("Application requested removal of workspace (", + i, ", ", j, ")"); + }); + + on_ws_remove[i][j].connect(&workspaces[i][j]->events.remove_request); } } /* Initially, workspace 0,0 is active */ - wlr_workspace_handle_v1_set_active(workspaces[0][0], true); + wlr_ext_workspace_handle_v1_set_active(workspaces[0][0], true); output->connect_signal("workspace-changed", &on_current_workspace_changed); /* Listen for client requests */ @@ -81,7 +100,7 @@ class wlr_workspaces_intergration : public plugin_interface_t for (int j = 0; j < ws_dim.width; j++) { if (workspaces[i][j]->current & - WLR_WORKSPACE_HANDLE_V1_STATE_ACTIVE) + WLR_EXT_WORKSPACE_HANDLE_V1_STATE_ACTIVE) { // workspaces in core are [column, row] active_workspace = {j, i}; @@ -97,21 +116,21 @@ class wlr_workspaces_intergration : public plugin_interface_t signal_connection_t on_current_workspace_changed = [&] (signal_data_t *data) { auto ev = static_cast(data); - wlr_workspace_handle_v1_set_active( + wlr_ext_workspace_handle_v1_set_active( workspaces[ev->old_viewport.y][ev->old_viewport.x], false); - wlr_workspace_handle_v1_set_active( + wlr_ext_workspace_handle_v1_set_active( workspaces[ev->new_viewport.y][ev->new_viewport.x], true); }; void fini() override { - auto manager = wf::get_core().get_data(); + auto manager = wf::get_core().get_data(); --manager->refcount; if (manager->refcount <= 0) { /** Make sure to clean up global data on shutdown */ - wf::get_core().erase_data(); + wf::get_core().erase_data(); } } @@ -124,4 +143,4 @@ class wlr_workspaces_intergration : public plugin_interface_t }; } -DECLARE_WAYFIRE_PLUGIN(wf::wlr_workspaces_intergration); +DECLARE_WAYFIRE_PLUGIN(wf::wlr_ext_workspaces_intergration); From ee64e853cdca469f279502bda03c01c92fd03e7e Mon Sep 17 00:00:00 2001 From: Ilia Bozhinov Date: Fri, 21 May 2021 11:21:00 +0200 Subject: [PATCH 4/5] plugin-loader: print an error when plugin .so is not found --- src/output/plugin-loader.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/output/plugin-loader.cpp b/src/output/plugin-loader.cpp index 3202b1183..2a550ebeb 100644 --- a/src/output/plugin-loader.cpp +++ b/src/output/plugin-loader.cpp @@ -181,15 +181,23 @@ void plugin_manager::reload_dynamic_plugins() continue; } + bool found = false; for (std::filesystem::path plugin_prefix : plugin_prefixes) { auto plugin_path = plugin_prefix / ("lib" + plugin_name + ".so"); if (std::filesystem::exists(plugin_path)) { + found = true; next_plugins.push_back(plugin_path); break; } } + + if (!found) + { + LOGE("Could not find plugin \"", plugin_name, "\"", + " in WAYFIRE_PLUGIN_PATH or in \"", PLUGIN_PATH, "\""); + } } } From 409b47d435b693f266f498e9e450b029c4791bf9 Mon Sep 17 00:00:00 2001 From: Ilia Bozhinov Date: Fri, 21 May 2021 11:30:48 +0200 Subject: [PATCH 5/5] add support for newer functionality of workspace protocol --- plugins/single_plugins/wlr-workspaces.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/plugins/single_plugins/wlr-workspaces.cpp b/plugins/single_plugins/wlr-workspaces.cpp index f0e527c2f..1b529f9e1 100644 --- a/plugins/single_plugins/wlr-workspaces.cpp +++ b/plugins/single_plugins/wlr-workspaces.cpp @@ -30,7 +30,7 @@ class wlr_ext_workspaces_intergration : public plugin_interface_t public: wlr_ext_workspace_group_handle_v1 *group; std::vector> workspaces; - std::vector> on_ws_remove; + std::vector>> on_ws_remove; wf::wl_listener_wrapper on_commit; wf::wl_listener_wrapper on_ws_create; @@ -54,8 +54,7 @@ class wlr_ext_workspaces_intergration : public plugin_interface_t dimensions_t ws_dim = output->workspace->get_workspace_grid_size(); workspaces.resize(ws_dim.height, std::vector(ws_dim.width)); - on_ws_remove.resize(ws_dim.height, - std::vector(ws_dim.width)); + on_ws_remove.resize(ws_dim.height); for (int i = 0; i < ws_dim.height; i++) { for (int j = 0; j < ws_dim.width; j++) @@ -75,13 +74,16 @@ class wlr_ext_workspaces_intergration : public plugin_interface_t workspaces[i][j], &coordinates); wl_array_release(&coordinates); - on_ws_remove[i][j].set_callback([&] (void*) + on_ws_remove[i].emplace_back( + std::make_unique()); + on_ws_remove[i][j] = std::make_unique(); + on_ws_remove[i][j]->set_callback([=] (void*) { LOGD("Application requested removal of workspace (", i, ", ", j, ")"); }); - on_ws_remove[i][j].connect(&workspaces[i][j]->events.remove_request); + on_ws_remove[i][j]->connect(&workspaces[i][j]->events.remove_request); } }