Summary
When panel/mixer_middle_click_action (or ..._right_click_action) is set to
mute_quick_target, clicking that button also opens the mixer popup, same as
show_mixer. This makes the mute_quick_target action indistinguishable from
show_mixer in practice.
Root cause
mute_action in WayfireMixer::reload_config() toggles the quick target's
mute state via:
quick_target->button.set_active(!quick_target->button.get_active());
quick_target->button is a Gtk::ToggleButton whose signal_toggled() is
connected in MixerControl::init():
signals.push_back(mute_conn = button.signal_toggled().connect(
[this, id] ()
{
if (!parent->block_signals)
parent->button->popup(); // <-- fires unconditionally on any toggle
ignore = true;
WpCommon::get().set_mute(id, button.get_active());
}));
Calling set_active() synchronously fires signal_toggled(), which calls
parent->button->popup() regardless of why the button was toggled. So the
quick-mute gesture ends up opening the popup as a side effect, even though
nothing asked it to.
Proposed Fix
MixerControl already exposes set_btn_status_no_callbk() for updating the
toggle button's visual state without going through signal_toggled() (it's
used during initial setup for exactly this reason). mute_action now uses
that to update the button, and applies the mute itself via
WpCommon::get().set_mute(), bypassing the popup-opening side effect
entirely.
auto mute_action = [&] (int c, double x, double y)
{
if (!quick_target)
{
return;
}
guint32 id = wp_proxy_get_bound_id(WP_PROXY(quick_target->object));
bool new_state = !quick_target->button.get_active();
quick_target->set_btn_status_no_callbk(new_state);
WpCommon::get().set_mute(id, new_state);
};
Only src/panel/widgets/mixer/mixer.cpp is touched; no header or
mixer-control.cpp changes needed.
Testing
- Set:
mixer_left_click_action = show_mixer
mixer_middle_click_action = mute_quick_target
mixer_right_click_action = show_quick_target
- Middle-click the panel widget: mute now toggles (icon updates) and the
popup no longer opens.
- Confirmed muting via an external shortcut (not through this widget) still
updates the icon correctly, since that path goes through
notify_is_muted_signal independently of this lambda.
- Left/right click actions (
show_mixer, show_quick_target) unaffected.
Note for maintainers
mute_action (here) and MixerControl's signal_toggled handler now both
call WpCommon::get().set_mute(id, ...) independently. This is intentional
to avoid touching mixer-control.cpp/mixer.hpp, but if the mute-setting
logic grows additional bookkeeping in the future, both call sites will need
to stay in sync.
Summary
When
panel/mixer_middle_click_action(or..._right_click_action) is set tomute_quick_target, clicking that button also opens the mixer popup, same asshow_mixer. This makes themute_quick_targetaction indistinguishable fromshow_mixerin practice.Root cause
mute_actioninWayfireMixer::reload_config()toggles the quick target'smute state via:
quick_target->buttonis aGtk::ToggleButtonwhosesignal_toggled()isconnected in
MixerControl::init():signals.push_back(mute_conn = button.signal_toggled().connect( [this, id] () { if (!parent->block_signals) parent->button->popup(); // <-- fires unconditionally on any toggle ignore = true; WpCommon::get().set_mute(id, button.get_active()); }));Calling
set_active()synchronously firessignal_toggled(), which callsparent->button->popup()regardless of why the button was toggled. So thequick-mute gesture ends up opening the popup as a side effect, even though
nothing asked it to.
Proposed Fix
MixerControlalready exposesset_btn_status_no_callbk()for updating thetoggle button's visual state without going through
signal_toggled()(it'sused during initial setup for exactly this reason).
mute_actionnow usesthat to update the button, and applies the mute itself via
WpCommon::get().set_mute(), bypassing the popup-opening side effectentirely.
Only
src/panel/widgets/mixer/mixer.cppis touched; no header ormixer-control.cppchanges needed.Testing
popup no longer opens.
updates the icon correctly, since that path goes through
notify_is_muted_signalindependently of this lambda.show_mixer,show_quick_target) unaffected.Note for maintainers
mute_action(here) andMixerControl'ssignal_toggledhandler now bothcall
WpCommon::get().set_mute(id, ...)independently. This is intentionalto avoid touching
mixer-control.cpp/mixer.hpp, but if the mute-settinglogic grows additional bookkeeping in the future, both call sites will need
to stay in sync.