diff --git a/metadata/dock.xml b/metadata/dock.xml index 3451c111..ca791805 100644 --- a/metadata/dock.xml +++ b/metadata/dock.xml @@ -12,9 +12,20 @@ true - <_short>Autohide duration + <_short>Autohide animation duration + <_long>Time (in milliseconds) the dock takes to expand and retract 300 + + <_short>Autohide show delay + <_long>Amount of time (in milliseconds) the cursor needs to be in the zone before showing. + 300 + + + <_short>Autohide hide delay + <_long>Amount of time (in milliseconds) the cursor needs to be out of the zone before hiding. + 500 + <_short>Position bottom @@ -26,11 +37,33 @@ bottom <_name>Bottom + + left + <_name>Left + + + right + <_name>Right + + + + <_short>Max icons per line + <_long>If greater than 0, the dock will have a maximum number of entries per line, after which a new line is created. + 0 - - <_short>Dock height + + <_short>Minimal height 100 + + <_short>Minimal width + 100 + + + <_short>Anchor to edges + <_long>Wether the dock should extend all the way to the left and right; or top and bottom depending on orientation. + false + <_short>Dock icons height 72 diff --git a/metadata/panel.xml b/metadata/panel.xml index b59900e7..2da05f56 100644 --- a/metadata/panel.xml +++ b/metadata/panel.xml @@ -10,7 +10,8 @@ - <_short>Widgets Left + <_short>Widgets Left/Top + <_long>Widgets placed in the left zone of the bar, or top if the bar is vertical. menu spacing4 launchers window-list @@ -18,21 +19,50 @@ none - <_short>Widgets Right + <_short>Widgets Right/Bottom + <_long>Widgets placed in the right zone of the bar, or bottom if the bar is vertical. volume network battery clock <_short>Minimal Height 32 + <_long>Minimum height the panel takes. + + + <_short>Minimal Width + <_long>Minimum width the panel takes. + 32 + + + <_short>Anchor to edges + <_long>Wether the pannel should extend all the way to the left and right; or top and bottom depending on orientation. + true + + + <_short>Force center by widgets + <_long>If on, the widgets on the left and right of the panel always take the same amount of space and the widgets in center are forced in the middle of the screen. +This will lead to unused space on the side that has the least space taken up by the widgets. + false <_short>Autohide false - <_short>Autohide Duration + <_short>Autohide animation duration + <_long>Time (in milliseconds) the panel takes to expand and retract + 300 + + + <_short>Autohide show delay + <_long>Amount of time (in milliseconds) the cursor needs to be in the zone before showing. 300 + + <_short>Autohide hide delay + <_long>Amount of time (in milliseconds) the cursor needs to be out of the zone before hiding. + 500 + <_short>Panel Position top @@ -44,6 +74,14 @@ bottom <_name>Bottom + + left + <_name>Left + + + right + <_name>Right + <_short>Edge offset @@ -80,6 +118,7 @@ <_short>Launchers Spacing 4 + 0 <_short>Launchers Icon Size @@ -303,6 +342,11 @@ <_long>Displays the mute and set default icon on the left false + + <_short>Stack categories + <_long>Displays the outputs, inputs and streams stacked on top of each other instead of side by side + false + <_short>Spacing between controls 8 @@ -388,6 +432,11 @@ 0 0 + + <_short>Space between tray icons + 5 + 0 + <_short>Middle Button Activates Menu <_long>Mouse right button activates a tray item's secondary action instead of the item's menu. diff --git a/src/dock/dock-app.cpp b/src/dock/dock-app.cpp index dc6e6d9b..dfb6fc23 100644 --- a/src/dock/dock-app.cpp +++ b/src/dock/dock-app.cpp @@ -44,6 +44,14 @@ class WfDockApp::impl zwlr_foreign_toplevel_manager_v1 *toplevel_manager = NULL; }; +void WfDockApp::on_config_reload() +{ + for (auto& d : priv->docks) + { + d.second->handle_config_reload(); + } +} + void WfDockApp::on_activate() { WayfireShellApp::on_activate(); diff --git a/src/dock/dock.cpp b/src/dock/dock.cpp index 763cbfdb..feae78c0 100644 --- a/src/dock/dock.cpp +++ b/src/dock/dock.cpp @@ -1,17 +1,13 @@ -#include -#include -#include +#include +#include #include - -#include -#include #include -#include +#include #include "dock.hpp" +#include "wf-shell-app.hpp" +#include "wf-autohide-window.hpp" #include "../util/gtk-utils.hpp" -#include - class WfDock::impl { @@ -19,10 +15,11 @@ class WfDock::impl std::unique_ptr window; wl_surface *_wl_surface; Gtk::Box out_box; - Gtk::Box box; + Gtk::FlowBox box; WfOption css_path{"dock/css_path"}; - WfOption dock_height{"dock/dock_height"}; + WfOption position{"dock/position"}; + WfOption entries_per_line{"dock/max_per_line"}; public: impl(WayfireOutput *output) @@ -32,20 +29,20 @@ class WfDock::impl new WayfireAutohidingWindow(output, "dock")); window->set_auto_exclusive_zone(false); gtk_layer_set_layer(window->gobj(), GTK_LAYER_SHELL_LAYER_TOP); - gtk_layer_set_anchor(window->gobj(), GTK_LAYER_SHELL_EDGE_LEFT, true); - gtk_layer_set_anchor(window->gobj(), GTK_LAYER_SHELL_EDGE_RIGHT, true); + + gtk_layer_set_margin(window->gobj(), GTK_LAYER_SHELL_EDGE_TOP, 0); + gtk_layer_set_margin(window->gobj(), GTK_LAYER_SHELL_EDGE_BOTTOM, 0); gtk_layer_set_margin(window->gobj(), GTK_LAYER_SHELL_EDGE_LEFT, 0); gtk_layer_set_margin(window->gobj(), GTK_LAYER_SHELL_EDGE_RIGHT, 0); - out_box.append(box); - out_box.add_css_class("out-box"); + box.add_css_class("box"); - window->set_child(out_box); - window->add_css_class("wf-dock"); + window->set_child(box); + update_layout(); - out_box.set_halign(Gtk::Align::CENTER); + window->add_css_class("wf-dock"); - if ((std::string)css_path != "") + if (css_path.value() != "") { auto css = load_css_from_path(css_path); if (css) @@ -58,12 +55,40 @@ class WfDock::impl window->present(); _wl_surface = gdk_wayland_surface_get_wl_surface( window->get_surface()->gobj()); + } - box.add_tick_callback([=] (Glib::RefPtr fc) + void update_layout() + { + if (position.value() == "bottom") + { + // this is not great, but we lack better options without doing a + // layout with boxes in boxes (ugly) or some sort of custom layout manager + box.set_orientation(Gtk::Orientation::HORIZONTAL); + box.set_direction(Gtk::TextDirection::LTR); + } else if (position.value() == "left") + { + box.set_orientation(Gtk::Orientation::VERTICAL); + box.set_direction(Gtk::TextDirection::LTR); + } else if (position.value() == "right") { - set_clickable_region(); - return true; - }); + box.set_orientation(Gtk::Orientation::VERTICAL); + box.set_direction(Gtk::TextDirection::RTL); + } else // top + { + box.set_orientation(Gtk::Orientation::HORIZONTAL); + box.set_direction(Gtk::TextDirection::LTR); + } + + // 0 means no overflowing, so we just set the limits really high + if (entries_per_line == 0) + { + box.set_min_children_per_line(std::numeric_limits::max()); + box.set_max_children_per_line(std::numeric_limits::max()); + } else + { + box.set_min_children_per_line(entries_per_line); + box.set_max_children_per_line(entries_per_line); + } } void add_child(Gtk::Widget& widget) @@ -82,7 +107,7 @@ class WfDock::impl } /* Sets the central section as clickable and transparent edges as click-through - * Gets called regularly to ensure css size changes all register */ + * Gets called regularly to ensure css size changes all register */ void set_clickable_region() { auto surface = window->get_surface(); @@ -106,6 +131,11 @@ WfDock::WfDock(WayfireOutput *output) : {} WfDock::~WfDock() = default; +void WfDock::handle_config_reload() +{ + pimpl->update_layout(); +} + void WfDock::add_child(Gtk::Widget& w) { return pimpl->add_child(w); diff --git a/src/dock/dock.hpp b/src/dock/dock.hpp index d4db695c..8f8345e7 100644 --- a/src/dock/dock.hpp +++ b/src/dock/dock.hpp @@ -13,6 +13,7 @@ class WfDock WfDock(WayfireOutput *output); ~WfDock(); + void handle_config_reload(); void add_child(Gtk::Widget& widget); void rem_child(Gtk::Widget& widget); @@ -33,11 +34,11 @@ class WfDockApp : public WayfireShellApp static WfDockApp& get(); - /* Starts the program. get() is valid afterward the first (and the only) - * call to run() */ + /* Starts the program. get() is valid afterward the first (and the only) call to run() */ static void create(int argc, char **argv); virtual ~WfDockApp(); + void on_config_reload() override; void on_activate() override; void handle_new_output(WayfireOutput *output) override; void handle_output_removed(WayfireOutput *output) override; diff --git a/src/panel/panel.cpp b/src/panel/panel.cpp index 0864fb1f..178061c1 100644 --- a/src/panel/panel.cpp +++ b/src/panel/panel.cpp @@ -5,15 +5,18 @@ #include #include #include +#include +#include #include #include #include -#include #include + #include "panel.hpp" +#include "widget.hpp" #include "widgets/battery.hpp" #include "widgets/command-output.hpp" #include "widgets/language.hpp" @@ -41,6 +44,7 @@ class WayfirePanel::impl Gtk::CenterBox content_box; Gtk::Box left_box, center_box, right_box; + std::shared_ptr sides_size_group; using Widget = std::unique_ptr; using WidgetContainer = std::vector; @@ -48,46 +52,94 @@ class WayfirePanel::impl WayfireOutput *output; + WfOption panel_position{"panel/position"}; + WfOption force_center{"panel/force_center"}; + WfOption panel_layer{"panel/layer"}; std::function set_panel_layer = [=] () { - if ((std::string)panel_layer == "overlay") + if (panel_layer.value() == "overlay") { gtk_layer_set_layer(window->gobj(), GTK_LAYER_SHELL_LAYER_OVERLAY); } - if ((std::string)panel_layer == "top") + if (panel_layer.value() == "top") { gtk_layer_set_layer(window->gobj(), GTK_LAYER_SHELL_LAYER_TOP); } - if ((std::string)panel_layer == "bottom") + if (panel_layer.value() == "bottom") { gtk_layer_set_layer(window->gobj(), GTK_LAYER_SHELL_LAYER_BOTTOM); } - if ((std::string)panel_layer == "background") + if (panel_layer.value() == "background") { gtk_layer_set_layer(window->gobj(), GTK_LAYER_SHELL_LAYER_BACKGROUND); } }; - WfOption minimal_panel_height{"panel/minimal_height"}; + void set_boxes_orientation(Gtk::Orientation orientation) + { + content_box.set_orientation(orientation); + left_box.set_orientation(orientation); + center_box.set_orientation(orientation); + right_box.set_orientation(orientation); + } + + void update_orientation() + { + bool is_horizontal = !(panel_position.value() == "left" or panel_position.value() == + "right"); // checking like this also works with the fallback being the top + + set_boxes_orientation(is_horizontal ? Gtk::Orientation::HORIZONTAL : Gtk::Orientation::VERTICAL); + + if (force_center) + { + left_box.set_halign(Gtk::Align::CENTER); + right_box.set_halign(Gtk::Align::CENTER); + left_box.set_valign(Gtk::Align::CENTER); + right_box.set_valign(Gtk::Align::CENTER); + + if (is_horizontal) + { + sides_size_group->set_mode(Gtk::SizeGroup::Mode::HORIZONTAL); + } else + { + sides_size_group->set_mode(Gtk::SizeGroup::Mode::VERTICAL); + } + } else + { + sides_size_group->set_mode(Gtk::SizeGroup::Mode::NONE); + + if (is_horizontal) + { + left_box.set_halign(Gtk::Align::START); + right_box.set_halign(Gtk::Align::END); + left_box.set_valign(Gtk::Align::CENTER); + right_box.set_valign(Gtk::Align::CENTER); + } else + { + left_box.set_valign(Gtk::Align::START); + right_box.set_valign(Gtk::Align::END); + left_box.set_halign(Gtk::Align::CENTER); + right_box.set_halign(Gtk::Align::CENTER); + } + } + } void create_window() { window = std::make_unique(output, "panel"); - window->set_default_size(0, minimal_panel_height); window->add_css_class("wf-panel"); panel_layer.set_callback(set_panel_layer); set_panel_layer(); // initial setting - gtk_layer_set_anchor(window->gobj(), GTK_LAYER_SHELL_EDGE_LEFT, true); - gtk_layer_set_anchor(window->gobj(), GTK_LAYER_SHELL_EDGE_RIGHT, true); - gtk_layer_set_margin(window->gobj(), GTK_LAYER_SHELL_EDGE_LEFT, 0); - gtk_layer_set_margin(window->gobj(), GTK_LAYER_SHELL_EDGE_RIGHT, 0); + + update_orientation(); window->present(); + init_widgets(); init_layout(); } @@ -97,6 +149,7 @@ class WayfirePanel::impl left_box.add_css_class("left"); right_box.add_css_class("right"); center_box.add_css_class("center"); + content_box.set_start_widget(left_box); if (!center_box.get_children().empty()) { @@ -106,10 +159,12 @@ class WayfirePanel::impl content_box.set_end_widget(right_box); content_box.set_hexpand(true); + content_box.set_vexpand(true); - left_box.set_halign(Gtk::Align::START); center_box.set_halign(Gtk::Align::CENTER); - right_box.set_halign(Gtk::Align::END); + + sides_size_group->add_widget(left_box); + sides_size_group->add_widget(right_box); window->set_child(content_box); } @@ -277,15 +332,15 @@ class WayfirePanel::impl { left_widgets_opt.set_callback([=] () { - reload_widgets((std::string)left_widgets_opt, left_widgets, left_box); + reload_widgets(left_widgets_opt.value(), left_widgets, left_box); }); right_widgets_opt.set_callback([=] () { - reload_widgets((std::string)right_widgets_opt, right_widgets, right_box); + reload_widgets(right_widgets_opt.value(), right_widgets, right_box); }); center_widgets_opt.set_callback([=] () { - reload_widgets((std::string)center_widgets_opt, center_widgets, center_box); + reload_widgets(center_widgets_opt.value(), center_widgets, center_box); if (center_box.get_children().empty()) { content_box.unset_center_widget(); @@ -295,14 +350,15 @@ class WayfirePanel::impl } }); - reload_widgets((std::string)left_widgets_opt, left_widgets, left_box); - reload_widgets((std::string)right_widgets_opt, right_widgets, right_box); - reload_widgets((std::string)center_widgets_opt, center_widgets, center_box); + reload_widgets(left_widgets_opt.value(), left_widgets, left_box); + reload_widgets(right_widgets_opt.value(), right_widgets, right_box); + reload_widgets(center_widgets_opt.value(), center_widgets, center_box); } public: impl(WayfireOutput *output) : output(output) { + sides_size_group = Gtk::SizeGroup::create(Gtk::SizeGroup::Mode::NONE); create_window(); } @@ -318,6 +374,8 @@ class WayfirePanel::impl void handle_config_reload() { + update_orientation(); + for (auto& w : left_widgets) { w->handle_config_reload(); diff --git a/src/panel/widget.hpp b/src/panel/widget.hpp index 7452a901..fc8bd46f 100644 --- a/src/panel/widget.hpp +++ b/src/panel/widget.hpp @@ -7,8 +7,10 @@ #define DEFAULT_PANEL_HEIGHT "48" #define DEFAULT_ICON_SIZE 32 -#define PANEL_POSITION_BOTTOM "bottom" #define PANEL_POSITION_TOP "top" +#define PANEL_POSITION_BOTTOM "bottom" +#define PANEL_POSITION_LEFT "left" +#define PANEL_POSITION_RIGHT "right" class wayfire_config; class WayfireWidget diff --git a/src/panel/widgets/battery.cpp b/src/panel/widgets/battery.cpp index 4b7d2008..4e53702b 100644 --- a/src/panel/widgets/battery.cpp +++ b/src/panel/widgets/battery.cpp @@ -206,6 +206,24 @@ bool WayfireBatteryInfo::setup_dbus() return false; } +void WayfireBatteryInfo::update_layout() +{ + WfOption panel_position{"panel/position"}; + + if (panel_position.value() == PANEL_POSITION_LEFT or panel_position.value() == PANEL_POSITION_RIGHT) + { + button_box.set_orientation(Gtk::Orientation::VERTICAL); + } else + { + button_box.set_orientation(Gtk::Orientation::HORIZONTAL); + } +} + +void WayfireBatteryInfo::handle_config_reload() +{ + update_layout(); +} + // TODO: simplify config loading void WayfireBatteryInfo::init(Gtk::Box *container) @@ -232,6 +250,8 @@ void WayfireBatteryInfo::init(Gtk::Box *container) button.set_child(button_box); button.property_scale_factor().signal_changed() .connect(sigc::mem_fun(*this, &WayfireBatteryInfo::update_icon)); + + update_layout(); } WayfireBatteryInfo::~WayfireBatteryInfo() diff --git a/src/panel/widgets/battery.hpp b/src/panel/widgets/battery.hpp index d2b1e7d0..e0e5d257 100644 --- a/src/panel/widgets/battery.hpp +++ b/src/panel/widgets/battery.hpp @@ -41,6 +41,9 @@ class WayfireBatteryInfo : public WayfireWidget void update_details(); void update_state(); + void update_layout(); + void handle_config_reload(); + void on_properties_changed( const Gio::DBus::Proxy::MapChangedProperties& properties, const std::vector& invalidated); diff --git a/src/panel/widgets/launchers.cpp b/src/panel/widgets/launchers.cpp index 218316fd..d1f72636 100644 --- a/src/panel/widgets/launchers.cpp +++ b/src/panel/widgets/launchers.cpp @@ -45,6 +45,9 @@ bool WfLauncherButton::initialize(std::string name, std::string icon, std::strin return false; } + m_icon.set_halign(Gtk::Align::CENTER); + m_icon.set_valign(Gtk::Align::CENTER); + button.set_child(m_icon); button.add_css_class("widget-icon"); button.add_css_class("flat"); @@ -151,12 +154,34 @@ void WayfireLaunchers::init(Gtk::Box *container) { box.add_css_class("widget-icon"); box.add_css_class("launchers"); + container->append(box); + + box.set_halign(Gtk::Align::CENTER); + box.set_valign(Gtk::Align::CENTER); + handle_config_reload(); } +void WayfireLaunchers::update_layout() +{ + WfOption panel_position{"panel/position"}; + + if (panel_position.value() == PANEL_POSITION_LEFT or panel_position.value() == PANEL_POSITION_RIGHT) + { + box.set_orientation(Gtk::Orientation::VERTICAL); + } else + { + box.set_orientation(Gtk::Orientation::HORIZONTAL); + } + + box.set_spacing(spacing); +} + void WayfireLaunchers::handle_config_reload() { + update_layout(); + for (auto child : box.get_children()) { box.remove(*child); diff --git a/src/panel/widgets/launchers.hpp b/src/panel/widgets/launchers.hpp index ea424b21..4a5a5d0d 100644 --- a/src/panel/widgets/launchers.hpp +++ b/src/panel/widgets/launchers.hpp @@ -32,8 +32,12 @@ class WayfireLaunchers : public WayfireWidget launcher_container launchers; launcher_container get_launchers_from_config(); + WfOption spacing{"panel/launchers_spacing"}; + public: virtual void init(Gtk::Box *container); + + void update_layout(); virtual void handle_config_reload(); virtual ~WayfireLaunchers() {} diff --git a/src/panel/widgets/network.cpp b/src/panel/widgets/network.cpp index 788a6745..56a0f929 100644 --- a/src/panel/widgets/network.cpp +++ b/src/panel/widgets/network.cpp @@ -366,9 +366,9 @@ bool WayfireNetworkInfo::setup_dbus() void WayfireNetworkInfo::on_click() { - if ((std::string)click_command_opt != "default") + if (click_command_opt.value() != "default") { - Glib::spawn_command_line_async((std::string)click_command_opt); + Glib::spawn_command_line_async(click_command_opt.value()); } else { info->spawn_control_center(nm_proxy); @@ -408,8 +408,23 @@ void WayfireNetworkInfo::init(Gtk::Box *container) handle_config_reload(); } +void WayfireNetworkInfo::update_layout() +{ + WfOption panel_position{"panel/position"}; + + if (panel_position.value() == PANEL_POSITION_LEFT or panel_position.value() == PANEL_POSITION_RIGHT) + { + button_content.set_orientation(Gtk::Orientation::VERTICAL); + } else + { + button_content.set_orientation(Gtk::Orientation::HORIZONTAL); + } +} + void WayfireNetworkInfo::handle_config_reload() { + update_layout(); + if (status_opt.value() == NETWORK_STATUS_ICON) { if (status.get_parent()) diff --git a/src/panel/widgets/network.hpp b/src/panel/widgets/network.hpp index e6ab1d90..868b9f33 100644 --- a/src/panel/widgets/network.hpp +++ b/src/panel/widgets/network.hpp @@ -81,6 +81,8 @@ class WayfireNetworkInfo : public WayfireWidget void update_status(); void init(Gtk::Box *container); + + void update_layout(); void handle_config_reload(); virtual ~WayfireNetworkInfo(); }; diff --git a/src/panel/widgets/separator.cpp b/src/panel/widgets/separator.cpp index 08c4eac8..f5b88295 100644 --- a/src/panel/widgets/separator.cpp +++ b/src/panel/widgets/separator.cpp @@ -11,4 +11,24 @@ void WayfireSeparator::init(Gtk::Box *container) { separator.add_css_class("separator"); container->append(separator); + + update_layout(); +} + +void WayfireSeparator::update_layout() +{ + WfOption panel_position{"panel/position"}; + + if (panel_position.value() == PANEL_POSITION_LEFT or panel_position.value() == PANEL_POSITION_RIGHT) + { + separator.set_orientation(Gtk::Orientation::VERTICAL); + } else + { + separator.set_orientation(Gtk::Orientation::HORIZONTAL); + } +} + +void WayfireSeparator::handle_config_reload() +{ + update_layout(); } diff --git a/src/panel/widgets/separator.hpp b/src/panel/widgets/separator.hpp index bb70d3da..f21c8f94 100644 --- a/src/panel/widgets/separator.hpp +++ b/src/panel/widgets/separator.hpp @@ -11,6 +11,10 @@ class WayfireSeparator : public WayfireWidget WayfireSeparator(int pixels); virtual void init(Gtk::Box *container); + + void update_layout(); + void handle_config_reload(); + virtual ~WayfireSeparator() {} }; diff --git a/src/panel/widgets/tray/tray.cpp b/src/panel/widgets/tray/tray.cpp index dc4e670f..5b5e37ea 100644 --- a/src/panel/widgets/tray/tray.cpp +++ b/src/panel/widgets/tray/tray.cpp @@ -3,7 +3,11 @@ void WayfireStatusNotifier::init(Gtk::Box *container) { icons_box.add_css_class("tray"); - icons_box.set_spacing(5); + update_layout(); + icons_box.set_halign(Gtk::Align::FILL); + icons_box.set_valign(Gtk::Align::FILL); + icons_box.set_expand(true); + icons_box.set_homogeneous(true); container->append(icons_box); } @@ -28,3 +32,23 @@ void WayfireStatusNotifier::remove_item(const Glib::ustring & service) icons_box.remove(items.at(service)); items.erase(service); } + +void WayfireStatusNotifier::update_layout() +{ + WfOption panel_position{"panel/position"}; + + if ((panel_position.value() == PANEL_POSITION_LEFT) || (panel_position.value() == PANEL_POSITION_RIGHT)) + { + icons_box.set_orientation(Gtk::Orientation::VERTICAL); + } else + { + icons_box.set_orientation(Gtk::Orientation::HORIZONTAL); + } + + icons_box.set_spacing(spacing); +} + +void WayfireStatusNotifier::handle_config_reload() +{ + update_layout(); +} diff --git a/src/panel/widgets/tray/tray.hpp b/src/panel/widgets/tray/tray.hpp index b34bd9d5..a78245ea 100644 --- a/src/panel/widgets/tray/tray.hpp +++ b/src/panel/widgets/tray/tray.hpp @@ -13,6 +13,11 @@ class WayfireStatusNotifier : public WayfireWidget Gtk::Box icons_box; std::map items; + WfOption spacing{"panel/tray_spacing"}; + + void update_layout(); + void handle_config_reload(); + public: void init(Gtk::Box *container) override; diff --git a/src/panel/widgets/volume.hpp b/src/panel/widgets/volume.hpp index c93f919c..391bb77d 100644 --- a/src/panel/widgets/volume.hpp +++ b/src/panel/widgets/volume.hpp @@ -3,6 +3,7 @@ #include "../widget.hpp" #include #include "../../util/animated-scale.hpp" + #include #include #include diff --git a/src/panel/widgets/wp-mixer/wp-mixer.cpp b/src/panel/widgets/wp-mixer/wp-mixer.cpp index 0e051c68..8e0f3989 100644 --- a/src/panel/widgets/wp-mixer/wp-mixer.cpp +++ b/src/panel/widgets/wp-mixer/wp-mixer.cpp @@ -29,7 +29,6 @@ void WayfireWpMixer::cancel_popover_timeout() void WayfireWpMixer::reload_config() { // adjust margins and spacing - static WfOption spacing{"panel/wp_spacing"}; auto set_spacing = [&] (Gtk::Box& box) { box.set_spacing(spacing); @@ -41,6 +40,8 @@ void WayfireWpMixer::reload_config() set_spacing(sources_box); set_spacing(streams_box); + master_box.set_orientation(stack_categories ? Gtk::Orientation::VERTICAL : Gtk::Orientation::HORIZONTAL); + // big matching operation static WfOption str_quick_target_choice{"panel/wp_quick_target_choice"}; static WfOption str_wp_left_click_action{"panel/wp_left_click_action"}; diff --git a/src/panel/widgets/wp-mixer/wp-mixer.hpp b/src/panel/widgets/wp-mixer/wp-mixer.hpp index 09b42861..e4918e2d 100644 --- a/src/panel/widgets/wp-mixer/wp-mixer.hpp +++ b/src/panel/widgets/wp-mixer/wp-mixer.hpp @@ -28,6 +28,8 @@ class WayfireWpMixer : public WayfireWidget Gtk::Image main_image; + WfOption spacing{"panel/wp_spacing"}; + WfOption stack_categories{"panel/wp_stack_categories"}; WfOption timeout{"panel/wp_popup_timeout"}; void on_volume_value_changed(); diff --git a/src/util/wf-autohide-window.cpp b/src/util/wf-autohide-window.cpp index 81734ba2..5c603c10 100644 --- a/src/util/wf-autohide-window.cpp +++ b/src/util/wf-autohide-window.cpp @@ -10,15 +10,17 @@ #include #include -#define AUTOHIDE_SHOW_DELAY 300 -#define AUTOHIDE_HIDE_DELAY 500 - WayfireAutohidingWindow::WayfireAutohidingWindow(WayfireOutput *output, const std::string& section) : position{section + "/position"}, - y_position{WfOption{section + "/autohide_duration"}}, + full_span{section + "/full_span"}, + autohide_animation{WfOption{section + "/autohide_duration"}}, edge_offset{section + "/edge_offset"}, - autohide_opt{section + "/autohide"} + minimal_height{section + "/minimal_height"}, + minimal_width{section + "/minimal_width"}, + autohide_opt{section + "/autohide"}, + autohide_show_delay{section + "/autohide_show_delay"}, + autohide_hide_delay{section + "/autohide_hide_delay"} { this->output = output; this->set_decorated(false); @@ -28,8 +30,14 @@ WayfireAutohidingWindow::WayfireAutohidingWindow(WayfireOutput *output, gtk_layer_set_namespace(this->gobj(), "panel"); this->position.set_callback([=] () { this->update_position(); }); + this->full_span.set_callback([=] () { this->update_position(); }); this->update_position(); + const auto set_size = [=] () { this->set_default_size(minimal_width, minimal_height); }; + this->minimal_height.set_callback(set_size); + this->minimal_width.set_callback(set_size); + set_size(); + auto pointer_gesture = Gtk::EventControllerMotion::create(); pointer_gesture->signal_enter().connect([=] (double x, double y) { @@ -39,7 +47,7 @@ WayfireAutohidingWindow::WayfireAutohidingWindow(WayfireOutput *output, } this->input_inside_panel = true; - y_position.animate(0); + autohide_animation.animate(0); start_draw_timer(); }); pointer_gesture->signal_leave().connect([=] @@ -47,7 +55,7 @@ WayfireAutohidingWindow::WayfireAutohidingWindow(WayfireOutput *output, this->input_inside_panel = false; if (this->should_autohide()) { - this->schedule_hide(AUTOHIDE_HIDE_DELAY); + this->schedule_hide(autohide_hide_delay); } }); this->add_controller(pointer_gesture); @@ -111,6 +119,16 @@ static std::string check_position(std::string position) return WF_WINDOW_POSITION_BOTTOM; } + if (position == WF_WINDOW_POSITION_LEFT) + { + return WF_WINDOW_POSITION_LEFT; + } + + if (position == WF_WINDOW_POSITION_RIGHT) + { + return WF_WINDOW_POSITION_RIGHT; + } + std::cerr << "Bad position in config file, defaulting to top" << std::endl; return WF_WINDOW_POSITION_TOP; } @@ -128,6 +146,16 @@ static GtkLayerShellEdge get_anchor_edge(std::string position) return GTK_LAYER_SHELL_EDGE_BOTTOM; } + if (position == WF_WINDOW_POSITION_LEFT) + { + return GTK_LAYER_SHELL_EDGE_LEFT; + } + + if (position == WF_WINDOW_POSITION_RIGHT) + { + return GTK_LAYER_SHELL_EDGE_RIGHT; + } + assert(false); // not reached because check_position() } @@ -141,7 +169,7 @@ void WayfireAutohidingWindow::m_show_uncertain() { schedule_hide(0); return false; - }, AUTOHIDE_HIDE_DELAY); + }, autohide_hide_delay); } } @@ -150,18 +178,42 @@ void WayfireAutohidingWindow::update_position() /* Reset old anchors */ gtk_layer_set_anchor(this->gobj(), GTK_LAYER_SHELL_EDGE_TOP, false); gtk_layer_set_anchor(this->gobj(), GTK_LAYER_SHELL_EDGE_BOTTOM, false); + gtk_layer_set_anchor(this->gobj(), GTK_LAYER_SHELL_EDGE_LEFT, false); + gtk_layer_set_anchor(this->gobj(), GTK_LAYER_SHELL_EDGE_RIGHT, false); /* Set new anchor */ GtkLayerShellEdge anchor = get_anchor_edge(position); gtk_layer_set_anchor(this->gobj(), anchor, true); + if (full_span) + { + if ((anchor == GTK_LAYER_SHELL_EDGE_TOP) || (anchor == GTK_LAYER_SHELL_EDGE_BOTTOM)) + { + gtk_layer_set_anchor(this->gobj(), GTK_LAYER_SHELL_EDGE_LEFT, true); + gtk_layer_set_anchor(this->gobj(), GTK_LAYER_SHELL_EDGE_RIGHT, true); + } else if ((anchor == GTK_LAYER_SHELL_EDGE_LEFT) || (anchor == GTK_LAYER_SHELL_EDGE_RIGHT)) + { + gtk_layer_set_anchor(this->gobj(), GTK_LAYER_SHELL_EDGE_TOP, true); + gtk_layer_set_anchor(this->gobj(), GTK_LAYER_SHELL_EDGE_BOTTOM, true); + } + } + if (!output->output) { return; } + // need different measurements depending on position + if (anchor == GTK_LAYER_SHELL_EDGE_LEFT or anchor == GTK_LAYER_SHELL_EDGE_RIGHT) + { + get_allocated_height_or_width = &Gtk::Widget::get_allocated_width; + } else + { + get_allocated_height_or_width = &Gtk::Widget::get_allocated_height; + } + /* When the position changes, show an animation from the new edge. */ - y_position.animate(-this->get_allocated_height(), 0); + autohide_animation.animate(-(this->*get_allocated_height_or_width)(), 0); start_draw_timer(); m_show_uncertain(); setup_hotspot(); @@ -201,15 +253,19 @@ static zwf_hotspot_v2_listener hotspot_listener = { void WayfireAutohidingWindow::setup_hotspot() { - /* No need to recreate hotspots if the height didn't change */ - if ((this->get_allocated_height() == last_hotspot_height) && (edge_offset == last_edge_offset)) + auto position = check_position(this->position); + + int allocated = (this->*get_allocated_height_or_width)(); + + /* No need to recreate hotspots if the nothing changed */ + if ((allocated == last_hotspot_size) && (edge_offset == last_edge_offset) && (position == last_position)) { return; } - this->last_hotspot_height = get_allocated_height(); - this->last_edge_offset = edge_offset; - + this->last_hotspot_size = allocated; + this->last_edge_offset = edge_offset; + this->last_position = position; if (this->edge_hotspot) { zwf_hotspot_v2_destroy(edge_hotspot); @@ -220,15 +276,26 @@ void WayfireAutohidingWindow::setup_hotspot() zwf_hotspot_v2_destroy(panel_hotspot); } - auto position = check_position(this->position); - uint32_t edge = (position == WF_WINDOW_POSITION_TOP) ? - ZWF_OUTPUT_V2_HOTSPOT_EDGE_TOP : ZWF_OUTPUT_V2_HOTSPOT_EDGE_BOTTOM; + uint32_t edge; + if (position == WF_WINDOW_POSITION_TOP) + { + edge = ZWF_OUTPUT_V2_HOTSPOT_EDGE_TOP; + } else if (position == WF_WINDOW_POSITION_BOTTOM) + { + edge = ZWF_OUTPUT_V2_HOTSPOT_EDGE_BOTTOM; + } else if (position == WF_WINDOW_POSITION_LEFT) + { + edge = ZWF_OUTPUT_V2_HOTSPOT_EDGE_LEFT; + } else if (position == WF_WINDOW_POSITION_RIGHT) + { + edge = ZWF_OUTPUT_V2_HOTSPOT_EDGE_RIGHT; + } this->edge_hotspot = zwf_output_v2_create_hotspot(output->output, - edge, edge_offset, AUTOHIDE_SHOW_DELAY); + edge, edge_offset, autohide_show_delay); this->panel_hotspot = zwf_output_v2_create_hotspot(output->output, - edge, this->get_allocated_height(), 0); // immediate + edge, allocated, 0); // immediate this->edge_callbacks = std::make_unique(); @@ -261,7 +328,7 @@ void WayfireAutohidingWindow::setup_hotspot() this->input_inside_panel = false; if (this->should_autohide()) { - this->schedule_hide(AUTOHIDE_HIDE_DELAY); + this->schedule_hide(autohide_hide_delay); } }; @@ -330,7 +397,7 @@ bool WayfireAutohidingWindow::should_autohide() const bool WayfireAutohidingWindow::m_do_hide() { - y_position.animate(-get_allocated_height()); + autohide_animation.animate(-(this->*get_allocated_height_or_width)()); start_draw_timer(); update_margin(); return false; // disconnect @@ -346,7 +413,7 @@ gboolean WayfireAutohidingWindow::update_animation(Glib::RefPtr update_margin(); // this->queue_draw(); // Once we've finished fading, stop this callback - return y_position.running() ? G_SOURCE_CONTINUE : G_SOURCE_REMOVE; + return autohide_animation.running() ? G_SOURCE_CONTINUE : G_SOURCE_REMOVE; } void WayfireAutohidingWindow::schedule_hide(int delay) @@ -367,7 +434,7 @@ void WayfireAutohidingWindow::schedule_hide(int delay) bool WayfireAutohidingWindow::m_do_show() { - y_position.animate(0); + autohide_animation.animate(0); start_draw_timer(); update_margin(); return false; // disconnect @@ -391,10 +458,10 @@ void WayfireAutohidingWindow::schedule_show(int delay) bool WayfireAutohidingWindow::update_margin() { - if (y_position.running()) + if (autohide_animation.running()) { gtk_layer_set_margin(this->gobj(), - get_anchor_edge(position), y_position); + get_anchor_edge(position), autohide_animation); // queue_draw does not work when the panel is hidden // so calling wl_surface_commit to make WM show the panel back if (get_surface()) @@ -461,7 +528,7 @@ void WayfireAutohidingWindow::unset_active_popover(WayfireMenuButton& button) if (should_autohide()) { - schedule_hide(AUTOHIDE_HIDE_DELAY); + schedule_hide(autohide_hide_delay); } } diff --git a/src/util/wf-autohide-window.hpp b/src/util/wf-autohide-window.hpp index 2324c6d0..09088a31 100644 --- a/src/util/wf-autohide-window.hpp +++ b/src/util/wf-autohide-window.hpp @@ -12,6 +12,8 @@ struct zwf_hotspot_v2; #define WF_WINDOW_POSITION_TOP "top" #define WF_WINDOW_POSITION_BOTTOM "bottom" +#define WF_WINDOW_POSITION_LEFT "left" +#define WF_WINDOW_POSITION_RIGHT "right" struct WayfireAutohidingWindowHotspotCallbacks; /** @@ -23,13 +25,16 @@ class WayfireAutohidingWindow : public Gtk::Window { public: /** - * WayfireAutohidingWindow's behavior can be modified with several config - * file options: - * + * WayfireAutohidingWindow's behavior can be modified with several config file options: * 1. section/position - * 2. section/autohide_duration - * 3. section/edge_offset - * 4. section/autohide + * 2. section/full_span + * 3. section/autohide_duration + * 4. section/edge_offset + * 5. section/minimal_height + * 6. section/minimal_width + * 7. section/autohide + * 8. section/autohide_show_delay + * 9. section/autohide_hide_delay */ WayfireAutohidingWindow(WayfireOutput *output, const std::string& section); WayfireAutohidingWindow(WayfireAutohidingWindow&&) = delete; @@ -47,8 +52,7 @@ class WayfireAutohidingWindow : public Gtk::Window /* Returns true if the window should autohide */ bool should_autohide() const; - /* Hide or show the panel after delay milliseconds, if nothing happens - * in the meantime */ + /* Hide or show the panel after delay milliseconds, if nothing happens in the meantime */ void schedule_hide(int delay); void schedule_show(int delay); @@ -60,8 +64,8 @@ class WayfireAutohidingWindow : public Gtk::Window /** * Set the currently active popover button. - * The lastly activated popover, if any, will be closed, in order to - * show this new one. + * The lastly activated popover, if any, will be closed, + * in order to show this new one. * * In addition, if the window has an active popover, it will grab the * keyboard input and deactivate the popover when the focus is lost. @@ -80,15 +84,23 @@ class WayfireAutohidingWindow : public Gtk::Window WayfireOutput *output; WfOption position; + WfOption full_span; void update_position(); - wf::animation::simple_animation_t y_position; + wf::animation::simple_animation_t autohide_animation; + int (Gtk::Widget::*get_allocated_height_or_width)() const; bool update_margin(); WfOption edge_offset; int last_edge_offset = -1; + WfOption minimal_height; + WfOption minimal_width; + WfOption autohide_opt; + WfOption autohide_show_delay; + WfOption autohide_hide_delay; + bool last_autohide_value = autohide_opt; void setup_autohide(); void update_autohide(); @@ -109,8 +121,9 @@ class WayfireAutohidingWindow : public Gtk::Window /** Show the window but hide if no pointer input */ void m_show_uncertain(); - int32_t last_hotspot_height = -1; - bool input_inside_panel = false; + std::string last_position = ""; + int32_t last_hotspot_size = -1; + bool input_inside_panel = false; zwf_hotspot_v2 *edge_hotspot = NULL; zwf_hotspot_v2 *panel_hotspot = NULL; std::unique_ptr edge_callbacks; diff --git a/src/util/wf-popover.cpp b/src/util/wf-popover.cpp index 0a38af47..4c0b2ced 100644 --- a/src/util/wf-popover.cpp +++ b/src/util/wf-popover.cpp @@ -1,4 +1,5 @@ #include "wf-popover.hpp" +#include "gtkmm/enums.h" #include "wf-autohide-window.hpp" WayfireMenuButton::WayfireMenuButton(const std::string& section) : @@ -9,8 +10,19 @@ WayfireMenuButton::WayfireMenuButton(const std::string& section) : auto cb = [=] () { - // set_direction((std::string)panel_position == "top" ? - // Gtk::Arrow::DOWN : Gtk::Arrow::UP); + if (panel_position.value() == "top") + { + set_direction(Gtk::ArrowType::DOWN); + } else if (panel_position.value() == "bottom") + { + set_direction(Gtk::ArrowType::UP); + } else if (panel_position.value() == "left") + { + set_direction(Gtk::ArrowType::RIGHT); + } else if (panel_position.value() == "right") + { + set_direction(Gtk::ArrowType::LEFT); + } this->unset_popover(); // m_popover.set_constrain_to(Gtk::POPOVER_CONSTRAINT_NONE); diff --git a/wf-shell.ini.example b/wf-shell.ini.example index e95fd8c1..bc25e2b6 100644 --- a/wf-shell.ini.example +++ b/wf-shell.ini.example @@ -30,9 +30,16 @@ minimal_height = 24 # automatically hide when pointer isn't over the panel autohide = false -# time in milliseconds to wait before hiding +# time in milliseconds the showing/hiding animation takes autohide_duration = 300 +# time in milliseconds to wait before showing +autohide_show_delay= 300 + +# time in milliseconds to wait before hiding +autohide_hide_delay = 500 + + # layer can be top, bottom, overlay or background layer = top