diff --git a/metadata/panel.xml b/metadata/panel.xml index 6508a9db..0315f5cd 100644 --- a/metadata/panel.xml +++ b/metadata/panel.xml @@ -33,6 +33,11 @@ <_short>Autohide Duration 300 + + <_short>Outputs on which to show a panel instance + <_long>A comma separated list of output names on which to show panel instances. Set to * wildcard for all outputs. + * + <_short>Panel Position top diff --git a/src/panel/panel.cpp b/src/panel/panel.cpp index 0a7fccbf..6287d7b7 100644 --- a/src/panel/panel.cpp +++ b/src/panel/panel.cpp @@ -411,20 +411,109 @@ class WayfirePanelApp::impl { public: std::map> panels; + WfOption *panel_outputs = NULL; }; void WayfirePanelApp::on_config_reload() { + if (!priv->panel_outputs) + { + priv->panel_outputs = new WfOption("panel/outputs"); + } + for (auto& p : priv->panels) { p.second->handle_config_reload(); } } +bool WayfirePanelApp::panel_allowed_by_config(bool allowed, std::string output_name) +{ + if (allowed) + { + return std::string(*priv->panel_outputs).find("*") != std::string::npos || + std::string(*priv->panel_outputs).find(output_name) != std::string::npos; + } else + { + return std::string(*priv->panel_outputs).find("*") == std::string::npos && + std::string(*priv->panel_outputs).find(output_name) == std::string::npos; + } +} + +void WayfirePanelApp::update_panels() +{ + for (auto& o : *get_wayfire_outputs()) + { + auto output = o.get(); + auto output_name = o->monitor->get_connector(); + + if (panel_allowed_by_config(false, output_name)) + { + std::cout << "Removing panel from output: " << output_name << std::endl; + priv->panels.erase(output); + } + + const auto it = std::find_if(priv->panels.begin(), priv->panels.end(), + [&output_name] (const auto& panel) + { + return panel.first->monitor->get_connector() == output_name; + }); + + if ((it == priv->panels.end()) && panel_allowed_by_config(true, output_name)) + { + std::cout << "Adding panel for output: " << output_name << std::endl; + priv->panels[output] = std::unique_ptr( + new WayfirePanel(output)); + + if (ipc_server) + { + priv->panels[output]->handle_config_reload(); + priv->panels[output]->set_panel_app(this); + priv->panels[output]->init_widgets(); + } + } + } +} + void WayfirePanelApp::on_activate() { WayfireShellApp::on_activate(); + priv->panel_outputs->set_callback([=] () + { + update_panels(); + }); + + if (!ipc_server) + { + ipc_server = WayfireIPC::get_instance(); + } + + for (auto& p : priv->panels) + { + p.second->handle_config_reload(); + p.second->set_panel_app(this); + p.second->init_widgets(); + } + + if (priv->panels.empty()) + { + std::cout << std::endl << + "WARNING: wf-panel outputs option did not match any outputs, " \ + "so none were created. Set the [panel] outputs option to * " \ + "wildcard character in wf-shell configuariton file to match " \ + "all outputs, or set one or more of the following detected outputs:" << + std::endl << std::endl; + + for (auto& o : *get_wayfire_outputs()) + { + std::cout << o->monitor->get_connector() << std::endl; + } + + std::cout << std::endl << "Currently the [panel] outputs option is set to: " << + std::string(*priv->panel_outputs) << std::endl; + } + const static std::vector> icon_sizes_args = { {"panel/minimal_height", ""}, @@ -450,13 +539,6 @@ void WayfirePanelApp::on_activate() new CssFromConfigFont("panel/battery_font", ".battery {", "}"); new CssFromConfigFont("panel/clock_font", ".clock {", "}"); new CssFromConfigFont("panel/weather_font", ".weather {", "}"); - - ipc_server = WayfireIPC::get_instance(); - for (auto& p : priv->panels) - { - p.second->set_panel_app(this); - p.second->init_widgets(); - } } std::shared_ptr WayfirePanelApp::get_ipc_server_instance() @@ -466,8 +548,7 @@ std::shared_ptr WayfirePanelApp::get_ipc_server_instance() void WayfirePanelApp::handle_new_output(WayfireOutput *output) { - priv->panels[output] = std::unique_ptr( - new WayfirePanel(output)); + update_panels(); } WayfirePanel*WayfirePanelApp::panel_for_wl_output(wl_output *output) diff --git a/src/panel/panel.hpp b/src/panel/panel.hpp index 59ac66d6..a74fd3bf 100644 --- a/src/panel/panel.hpp +++ b/src/panel/panel.hpp @@ -45,10 +45,12 @@ class WayfirePanelApp : public WayfireShellApp void on_activate() override; void handle_new_output(WayfireOutput *output) override; void handle_output_removed(WayfireOutput *output) override; + bool panel_allowed_by_config(bool allowed, std::string output_name); + void update_panels(); void on_config_reload() override; void reload_css(); std::shared_ptr get_ipc_server_instance(); - std::shared_ptr ipc_server; + std::shared_ptr ipc_server = nullptr; private: WayfirePanelApp(); diff --git a/src/util/wf-shell-app.cpp b/src/util/wf-shell-app.cpp index 8a90b18d..90e78d87 100644 --- a/src/util/wf-shell-app.cpp +++ b/src/util/wf-shell-app.cpp @@ -249,12 +249,16 @@ void WayfireShellApp::on_activate() void WayfireShellApp::output_list_updated(const int pos, const int rem, const int add) { - auto display = Gdk::Display::get_default(); - auto monitors = display->get_monitors(); - for (int i = 0; i < add; i++) + auto display = Gdk::Display::get_default(); + auto monitors = display->get_monitors(); + int num_monitors = monitors->get_n_items(); + for (int i = 0; i < num_monitors; i++) { - auto obj = std::dynamic_pointer_cast(monitors->get_object(i + pos)); - add_output(obj); + auto obj = std::dynamic_pointer_cast(monitors->get_object(i)); + if (obj && !obj->get_connector().empty()) + { + add_output(obj); + } } } @@ -297,6 +301,11 @@ Gio::Application::Flags WayfireShellApp::get_extra_application_flags() return Gio::Application::Flags::NONE; } +std::vector>*WayfireShellApp::get_wayfire_outputs() +{ + return &monitors; +} + WayfireShellApp::WayfireShellApp() {} diff --git a/src/util/wf-shell-app.hpp b/src/util/wf-shell-app.hpp index e582fb06..6862f84c 100644 --- a/src/util/wf-shell-app.hpp +++ b/src/util/wf-shell-app.hpp @@ -89,6 +89,7 @@ class WayfireShellApp void add_css_file(std::string file, int priority); virtual Gio::Application::Flags get_extra_application_flags(); virtual std::string get_application_name() = 0; + std::vector> *get_wayfire_outputs(); /** * WayfireShellApp is a singleton class.