diff --git a/metadata/dock.xml b/metadata/dock.xml index 3451c111..e8ae4f73 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,18 +37,45 @@ bottom <_name>Bottom + + left + <_name>Left + + + right + <_name>Right + - - <_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 - - <_short>Edge offset - <_long>The distance from the cursor to the edge of screen to show the panel when it's hidden. + + <_short>Edge margin + <_long>Space between the dock the edge + 0 + + + <_short>Edge hotspot size + <_long>The distance to the edge of screen to place the cursor in to show the dock when it's hidden. + 20 + + + <_short>Edge hotspot size + <_long>The distance to the edge of screen to place the cursor in to show the dock when it's hidden. 20 diff --git a/metadata/panel.xml b/metadata/panel.xml index 9da3261b..87eb584c 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,19 +19,38 @@ 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 + 42 + <_long>Minimum height the panel takes. + + + <_short>Minimal Width + <_long>Minimum width the panel takes. + 42 + + + <_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 @@ -38,6 +58,16 @@ <_long>A comma separated list of output names on which to show panel instances. Set to * wildcard for all outputs. * + + <_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 @@ -49,10 +79,28 @@ bottom <_name>Bottom + + left + <_name>Left + + + right + <_name>Right + + + + <_short>Edge margin + <_long>Space between the panel the edge + 0 + + + <_short>Edge hotspot size + <_long>The distance to the edge of screen to place the cursor in to show the panel when it's hidden. + 20 - - <_short>Edge offset - <_long>The distance from the cursor to the edge of screen to show the panel when it's hidden. + + <_short>Edge hotspot size + <_long>The distance to the edge of screen to place the cursor in to show the panel when it's hidden. 20 @@ -85,10 +133,11 @@ <_short>Launchers Spacing 4 + 0 <_short>Launchers Icon Size - 42 + 0 0 @@ -191,7 +240,7 @@ <_short>Menu Icon Size - 42 + 0 0 @@ -502,8 +551,8 @@ Set to -1 to only run it by clicking the button. row - - <_short>Target height for workspace switcher widget in pixels + + <_short>Target size for workspace switcher widget in pixels 0 diff --git a/src/dock/dock.cpp b/src/dock/dock.cpp index 763cbfdb..78b609df 100644 --- a/src/dock/dock.cpp +++ b/src/dock/dock.cpp @@ -1,17 +1,12 @@ -#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 { @@ -22,7 +17,7 @@ class WfDock::impl Gtk::Box box; WfOption css_path{"dock/css_path"}; - WfOption dock_height{"dock/dock_height"}; + WfOption position{"dock/position"}; public: impl(WayfireOutput *output) @@ -32,18 +27,15 @@ 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_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); + out_box.add_css_class("out_box"); - window->add_css_class("wf-dock"); + box.add_css_class("box"); out_box.set_halign(Gtk::Align::CENTER); + window->add_css_class("wf-dock"); + window->set_child(out_box); if ((std::string)css_path != "") { @@ -64,6 +56,31 @@ class WfDock::impl set_clickable_region(); return true; }); + + auto update_position = [=] () + { + 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") + { + 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); + } + }; + position.set_callback(update_position); + update_position(); } void add_child(Gtk::Widget& widget) @@ -82,7 +99,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(); diff --git a/src/dock/dock.hpp b/src/dock/dock.hpp index 3ae4b1f7..59062da9 100644 --- a/src/dock/dock.hpp +++ b/src/dock/dock.hpp @@ -34,8 +34,7 @@ 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(); std::string get_application_name() override; diff --git a/src/panel/panel.cpp b/src/panel/panel.cpp index bf6948bc..b711ac78 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" @@ -45,6 +48,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; @@ -52,46 +56,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_layout(); } @@ -100,6 +152,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()) { @@ -109,10 +162,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); } @@ -187,7 +242,7 @@ class WayfirePanel::impl " is not available." << std::endl; #endif } - + if (name == "window-list") { return Widget(new WayfireWindowList(output)); @@ -302,13 +357,10 @@ class WayfirePanel::impl } } - WfOption left_widgets_opt{"panel/widgets_left"}; - WfOption right_widgets_opt{"panel/widgets_right"}; - WfOption center_widgets_opt{"panel/widgets_center"}; - public: impl(WayfireOutput *output) : output(output) { + sides_size_group = Gtk::SizeGroup::create(Gtk::SizeGroup::Mode::NONE); create_window(); } @@ -324,6 +376,8 @@ class WayfirePanel::impl void handle_config_reload() { + update_orientation(); + for (auto& w : left_widgets) { w->handle_config_reload(); @@ -346,19 +400,23 @@ class WayfirePanel::impl this->panel_app = panel_app; } + WfOption left_widgets_opt{"panel/widgets_left"}; + WfOption right_widgets_opt{"panel/widgets_right"}; + WfOption center_widgets_opt{"panel/widgets_center"}; + void init_widgets() { 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(); 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..f95bd08c 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,32 @@ 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); + } +} + 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 5b9bb181..dfe8a288 100644 --- a/src/panel/widgets/network.cpp +++ b/src/panel/widgets/network.cpp @@ -398,9 +398,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); @@ -440,8 +440,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..3f1ea813 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,21 @@ 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); + } +} + +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..912bcec5 100644 --- a/src/panel/widgets/tray/tray.hpp +++ b/src/panel/widgets/tray/tray.hpp @@ -13,6 +13,9 @@ class WayfireStatusNotifier : public WayfireWidget Gtk::Box icons_box; std::map items; + 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 dc5a6d18..ffc09f04 100644 --- a/src/panel/widgets/volume.hpp +++ b/src/panel/widgets/volume.hpp @@ -1,10 +1,9 @@ #pragma once #include "../widget.hpp" -#include "wf-popover.hpp" -#include #include #include "../../util/animated-scale.hpp" + #include #include #include diff --git a/src/panel/widgets/workspace-switcher.cpp b/src/panel/widgets/workspace-switcher.cpp index f91dca61..0071061f 100644 --- a/src/panel/widgets/workspace-switcher.cpp +++ b/src/panel/widgets/workspace-switcher.cpp @@ -33,7 +33,7 @@ void WayfireWorkspaceSwitcher::init(Gtk::Box *container) ipc_client->subscribe(this, {"output-layout-changed"}); ipc_client->subscribe(this, {"wset-workspace-changed"}); - workspace_switcher_target_height_opt.set_callback([=] () {set_height();}); + workspace_switcher_target_size_opt.set_callback([=] () {set_size();}); auto mode_cb = ([=] () { @@ -71,20 +71,27 @@ void WayfireWorkspaceSwitcher::init(Gtk::Box *container) mode_cb(); } -void WayfireWorkspaceSwitcher::set_height() +void WayfireWorkspaceSwitcher::set_size() { - double val = workspace_switcher_target_height_opt.value(); + double val = workspace_switcher_target_size_opt.value(); if (val == 0.0) { val = (double)WfOption{"panel/minimal_height"}.value(); } - if (workspace_switcher_mode.value() == "grid") + if (workspace_switcher_mode.value() == "row") + { + WfOption panel_position{"panel/position"}; + if (panel_position.value() == PANEL_POSITION_LEFT or panel_position.value() == PANEL_POSITION_RIGHT) + { + val = val / grid_width; + } + } else if (workspace_switcher_mode.value() == "grid") { val = val / grid_height; } - workspace_switcher_target_height = val; + workspace_switcher_target_size = val; } void WayfireWorkspaceSwitcher::get_wsets() @@ -106,7 +113,7 @@ void WayfireWorkspaceSwitcher::get_wsets() grid_process_workspaces(data); } - set_height(); + set_size(); }); } @@ -142,8 +149,9 @@ std::pair WayfireWorkspaceSwitcher::get_workspace(WayfireWorkspaceBox WayfireWorkspaceWindow *w) { std::pair workspace; - double scaled_output_width = ws->get_scaled_width(); - double scaled_output_height = workspace_switcher_target_height; + auto size = ws->get_scaled_size(); + double scaled_output_width = size.first; + double scaled_output_height = size.second; workspace.first = std::floor((w->x + (w->w / 2)) / scaled_output_width) + this->current_ws_x; workspace.second = std::floor((w->y + (w->h / 2)) / scaled_output_height) + this->current_ws_y; return workspace; @@ -152,8 +160,9 @@ std::pair WayfireWorkspaceSwitcher::get_workspace(WayfireWorkspaceBox std::pair WayfireWorkspaceSwitcher::grid_get_workspace(WayfireWorkspaceWindow *w) { std::pair workspace; - double scaled_output_width = this->get_scaled_width(); - double scaled_output_height = workspace_switcher_target_height; + auto size = this->get_scaled_size(); + double scaled_output_width = size.first; + double scaled_output_height = size.second; workspace.first = std::floor((w->x + (w->w / 2)) / scaled_output_width) + this->current_ws_x; workspace.second = std::floor((w->y + (w->h / 2)) / scaled_output_height) + this->current_ws_y; return workspace; @@ -177,8 +186,9 @@ bool WayfireWorkspaceSwitcher::on_grid_get_child_position(Gtk::Widget *widget, G { if (auto w = static_cast(widget)) { - allocation.set_x(w->x + this->current_ws_x * this->get_scaled_width()); - allocation.set_y(w->y + this->current_ws_y * this->workspace_switcher_target_height); + auto size = this->get_scaled_size(); + allocation.set_x(w->x + this->current_ws_x * size.first); + allocation.set_y(w->y + this->current_ws_y * size.second); allocation.set_width(w->w); allocation.set_height(w->h); return true; @@ -251,16 +261,28 @@ void WayfireWorkspaceBox::on_workspace_clicked(int count, double x, double y) } } -double WayfireWorkspaceSwitcher::get_scaled_width() +std::pair WayfireWorkspaceSwitcher::get_scaled_size() { - return this->workspace_switcher_target_height * - (this->output_width / float(this->output_height)); + WfOption panel_position{"panel/position"}; + + if (panel_position.value() == PANEL_POSITION_LEFT or panel_position.value() == PANEL_POSITION_RIGHT) + { + return { + workspace_switcher_target_size, + (workspace_switcher_target_size * this->output_height / float(this->output_width)) + }; + } else + { + return { + (workspace_switcher_target_size * this->output_width / float(this->output_height)), + workspace_switcher_target_size + }; + } } -int WayfireWorkspaceBox::get_scaled_width() +std::pair WayfireWorkspaceBox::get_scaled_size() { - return this->switcher->workspace_switcher_target_height * - (this->output_width / float(this->output_height)); + return this->switcher->get_scaled_size(); } bool WayfireWorkspaceBox::on_workspace_scrolled(double x, double y) @@ -347,7 +369,8 @@ void WayfireWorkspaceSwitcher::render_workspace(wf::json_t workspace, int j, int false); ws->set_hexpand(false); ws->set_vexpand(false); - ws->set_size_request(ws->get_scaled_width(), workspace_switcher_target_height); + auto size = get_scaled_size(); + ws->set_size_request(size.first, size.second); ws->add_controller(click_gesture); ws->add_controller(scroll_controller); box.append(*ws); @@ -464,8 +487,9 @@ void WayfireWorkspaceSwitcher::grid_process_workspaces(wf::json_t workspace_data auto ws = Gtk::make_managed(this); ws->output_id = output_data["id"].as_int(); ws->set_can_target(false); - auto ws_width = this->get_scaled_width() / this->grid_width; - auto ws_height = this->workspace_switcher_target_height / this->grid_height; + auto size = this->get_scaled_size(); + auto ws_width = size.first / this->grid_width; + auto ws_height = size.second / this->grid_height; ws->set_size_request(ws_width, ws_height); ws->add_css_class("workspace"); if ((workspace_data[i]["workspace"]["x"].as_int() == k) && @@ -485,8 +509,7 @@ void WayfireWorkspaceSwitcher::grid_process_workspaces(wf::json_t workspace_data ws = Gtk::make_managed(this); ws->output_id = output_data["id"].as_int(); - ws->set_size_request( - this->get_scaled_width(), this->workspace_switcher_target_height); + ws->set_size_request(size.first, size.second); ws->add_css_class("workspace"); if ((workspace_data[i]["workspace"]["x"].as_int() == k) && (workspace_data[i]["workspace"]["y"].as_int() == j)) @@ -579,8 +602,9 @@ void WayfireWorkspaceSwitcher::add_view(wf::json_t view_data) } } - double width = ws->get_scaled_width(); - double height = workspace_switcher_target_height; + auto size = ws->get_scaled_size(); + double width = size.first; + double height = size.second; v->x = x * (width / float(ws->output_width)); v->y = y * (height / float(ws->output_height)); @@ -648,8 +672,9 @@ void WayfireWorkspaceSwitcher::grid_add_view(wf::json_t view_data) return; } - double width = this->get_scaled_width(); - double height = workspace_switcher_target_height; + auto size = this->get_scaled_size(); + double width = size.first; + double height = size.second; v->x = x * (width / float(this->output_width)); v->y = y * (height / float(this->output_height)); diff --git a/src/panel/widgets/workspace-switcher.hpp b/src/panel/widgets/workspace-switcher.hpp index be5ed99d..617857f2 100644 --- a/src/panel/widgets/workspace-switcher.hpp +++ b/src/panel/widgets/workspace-switcher.hpp @@ -24,7 +24,7 @@ class WayfireWorkspaceWindow : public Gtk::Widget class WayfireWorkspaceSwitcher : public WayfireWidget, public IIPCSubscriber { std::string output_name; - void set_height(); + void set_size(); void on_event(wf::json_t data) override; void switcher_on_event(wf::json_t data); void grid_on_event(wf::json_t data); @@ -50,7 +50,7 @@ class WayfireWorkspaceSwitcher : public WayfireWidget, public IIPCSubscriber Gtk::Box switcher_box; Gtk::Grid switch_grid; Gtk::Overlay overlay; - double get_scaled_width(); + std::pair get_scaled_size(); std::unique_ptr button; int output_width, output_height; void init(Gtk::Box *container) override; @@ -64,8 +64,8 @@ class WayfireWorkspaceSwitcher : public WayfireWidget, public IIPCSubscriber int current_ws_x, current_ws_y; std::vector windows; WfOption workspace_switcher_mode{"panel/workspace_switcher_mode"}; - WfOption workspace_switcher_target_height_opt{"panel/workspace_switcher_target_height"}; - double workspace_switcher_target_height; + WfOption workspace_switcher_target_size_opt{"panel/workspace_switcher_target_size"}; + double workspace_switcher_target_size; WfOption workspace_switcher_render_views{"panel/workspace_switcher_render_views"}; }; @@ -76,7 +76,7 @@ class WayfireWorkspaceBox : public Gtk::Overlay public: int x_index, y_index; int output_id, output_width, output_height; - int get_scaled_width(); + std::pair get_scaled_size(); WayfireWorkspaceBox(WayfireWorkspaceSwitcher *switcher) { this->switcher = switcher; diff --git a/src/util/wf-autohide-window.cpp b/src/util/wf-autohide-window.cpp index 541ae4ad..76f8850b 100644 --- a/src/util/wf-autohide-window.cpp +++ b/src/util/wf-autohide-window.cpp @@ -10,15 +10,19 @@ #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"}}, - edge_offset{section + "/edge_offset"}, - autohide_opt{section + "/autohide"} + full_span{section + "/full_span"}, + autohide_animation{WfOption{section + "/autohide_duration"}}, + autohide_opt{section + "/autohide"}, + autohide_show_delay{section + "/autohide_show_delay"}, + autohide_hide_delay{section + "/autohide_hide_delay"}, + edge_margin{section + "/edge_margin"}, + edge_hotspot_size{section + "/edge_hotspot_size"}, + adjeacent_edge_hotspot_size{section + "/adjeacent_edge_hotspot_size"}, + minimal_height{section + "/minimal_height"}, + minimal_width{section + "/minimal_width"} { this->output = output; this->set_decorated(false); @@ -27,9 +31,17 @@ WayfireAutohidingWindow::WayfireAutohidingWindow(WayfireOutput *output, gtk_layer_set_monitor(this->gobj(), output->monitor->gobj()); gtk_layer_set_namespace(this->gobj(), "panel"); + this->position.set_callback([=] () { this->update_position(); }); + this->full_span.set_callback([=] () { this->update_position(); }); + edge_margin.set_callback([=] () { 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 +51,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,17 +59,27 @@ 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); this->setup_autohide(); - this->edge_offset.set_callback([=] () { this->setup_hotspot(); }); + this->edge_hotspot_size.set_callback([=] () { this->setup_hotspot(); }); this->autohide_opt.set_callback([=] { setup_autohide(); }); + auto display = Gdk::Display::get_default(); + auto monitors = display->get_monitors(); + monitors->signal_items_changed().connect([=] (auto, auto, auto) + { + this->setup_hotspot(); + }); + + // wait for idle, so once everything is initialised. Else, things depend on loading order. + Glib::signal_idle().connect_once([=] () { this->setup_hotspot(); }); + if (!output->output) { std::cerr << "WARNING: Compositor does not support zwf_shell_manager_v2 " << \ @@ -111,6 +133,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 +160,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 +183,7 @@ void WayfireAutohidingWindow::m_show_uncertain() { schedule_hide(0); return false; - }, AUTOHIDE_HIDE_DELAY); + }, autohide_hide_delay); } } @@ -150,18 +192,43 @@ 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); + GtkLayerShellEdge edge = get_anchor_edge(position); + gtk_layer_set_anchor(this->gobj(), edge, true); + gtk_layer_set_margin(this->gobj(), edge, edge_margin); + + if (full_span) + { + if ((edge == GTK_LAYER_SHELL_EDGE_TOP) || (edge == 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 ((edge == GTK_LAYER_SHELL_EDGE_LEFT) || (edge == 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 ((edge == GTK_LAYER_SHELL_EDGE_LEFT) || (edge == 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(); @@ -190,6 +257,57 @@ static zwf_hotspot_v2_listener hotspot_listener = { .leave = handle_hotspot_leave, }; +WayfireOutput*WayfireAutohidingWindow::find_adjeacent_output() +{ + Gdk::Rectangle geom_this; + this->output->monitor->get_geometry(geom_this); + auto pos = check_position(this->position); + + for (auto& wo : *WayfireShellApp::get().get_wayfire_outputs()) + { + if (wo.get() == this->output) + { + continue; + } + + if (!wo->output) + { + continue; + } + + Gdk::Rectangle other_geo; + wo->monitor->get_geometry(other_geo); + + if (pos == WF_WINDOW_POSITION_TOP) + { + if (other_geo.get_y() + other_geo.get_height() == geom_this.get_y()) + { + return wo.get(); + } + } else if (pos == WF_WINDOW_POSITION_BOTTOM) + { + if (other_geo.get_y() == geom_this.get_y() + geom_this.get_height()) + { + return wo.get(); + } + } else if (pos == WF_WINDOW_POSITION_LEFT) + { + if (other_geo.get_x() + other_geo.get_width() == geom_this.get_x()) + { + return wo.get(); + } + } else if (pos == WF_WINDOW_POSITION_RIGHT) + { + if (other_geo.get_x() == geom_this.get_x() + geom_this.get_width()) + { + return wo.get(); + } + } + } + + return nullptr; +} + /** * An autohide window needs 2 hotspots. * One of them is used to trigger autohide and is generally a tiny strip on the @@ -197,22 +315,21 @@ static zwf_hotspot_v2_listener hotspot_listener = { * * The other hotspot covers the whole window. It is used primarily to know when * the input leaves the window, in which case we need to hide the window again. + * + * A last one is optional and is placed as a mirror of the first one on an + * adjeacent monitor, and serves to have more room to pop out the window */ 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)) + if (this->edge_hotspot) { - return; + zwf_hotspot_v2_destroy(edge_hotspot); } - this->last_hotspot_height = get_allocated_height(); - this->last_edge_offset = edge_offset; - - if (this->edge_hotspot) + if (this->adjeacent_edge_hotspot) { - zwf_hotspot_v2_destroy(edge_hotspot); + zwf_hotspot_v2_destroy(adjeacent_edge_hotspot); } if (this->panel_hotspot) @@ -220,18 +337,43 @@ void WayfireAutohidingWindow::setup_hotspot() zwf_hotspot_v2_destroy(panel_hotspot); } + uint32_t edge, adjeacent_edge; 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; + if (position == WF_WINDOW_POSITION_TOP) + { + edge = ZWF_OUTPUT_V2_HOTSPOT_EDGE_TOP; + adjeacent_edge = ZWF_OUTPUT_V2_HOTSPOT_EDGE_BOTTOM; + } else if (position == WF_WINDOW_POSITION_BOTTOM) + { + edge = ZWF_OUTPUT_V2_HOTSPOT_EDGE_BOTTOM; + adjeacent_edge = ZWF_OUTPUT_V2_HOTSPOT_EDGE_TOP; + } else if (position == WF_WINDOW_POSITION_LEFT) + { + edge = ZWF_OUTPUT_V2_HOTSPOT_EDGE_LEFT; + adjeacent_edge = ZWF_OUTPUT_V2_HOTSPOT_EDGE_RIGHT; + } else if (position == WF_WINDOW_POSITION_RIGHT) + { + edge = ZWF_OUTPUT_V2_HOTSPOT_EDGE_RIGHT; + adjeacent_edge = ZWF_OUTPUT_V2_HOTSPOT_EDGE_LEFT; + } this->edge_hotspot = zwf_output_v2_create_hotspot(output->output, - edge, edge_offset, AUTOHIDE_SHOW_DELAY); + edge, edge_hotspot_size, autohide_show_delay); + + auto adjeacent_output = find_adjeacent_output(); + if (adjeacent_output) + { + this->adjeacent_edge_hotspot = zwf_output_v2_create_hotspot(adjeacent_output->output, + adjeacent_edge, adjeacent_edge_hotspot_size, autohide_show_delay); + } this->panel_hotspot = zwf_output_v2_create_hotspot(output->output, - edge, this->get_allocated_height(), 0); // immediate + edge, (this->*get_allocated_height_or_width)(), 0); // immediate this->edge_callbacks = std::make_unique(); + this->adjeacent_edge_callbacks = + std::make_unique(); this->panel_callbacks = std::make_unique(); @@ -245,6 +387,16 @@ void WayfireAutohidingWindow::setup_hotspot() // nothing }; + adjeacent_edge_callbacks->on_enter = [=] () + { + schedule_show(0); + }; + + adjeacent_edge_callbacks->on_leave = [=] () + { + m_do_hide(); + }; + this->input_inside_panel = false; panel_callbacks->on_enter = [=] () { @@ -261,12 +413,18 @@ 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); } }; zwf_hotspot_v2_add_listener(edge_hotspot, &hotspot_listener, edge_callbacks.get()); + if (adjeacent_output) + { + zwf_hotspot_v2_add_listener(adjeacent_edge_hotspot, &hotspot_listener, + adjeacent_edge_callbacks.get()); + } + zwf_hotspot_v2_add_listener(panel_hotspot, &hotspot_listener, panel_callbacks.get()); } @@ -330,7 +488,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)() + edge_margin)); start_draw_timer(); update_margin(); return false; // disconnect @@ -346,7 +504,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 +525,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 +549,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), edge_margin + 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 +619,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..b12d8f37 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,24 @@ class WayfireAutohidingWindow : public Gtk::Window WayfireOutput *output; WfOption position; + WfOption full_span; void update_position(); - wf::animation::simple_animation_t y_position; + int (Gtk::Widget::*get_allocated_height_or_width)() const; bool update_margin(); - WfOption edge_offset; - int last_edge_offset = -1; - + wf::animation::simple_animation_t autohide_animation; WfOption autohide_opt; + WfOption autohide_show_delay; + WfOption autohide_hide_delay; + + WfOption edge_margin; + WfOption edge_hotspot_size, adjeacent_edge_hotspot_size; + int last_edge_hotspot_size = 0, last_adjeacent_edge_hotspot_size = 0; + + WfOption minimal_height; + WfOption minimal_width; + bool last_autohide_value = autohide_opt; void setup_autohide(); void update_autohide(); @@ -109,12 +122,11 @@ 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; - zwf_hotspot_v2 *edge_hotspot = NULL; - zwf_hotspot_v2 *panel_hotspot = NULL; - std::unique_ptr edge_callbacks; - std::unique_ptr panel_callbacks; + bool input_inside_panel = false; + zwf_hotspot_v2 *edge_hotspot = NULL, *adjeacent_edge_hotspot = NULL, *panel_hotspot = NULL; + std::unique_ptr edge_callbacks, adjeacent_edge_callbacks, + panel_callbacks; + WayfireOutput *find_adjeacent_output(); void setup_hotspot(); sigc::connection popover_hide; 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/src/util/wf-shell-app.hpp b/src/util/wf-shell-app.hpp index dd2c7746..5ff24a88 100644 --- a/src/util/wf-shell-app.hpp +++ b/src/util/wf-shell-app.hpp @@ -40,8 +40,7 @@ class WayfireShellApp std::vector> css_rules; protected: - /** This should be initialized by the subclass in each program which uses - * wf-shell-app */ + /** This should be initialized by the subclass in each program which uses wf-shell-app */ bool alternative_monitors = false; /* Used to skip monitor management in lockscreen */ static std::unique_ptr instance; std::optional cmdline_config; diff --git a/wf-shell.ini.example b/wf-shell.ini.example index a86e709d..5d9a233d 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