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

Updated sway-hide work to the latest master #1241

Closed
wants to merge 36 commits into from

Conversation

emirror-de
Copy link

Updates the previous work by @somini and @xPMo to the latest master branch.

Fixes #255

Changes:

  • set_opacity has been removed, as it seems to raise an address boundary sigsegv
  • The bar does not reserve any space on the screen when the hide mode is enabled (value is being set on initialization)
  • When shown, the bar is on the TOP layer, when hidden on the BOTTOM

nyyManni and others added 17 commits September 21, 2020 23:07
Configuration option `layer` can now take a value "overlay", which draws the bar
on top of the windows without creating an exclusive zone.
This allows auto-showing the bar when the modifier is pressed

Closes Alexays#255

Setup instructions:
- Set the `mode` of the bar to "hide" in sway configuration file
- Set the `layer` of the bar to "overlay" in Waybar configuration file
- Add "sway/hide" into `modules-left` in Waybar configuration file
Currently, it won't build.
I am unfamiliar with C++, I don't know what's wrong.
This is also a rebase-fix
Call this when toggling visibility with SIGUSR1, and for `sway/hide`
events.
This doesn't solve the issue, but it crashes less often...
Keep this as similar to "upstream" as possible.
This is a CSS-only change. It should be properly hidden.
@xPMo
Copy link
Contributor

xPMo commented Sep 13, 2021

Thanks for your work!

src/modules/sway/hide.cpp Outdated Show resolved Hide resolved
Copy link
Contributor

@alebastr alebastr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Certain changes in bar.cpp are breaking the existing functionality.
I also don't feel comfortable with reverting setVisible to an implementation before all my changes.

src/bar.cpp Outdated
} else {
window.get_style_context()->remove_class("hidden");
window.set_opacity(1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are fixing the symptom and also breaking existing features (show/hide by signal).

set_opacity should not fail on a correct visible Gtk window. The only cases of crash I can imagine without looking at the backtrace are when the window is not yet initialized or already destroyed.
Can you try checking window.get_realized() or window.get_mapped() right after setting the visible property?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry by introducing breaking changes, that was not my intention. I will reset it to the current master branch implementation.

Copy link
Author

@emirror-de emirror-de Sep 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reset the changes to the setVisible function. Calling get_realized or get_mapped did not make a difference.

The following error occurs when set_opacity is in the function and is used when the modifier key is pressed.

fish: “./build/waybar” terminated by signal SIGSEGV (Address boundary error)

In my configuration, I have a transition on the opacity property. Could it be possible that this conflicts to each other?

src/bar.cpp Outdated
wl_surface_commit(surface);
}

auto waybar::Bar::removeExclusiveZone() const -> void {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest to do it like this:

void waybar::Bar::setExclusive(bool value) {
  exclusive = value;
  surface_impl_->setExclusiveZone(exclusive && visible);
} 

src/bar.cpp Outdated
surface_impl_->setLayer(bar_layer::BOTTOM);
} else {
window.get_style_context()->remove_class("hidden");
surface_impl_->setLayer(bar_layer::TOP);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This overrides the layer set in the config file.
You can implement that differently:

void waybar::Bar::setLayer(bar_layer layer) {
  layer_ = layer;
  surface_impl_->setLayer(layer_);
}

and call the method from the same location where you are disabling exclusive zone.

src/bar.cpp Outdated
window.get_style_context()->remove_class("hidden");
surface_impl_->setLayer(bar_layer::TOP);
}
wl_surface_commit(surface);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extraneous wl_surface_commit is known to be able to crash Gtk in certain cases (as found and fixed in gtk-layer-shell). Also, surface can be unset you call that on an unmapped window.
That's why the code in master branch is calling surface_impl_->commit() which is noop for the most cases.

include/bar.hpp Outdated
Comment on lines 61 to 62
auto setVisible(bool nvis) -> void;
auto toggle() -> void;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know I'm nitpicking, but why was that change necessary?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No that's totally justified. I took the wrong definition while resolving the merge conflicts. I will correct this.

@emirror-de emirror-de marked this pull request as draft September 14, 2021 14:16
@emirror-de
Copy link
Author

@alebastr

Most likely, one of the outputs was disabled while idle and enabled again. I.e. you've got a new bar instance with clean initial state.

Ok that sounds reasonable. My monitors are in energy saving mode, so this could be the case here.

That's the case where you'd want to request bar configuration in the constructor of sway/hide and set mode immediately (before the window is visible).

The possible code for fetching an initial mode is in my branch, https://github.com/Alexays/Waybar/pull/1244/files#diff-0d4cf783ddd7af6ea0c6abcfa5a8b50f29b433a0397b9e8f4c24634a452ca092R14-R20. Feel free to use that and modify as necessary for this PR.

I did not know how to change your suggestion for this case. So I added two lines to the constructor in this commit. I do not know if this update is correct?

Ugh... Sounds like waybar haven't received the GTK event that the output in question is available again. Or somehow failed to process one.
I'd love to see waybar -l trace output for that scenario, even if it's not verbose enough to see all the details we want. But I guess it would be hard to reproduce.

I will run waybar with the trace option and hope for it to occur :)

I have another use case, which is a single monitor with two bars. One stays always on, the other one is hidden, shown with the modifier.

With the latest code here, the bar defaults to being show, and when the modifier toggles it, it changes layer (it overlaps the visible window), but it's not hidden. Sounds like another case of multiple bars @alebastr mentioned in the last comment.

@somini, @xPMo, this use case should be handled already from this commit on. The iteration through all bars has been replaced by the bar passed in the constructor.

@somini Could you share your config for this use case? So it is easier for me to have a look at the behavior.

I don't know why resuming from swayidle should change anything. Is Sway inconsistent with the events it sends, or is it a /gtk(-layer-shell)?/ thing? Just curious whether Waybar's behavior agrees or disagrees with the events received from sway:

I will leave that command running during testing.

@emirror-de
Copy link
Author

emirror-de commented Sep 20, 2021

Hm ok. So I just found another behavior that is close to No2.

Resuming from swaylock (monitors are on, did not switch off while swaylock is active).
One bar is hidden and shows when modifier is pressed, the other bar does not show up anymore. Both do not have exclusive set to true.

When is the Hide::update function triggered? Maybe something needs to go in there?

waybar -l trace does show

[2021-09-20 13:14:26.582] [debug] Received SIGCHLD in signalThread
[2021-09-20 13:14:26.582] [debug] Cmd exited with code 0
[2021-09-20 13:14:26.637] [debug] Received SIGCHLD in signalThread
[2021-09-20 13:14:26.637] [debug] Cmd exited with code 0

regularly. At some point, one of the bars does not show up anymore. I do not know if this is connected to each other.

@somini
Copy link

somini commented Sep 23, 2021

@somini Could you share your config for this use case? So it is easier for me to have a look at the behavior.

Waybar Config:

{
    "layer": "top",
    "position": "top",
    "name": "main",
    "modules-left": [
	"sway/hide",
	"sway/workspaces",
	"sway/mode"
    ],
    "modules-center": [
	"tray"
    ],
    "modules-right": [
	"idle_inhibitor",
	"backlight",
	"network#wifi",
	"network#ethernet",
	"pulseaudio",
	"battery",
	"clock#localtime"
    ],
    "sway/workspaces": {
	"disable-scroll-wraparound": true
    },
    "sway/mode": {},
    "idle_inhibitor": {
        "format": "{icon}",
        "format-icons": {
            "activated": "",
            "deactivated": ""
        }
    },
    "backlight": {
        "format": "{percent}",
	"on-click": "brightnessctl -q set 100%",
	"on-scroll-up": "brightnessctl -q set 1%+",
	"on-scroll-down": "brightnessctl -q set 1%-"
    },
    "network#wifi": {
	"interface": "wifi",
	"interval": 5,
        "format-wifi": "",
        "format-linked": "⚠",
        "format-disconnected": "",
        "tooltip-format": "{ifname}: {ipaddr}/{cidr}",
	"tooltip-format-linked": "{ifname}: No IP",
	"tooltip-format-disconnected": "{ifname}: OFF",
        "format-alt": "{ifname}[{essid}]: {ipaddr}/{cidr}"
    },
    "network#ethernet": {
	"interface": "ethernet",
	"interval": 5,
        "format-ethernet": "",
        "format-linked": "⚠",
        "format-disconnected": "",
        "tooltip-format": "{ifname}: {ipaddr}/{cidr}",
	"tooltip-format-linked": "{ifname}: No IP",
	"tooltip-format-disconnected": "{ifname}: OFF",
        "format-alt": "{ifname}: {ipaddr}/{cidr}"
    },
    "pulseaudio": {
        "format": "{icon}{volume}%|{format_source}",
        "format-muted": "|{format_source}",
        "format-bluetooth": "{icon}{volume}%|{format_source}",
        "format-bluetooth-muted": "|{format_source}",
        "format-source": "{volume}%",
        "format-source-muted": "",
        "format-icons": {
            "headphone": "",
            "hands-free": "",
            "headset": "",
            "phone": "",
            "portable": "",
            "car": "",
            "default": ["", "", ""]
        },
        "on-click": "pulseaudio-ctl mute toggle",
        "on-click-right": "pavucontrol",
	"on-clock-middle": "pulseaudio-ctl set 20"
    },
    "battery": {
	"format": "{icon}",
        "format-charging": "{capacity}%",
        "format-plugged": "{capacity}%",
        "format-alt": "{icon}{capacity}%",
	"format-time": "{H}h{M}",
	"format-icons": [
	    "",
	    "",
	    "",
	    "",
	    ""
	],
	"tooltip": true
    },
    "tray": {
	"spacing": 10
    },
    "clock#localtime": {
	"format": "{:%d%b %H:%M:%S}",
	"tooltip": true,
	"tooltip-format": "<big>{:%Y %B}</big>\n<tt>{calendar}</tt>"
    }
}

Sway Config:

# Bars
bar {
    id main
    swaybar_command waybar-configured
    mode dock
    hidden_state show
    modifier none
}

bar {
    id info
    swaybar_command waybar-configured
    mode hide
    hidden_state hide
    modifier $mod
    position top
    tray_output none
}

waybar-configured is just a wrapper script to allow multiple configurations:

#!/bin/bash
bar_id=
while getopts ":b:" opt; do
	case "$opt" in
		b)
			bar_id="$OPTARG"
			;;
		*)
			echo "Usage: $0 [-b bar] args"
			exit 2
			;;
	esac
done
shift $((OPTIND - 1))

if [ -z "$bar_id" ]; then
	echo "Missing bar ID"
	exit 3
fi

bar_folder="$HOME/.config/waybar/$bar_id"
if [ ! -d "$bar_folder" ]; then
	echo "Missing bar configuration folder: $bar_folder"
	exit 4
fi

declare -a ARGS
folder_config="$bar_folder/config.json"
if [ -r "$folder_config" ]; then
	ARGS+=(--config "$folder_config")
fi
folder_style="$bar_folder/style.css"
if [ -r "$folder_style" ]; then
	ARGS+=(--style "$folder_style")
fi

exec waybar -b "$bar_id" "${ARGS[@]}" "$@"

@emirror-de
Copy link
Author

Thanks for sharing. I am currently limited on time, so I am not able to do further testing on this currently. I found another thing to consider:
While holding down the Mod key, it is not possible to move a window down to be tiled at the area of the screen (bottom in my case). This seems to be because waybar is then visible and on top layer not having exclusive space, so that sway does not recognize that the window should be tiled horizontally at the bottom. Does someone know how i3/swaybar handles this?

@woutdp
Copy link

woutdp commented Oct 21, 2021

This PR is great, it works for me. It wasn't clear to me how to configure this but here's how I did it:

Include the following in:

~./config/sway/config

bar {
    mode hide
    swaybar_command waybar
}

~./config/waybar/config

    ...
    "layer": "bottom",  // <-- Set this to bottom
    "modules-left": [
        "sway/hide", // <--- Include this module
        "sway/mode",
        "sway/workspaces",
        ...
    ],
    ...

@emirror-de
Copy link
Author

emirror-de commented Oct 21, 2021

Thanks @woutdp! Nice that it works on your setup.

While holding down the Mod key, it is not possible to move a window down to be tiled at the area of the screen (bottom in my case).

I do not know why, but this issue does not occur any longer here as well. At least on my notebook it is possible to tile at the side of the screen where the bar is. Next week I am going to test multi monitor setup and will have a look at your configuration @somini.

In addition, I think it would be nice to add an "alert" that fires when the battery hits critical level. This could prevent surprising shutdowns when the bar is hidden. With "alert" I mean, that the bar automatically switches to be shown when the critical battery level has been reached. From then on, the bar behaves the same as before, if the user presses the MOD key, the bar hides again. Maybe this could be combined with the battery module, so that it automatically will be enabled when the battery module is enabled.

@emirror-de
Copy link
Author

emirror-de commented Oct 26, 2021

I just tried your config @somini

If you change your sway config to this:

bar {
    swaybar_command waybar
    mode hide
}

If mode hide is not present, both bars are being visible all the time.

Change your waybar config:

[
{
    "layer": "top",
    "position": "top",
    "name": "main",
    "modules-left": [
	"sway/hide",
	"sway/workspaces",
	"sway/mode"
    ],
    ... all your config for this bar
},
{
    "layer": "top",
    "position": "bottom",
    "name": "info",
    "modules-left": [
	"sway/workspaces",
	"sway/mode"
    ],
    ... all your config for this bar
}
]

Note the change to an array of bars in the waybar config.

The main bar should be the one only visible when MOD is pressed, the info bar should be always visible. It is pretty much the same that @woutdp already wrote.

In my opinion this PR is ready. Until now I did not discover any further issues.

@somini
Copy link

somini commented Oct 27, 2021

@emirror-de Thanks for testing this.

So, from what I can tell, the trick is to have a single Waybar process do both bars at once, using an array of configurations. Did not know about that.

I just can't reproduce it myself. I get both bars, but instead of hiding the top bar, the bar remains visible, but on top of the regular window. Here's before the first $Mod event, and afterwards.

2021-10-27T01:38:27+01:00
2021-10-27T01:38:45+01:00

Running this with debug logs, I get the message about hiding/showing:

[2021-10-27 01:41:34.885] [debug] sway/hide: visible by modifier: true
[2021-10-27 01:41:35.498] [debug] sway/hide: visible by modifier: false
[2021-10-27 01:41:36.896] [debug] sway/hide: visible by modifier: true
[2021-10-27 01:41:37.717] [debug] sway/hide: visible by modifier: false

I pulled the latest code for this branch (c502e25) and here's my bar-related Sway config:

bar {
    swaybar_command waybar
    id info
    mode hide
    modifier $mod
}

And the waybar config:

[
{
    "layer": "top",
    "position": "top",
    "name": "info",
    "modules-left": [
	"sway/hide",
    ],
    "modules-center": [
	"clock#localtime"
    ],
    "modules-right": [
    ],
    "clock#localtime": {
	"format": "HIDE {:%d%b %H:%M:%S}",
	"tooltip": true,
	"tooltip-format": "<big>{:%Y %B}</big>\n<tt>{calendar}</tt>"
    }
},
{
    "layer": "top",
    "position": "bottom",
    "name": "main",
    "modules-left": [
	"sway/workspaces",
	"sway/mode"
    ],
    "modules-center": [
	"tray"
    ],
    "modules-right": [
	"clock#localtime"
    ],
    "sway/workspaces": {
	"disable-scroll-wraparound": true
    },
    "sway/mode": {},
    "clock#localtime": {
	"format": "SHOW {:%d%b %H:%M:%S}",
	"tooltip": true,
	"tooltip-format": "<big>{:%Y %B}</big>\n<tt>{calendar}</tt>"
    },
}
]

@somini
Copy link

somini commented Oct 27, 2021

It works! I guess, just need more testing.

According to #732 (comment), layer: "top" is no longer relevant, so I removed it from the "hidden" Waybar configuration JSON objects, and now the bar is correctly hidden.

There's only a very small "bug", the bar starts out in the shown position, and only reverts to the hidden position on the first $Mod event (which triggers a main window resize). If the bar is to be hidden, I would expect it to start hidden. I would accept it if there's a strong technical issue that prevents this behaviour.

Set "hide-on-startup" to true in your sway/hide config to enable.
@emirror-de
Copy link
Author

This behavior is indeed intended.

The idea behind this is in case there is only one bar per screen and with sway/hide module, the user should know about the bar being available. Otherwise there is no information about the correct startup of waybar.

I added a config parameter to hide the bar containing the module on startup. To enable, add the following lines to your bar that should be hidden:

{
    // this is your bar config object
    // add the following lines to the json
    "sway/hide": {
        "hide-on-startup": true
    }
}

@somini
Copy link

somini commented Oct 30, 2021

Makes sense. Many thanks for that configuration option.

I guess this is ready now, you can remove the Draft option now.

Great work, I'll be using this more widely as soon as it goes in a release.

@emirror-de emirror-de marked this pull request as ready for review October 30, 2021 18:12
@emirror-de emirror-de marked this pull request as draft November 3, 2021 08:25
@emirror-de
Copy link
Author

I did some refactoring on the code to make it more readable. Also the behavior has been changed a bit:

  • Exclusive Zone has been removed for the bar. This means the bar draws over other windows on startup without having exclusive space on the screen. So no resizing any longer after the first MOD press. Toggling by USR1 signal has been untouched.
  • A new boolean configuration option has been added "hide-to-bottom-layer". If set, the bar is sent to the bottom layer instead of the configured layer. Also a "bottom-layer" CSS class is then added to it. This enables eg. that the bar is shown on screens that do not have any windows open while hidden on monitors with shown windows.

Summary of config options:

{
    "sway/hide": {
        "hide-on-startup": true,
        "hide-to-bottom-layer": true
    }
}

@emirror-de emirror-de marked this pull request as ready for review November 3, 2021 21:12
@emirror-de emirror-de marked this pull request as draft November 9, 2021 13:55
@alebastr
Copy link
Contributor

@emirror-de so I finally found time to complete my alternative implementation in #1244. I looked through all the comments here and ended up with pretty similar approach and functionality (but cleaner design, IMO). Sorry for doing that instead of continuing to review this PR :-(

Do you mind checking if there's something missing or behaving not as you expected in my branch?

@emirror-de
Copy link
Author

Hey @alebastr! This indeed looks much cleaner than an approach with an additional module. I will close this PR in favor of #1244. Discussion will also move to the other PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Only show waybar when modifier key is pressed
6 participants