Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Auto-Hide feature #2248

Closed
wants to merge 5 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions include/bar.hpp
Original file line number Diff line number Diff line change
@@ -83,13 +83,15 @@ class Bar {
void setVisible(bool visible);
void toggle();
void handleSignal(int);
void setupAutohide();

struct waybar_output *output;
Json::Value config;
struct wl_surface *surface;
bool visible = true;
bool vertical = false;
Gtk::Window window;
Gtk::Window hotspotWindow;

#ifdef HAVE_SWAY
std::string bar_id;
@@ -102,12 +104,16 @@ class Bar {
void setupAltFormatKeyForModule(const std::string &module_name);
void setupAltFormatKeyForModuleList(const char *module_list_name);
void setMode(const bar_mode &);
void showMainbar(GdkEventCrossing* ev);
void hideMainbar(GdkEventCrossing* ev);
bool hideMainbarCallback();

/* Copy initial set of modes to allow customization */
bar_mode_map configured_modes = PRESET_MODES;
std::string last_mode_{MODE_DEFAULT};

std::unique_ptr<BarSurface> surface_impl_;
std::unique_ptr<BarSurface> hotspotsurface_impl_;
Gtk::Box left_;
Gtk::Box center_;
Gtk::Box right_;
@@ -120,6 +126,9 @@ class Bar {
std::unique_ptr<BarIpcClient> _ipc_client;
#endif
std::vector<std::shared_ptr<waybar::AModule>> modules_all_;

unsigned int autohide_delay_ms = 0;
sigc::connection autohide_connection;
};

} // namespace waybar
16 changes: 16 additions & 0 deletions man/waybar.5.scd.in
Original file line number Diff line number Diff line change
@@ -118,6 +118,22 @@ modifier-reset ++
typeof: string ++
*bar_id* for the Sway IPC. Use this if you need to override the value passed with the *-b bar_id* commandline argument for the specific bar instance.

*autohide* ++
typeof: bool ++
default: false ++
Option to specify whether bar must autohide.
Use *autohide-delay* and *autohide-starthidden* to customize autohide.

*autohide-delay* ++
typeof: integer ++
default: 0 ++
Time in milliseconds after which the bar must autohide if cursor is no longer over the bar.

*autohide-starthidden* ++
typeof: bool ++
default: false ++
Option to specify whether the bar must start in hidden state if *autohide* option is true.

*include* ++
typeof: string|array ++
Paths to additional configuration files.
58 changes: 57 additions & 1 deletion src/bar.cpp
Original file line number Diff line number Diff line change
@@ -481,6 +481,7 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
: output(w_output),
config(w_config),
window{Gtk::WindowType::WINDOW_TOPLEVEL},
hotspotWindow{Gtk::WindowType::WINDOW_TOPLEVEL},
left_(Gtk::ORIENTATION_HORIZONTAL, 0),
center_(Gtk::ORIENTATION_HORIZONTAL, 0),
right_(Gtk::ORIENTATION_HORIZONTAL, 0),
@@ -492,6 +493,11 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
window.get_style_context()->add_class(config["name"].asString());
window.get_style_context()->add_class(config["position"].asString());

hotspotWindow.set_opacity(0);
hotspotWindow.set_title("waybar-autohide");
hotspotWindow.set_name("waybar-autohide");
hotspotWindow.set_decorated(false);

auto position = config["position"].asString();

if (position == "right" || position == "left") {
@@ -563,14 +569,19 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
margins_ = {.top = gaps, .right = gaps, .bottom = gaps, .left = gaps};
}

auto autohide_enabled = config["autohide"].isBool() ? config["autohide"].asBool() : false;
auto autohide_starthidden = autohide_enabled && ( config["autohide-starthidden"].isBool() ? config["autohide-starthidden"].asBool() : false);

#ifdef HAVE_GTK_LAYER_SHELL
bool use_gls = config["gtk-layer-shell"].isBool() ? config["gtk-layer-shell"].asBool() : true;
if (use_gls) {
surface_impl_ = std::make_unique<GLSSurfaceImpl>(window, *output);
hotspotsurface_impl_ = std::make_unique<GLSSurfaceImpl>(hotspotWindow, *output);
} else
#endif
{
surface_impl_ = std::make_unique<RawSurfaceImpl>(window, *output);
hotspotsurface_impl_ = std::make_unique<RawSurfaceImpl>(hotspotWindow, *output);
}

surface_impl_->setMargins(margins_);
@@ -579,6 +590,12 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
// GTK layer shell anchors logic relying on the dimensions of the bar.
surface_impl_->setPosition(position);

// Height of Hotspot is 1
hotspotsurface_impl_->setSize(width, 1);
// Position needs to be set after calculating the height due to the
// GTK layer shell anchors logic relying on the dimensions of the bar.
hotspotsurface_impl_->setPosition(position);

/* Read custom modes if available */
if (auto modes = config.get("modes", {}); modes.isObject()) {
from_json(modes, configured_modes);
@@ -613,7 +630,16 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
#endif

setupWidgets();
window.show_all();

if(autohide_enabled) setupAutohide();

if(autohide_starthidden) {
window.hide();
hotspotWindow.show_all();
} else {
hotspotWindow.hide();
window.show_all();
}

if (spdlog::should_log(spdlog::level::debug)) {
// Unfortunately, this function isn't in the C++ bindings, so we have to call the C version.
@@ -683,6 +709,36 @@ void waybar::Bar::setVisible(bool value) {

void waybar::Bar::toggle() { setVisible(!visible); }

void waybar::Bar::showMainbar(GdkEventCrossing* ev) {
spdlog::debug("hotspot: off; bar: on");
this->autohide_connection.disconnect();
if(!this->window.is_visible()) this->window.show_all();
if(this->hotspotWindow.is_visible()) this->hotspotWindow.hide();
}

bool waybar::Bar::hideMainbarCallback() {
spdlog::debug("hotspot: on; bar: off");
if(!this->hotspotWindow.is_visible()) this->hotspotWindow.show_all();
if(this->window.is_visible())this->window.hide();
return false;
}

void waybar::Bar::hideMainbar(GdkEventCrossing* ev) {
this->autohide_connection.disconnect();
this->autohide_connection = Glib::signal_timeout().connect(sigc::mem_fun(*this,&Bar::hideMainbarCallback), this->autohide_delay_ms);
}

void waybar::Bar::setupAutohide() {
this->autohide_connection.disconnect();
this->autohide_delay_ms = config["autohide-delay"].isUInt() ? config["autohide-delay"].asUInt() : 0;

hotspotsurface_impl_->setLayer(bar_layer::OVERLAY);
hotspotsurface_impl_->setExclusiveZone(true);

hotspotWindow.signal_enter_notify_event().connect_notify(sigc::mem_fun(*this, &waybar::Bar::showMainbar));
window.signal_leave_notify_event().connect_notify(sigc::mem_fun(*this, &waybar::Bar::hideMainbar));
}

// Converting string to button code rn as to avoid doing it later
void waybar::Bar::setupAltFormatKeyForModule(const std::string& module_name) {
if (config.isMember(module_name)) {