Alexays / Waybar

Highly customizable Wayland bar for Sway and Wlroots based compositors. :v: :tada:
MIT License
6.79k stars 712 forks source link

Only show waybar when modifier key is pressed #255

Closed vially closed 2 years ago

vially commented 5 years ago

Is there any way to configure sway/waybar so that it behaves similar to i3's mode hide?

Sway already supports mode hide for their swaybar. I was wondering if it would be possible to implement the same for waybar?

Basically what I'm looking for is having this sway configuration work as expected:

bar {
  mode hide
  swaybar_command waybar
}
rif commented 5 years ago

This is the feature that I'm also waiting for to be able to make the switch to waybar, great tool!

toger5 commented 5 years ago

Would be great to have that feature!

toger5 commented 5 years ago

Seems like there is already some kind of hide functionality built in the code (the toggle function). It probably just needs to listen to some kind of sway events. See the main function: https://github.com/Alexays/Waybar/blob/67593b8c0fb9fe9e51eb99b9bc578e0c280b4c5f/src/main.cpp#L8 It seems that there is a USRSIG which is used for the toggle. I tired with a little c program

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

int main(void)
{
    kill(/*the Pid*/, SIGUSR1);
}

and the bar actually gives the space to the compositor.

toger5 commented 5 years ago

Also this is realted to #157. Basically the c program i posted is eqivalent to killall -SIGUSR1 waybar which can be bound to some shortcut. But it is still not possible to toggle when holding $mod.

xPMo commented 5 years ago

I've been poking around in sway's IPC docs and here's what I've learned. I will use this as an example config:

bar {
    id bar1
    modifier $mod
}

By default, bar1 is started in mode dock. Pressing and releasing $mod sends no events while the bar is in this mode. Now suppose that by a binding or a swaymsg call, that the command bar mode invisible was run. An event of type barconfig_update is sent, the json object sent has fields including "mode": "invisible", and "id": "bar1". Pressing and releasing $mod while the bar is in this mode also sends no events. Similarly for mode "overlay".

Now, if either bar mode hide or (while the bar is in "dock" mode) bar mode toggle is sent, an event of type "barconfig_update" is sent with field "mode": "hide", just like before.

While the bar is in mode "hide", pressing and releasing $mod will send events of type bar_status_update. The objects will be: {"id": "bar1", "visible_by_modifier": [bool]}, where [bool] is true or false.


Either:

There are a number of benefits to the second option:

The downsides to the second option:

EDIT: @Alexays, comments on feasibility? Am I off the mark here?

EDIT2: Optimally, https://github.com/swaywm/wlr-protocols/issues/41 would be adopted so waybar can change layers without destroying its surface.

l3s2d commented 5 years ago

Not sure if I'm off the mark here, but another, albeit more complex, option would be to implement a control program for waybar, i.e. waybarctl. This would be useful for a few reasons:

xPMo commented 5 years ago

This might address the current issue by doing something like

  • bindsym $key exec waybarctl show
  • bindsym --release $key exec waybarctl hide

This works for normal keys, but not modifiers. If you want to bind this to Mod4 (for example), you can use bindsym Super_L exec waybarctl show (and similar with --release). However, while the first gets run consistently when the key is pressed, the --release binding is ONLY run if another shortcut is not run first. So if you have the show/hide bindings as above, running any command (like $mod+l to focus left) will show the bar and not hide it when Mod4 is released.

This can be worked around by having another IPC client which reads the bar_status_update events and then calls waybarctl, but it seems wasteful to attach a whole other process when waybar already has a connected socket.

nyyManni commented 5 years ago

I was playing around with this feature in my fork, and have got it into a shape where it is mostly good enough for my use.

In order to not tie Waybar too much into sway, I created a "meta-module" sway/hide which does not actually have any visible GUI, but just hooks into bar_status_update events from sway and toggles the visibility of the bar accordingly. This way the core of waybar is kept "non-sway-aware". The only thing added to the core was the support for showing the bar in an overlay mode (, which also would solve #491).

There are still problems, though. The biggest one I am facing right now is that when the bar is in overlay mode (on top of tiled windows) and hidden by the gtk style option, the invisible bar still sucks the mouse events from the area. In other words for example the tab bar in my browser is difficult to use with a mouse as the invisible bar covers about 75% of it. (I am still ok with it, as I mostly use keyboard shortcuts anyway, but...)

Ideas on how to solve the invisible overlay stealing mouse clicks would be welcome, as that would make the feature more suitable for daily use.

xPMo commented 5 years ago

@nyyManni Have you tried setting waybar to use the bottom layer?

nyyManni commented 5 years ago

@xPMo I am setting the layer into ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY which is needed as I want to show the bar on top of other clients whenever it is visible. A solution might be to dynamically set the layer to ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM while the bar is hidden, allthough I am not sure if I can modify that attribute without destroying and recreating the surface.

xPMo commented 5 years ago

dynamically set the layer

You can't right now, but there's already an issue for it (swaywm/wlr-protocols#41, I linked it earlier in this thread).

Currently, swaybar destroys its surface instead of changing layers when it hides.

xPMo commented 4 years ago

@nyyManni @all Good news:

wlroots 0.9.0 has been released; the layer shell protocol and wlroots now support changing layer at runtime.

It is now possible for waybar to simply raise its layer on modifier. I like this option, since waybar will always be visible on empty workspaces, or when it is uncovered/partially covered by floating windows. Additionally, it solves the focus-stealing problem @nyyManni mentioned.

However, some may prefer their bar to be completely hidden, even on empty workspaces (like swaybar). A "hide-on-modifier": <bool> option in the module may be useful; setting it to false makes waybar change layer without hiding. If this is supported, a name like "sway/hide" may be misleading; maybe call the module "sway/bar_events".

nyyManni commented 4 years ago

@xPMo indeed!

I already tried it last week (see the referenced commit 5 days ago), and have been using it since.

My solution is a hack, though, and I am having an issue that when I "raise" the bar with the modifier, sometimes the remaining of the screen "jumps back in time" showing an old version of my framebuffer, at least with XWayland clients.

ghost commented 4 years ago

I am wanting to raise the ante' and configure the bar to be say '2px and transparent(or peaking through)' and then when the move hovers over the area, the bar changes height to the full area with whatever styling

I tried using hideIt.sh but couldn't get it to work properly. :/

VV theres also this bit of code in bar.cpp VV

auto waybar::Bar::toggle() -> void { ...
...
window.get_style_context()->add_class("hidden")
...
}

but I am not quite sure what to do with it. I don't know .. ?

ghost commented 4 years ago

theres also this bit of code .. auto waybar::Bar::toggle() -> void { ... ... window.get_style_context()->add_class("hidden") ... } but I am not quite sure what to do with it. I don't know .. ?

mox-mox commented 4 years ago

Hey, is there any progress so far?

ghost commented 4 years ago

Can we not make a modifier/module that contains the entire bar - or overrides it's settings to turn everything off like a docker.

Essentially just aa waybar container that could be configured to work with mouse over or hotkeys/keybind?

I would just do this myself but I don't know enough about programming/Wayland to even know where to start.

On Thu, Aug 27, 2020, 6:09 AM mox-mox notifications@github.com wrote:

Hey, is there any progress so far?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/Alexays/Waybar/issues/255#issuecomment-681881713, or unsubscribe https://github.com/notifications/unsubscribe-auth/AKQVPQK3TUKXSUCOFUQPPDTSCY5F3ANCNFSM4HCQ77BA .

xPMo commented 4 years ago

Hey, is there any progress so far?

I have some work on the feature, but unfortunately it is both old and didn't quite work. My severe inexperience with C++ is the biggest culprit, I have a decent grasp on the wayland/sway side of things.

somini commented 4 years ago

https://github.com/swaywm/wlr-protocols/issues/41 was fixed by https://github.com/swaywm/wlr-protocols/pull/59 apparently, I don't have problem with hiding and showing the bar now, if I send a USR1 to the waybar process.

My use case is having a simple main bar that it's always on, and another more complex one that is only shown when a modifier is pressed, for extra information.

https://github.com/xPMo/Waybar/tree/sway-hide sounds like a good solution that doesn't tie Waybar to sway so much, but provides integration, particularly with more than one bar.

I tweaked the code by trying to reuse the toggle function, and I get some segfaults if I toggle it too rapidly (I also don't know enough C++, might be something on my side). It seems that if a toggle operation is triggered while the previous operation is happening yet, there's a crash. The code in in #860

creeperdeking commented 3 years ago

Is it possible to merge this commit? This is a functionality I am personally very much waiting for!

xPMo commented 3 years ago

Is it possible to merge this commit? This is a functionality I am personally very much waiting for!

860 is still only marked as a Draft PR, @somini needs to mark it as ready to merge first. I don't know whether or not it is, so we'll have to wait. :)

somini commented 3 years ago

Please see https://github.com/Alexays/Waybar/pull/860#issuecomment-696418271, it's really just a draft. It needs more C++ expertise than I have, sadly.

creeperdeking commented 3 years ago

Okay, I really like this hide functionality, so I have switched back to sway-bar for the time being.

emirror-de commented 3 years ago

Hi, is there any progress on this?

somini commented 3 years ago

Hi, is there any progress on this?

860 has some initial work, but my C++ knowledge prevents me from going further. It's out of sync with the main branch now.

emirror-de commented 3 years ago

Hey there, thanks for all your work already done @somini and @xPMo! I had a look into it and merged it to the latest master branch. Also tried a bit around and it seems that I have found the SIGSEGV reason. See my pull request for the changes I did.

I am happy to adjust anything further that is required to merge it!

Sorry @somini, I was not able to push to your draft. However if thats somehow possible, I am happy to push the changes to your PR and cancel mine.

Greetings!

somini commented 3 years ago

@emirror-de No problem, my PR was a just a hack anyway. I'll close it in favour of your PR, it's more advanced than mine.

creeperdeking commented 3 years ago

great news!

somini commented 3 years ago

In case anyone is only tracking this on this issue, #1241 by @emirror-de does the trick, it's implemented now.

emirror-de commented 3 years ago

The PR is still marked as Draft because I found that it is not stable enough yet. I have a multimonitor setup and sometimes one bar freezes and the other one works as expected. In addition to that, the application sometimes crashes with an "Address boundary error". I was not able to find the reason yet, I think I need help to fix this.

Analysis with valgrind --leak-check=yes waybar returns multiple memory leaks:

...

==9792== 464 bytes in 1 blocks are possibly lost in loss record 14,701 of 15,829
==9792==    at 0x483E5EF: calloc (vg_replace_malloc.c:1328)
==9792==    by 0x40130E7: calloc (rtld-malloc.h:44)
==9792==    by 0x40130E7: allocate_dtv (dl-tls.c:366)
==9792==    by 0x40130E7: _dl_allocate_tls (dl-tls.c:612)
==9792==    by 0x62E0BE4: allocate_stack (allocatestack.c:624)
==9792==    by 0x62E0BE4: pthread_create@@GLIBC_2.2.5 (pthread_create.c:634)
==9792==    by 0x603DB19: std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.29)
==9792==    by 0x196887: waybar::modules::sway::Ipc::setWorker(std::function<void ()>&&) (in /home/dev/bin/waybar)
==9792==    by 0x1BCA03: waybar::modules::sway::Hide::Hide(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, waybar::Bar const&, Json::Value const&) (in /home/dev/bin/waybar)
==9792==    by 0x147E22: waybar::Factory::makeModule(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const (in /home/dev/bin/waybar)
==9792==    by 0x16A4C5: waybar::Bar::getModules(waybar::Factory const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (in /home/dev/bin/waybar)
==9792==    by 0x16A6D3: waybar::Bar::setupWidgets() (in /home/dev/bin/waybar)
==9792==    by 0x16B4C2: waybar::Bar::Bar(waybar::waybar_output*, Json::Value const&) (in /home/dev/bin/waybar)
==9792==    by 0x173E4B: waybar::Client::handleOutputDone(void*, zxdg_output_v1*) (in /home/dev/bin/waybar)
==9792==    by 0x64C49D9: ??? (in /usr/lib/x86_64-linux-gnu/libffi.so.8.1.0)

...

This report repeats for every module that is configured on the bar. Maybe this is a separate issue? When I am correctly interpreting the report, this is an error in libstdc++.so.6.0.29? But I am not too deep into this debugging methods to be sure.

Any help would be appreciated! :rocket:

somini commented 2 years ago

This finally moved to #1244, that's already merged. This issue can be closed once that's released.

TRPB commented 2 years ago

How can I send the IPC message on another WM?

hamdav commented 2 years ago

I would also love to have this feature on Hyprfine, has anyone tried that?

vlbn commented 11 months ago

i'm using hyprland. i just binded a key combination (super+Print) to toggle the waybar process. it does the job. bind = $mainMod, Print, exec, pkill waybar || waybar @Alexays am i being too lazy?

dron1885 commented 10 months ago

am i being too lazy?

Well you can do it a bit more "properly".

Add these lines to the hyprland config

bind = , SUPER_L, exec, killall -SIGUSR1 waybar
bindir = , SUPER_L, exec, sleep 0.5 && killall -SIGUSR1 waybar

And following to waybar config:

"mode": "hide",
"start_hidden": true
Hubro commented 8 months ago

@dron1885 Does that work for you? For me, the "release" modifier only works if I click and release Super_L alone. If I hold the Super_L key as part of another key bind, like Superh, waybar appears and never disappears, and the toggle behavior is now inverted :S

dron1885 commented 8 months ago

@Hubro It should be bindit and binditr respectively.

Hubro commented 8 months ago

@Hubro It should be bindit and binditr respectively.

Ah, I was missing the t, now it works :grin: But after playing with it for a couple of minutes I realized it completely breaks the system tray. I can't interact with it while holding Super_L, and if I add a short sleep so I can open context menus, the menus disappear together with waybar after the delay.

Also the background blur behind waybar seems to stick around while waybar is hidden.

This would definitely need some polish in order to be usable.

gustavosbarreto commented 6 months ago

@Hubro It should be bindit and binditr respectively.

Ah, I was missing the t, now it works 😁 But after playing with it for a couple of minutes I realized it completely breaks the system tray. I can't interact with it while holding Super_L, and if I add a short sleep so I can open context menus, the menus disappear together with waybar after the delay.

Also the background blur behind waybar seems to stick around while waybar is hidden.

This would definitely need some polish in order to be usable.

@Hubro The issue with the system tray is caused by the bindings to resize windows where it is listening for mouse events and not propagating to waybar. To fix it, simply disable it by removing the following lines from hyprland.conf:

# Move/resize windows with mainMod + LMB/RMB and dragging
bindm = $mainMod, mouse:272, movewindow
bindm = $mainMod, mouse:273, resizewindow

I'm keyboard-oriented, so mouse bindings in a tiling window manager are completely useless for me.

Hubro commented 6 months ago

@gustavosbarreto Aha, you're right! Unfortunately I'm a heavy user of the mouse for moving and resizing floating windows :disappointed: I guess I can't have both without some changes to Hyprland.