diff --git a/data/config b/data/config index fe1362e..bef02bb 100644 --- a/data/config +++ b/data/config @@ -31,3 +31,6 @@ DefaultWorkspaceSymbol:  # Forces the time to be centered. # This can cause issues, if there is not enough space on screen (e.g. when opening the text) CenterTime: true + +# Sets the audio slider to be on reveal (Just like the sensors) when true. Only affects the bar. +AudioRevealer: false diff --git a/src/Bar.cpp b/src/Bar.cpp index 64b6ab3..9421f63 100644 --- a/src/Bar.cpp +++ b/src/Bar.cpp @@ -221,15 +221,8 @@ namespace Bar void WidgetAudio(Widget& parent) { - auto box = Widget::Create(); - box->SetSpacing({8, false}); - box->SetHorizontalTransform({-1, false, Alignment::Right}); + auto widgetAudioSlider = [](Widget& parent) { - auto icon = Widget::Create(); - icon->SetClass("audio-icon"); - icon->SetText("墳"); - DynCtx::audioIcon = icon.get(); - auto slider = Widget::Create(); slider->SetOrientation(Orientation::Horizontal); slider->SetHorizontalTransform({100, true, Alignment::Fill}); @@ -239,11 +232,60 @@ namespace Bar slider->OnValueChange(DynCtx::OnChangeVolume); slider->SetRange({0, 1, 0.01}); - box->AddChild(std::move(slider)); - box->AddChild(std::move(icon)); - } + parent.AddChild(std::move(slider)); + }; - parent.AddChild(std::move(box)); + auto widgetAudioBody = [&widgetAudioSlider](Widget& parent) + { + auto box = Widget::Create(); + box->SetSpacing({8, false}); + box->SetHorizontalTransform({-1, true, Alignment::Right}); + { + auto icon = Widget::Create(); + icon->SetClass("audio-icon"); + icon->SetText("墳"); + DynCtx::audioIcon = icon.get(); + + if (Config::Get().audioRevealer) + { + EventBox& eventBox = (EventBox&)parent; + auto revealer = Widget::Create(); + revealer->SetTransition({TransitionType::SlideLeft, 500}); + // Add event to eventbox for the revealer to open + eventBox.SetEventFn( + [slideRevealer = revealer.get()](EventBox&, bool hovered) + { + slideRevealer->SetRevealed(hovered); + }); + { + widgetAudioSlider(*revealer); + } + + box->AddChild(std::move(revealer)); + } + else + { + // Straight forward + widgetAudioSlider(*box); + } + + box->AddChild(std::move(icon)); + } + parent.AddChild(std::move(box)); + }; + + if (Config::Get().audioRevealer) + { + // Need an EventBox + auto eventBox = Widget::Create(); + widgetAudioBody(*eventBox); + parent.AddChild(std::move(eventBox)); + } + else + { + // Just invoke it. + widgetAudioBody(parent); + } } #ifdef WITH_BLUEZ diff --git a/src/Config.cpp b/src/Config.cpp index c693878..c08ba16 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -123,7 +123,6 @@ void Config::Load() AddConfigVar("LockCommand", config.lockCommand, lineView, foundProperty); AddConfigVar("ExitCommand", config.exitCommand, lineView, foundProperty); AddConfigVar("BatteryFolder", config.batteryFolder, lineView, foundProperty); - AddConfigVar("CenterTime", config.centerTime, lineView, foundProperty); AddConfigVar("DefaultWorkspaceSymbol", config.defaultWorkspaceSymbol, lineView, foundProperty); for (int i = 1; i < 10; i++) { @@ -131,6 +130,9 @@ void Config::Load() AddConfigVar("WorkspaceSymbol-" + std::to_string(i), config.workspaceSymbols[i - 1], lineView, foundProperty); } + AddConfigVar("CenterTime", config.centerTime, lineView, foundProperty); + AddConfigVar("AudioRevealer", config.audioRevealer, lineView, foundProperty); + if (foundProperty == false) { LOG("Warning: unknown config var: " << line); diff --git a/src/Config.h b/src/Config.h index 0f81ad2..90c1e59 100644 --- a/src/Config.h +++ b/src/Config.h @@ -14,6 +14,7 @@ public: std::string defaultWorkspaceSymbol = ""; bool centerTime = true; + bool audioRevealer = false; static void Load(); static const Config& Get(); diff --git a/src/Widget.cpp b/src/Widget.cpp index 29b35fd..426c32e 100644 --- a/src/Widget.cpp +++ b/src/Widget.cpp @@ -131,6 +131,11 @@ void Widget::SetVisible(bool visible) gtk_widget_set_visible(m_Widget, visible); } +void Widget::PropagateToParent(GdkEvent* event) +{ + gtk_propagate_event(gtk_widget_get_parent(m_Widget), event); +} + void Widget::ApplyPropertiesToWidget() { // Apply style @@ -189,6 +194,7 @@ void EventBox::SetEventFn(std::function&& fn) void EventBox::Create() { m_Widget = gtk_event_box_new(); + gtk_event_box_set_above_child((GtkEventBox*)m_Widget, false); auto enter = [](GtkWidget*, GdkEventCrossing*, gpointer data) -> gboolean { EventBox* box = (EventBox*)data; @@ -324,11 +330,12 @@ void Text::Create() void Button::Create() { m_Widget = gtk_button_new_with_label(m_Text.c_str()); - auto clickFn = [](UNUSED GtkButton* gtkButton, void* data) + auto clickFn = [](UNUSED GtkButton* gtkButton, void* data) -> gboolean { Button* button = (Button*)data; if (button->m_OnClick) button->m_OnClick(*button); + return GDK_EVENT_STOP; }; g_signal_connect(m_Widget, "clicked", G_CALLBACK(+clickFn), this); ApplyPropertiesToWidget(); @@ -386,5 +393,18 @@ void Slider::Create() return false; }; g_signal_connect(m_Widget, "change-value", G_CALLBACK(+changedFn), this); + + // Propagate events to any parent eventboxes + auto propagate = [](GtkWidget*, GdkEventCrossing* data, gpointer widget) -> gboolean + { + Slider* slider = (Slider*)widget; + // Seems to be necessary. For revealers to work properly, we need to notify it of the event through propagation. + // Automatic propagation with GDK_EVENT_PROPAGATE doesn't work for some reason + slider->PropagateToParent((GdkEvent*)data); + return GDK_EVENT_PROPAGATE; + }; + gtk_widget_set_events(m_Widget, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); + g_signal_connect(m_Widget, "enter-notify-event", G_CALLBACK(+propagate), this); + g_signal_connect(m_Widget, "leave-notify-event", G_CALLBACK(+propagate), this); ApplyPropertiesToWidget(); } diff --git a/src/Widget.h b/src/Widget.h index 4427cef..24870d5 100644 --- a/src/Widget.h +++ b/src/Widget.h @@ -141,6 +141,7 @@ public: void SetVisible(bool visible); protected: + void PropagateToParent(GdkEvent* event); void ApplyPropertiesToWidget(); GtkWidget* m_Widget = nullptr;