Merge branch 'master' into river-tags-monitor-focus

This commit is contained in:
lilly-lizard
2025-03-30 18:57:27 +13:00
147 changed files with 2886 additions and 751 deletions
+2 -1
View File
@@ -16,4 +16,5 @@ jobs:
with: with:
source: "." source: "."
extensions: "hpp,h,cpp,c" extensions: "hpp,h,cpp,c"
clangFormatVersion: 16 style: "file:.clang-format"
clangFormatVersion: 19
+1
View File
@@ -8,6 +8,7 @@ on:
jobs: jobs:
build-and-push: build-and-push:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.repository == 'Alexays/Waybar'
strategy: strategy:
fail-fast: false # don't fail the other jobs if one of the images fails to build fail-fast: false # don't fail the other jobs if one of the images fails to build
matrix: matrix:
+2 -3
View File
@@ -14,18 +14,17 @@ jobs:
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Test in FreeBSD VM - name: Test in FreeBSD VM
uses: cross-platform-actions/action@v0.23.0 uses: cross-platform-actions/action@v0.25.0
timeout-minutes: 180 timeout-minutes: 180
env: env:
CPPFLAGS: '-isystem/usr/local/include' CPPFLAGS: '-isystem/usr/local/include'
LDFLAGS: '-L/usr/local/lib' LDFLAGS: '-L/usr/local/lib'
with: with:
operating_system: freebsd operating_system: freebsd
version: "13.2" version: "14.1"
environment_variables: CPPFLAGS LDFLAGS environment_variables: CPPFLAGS LDFLAGS
sync_files: runner-to-vm sync_files: runner-to-vm
run: | run: |
sudo sed -i '' 's/quarterly/latest/' /etc/pkg/FreeBSD.conf
sudo pkg install -y git # subprojects/date sudo pkg install -y git # subprojects/date
sudo pkg install -y catch evdev-proto gtk-layer-shell gtkmm30 jsoncpp \ sudo pkg install -y catch evdev-proto gtk-layer-shell gtkmm30 jsoncpp \
libdbusmenu libevdev libfmt libmpdclient libudev-devd meson \ libdbusmenu libevdev libfmt libmpdclient libudev-devd meson \
@@ -9,6 +9,7 @@ on:
jobs: jobs:
lockfile: lockfile:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.event_name != 'schedule' || github.repository == 'Alexays/Waybar'
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2018 Alex Copyright (c) 2025 Alex
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
+2 -1
View File
@@ -8,7 +8,8 @@
- Sway (Workspaces, Binding mode, Focused window name) - Sway (Workspaces, Binding mode, Focused window name)
- River (Mapping mode, Tags, Focused window name) - River (Mapping mode, Tags, Focused window name)
- Hyprland (Window Icons, Workspaces, Focused window name) - Hyprland (Window Icons, Workspaces, Focused window name)
- DWL (Tags, Focused window name) [requires dwl ipc patch](https://github.com/djpohly/dwl/wiki/ipc) - Niri (Workspaces, Focused window name, Language)
- DWL (Tags, Focused window name) [requires dwl ipc patch](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/ipc)
- Tray [#21](https://github.com/Alexays/Waybar/issues/21) - Tray [#21](https://github.com/Alexays/Waybar/issues/21)
- Local time - Local time
- Battery - Battery
Generated
+6 -6
View File
@@ -3,11 +3,11 @@
"flake-compat": { "flake-compat": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1696426674, "lastModified": 1733328505,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=",
"owner": "edolstra", "owner": "edolstra",
"repo": "flake-compat", "repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -18,11 +18,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1719506693, "lastModified": 1740560979,
"narHash": "sha256-C8e9S7RzshSdHB7L+v9I51af1gDM5unhJ2xO1ywxNH8=", "narHash": "sha256-Vr3Qi346M+8CjedtbyUevIGDZW8LcA1fTG0ugPY/Hic=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "b2852eb9365c6de48ffb0dc2c9562591f652242a", "rev": "5135c59491985879812717f4c9fea69604e7f26f",
"type": "github" "type": "github"
}, },
"original": { "original": {
+4 -1
View File
@@ -16,13 +16,15 @@ class AModule : public IModule {
~AModule() override; ~AModule() override;
auto update() -> void override; auto update() -> void override;
virtual auto refresh(int shouldRefresh) -> void{}; virtual auto refresh(int shouldRefresh) -> void {};
operator Gtk::Widget &() override; operator Gtk::Widget &() override;
auto doAction(const std::string &name) -> void override; auto doAction(const std::string &name) -> void override;
/// Emitting on this dispatcher triggers a update() call /// Emitting on this dispatcher triggers a update() call
Glib::Dispatcher dp; Glib::Dispatcher dp;
bool expandEnabled() const;
protected: protected:
// Don't need to make an object directly // Don't need to make an object directly
// Derived classes are able to use it // Derived classes are able to use it
@@ -50,6 +52,7 @@ class AModule : public IModule {
private: private:
bool handleUserEvent(GdkEventButton *const &ev); bool handleUserEvent(GdkEventButton *const &ev);
const bool isTooltip; const bool isTooltip;
const bool isExpand;
bool hasUserEvents_; bool hasUserEvents_;
std::vector<int> pid_; std::vector<int> pid_;
gdouble distance_scrolled_y_; gdouble distance_scrolled_y_;
+3 -3
View File
@@ -42,7 +42,7 @@ struct bar_margins {
}; };
struct bar_mode { struct bar_mode {
std::optional<bar_layer> layer; bar_layer layer;
bool exclusive; bool exclusive;
bool passthrough; bool passthrough;
bool visible; bool visible;
@@ -54,7 +54,7 @@ class BarIpcClient;
} }
#endif // HAVE_SWAY #endif // HAVE_SWAY
class Bar { class Bar : public sigc::trackable {
public: public:
using bar_mode_map = std::map<std::string, struct bar_mode>; using bar_mode_map = std::map<std::string, struct bar_mode>;
static const bar_mode_map PRESET_MODES; static const bar_mode_map PRESET_MODES;
@@ -66,7 +66,7 @@ class Bar {
~Bar(); ~Bar();
void setMode(const std::string &mode); void setMode(const std::string &mode);
void setVisible(bool visible); void setVisible(bool value);
void toggle(); void toggle();
void handleSignal(int); void handleSignal(int);
+3
View File
@@ -20,6 +20,9 @@ class Config {
static std::optional<std::string> findConfigPath( static std::optional<std::string> findConfigPath(
const std::vector<std::string> &names, const std::vector<std::string> &dirs = CONFIG_DIRS); const std::vector<std::string> &names, const std::vector<std::string> &dirs = CONFIG_DIRS);
static std::vector<std::string> tryExpandPath(const std::string &base,
const std::string &filename);
Config() = default; Config() = default;
void load(const std::string &config); void load(const std::string &config);
+5 -1
View File
@@ -12,7 +12,7 @@ namespace waybar {
class Group : public AModule { class Group : public AModule {
public: public:
Group(const std::string &, const std::string &, const Json::Value &, bool); Group(const std::string &, const std::string &, const Json::Value &, bool);
virtual ~Group() = default; ~Group() override = default;
auto update() -> void override; auto update() -> void override;
operator Gtk::Widget &() override; operator Gtk::Widget &() override;
@@ -25,9 +25,13 @@ class Group : public AModule {
Gtk::Revealer revealer; Gtk::Revealer revealer;
bool is_first_widget = true; bool is_first_widget = true;
bool is_drawer = false; bool is_drawer = false;
bool click_to_reveal = false;
std::string add_class_to_drawer_children; std::string add_class_to_drawer_children;
bool handleMouseEnter(GdkEventCrossing *const &ev) override; bool handleMouseEnter(GdkEventCrossing *const &ev) override;
bool handleMouseLeave(GdkEventCrossing *const &ev) override; bool handleMouseLeave(GdkEventCrossing *const &ev) override;
bool handleToggle(GdkEventButton *const &ev) override;
void show_group();
void hide_group();
}; };
} // namespace waybar } // namespace waybar
+7 -6
View File
@@ -23,11 +23,11 @@ class Cava final : public ALabel {
util::SleeperThread thread_; util::SleeperThread thread_;
util::SleeperThread thread_fetch_input_; util::SleeperThread thread_fetch_input_;
struct cava::error_s error_ {}; // cava errors struct cava::error_s error_{}; // cava errors
struct cava::config_params prm_ {}; // cava parameters struct cava::config_params prm_{}; // cava parameters
struct cava::audio_raw audio_raw_ {}; // cava handled raw audio data(is based on audio_data) struct cava::audio_raw audio_raw_{}; // cava handled raw audio data(is based on audio_data)
struct cava::audio_data audio_data_ {}; // cava audio data struct cava::audio_data audio_data_{}; // cava audio data
struct cava::cava_plan* plan_; //{new cava_plan{}}; struct cava::cava_plan* plan_; //{new cava_plan{}};
// Cava API to read audio source // Cava API to read audio source
cava::ptr input_source_; cava::ptr input_source_;
// Delay to handle audio source // Delay to handle audio source
@@ -39,11 +39,12 @@ class Cava final : public ALabel {
std::chrono::seconds suspend_silence_delay_{0}; std::chrono::seconds suspend_silence_delay_{0};
bool silence_{false}; bool silence_{false};
bool hide_on_silence_{false}; bool hide_on_silence_{false};
std::string format_silent_{""};
int sleep_counter_{0}; int sleep_counter_{0};
// Cava method // Cava method
void pause_resume(); void pause_resume();
// ModuleActionMap // ModuleActionMap
static inline std::map<const std::string, void (waybar::modules::Cava::*const)()> actionMap_{ static inline std::map<const std::string, void (waybar::modules::Cava::* const)()> actionMap_{
{"mode", &waybar::modules::Cava::pause_resume}}; {"mode", &waybar::modules::Cava::pause_resume}};
}; };
} // namespace waybar::modules } // namespace waybar::modules
+1 -1
View File
@@ -79,7 +79,7 @@ class Clock final : public ALabel {
void tz_up(); void tz_up();
void tz_down(); void tz_down();
// Module Action Map // Module Action Map
static inline std::map<const std::string, void (waybar::modules::Clock::*const)()> actionMap_{ static inline std::map<const std::string, void (waybar::modules::Clock::* const)()> actionMap_{
{"mode", &waybar::modules::Clock::cldModeSwitch}, {"mode", &waybar::modules::Clock::cldModeSwitch},
{"shift_up", &waybar::modules::Clock::cldShift_up}, {"shift_up", &waybar::modules::Clock::cldShift_up},
{"shift_down", &waybar::modules::Clock::cldShift_down}, {"shift_down", &waybar::modules::Clock::cldShift_down},
+8 -4
View File
@@ -2,9 +2,9 @@
#include <filesystem> #include <filesystem>
#include <list> #include <list>
#include <memory>
#include <mutex> #include <mutex>
#include <string> #include <string>
#include <thread>
#include <utility> #include <utility>
#include "util/json.hpp" #include "util/json.hpp"
@@ -19,7 +19,9 @@ class EventHandler {
class IPC { class IPC {
public: public:
IPC() { startIPC(); } IPC();
~IPC();
static IPC& inst();
void registerForIPC(const std::string& ev, EventHandler* ev_handler); void registerForIPC(const std::string& ev, EventHandler* ev_handler);
void unregisterForIPC(EventHandler* handler); void unregisterForIPC(EventHandler* handler);
@@ -32,14 +34,16 @@ class IPC {
static std::filesystem::path socketFolder_; static std::filesystem::path socketFolder_;
private: private:
void startIPC(); void socketListener();
void parseIPC(const std::string&); void parseIPC(const std::string&);
std::thread ipcThread_;
std::mutex callbackMutex_; std::mutex callbackMutex_;
util::JsonParser parser_; util::JsonParser parser_;
std::list<std::pair<std::string, EventHandler*>> callbacks_; std::list<std::pair<std::string, EventHandler*>> callbacks_;
int socketfd_; // the hyprland socket file descriptor
bool running_ = true;
}; };
inline std::unique_ptr<IPC> gIPC;
inline bool modulesReady = false; inline bool modulesReady = false;
}; // namespace waybar::modules::hyprland }; // namespace waybar::modules::hyprland
+2
View File
@@ -37,6 +37,8 @@ class Language : public waybar::ALabel, public EventHandler {
util::JsonParser parser_; util::JsonParser parser_;
Layout layout_; Layout layout_;
IPC& m_ipc;
}; };
} // namespace waybar::modules::hyprland } // namespace waybar::modules::hyprland
+2
View File
@@ -28,6 +28,8 @@ class Submap : public waybar::ALabel, public EventHandler {
std::string submap_; std::string submap_;
bool always_on_ = false; bool always_on_ = false;
std::string default_submap_ = "Default"; std::string default_submap_ = "Default";
IPC& m_ipc;
}; };
} // namespace waybar::modules::hyprland } // namespace waybar::modules::hyprland
+2
View File
@@ -60,6 +60,8 @@ class Window : public waybar::AAppIconLabel, public EventHandler {
bool swallowing_; bool swallowing_;
bool fullscreen_; bool fullscreen_;
bool focused_; bool focused_;
IPC& m_ipc;
}; };
} // namespace waybar::modules::hyprland } // namespace waybar::modules::hyprland
+1
View File
@@ -83,6 +83,7 @@ class Workspace {
Gtk::Button m_button; Gtk::Button m_button;
Gtk::Box m_content; Gtk::Box m_content;
Gtk::Label m_label; Gtk::Label m_label;
IPC& m_ipc;
}; };
} // namespace waybar::modules::hyprland } // namespace waybar::modules::hyprland
+14 -4
View File
@@ -7,6 +7,7 @@
#include <cstdint> #include <cstdint>
#include <map> #include <map>
#include <memory> #include <memory>
#include <optional>
#include <regex> #include <regex>
#include <string> #include <string>
#include <vector> #include <vector>
@@ -55,7 +56,7 @@ class Workspaces : public AModule, public EventHandler {
static Json::Value createMonitorWorkspaceData(std::string const& name, static Json::Value createMonitorWorkspaceData(std::string const& name,
std::string const& monitor); std::string const& monitor);
void removeWorkspace(std::string const& name); void removeWorkspace(std::string const& workspaceString);
void setUrgentWorkspace(std::string const& windowaddress); void setUrgentWorkspace(std::string const& windowaddress);
// Config // Config
@@ -74,10 +75,11 @@ class Workspaces : public AModule, public EventHandler {
void onWorkspaceActivated(std::string const& payload); void onWorkspaceActivated(std::string const& payload);
void onSpecialWorkspaceActivated(std::string const& payload); void onSpecialWorkspaceActivated(std::string const& payload);
void onWorkspaceDestroyed(std::string const& payload); void onWorkspaceDestroyed(std::string const& payload);
void onWorkspaceCreated(std::string const& workspaceName, void onWorkspaceCreated(std::string const& payload,
Json::Value const& clientsData = Json::Value::nullRef); Json::Value const& clientsData = Json::Value::nullRef);
void onWorkspaceMoved(std::string const& payload); void onWorkspaceMoved(std::string const& payload);
void onWorkspaceRenamed(std::string const& payload); void onWorkspaceRenamed(std::string const& payload);
static std::optional<int> parseWorkspaceId(std::string const& workspaceIdStr);
// monitor events // monitor events
void onMonitorFocused(std::string const& payload); void onMonitorFocused(std::string const& payload);
@@ -93,11 +95,18 @@ class Workspaces : public AModule, public EventHandler {
int windowRewritePriorityFunction(std::string const& window_rule); int windowRewritePriorityFunction(std::string const& window_rule);
// event payload management
template <typename... Args>
static std::string makePayload(Args const&... args);
static std::pair<std::string, std::string> splitDoublePayload(std::string const& payload);
static std::tuple<std::string, std::string, std::string> splitTriplePayload(
std::string const& payload);
// Update methods // Update methods
void doUpdate(); void doUpdate();
void removeWorkspacesToRemove(); void removeWorkspacesToRemove();
void createWorkspacesToCreate(); void createWorkspacesToCreate();
static std::vector<std::string> getVisibleWorkspaces(); static std::vector<int> getVisibleWorkspaces();
void updateWorkspaceStates(); void updateWorkspaceStates();
bool updateWindowsToCreate(); bool updateWindowsToCreate();
@@ -138,7 +147,7 @@ class Workspaces : public AModule, public EventHandler {
bool m_withIcon; bool m_withIcon;
uint64_t m_monitorId; uint64_t m_monitorId;
std::string m_activeWorkspaceName; int m_activeWorkspaceId;
std::string m_activeSpecialWorkspaceName; std::string m_activeSpecialWorkspaceName;
std::vector<std::unique_ptr<Workspace>> m_workspaces; std::vector<std::unique_ptr<Workspace>> m_workspaces;
std::vector<std::pair<Json::Value, Json::Value>> m_workspacesToCreate; std::vector<std::pair<Json::Value, Json::Value>> m_workspacesToCreate;
@@ -150,6 +159,7 @@ class Workspaces : public AModule, public EventHandler {
std::mutex m_mutex; std::mutex m_mutex;
const Bar& m_bar; const Bar& m_bar;
Gtk::Box m_box; Gtk::Box m_box;
IPC& m_ipc;
}; };
} // namespace waybar::modules::hyprland } // namespace waybar::modules::hyprland
+8 -1
View File
@@ -16,6 +16,8 @@
#include "util/rfkill.hpp" #include "util/rfkill.hpp"
#endif #endif
enum ip_addr_pref : uint8_t { IPV4, IPV6, IPV4_6 };
namespace waybar::modules { namespace waybar::modules {
class Network : public ALabel { class Network : public ALabel {
@@ -40,6 +42,7 @@ class Network : public ALabel {
void parseEssid(struct nlattr**); void parseEssid(struct nlattr**);
void parseSignal(struct nlattr**); void parseSignal(struct nlattr**);
void parseFreq(struct nlattr**); void parseFreq(struct nlattr**);
void parseBssid(struct nlattr**);
bool associatedOrJoined(struct nlattr**); bool associatedOrJoined(struct nlattr**);
bool checkInterface(std::string name); bool checkInterface(std::string name);
auto getInfo() -> void; auto getInfo() -> void;
@@ -49,7 +52,7 @@ class Network : public ALabel {
std::optional<std::pair<unsigned long long, unsigned long long>> readBandwidthUsage(); std::optional<std::pair<unsigned long long, unsigned long long>> readBandwidthUsage();
int ifid_; int ifid_;
sa_family_t family_; ip_addr_pref addr_pref_;
struct sockaddr_nl nladdr_ = {0}; struct sockaddr_nl nladdr_ = {0};
struct nl_sock* sock_ = nullptr; struct nl_sock* sock_ = nullptr;
struct nl_sock* ev_sock_ = nullptr; struct nl_sock* ev_sock_ = nullptr;
@@ -69,12 +72,16 @@ class Network : public ALabel {
std::string state_; std::string state_;
std::string essid_; std::string essid_;
std::string bssid_;
bool carrier_; bool carrier_;
std::string ifname_; std::string ifname_;
std::string ipaddr_; std::string ipaddr_;
std::string ipaddr6_;
std::string gwaddr_; std::string gwaddr_;
std::string netmask_; std::string netmask_;
std::string netmask6_;
int cidr_; int cidr_;
int cidr6_;
int32_t signal_strength_dbm_; int32_t signal_strength_dbm_;
uint8_t signal_strength_; uint8_t signal_strength_;
std::string signal_strength_app_; std::string signal_strength_app_;
+52
View File
@@ -0,0 +1,52 @@
#pragma once
#include <list>
#include <mutex>
#include <string>
#include <utility>
#include "util/json.hpp"
namespace waybar::modules::niri {
class EventHandler {
public:
virtual void onEvent(const Json::Value& ev) = 0;
virtual ~EventHandler() = default;
};
class IPC {
public:
IPC() { startIPC(); }
void registerForIPC(const std::string& ev, EventHandler* ev_handler);
void unregisterForIPC(EventHandler* handler);
static Json::Value send(const Json::Value& request);
// The data members are only safe to access while dataMutex_ is locked.
std::lock_guard<std::mutex> lockData() { return std::lock_guard(dataMutex_); }
const std::vector<Json::Value>& workspaces() const { return workspaces_; }
const std::vector<Json::Value>& windows() const { return windows_; }
const std::vector<std::string>& keyboardLayoutNames() const { return keyboardLayoutNames_; }
unsigned keyboardLayoutCurrent() const { return keyboardLayoutCurrent_; }
private:
void startIPC();
static int connectToSocket();
void parseIPC(const std::string&);
std::mutex dataMutex_;
std::vector<Json::Value> workspaces_;
std::vector<Json::Value> windows_;
std::vector<std::string> keyboardLayoutNames_;
unsigned keyboardLayoutCurrent_;
util::JsonParser parser_;
std::mutex callbackMutex_;
std::list<std::pair<std::string, EventHandler*>> callbacks_;
};
inline std::unique_ptr<IPC> gIPC;
}; // namespace waybar::modules::niri
+38
View File
@@ -0,0 +1,38 @@
#pragma once
#include <string>
#include "ALabel.hpp"
#include "bar.hpp"
#include "modules/niri/backend.hpp"
namespace waybar::modules::niri {
class Language : public ALabel, public EventHandler {
public:
Language(const std::string &, const Bar &, const Json::Value &);
~Language() override;
void update() override;
private:
void updateFromIPC();
void onEvent(const Json::Value &ev) override;
void doUpdate();
struct Layout {
std::string full_name;
std::string short_name;
std::string variant;
std::string short_description;
};
static Layout getLayout(const std::string &fullName);
std::mutex mutex_;
const Bar &bar_;
std::vector<Layout> layouts_;
unsigned current_idx_;
};
} // namespace waybar::modules::niri
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#include <gtkmm/button.h>
#include <json/value.h>
#include "AAppIconLabel.hpp"
#include "bar.hpp"
#include "modules/niri/backend.hpp"
namespace waybar::modules::niri {
class Window : public AAppIconLabel, public EventHandler {
public:
Window(const std::string &, const Bar &, const Json::Value &);
~Window() override;
void update() override;
private:
void onEvent(const Json::Value &ev) override;
void doUpdate();
void setClass(const std::string &className, bool enable);
const Bar &bar_;
std::string oldAppId_;
};
} // namespace waybar::modules::niri
+30
View File
@@ -0,0 +1,30 @@
#pragma once
#include <gtkmm/button.h>
#include <json/value.h>
#include "AModule.hpp"
#include "bar.hpp"
#include "modules/niri/backend.hpp"
namespace waybar::modules::niri {
class Workspaces : public AModule, public EventHandler {
public:
Workspaces(const std::string &, const Bar &, const Json::Value &);
~Workspaces() override;
void update() override;
private:
void onEvent(const Json::Value &ev) override;
void doUpdate();
Gtk::Button &addButton(const Json::Value &ws);
std::string getIcon(const std::string &value, const Json::Value &ws);
const Bar &bar_;
Gtk::Box box_;
// Map from niri workspace id to button.
std::unordered_map<uint64_t, Gtk::Button> buttons_;
};
} // namespace waybar::modules::niri
+1 -1
View File
@@ -13,7 +13,7 @@ namespace waybar::modules::privacy {
class Privacy : public AModule { class Privacy : public AModule {
public: public:
Privacy(const std::string &, const Json::Value &, const std::string &pos); Privacy(const std::string &, const Json::Value &, Gtk::Orientation, const std::string &pos);
auto update() -> void override; auto update() -> void override;
void onPrivacyNodesChanged(); void onPrivacyNodesChanged();
+2 -2
View File
@@ -17,8 +17,8 @@ namespace waybar::modules::privacy {
class PrivacyItem : public Gtk::Revealer { class PrivacyItem : public Gtk::Revealer {
public: public:
PrivacyItem(const Json::Value &config_, enum PrivacyNodeType privacy_type_, PrivacyItem(const Json::Value &config_, enum PrivacyNodeType privacy_type_,
std::list<PrivacyNodeInfo *> *nodes, const std::string &pos, const uint icon_size, std::list<PrivacyNodeInfo *> *nodes, Gtk::Orientation orientation,
const uint transition_duration); const std::string &pos, const uint icon_size, const uint transition_duration);
enum PrivacyNodeType privacy_type; enum PrivacyNodeType privacy_type;
+43
View File
@@ -0,0 +1,43 @@
#pragma once
#include <json/json.h>
#include <spdlog/spdlog.h>
#include <string>
#include <unordered_map>
class IconManager {
public:
static IconManager& instance() {
static IconManager instance;
return instance;
}
void setIconsConfig(const Json::Value& icons_config) {
if (icons_config.isObject()) {
for (const auto& key : icons_config.getMemberNames()) {
std::string app_name = key;
const Json::Value& icon_value = icons_config[key];
if (icon_value.isString()) {
std::string icon_path = icon_value.asString();
icons_map_[app_name] = icon_path;
}
}
} else {
spdlog::warn("Invalid icon config format.");
}
}
std::string getIconForApp(const std::string& app_name) const {
auto it = icons_map_.find(app_name);
if (it != icons_map_.end()) {
return it->second;
}
return "";
}
private:
IconManager() = default;
std::unordered_map<std::string, std::string> icons_map_;
};
+1
View File
@@ -62,6 +62,7 @@ class Item : public sigc::trackable {
void proxyReady(Glib::RefPtr<Gio::AsyncResult>& result); void proxyReady(Glib::RefPtr<Gio::AsyncResult>& result);
void setProperty(const Glib::ustring& name, Glib::VariantBase& value); void setProperty(const Glib::ustring& name, Glib::VariantBase& value);
void setStatus(const Glib::ustring& value); void setStatus(const Glib::ustring& value);
void setCustomIcon(const std::string& id);
void getUpdatedProperties(); void getUpdatedProperties();
void processUpdatedProperties(Glib::RefPtr<Gio::AsyncResult>& result); void processUpdatedProperties(Glib::RefPtr<Gio::AsyncResult>& result);
void onSignal(const Glib::ustring& sender_name, const Glib::ustring& signal_name, void onSignal(const Glib::ustring& sender_name, const Glib::ustring& signal_name,
+4 -5
View File
@@ -19,7 +19,7 @@ namespace waybar::modules::sway {
class Workspaces : public AModule, public sigc::trackable { class Workspaces : public AModule, public sigc::trackable {
public: public:
Workspaces(const std::string&, const waybar::Bar&, const Json::Value&); Workspaces(const std::string&, const waybar::Bar&, const Json::Value&);
virtual ~Workspaces() = default; ~Workspaces() override = default;
auto update() -> void override; auto update() -> void override;
private: private:
@@ -38,10 +38,10 @@ class Workspaces : public AModule, public sigc::trackable {
Gtk::Button& addButton(const Json::Value&); Gtk::Button& addButton(const Json::Value&);
void onButtonReady(const Json::Value&, Gtk::Button&); void onButtonReady(const Json::Value&, Gtk::Button&);
std::string getIcon(const std::string&, const Json::Value&); std::string getIcon(const std::string&, const Json::Value&);
const std::string getCycleWorkspace(std::vector<Json::Value>::iterator, bool prev) const; std::string getCycleWorkspace(std::vector<Json::Value>::iterator, bool prev) const;
uint16_t getWorkspaceIndex(const std::string& name) const; uint16_t getWorkspaceIndex(const std::string& name) const;
std::string trimWorkspaceName(std::string); static std::string trimWorkspaceName(std::string);
bool handleScroll(GdkEventScroll*) override; bool handleScroll(GdkEventScroll* /*unused*/) override;
const Bar& bar_; const Bar& bar_;
std::vector<Json::Value> workspaces_; std::vector<Json::Value> workspaces_;
@@ -49,7 +49,6 @@ class Workspaces : public AModule, public sigc::trackable {
std::vector<std::string> workspaces_order_; std::vector<std::string> workspaces_order_;
Gtk::Box box_; Gtk::Box box_;
std::string m_formatWindowSeperator; std::string m_formatWindowSeperator;
std::string m_windowRewriteDefault;
util::RegexCollection m_windowRewriteRules; util::RegexCollection m_windowRewriteRules;
util::JsonParser parser_; util::JsonParser parser_;
std::unordered_map<std::string, Gtk::Button> buttons_; std::unordered_map<std::string, Gtk::Button> buttons_;
+1
View File
@@ -18,6 +18,7 @@ class Temperature : public ALabel {
private: private:
float getTemperature(); float getTemperature();
bool isCritical(uint16_t); bool isCritical(uint16_t);
bool isWarning(uint16_t);
std::string file_path_; std::string file_path_;
util::SleeperThread thread_; util::SleeperThread thread_;
+4 -1
View File
@@ -18,7 +18,7 @@ class Wireplumber : public ALabel {
private: private:
void asyncLoadRequiredApiModules(); void asyncLoadRequiredApiModules();
void prepare(); void prepare(waybar::modules::Wireplumber* self);
void activatePlugins(); void activatePlugins();
static void updateVolume(waybar::modules::Wireplumber* self, uint32_t id); static void updateVolume(waybar::modules::Wireplumber* self, uint32_t id);
static void updateNodeName(waybar::modules::Wireplumber* self, uint32_t id); static void updateNodeName(waybar::modules::Wireplumber* self, uint32_t id);
@@ -32,6 +32,8 @@ class Wireplumber : public ALabel {
bool handleScroll(GdkEventScroll* e) override; bool handleScroll(GdkEventScroll* e) override;
static std::list<waybar::modules::Wireplumber*> modules;
WpCore* wp_core_; WpCore* wp_core_;
GPtrArray* apis_; GPtrArray* apis_;
WpObjectManager* om_; WpObjectManager* om_;
@@ -44,6 +46,7 @@ class Wireplumber : public ALabel {
double min_step_; double min_step_;
uint32_t node_id_{0}; uint32_t node_id_{0};
std::string node_name_; std::string node_name_;
gchar* type_;
}; };
} // namespace waybar::modules } // namespace waybar::modules
+7
View File
@@ -24,6 +24,10 @@
namespace waybar::modules::wlr { namespace waybar::modules::wlr {
struct widget_geometry {
int x, y, w, h;
};
class Taskbar; class Taskbar;
class Task { class Task {
@@ -42,6 +46,7 @@ class Task {
}; };
// made public so TaskBar can reorder based on configuration. // made public so TaskBar can reorder based on configuration.
Gtk::Button button; Gtk::Button button;
struct widget_geometry minimize_hint;
private: private:
static uint32_t global_id; static uint32_t global_id;
@@ -82,6 +87,8 @@ class Task {
private: private:
std::string repr() const; std::string repr() const;
std::string state_string(bool = false) const; std::string state_string(bool = false) const;
void set_minimize_hint();
void on_button_size_allocated(Gtk::Allocation &alloc);
void set_app_info_from_app_id_list(const std::string &app_id_list); void set_app_info_from_app_id_list(const std::string &app_id_list);
bool image_load_icon(Gtk::Image &image, const Glib::RefPtr<Gtk::IconTheme> &icon_theme, bool image_load_icon(Gtk::Image &image, const Glib::RefPtr<Gtk::IconTheme> &icon_theme,
Glib::RefPtr<Gio::DesktopAppInfo> app_info, int size); Glib::RefPtr<Gio::DesktopAppInfo> app_info, int size);
+2
View File
@@ -38,6 +38,8 @@ class AudioBackend {
std::string desc_; std::string desc_;
std::string monitor_; std::string monitor_;
std::string current_sink_name_; std::string current_sink_name_;
std::string default_sink_name;
bool default_sink_running_;
bool current_sink_running_; bool current_sink_running_;
// SOURCE // SOURCE
uint32_t source_idx_{0}; uint32_t source_idx_{0};
+2 -2
View File
@@ -6,7 +6,7 @@
class pow_format { class pow_format {
public: public:
pow_format(long long val, std::string&& unit, bool binary = false) pow_format(long long val, std::string&& unit, bool binary = false)
: val_(val), unit_(unit), binary_(binary){}; : val_(val), unit_(unit), binary_(binary) {};
long long val_; long long val_;
std::string unit_; std::string unit_;
@@ -92,7 +92,7 @@ struct formatter<pow_format> {
template <> template <>
struct formatter<Glib::ustring> : formatter<std::string> { struct formatter<Glib::ustring> : formatter<std::string> {
template <typename FormatContext> template <typename FormatContext>
auto format(const Glib::ustring& value, FormatContext& ctx) { auto format(const Glib::ustring& value, FormatContext& ctx) const {
return formatter<std::string>::format(static_cast<std::string>(value), ctx); return formatter<std::string>::format(static_cast<std::string>(value), ctx);
} }
}; };
+5
View File
@@ -31,6 +31,11 @@ The brightness can be controlled by dragging the slider across the bar or clicki
typeof: string ++ typeof: string ++
The name of the preferred device to control. If left empty, a device will be chosen automatically. The name of the preferred device to control. If left empty, a device will be chosen automatically.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# EXAMPLES # EXAMPLES
``` ```
+11 -1
View File
@@ -38,7 +38,7 @@ The *backlight* module displays the current backlight level.
*rotate*: ++ *rotate*: ++
typeof: integer ++ typeof: integer ++
Positive value to rotate the text label. Positive value to rotate the text label (in 90 degree increments).
*states*: ++ *states*: ++
typeof: object ++ typeof: object ++
@@ -81,6 +81,11 @@ The *backlight* module displays the current backlight level.
default: 1.0 ++ default: 1.0 ++
The speed at which to change the brightness when scrolling. The speed at which to change the brightness when scrolling.
*min-brightness*: ++
typeof: double ++
default: 0.0 ++
The minimum brightness of the backlight.
*menu*: ++ *menu*: ++
typeof: string ++ typeof: string ++
Action that popups the menu. Action that popups the menu.
@@ -94,6 +99,11 @@ The *backlight* module displays the current backlight level.
typeof: array ++ typeof: array ++
The actions corresponding to the buttons of the menu. The actions corresponding to the buttons of the menu.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# EXAMPLE: # EXAMPLE:
``` ```
+6 -1
View File
@@ -69,7 +69,7 @@ The *battery* module displays the current capacity and state (eg. charging) of y
*rotate*: ++ *rotate*: ++
typeof: integer++ typeof: integer++
Positive value to rotate the text label. Positive value to rotate the text label (in 90 degree increments).
*on-click*: ++ *on-click*: ++
typeof: string ++ typeof: string ++
@@ -122,6 +122,11 @@ The *battery* module displays the current capacity and state (eg. charging) of y
typeof: array ++ typeof: array ++
The actions corresponding to the buttons of the menu. The actions corresponding to the buttons of the menu.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
*{capacity}*: Capacity in percentage *{capacity}*: Capacity in percentage
+6 -1
View File
@@ -54,7 +54,7 @@ Addressed by *bluetooth*
*rotate*: ++ *rotate*: ++
typeof: integer ++ typeof: integer ++
Positive value to rotate the text label. Positive value to rotate the text label (in 90 degree increments).
*max-length*: ++ *max-length*: ++
typeof: integer ++ typeof: integer ++
@@ -142,6 +142,11 @@ Addressed by *bluetooth*
typeof: array ++ typeof: array ++
The actions corresponding to the buttons of the menu. The actions corresponding to the buttons of the menu.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
*{status}*: Status of the bluetooth device. *{status}*: Status of the bluetooth device.
+9
View File
@@ -64,6 +64,10 @@ libcava lives in:
:[ bool :[ bool
:[ false :[ false
:[ Hides the widget if no input (after sleep_timer elapsed) :[ Hides the widget if no input (after sleep_timer elapsed)
|[ *format_silent*
:[ string
:[
:[ Widget's text after sleep_timer elapsed (hide_on_silence has to be false)
|[ *method* |[ *method*
:[ string :[ string
:[ pulse :[ pulse
@@ -196,3 +200,8 @@ In case when cava releases new version and you're wanna get it, it should be rai
} }
}, },
``` ```
# STYLE
- *#cava*
- *#cava.silent* Applied after no sound has been detected for sleep_timer seconds
- *#cava.updated* Applied when a new frame is shown
+5
View File
@@ -15,6 +15,11 @@ Addressed by *cffi/<name>*
typeof: string ++ typeof: string ++
The path to the dynamic library to load to control the widget. The path to the dynamic library to load to control the widget.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
Some additional configuration may be required depending on the cffi dynamic library being used. Some additional configuration may be required depending on the cffi dynamic library being used.
+6 -2
View File
@@ -51,7 +51,7 @@ $XDG_CONFIG_HOME/waybar/config ++
|[ *rotate* |[ *rotate*
:[ integer :[ integer
:[ :[
:[ Positive value to rotate the text label :[ Positive value to rotate the text label (in 90 degree increments)
|[ *on-click* |[ *on-click*
:[ string :[ string
:[ :[
@@ -96,6 +96,10 @@ $XDG_CONFIG_HOME/waybar/config ++
:[ array :[ array
:[ :[
:[ The actions corresponding to the buttons of the menu. :[ The actions corresponding to the buttons of the menu.
|[ *expand*:
:[ bool
:[ false
:[ Enables this module to consume all left over space dynamically.
View all valid format options in *strftime(3)* or have a look https://en.cppreference.com/w/cpp/chrono/duration/formatter View all valid format options in *strftime(3)* or have a look https://en.cppreference.com/w/cpp/chrono/duration/formatter
@@ -113,7 +117,7 @@ View all valid format options in *strftime(3)* or have a look https://en.cpprefe
:[ 3 :[ 3
:[ Relevant for *mode=year*. Count of months per row :[ Relevant for *mode=year*. Count of months per row
|[ *weeks-pos* |[ *weeks-pos*
:[ integer :[ string
:[ :[
:[ The position where week numbers should be displayed. Disabled when is empty. :[ The position where week numbers should be displayed. Disabled when is empty.
Possible values: left|right Possible values: left|right
+6 -1
View File
@@ -43,7 +43,7 @@ The *cpu* module displays the current CPU utilization.
*rotate*: ++ *rotate*: ++
typeof: integer ++ typeof: integer ++
Positive value to rotate the text label. Positive value to rotate the text label (in 90 degree increments).
*states*: ++ *states*: ++
typeof: object ++ typeof: object ++
@@ -82,6 +82,11 @@ The *cpu* module displays the current CPU utilization.
default: true ++ default: true ++
Option to disable tooltip on hover. Option to disable tooltip on hover.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
*{load}*: Current CPU load. *{load}*: Current CPU load.
+14 -9
View File
@@ -55,8 +55,8 @@ Addressed by *custom/<name>*
*format*: ++ *format*: ++
typeof: string ++ typeof: string ++
default: {} ++ default: {text} ++
The format, how information should be displayed. On {} data gets inserted. The format, how information should be displayed. On {text} data gets inserted.
*format-icons*: ++ *format-icons*: ++
typeof: array ++ typeof: array ++
@@ -64,7 +64,7 @@ Addressed by *custom/<name>*
*rotate*: ++ *rotate*: ++
typeof: integer ++ typeof: integer ++
Positive value to rotate the text label. Positive value to rotate the text label (in 90 degree increments).
*max-length*: ++ *max-length*: ++
typeof: integer ++ typeof: integer ++
@@ -138,6 +138,11 @@ Addressed by *custom/<name>*
typeof: array ++ typeof: array ++
The actions corresponding to the buttons of the menu. The actions corresponding to the buttons of the menu.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# RETURN-TYPE # RETURN-TYPE
When *return-type* is set to *json*, Waybar expects the *exec*-script to output its data in JSON format. When *return-type* is set to *json*, Waybar expects the *exec*-script to output its data in JSON format.
@@ -160,7 +165,7 @@ $text\\n$tooltip\\n$class*
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
*{}*: Output of the script. *{text}*: Output of the script.
*{percentage}* Percentage which can be set via a json return type. *{percentage}* Percentage which can be set via a json return type.
@@ -172,7 +177,7 @@ $text\\n$tooltip\\n$class*
``` ```
"custom/spotify": { "custom/spotify": {
"format": " {}", "format": " {text}",
"max-length": 40, "max-length": 40,
"interval": 30, // Remove this if your script is endless and write in loop "interval": 30, // Remove this if your script is endless and write in loop
"exec": "$HOME/.config/waybar/mediaplayer.sh 2> /dev/null", // Script in resources folder "exec": "$HOME/.config/waybar/mediaplayer.sh 2> /dev/null", // Script in resources folder
@@ -185,7 +190,7 @@ $text\\n$tooltip\\n$class*
``` ```
"custom/mpd": { "custom/mpd": {
"format": "♪ {}", "format": "♪ {text}",
//"max-length": 15, //"max-length": 15,
"interval": 10, "interval": 10,
"exec": "mpc current", "exec": "mpc current",
@@ -199,7 +204,7 @@ $text\\n$tooltip\\n$class*
``` ```
"custom/cmus": { "custom/cmus": {
"format": "♪ {}", "format": "♪ {text}",
//"max-length": 15, //"max-length": 15,
"interval": 10, "interval": 10,
"exec": "cmus-remote -C \"format_print '%a - %t'\"", // artist - title "exec": "cmus-remote -C \"format_print '%a - %t'\"", // artist - title
@@ -214,7 +219,7 @@ $text\\n$tooltip\\n$class*
``` ```
"custom/pacman": { "custom/pacman": {
"format": "{} ", "format": "{text} ",
"interval": "once", "interval": "once",
"exec": "pacman_packages", "exec": "pacman_packages",
"on-click": "update-system", "on-click": "update-system",
@@ -226,7 +231,7 @@ $text\\n$tooltip\\n$class*
``` ```
"custom/pacman": { "custom/pacman": {
"format": "{} ", "format": "{text} ",
"interval": 3600, // every hour "interval": 3600, // every hour
"exec": "checkupdates | wc -l", // # of updates "exec": "checkupdates | wc -l", // # of updates
"exec-if": "exit 0", // always run; consider advanced run conditions "exec-if": "exit 0", // always run; consider advanced run conditions
+6 -1
View File
@@ -29,7 +29,7 @@ Addressed by *disk*
*rotate*: ++ *rotate*: ++
typeof: integer ++ typeof: integer ++
Positive value to rotate the text label. Positive value to rotate the text label (in 90 degree increments).
*states*: ++ *states*: ++
typeof: object ++ typeof: object ++
@@ -106,6 +106,11 @@ Addressed by *disk*
typeof: array ++ typeof: array ++
The actions corresponding to the buttons of the menu. The actions corresponding to the buttons of the menu.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
*{percentage_used}*: Percentage of disk in use. *{percentage_used}*: Percentage of disk in use.
+5
View File
@@ -26,6 +26,11 @@ Addressed by *dwl/tags*
default: false ++ default: false ++
If set to false, you can left-click to set focused tag. Right-click to toggle tag focus. If set to true this behaviour is disabled. If set to false, you can left-click to set focused tag. Right-click to toggle tag focus. If set to true this behaviour is disabled.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# EXAMPLE # EXAMPLE
``` ```
+6 -1
View File
@@ -19,7 +19,7 @@ Addressed by *dwl/window*
*rotate*: ++ *rotate*: ++
typeof: integer ++ typeof: integer ++
Positive value to rotate the text label. Positive value to rotate the text label (in 90 degree increments).
*max-length*: ++ *max-length*: ++
typeof: integer ++ typeof: integer ++
@@ -84,6 +84,11 @@ Addressed by *dwl/window*
default: 24 ++ default: 24 ++
Option to change the size of the application icon. Option to change the size of the application icon.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
*{title}*: The title of the focused window. *{title}*: The title of the focused window.
+5
View File
@@ -61,6 +61,11 @@ Feral Gamemode optimizations.
default: 4 ++ default: 4 ++
Defines the spacing between the icon and the text. Defines the spacing between the icon and the text.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
*{glyph}*: The string icon glyph to use instead. *{glyph}*: The string icon glyph to use instead.
+8 -3
View File
@@ -38,6 +38,11 @@ Addressed by *hyprland/language*
typeof: array ++ typeof: array ++
The actions corresponding to the buttons of the menu. The actions corresponding to the buttons of the menu.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
@@ -54,9 +59,9 @@ Addressed by *hyprland/language*
``` ```
"hyprland/language": { "hyprland/language": {
"format": "Lang: {long}" "format": "Lang: {long}",
"format-en": "AMERICA, HELL YEAH!" "format-en": "AMERICA, HELL YEAH!",
"format-tr": "As bayrakları" "format-tr": "As bayrakları",
"keyboard-name": "at-translated-set-2-keyboard" "keyboard-name": "at-translated-set-2-keyboard"
} }
``` ```
+6 -1
View File
@@ -19,7 +19,7 @@ Addressed by *hyprland/submap*
*rotate*: ++ *rotate*: ++
typeof: integer ++ typeof: integer ++
Positive value to rotate the text label. Positive value to rotate the text label (in 90 degree increments).
*max-length*: ++ *max-length*: ++
typeof: integer ++ typeof: integer ++
@@ -93,6 +93,11 @@ Addressed by *hyprland/submap*
typeof: array ++ typeof: array ++
The actions corresponding to the buttons of the menu. The actions corresponding to the buttons of the menu.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# EXAMPLES # EXAMPLES
+5
View File
@@ -35,6 +35,11 @@ Addressed by *hyprland/window*
default: 24 ++ default: 24 ++
Option to change the size of the application icon. Option to change the size of the application icon.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
See the output of "hyprctl clients" for examples See the output of "hyprctl clients" for examples
+5
View File
@@ -78,6 +78,11 @@ Addressed by *hyprland/workspaces*
If set to id, workspaces will sort by id. If set to id, workspaces will sort by id.
If none of those, workspaces will sort with default behavior. If none of those, workspaces will sort with default behavior.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
*{id}*: id of workspace assigned by compositor *{id}*: id of workspace assigned by compositor
+6 -1
View File
@@ -21,7 +21,7 @@ screensaver, also known as "presentation mode".
*rotate*: ++ *rotate*: ++
typeof: integer ++ typeof: integer ++
Positive value to rotate the text label. Positive value to rotate the text label (in 90 degree increments).
*max-length*: ++ *max-length*: ++
typeof: integer ++ typeof: integer ++
@@ -102,6 +102,11 @@ screensaver, also known as "presentation mode".
typeof: array ++ typeof: array ++
The actions corresponding to the buttons of the menu. The actions corresponding to the buttons of the menu.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
*{status}*: status (*activated* or *deactivated*) *{status}*: status (*activated* or *deactivated*)
+5
View File
@@ -64,6 +64,11 @@ The *image* module displays an image from a path.
default: true ++ default: true ++
Option to enable tooltip on hover. Option to enable tooltip on hover.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# SCRIPT OUTPUT # SCRIPT OUTPUT
Similar to the *custom* module, output values of the script are *newline* separated. Similar to the *custom* module, output values of the script are *newline* separated.
+6 -1
View File
@@ -25,7 +25,7 @@ See *systemd-inhibit*(1) for more information.
*rotate*: ++ *rotate*: ++
typeof: integer ++ typeof: integer ++
Positive value to rotate the text label. Positive value to rotate the text label (in 90 degree increments).
*max-length*: ++ *max-length*: ++
typeof: integer ++ typeof: integer ++
@@ -89,6 +89,11 @@ See *systemd-inhibit*(1) for more information.
typeof: array ++ typeof: array ++
The actions corresponding to the buttons of the menu. The actions corresponding to the buttons of the menu.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
*{status}*: status (*activated* or *deactivated*) *{status}*: status (*activated* or *deactivated*)
+6 -1
View File
@@ -51,7 +51,7 @@ Addressed by *jack*
*rotate*: ++ *rotate*: ++
typeof: integer ++ typeof: integer ++
Positive value to rotate the text label. Positive value to rotate the text label (in 90 degree increments).
*max-length*: ++ *max-length*: ++
typeof: integer ++ typeof: integer ++
@@ -98,6 +98,11 @@ Addressed by *jack*
typeof: array ++ typeof: array ++
The actions corresponding to the buttons of the menu. The actions corresponding to the buttons of the menu.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
*{load}*: The current CPU load estimated by JACK. *{load}*: The current CPU load estimated by JACK.
+5
View File
@@ -53,6 +53,11 @@ You must be a member of the input group to use this module.
default: [58, 69, 70] ++ default: [58, 69, 70] ++
Customize the key to trigger this module, the key number can be found in /usr/include/linux/input-event-codes.h or running sudo libinput debug-events --show-keycodes. Customize the key to trigger this module, the key number can be found in /usr/include/linux/input-event-codes.h or running sudo libinput debug-events --show-keycodes.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
*{name}*: Caps, Num, or Scroll. *{name}*: Caps, Num, or Scroll.
+6 -1
View File
@@ -29,7 +29,7 @@ Addressed by *memory*
*rotate*: ++ *rotate*: ++
typeof: integer ++ typeof: integer ++
Positive value to rotate the text label. Positive value to rotate the text label (in 90 degree increments).
*states*: ++ *states*: ++
typeof: object ++ typeof: object ++
@@ -97,6 +97,11 @@ Addressed by *memory*
typeof: array ++ typeof: array ++
The actions corresponding to the buttons of the menu. The actions corresponding to the buttons of the menu.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
*{percentage}*: Percentage of memory in use. *{percentage}*: Percentage of memory in use.
+6 -1
View File
@@ -91,7 +91,7 @@ Addressed by *mpd*
*rotate*: ++ *rotate*: ++
typeof: integer ++ typeof: integer ++
Positive value to rotate the text label. Positive value to rotate the text label (in 90 degree increments).
*max-length*: ++ *max-length*: ++
typeof: integer ++ typeof: integer ++
@@ -175,6 +175,11 @@ Addressed by *mpd*
typeof: array ++ typeof: array ++
The actions corresponding to the buttons of the menu. The actions corresponding to the buttons of the menu.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
## WHEN PLAYING/PAUSED ## WHEN PLAYING/PAUSED
+6 -1
View File
@@ -107,7 +107,7 @@ The *mpris* module displays currently playing media via libplayerctl.
*rotate*: ++ *rotate*: ++
typeof: integer ++ typeof: integer ++
Positive value to rotate the text label. Positive value to rotate the text label (in 90 degree increments).
*max-length*: ++ *max-length*: ++
typeof: integer ++ typeof: integer ++
@@ -148,6 +148,11 @@ The *mpris* module displays currently playing media via libplayerctl.
typeof: map[string]string ++ typeof: map[string]string ++
Allows setting _{status_icon}_ based on player status (playing, paused, stopped). Allows setting _{status_icon}_ based on player status (playing, paused, stopped).
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
+15 -4
View File
@@ -24,7 +24,7 @@ Addressed by *network*
*family*: ++ *family*: ++
typeof: string ++ typeof: string ++
default: *ipv4* ++ default: *ipv4* ++
The address family that is used for the format replacement {ipaddr} and to determine if a network connection is present. The address family that is used for the format replacement {ipaddr} and to determine if a network connection is present. Set it to ipv4_6 to display both.
*format*: ++ *format*: ++
typeof: string ++ typeof: string ++
@@ -58,7 +58,7 @@ Addressed by *network*
*rotate*: ++ *rotate*: ++
typeof: integer ++ typeof: integer ++
Positive value to rotate the text label. Positive value to rotate the text label (in 90 degree increments).
*max-length*: ++ *max-length*: ++
typeof: integer ++ typeof: integer ++
@@ -142,6 +142,11 @@ Addressed by *network*
typeof: array ++ typeof: array ++
The actions corresponding to the buttons of the menu. The actions corresponding to the buttons of the menu.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
*{ifname}*: Name of the network interface. *{ifname}*: Name of the network interface.
@@ -150,12 +155,18 @@ Addressed by *network*
*{gwaddr}*: The default gateway for the interface *{gwaddr}*: The default gateway for the interface
*{netmask}*: The subnetmask corresponding to the IP. *{netmask}*: The subnetmask corresponding to the IP(V4).
*{cidr}*: The subnetmask corresponding to the IP in CIDR notation. *{netmask6}*: The subnetmask corresponding to the IP(V6).
*{cidr}*: The subnetmask corresponding to the IP(V4) in CIDR notation.
*{cidr6}*: The subnetmask corresponding to the IP(V6) in CIDR notation.
*{essid}*: Name (SSID) of the wireless network. *{essid}*: Name (SSID) of the wireless network.
*{bssid}*: MAC address (BSSID) of the wireless access point.
*{signalStrength}*: Signal strength of the wireless network. *{signalStrength}*: Signal strength of the wireless network.
*{signaldBm}*: Signal strength of the wireless network in dBm. *{signaldBm}*: Signal strength of the wireless network in dBm.
+63
View File
@@ -0,0 +1,63 @@
waybar-niri-language(5)
# NAME
waybar - niri language module
# DESCRIPTION
The *language* module displays the currently selected language in niri.
# CONFIGURATION
Addressed by *niri/language*
*format*: ++
typeof: string ++
default: {} ++
The format, how information should be displayed.
*format-<lang>* ++
typeof: string++
Provide an alternative name to display per language where <lang> is the language of your choosing. Can be passed multiple times with multiple languages as shown by the example below.
*menu*: ++
typeof: string ++
Action that popups the menu.
*menu-file*: ++
typeof: string ++
Location of the menu descriptor file. There need to be an element of type GtkMenu with id *menu*
*menu-actions*: ++
typeof: array ++
The actions corresponding to the buttons of the menu.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS
*{short}*: Short name of layout (e.g. "us"). Equals to {}.
*{shortDescription}*: Short description of layout (e.g. "en").
*{long}*: Long name of layout (e.g. "English (Dvorak)").
*{variant}*: Variant of layout (e.g. "dvorak").
# EXAMPLES
```
"niri/language": {
"format": "Lang: {long}"
"format-en": "AMERICA, HELL YEAH!"
"format-tr": "As bayrakları"
}
```
# STYLE
- *#language*
+86
View File
@@ -0,0 +1,86 @@
waybar-niri-window(5)
# NAME
waybar - niri window module
# DESCRIPTION
The *window* module displays the title of the currently focused window in niri.
# CONFIGURATION
Addressed by *niri/window*
*format*: ++
typeof: string ++
default: {title} ++
The format, how information should be displayed. On {} the current window title is displayed.
*rewrite*: ++
typeof: object ++
Rules to rewrite window title. See *rewrite rules*.
*separate-outputs*: ++
typeof: bool ++
Show the active window of the monitor the bar belongs to, instead of the focused window.
*icon*: ++
typeof: bool ++
default: false ++
Option to hide the application icon.
*icon-size*: ++
typeof: integer ++
default: 24 ++
Option to change the size of the application icon.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS
See the output of "niri msg windows" for examples
*{title}*: The current title of the focused window.
*{app_id}*: The current app ID of the focused window.
# REWRITE RULES
*rewrite* is an object where keys are regular expressions and values are
rewrite rules if the expression matches. Rules may contain references to
captures of the expression.
Regular expression and replacement follow ECMA-script rules.
If no expression matches, the title is left unchanged.
Invalid expressions (e.g., mismatched parentheses) are skipped.
# EXAMPLES
```
"niri/window": {
"format": "{}",
"rewrite": {
"(.*) - Mozilla Firefox": "🌎 $1",
"(.*) - zsh": "> [$1]"
}
}
```
# STYLE
- *#window*
- *window#waybar.empty #window* When no windows are on the workspace
The following classes are applied to the entire Waybar rather than just the
window widget:
- *window#waybar.empty* When no windows are in the workspace
- *window#waybar.solo* When only one window is on the workspace
- *window#waybar.<app-id>* Where *app-id* is the app ID of the only window on
the workspace
+102
View File
@@ -0,0 +1,102 @@
waybar-niri-workspaces(5)
# NAME
waybar - niri workspaces module
# DESCRIPTION
The *workspaces* module displays the currently used workspaces in niri.
# CONFIGURATION
Addressed by *niri/workspaces*
*all-outputs*: ++
typeof: bool ++
default: false ++
If set to false, workspaces will only be shown on the output they are on. If set to true all workspaces will be shown on every output.
*format*: ++
typeof: string ++
default: {value} ++
The format, how information should be displayed.
*format-icons*: ++
typeof: array ++
Based on the workspace name, index and state, the corresponding icon gets selected. See *icons*.
*disable-click*: ++
typeof: bool ++
default: false ++
If set to false, you can click to change workspace. If set to true this behaviour is disabled.
*disable-markup*: ++
typeof: bool ++
default: false ++
If set to true, button label will escape pango markup.
*current-only*: ++
typeof: bool ++
default: false ++
If set to true, only the active or focused workspace will be shown.
*on-update*: ++
typeof: string ++
Command to execute when the module is updated.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS
*{value}*: Name of the workspace, or index for unnamed workspaces,
as defined by niri.
*{name}*: Name of the workspace for named workspaces.
*{icon}*: Icon, as defined in *format-icons*.
*{index}*: Index of the workspace on its output.
*{output}*: Output where the workspace is located.
# ICONS
Additional to workspace name matching, the following *format-icons* can be set.
- *default*: Will be shown, when no string matches are found.
- *focused*: Will be shown, when workspace is focused.
- *active*: Will be shown, when workspace is active on its output.
# EXAMPLES
```
"niri/workspaces": {
"format": "{icon}",
"format-icons": {
// Named workspaces
// (you need to configure them in niri)
"browser": "",
"discord": "",
"chat": "<b></b>",
// Icons by state
"active": "",
"default": ""
}
}
```
# Style
- *#workspaces button*
- *#workspaces button.focused*: The single focused workspace.
- *#workspaces button.active*: The workspace is active (visible) on its output.
- *#workspaces button.empty*: The workspace is empty.
- *#workspaces button.current_output*: The workspace is from the same output as
the bar that it is displayed on.
- *#workspaces button#niri-workspace-<name>*: Workspaces named this, or index
for unnamed workspaces.
+7
View File
@@ -35,6 +35,13 @@ $XDG_CONFIG_HOME/waybar/config
:[ object :[ object
:[ See default value in the example below. :[ See default value in the example below.
:[ Icons used to represent the various power-profile. *Note*: the default configuration uses the font-awesome icons. You may want to override it if you don't have this font installed on your system. :[ Icons used to represent the various power-profile. *Note*: the default configuration uses the font-awesome icons. You may want to override it if you don't have this font installed on your system.
|[ *expand*:
:[ bool
:[ false
:[ Enables this module to consume all left over space dynamically.
# CONFIGURATION EXAMPLES # CONFIGURATION EXAMPLES
+5
View File
@@ -32,6 +32,11 @@ the screen or playing audio.
Which privacy modules to monitor. See *MODULES CONFIGURATION* for++ Which privacy modules to monitor. See *MODULES CONFIGURATION* for++
more information. more information.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# MODULES CONFIGURATION # MODULES CONFIGURATION
*type*: ++ *type*: ++
+5
View File
@@ -27,6 +27,11 @@ The volume can be controlled by dragging the slider across the bar or clicking o
default: horizontal ++ default: horizontal ++
The orientation of the slider. Can be either `horizontal` or `vertical`. The orientation of the slider. Can be either `horizontal` or `vertical`.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# EXAMPLES # EXAMPLES
``` ```
+6 -1
View File
@@ -40,7 +40,7 @@ Additionally, you can control the volume by scrolling *up* or *down* while the c
*rotate*: ++ *rotate*: ++
typeof: integer ++ typeof: integer ++
Positive value to rotate the text label. Positive value to rotate the text label (in 90 degree increments).
*states*: ++ *states*: ++
typeof: object ++ typeof: object ++
@@ -126,6 +126,11 @@ Additionally, you can control the volume by scrolling *up* or *down* while the c
typeof: array ++ typeof: array ++
The actions corresponding to the buttons of the menu. The actions corresponding to the buttons of the menu.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
*{desc}*: Pulseaudio port's description, for bluetooth it'll be the device name. *{desc}*: Pulseaudio port's description, for bluetooth it'll be the device name.
+6 -1
View File
@@ -21,7 +21,7 @@ Addressed by *river/layout*
*rotate*: ++ *rotate*: ++
typeof: integer ++ typeof: integer ++
Positive value to rotate the text label. Positive value to rotate the text label (in 90 degree increments).
*max-length*: ++ *max-length*: ++
typeof: integer ++ typeof: integer ++
@@ -64,6 +64,11 @@ Addressed by *river/layout*
typeof: array ++ typeof: array ++
The actions corresponding to the buttons of the menu. The actions corresponding to the buttons of the menu.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# EXAMPLE # EXAMPLE
``` ```
+6 -1
View File
@@ -19,7 +19,7 @@ Addressed by *river/mode*
*rotate*: ++ *rotate*: ++
typeof: integer ++ typeof: integer ++
Positive value to rotate the text label. Positive value to rotate the text label (in 90 degree increments).
*max-length*: ++ *max-length*: ++
typeof: integer ++ typeof: integer ++
@@ -78,6 +78,11 @@ Addressed by *river/mode*
typeof: array ++ typeof: array ++
The actions corresponding to the buttons of the menu. The actions corresponding to the buttons of the menu.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# EXAMPLES # EXAMPLES
``` ```
+10
View File
@@ -26,6 +26,16 @@ Addressed by *river/tags*
default: false ++ default: false ++
If set to false, you can left-click to set focused tag. Right-click to toggle tag focus. If set to true this behaviour is disabled. If set to false, you can left-click to set focused tag. Right-click to toggle tag focus. If set to true this behaviour is disabled.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
*hide-vacant*: ++
typeof: bool ++
default: false ++
Only show relevant tags: tags that are either focused or have a window on them.
# EXAMPLE # EXAMPLE
``` ```
+6 -1
View File
@@ -19,7 +19,7 @@ Addressed by *river/window*
*rotate*: ++ *rotate*: ++
typeof: integer ++ typeof: integer ++
Positive value to rotate the text label. Positive value to rotate the text label (in 90 degree increments).
*max-length*: ++ *max-length*: ++
typeof: integer ++ typeof: integer ++
@@ -62,6 +62,11 @@ Addressed by *river/window*
typeof: array ++ typeof: array ++
The actions corresponding to the buttons of the menu. The actions corresponding to the buttons of the menu.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# EXAMPLES # EXAMPLES
``` ```
+6 -1
View File
@@ -20,7 +20,7 @@ cursor is over the module, and clicking on the module toggles mute.
*rotate*: ++ *rotate*: ++
typeof: integer ++ typeof: integer ++
Positive value to rotate the text label. Positive value to rotate the text label (in 90 degree increments).
*max-length*: ++ *max-length*: ++
typeof: integer ++ typeof: integer ++
@@ -87,6 +87,11 @@ cursor is over the module, and clicking on the module toggles mute.
typeof: array ++ typeof: array ++
The actions corresponding to the buttons of the menu. The actions corresponding to the buttons of the menu.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
*{volume}*: Volume in percentage. *{volume}*: Volume in percentage.
+34
View File
@@ -39,6 +39,40 @@ You can apply special styling to any module for when the cursor hovers it.
} }
``` ```
## Setting cursor style
Most, if not all, module types support setting the `cursor` option. This is
configured in your `config.jsonc`. If set to `false`, when hovering the module a
"pointer"(as commonly known from web CSS styling `cursor: pointer`) style cursor
will not be shown. Default behavior is to indicate an interaction event is
available.
There are more cursor types to choose from by setting the `cursor` option to
a number, see Gdk3 official docs for all possible cursor types:
https://docs.gtk.org/gdk3/enum.CursorType.html.
However, note that not all cursor options listed may be available on
your system. If you attempt to use a cursor which is not available, the
application will crash.
Example of disabling pointer(`Gdk::Hand2`) cursor type on a custom module:
```
"custom/my-custom-module": {
...
"cursor": false,
}
```
Example of setting cursor type to `Gdk::Boat`(according to
https://docs.gtk.org/gdk3/enum.CursorType.html#boat):
```
"custom/my-custom-module": {
...
"cursor": 8,
}
```
# SEE ALSO # SEE ALSO
- *waybar(5)* - *waybar(5)*
+5
View File
@@ -45,6 +45,11 @@ Addressed by *sway/language*
typeof: array ++ typeof: array ++
The actions corresponding to the buttons of the menu. The actions corresponding to the buttons of the menu.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
*{short}*: Short name of layout (e.g. "us"). Equals to {}. *{short}*: Short name of layout (e.g. "us"). Equals to {}.
+6 -1
View File
@@ -19,7 +19,7 @@ Addressed by *sway/mode*
*rotate*: ++ *rotate*: ++
typeof: integer ++ typeof: integer ++
Positive value to rotate the text label. Positive value to rotate the text label (in 90 degree increments).
*max-length*: ++ *max-length*: ++
typeof: integer ++ typeof: integer ++
@@ -83,6 +83,11 @@ Addressed by *sway/mode*
typeof: array ++ typeof: array ++
The actions corresponding to the buttons of the menu. The actions corresponding to the buttons of the menu.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# EXAMPLES # EXAMPLES
``` ```
+5
View File
@@ -49,6 +49,11 @@ Addressed by *sway/scratchpad*
typeof: array ++ typeof: array ++
The actions corresponding to the buttons of the menu. The actions corresponding to the buttons of the menu.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
*{icon}*: Icon, as defined in *format-icons*. *{icon}*: Icon, as defined in *format-icons*.
+6 -1
View File
@@ -19,7 +19,7 @@ Addressed by *sway/window*
*rotate*: ++ *rotate*: ++
typeof: integer ++ typeof: integer ++
Positive value to rotate the text label. Positive value to rotate the text label (in 90 degree increments).
*max-length*: ++ *max-length*: ++
typeof: integer ++ typeof: integer ++
@@ -103,6 +103,11 @@ Addressed by *sway/window*
default: 24 ++ default: 24 ++
Option to change the size of the application icon. Option to change the size of the application icon.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
*{title}*: The title of the focused window. *{title}*: The title of the focused window.
+7
View File
@@ -87,6 +87,8 @@ warp-on-scroll: ++
Regex rules to map window class to an icon or preferred method of representation for a workspace's window. Regex rules to map window class to an icon or preferred method of representation for a workspace's window.
Keys are the rules, while the values are the methods of representation. Keys are the rules, while the values are the methods of representation.
Rules may specify `class<...>`, `title<...>`, or both in order to fine-tune the matching. Rules may specify `class<...>`, `title<...>`, or both in order to fine-tune the matching.
You may assign an empty value to a rule to have it ignored from generating any representation in workspaces.
For Wayland windows `class` is matched against the `app_id`, and for X11 windows against the `class` property.
*window-rewrite-default*: *window-rewrite-default*:
typeof: string ++ typeof: string ++
@@ -98,6 +100,11 @@ warp-on-scroll: ++
default: " " ++ default: " " ++
The separator to be used between windows in a workspace. The separator to be used between windows in a workspace.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
+5
View File
@@ -49,6 +49,11 @@ Addressed by *systemd-failed-units*
typeof: array ++ typeof: array ++
The actions corresponding to the buttons of the menu. The actions corresponding to the buttons of the menu.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
*{nr_failed_system}*: Number of failed units from systemwide (PID=1) systemd. *{nr_failed_system}*: Number of failed units from systemwide (PID=1) systemd.
+14 -1
View File
@@ -31,6 +31,10 @@ Addressed by *temperature*
typeof: string ++ typeof: string ++
The temperature filename of your *hwmon-path-abs*, e.g. *temp1_input* The temperature filename of your *hwmon-path-abs*, e.g. *temp1_input*
*warning-threshold*: ++
typeof: integer ++
The threshold before it is considered warning (Celsius).
*critical-threshold*: ++ *critical-threshold*: ++
typeof: integer ++ typeof: integer ++
The threshold before it is considered critical (Celsius). The threshold before it is considered critical (Celsius).
@@ -40,6 +44,10 @@ Addressed by *temperature*
default: 10 ++ default: 10 ++
The interval in which the information gets polled. The interval in which the information gets polled.
*format-warning*: ++
typeof: string ++
The format to use when temperature is considered warning
*format-critical*: ++ *format-critical*: ++
typeof: string ++ typeof: string ++
The format to use when temperature is considered critical The format to use when temperature is considered critical
@@ -60,7 +68,7 @@ Addressed by *temperature*
*rotate*: ++ *rotate*: ++
typeof: integer ++ typeof: integer ++
Positive value to rotate the text label. Positive value to rotate the text label (in 90 degree increments).
*max-length*: ++ *max-length*: ++
typeof: integer ++ typeof: integer ++
@@ -124,6 +132,11 @@ Addressed by *temperature*
typeof: array ++ typeof: array ++
The actions corresponding to the buttons of the menu. The actions corresponding to the buttons of the menu.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
*{temperatureC}*: Temperature in Celsius. *{temperatureC}*: Temperature in Celsius.
+10 -1
View File
@@ -37,12 +37,21 @@ Addressed by *tray*
typeof: string ++ typeof: string ++
Command to execute when the module is updated. Command to execute when the module is updated.
*expand*: ++
typeof: bool ++
default: false ++
Enables this module to consume all left over space dynamically.
# EXAMPLES # EXAMPLES
``` ```
"tray": { "tray": {
"icon-size": 21, "icon-size": 21,
"spacing": 10 "spacing": 10,
"icons": {
"blueman": "bluetooth",
"TelegramDesktop": "$HOME/.local/share/icons/hicolor/16x16/apps/telegram.png"
}
} }
``` ```
+28 -1
View File
@@ -19,6 +19,11 @@ The *wireplumber* module displays the current volume reported by WirePlumber.
typeof: string ++ typeof: string ++
This format is used when the sound is muted. This format is used when the sound is muted.
*node-type*: ++
typeof: string ++
default: *Audio/Sink* ++
The WirePlumber node type to attach to. Use *Audio/Source* to manage microphones etc.
*tooltip*: ++ *tooltip*: ++
typeof: bool ++ typeof: bool ++
default: *true* ++ default: *true* ++
@@ -31,7 +36,7 @@ The *wireplumber* module displays the current volume reported by WirePlumber.
*rotate*: ++ *rotate*: ++
typeof: integer ++ typeof: integer ++
Positive value to rotate the text label. Positive value to rotate the text label (in 90 degree increments).
*states*: ++ *states*: ++
typeof: object ++ typeof: object ++
@@ -108,6 +113,8 @@ The *wireplumber* module displays the current volume reported by WirePlumber.
# EXAMPLES # EXAMPLES
## Basic:
``` ```
"wireplumber": { "wireplumber": {
"format": "{volume}%", "format": "{volume}%",
@@ -116,6 +123,26 @@ The *wireplumber* module displays the current volume reported by WirePlumber.
} }
``` ```
## Separate Sink and Source Widgets
```
"wireplumber#sink": {
"format": "{volume}% {icon}",
"format-muted": "",
"format-icons": ["", "", ""],
"on-click": "helvum",
"on-click-right": "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle",
"scroll-step": 5
},
"wireplumber#source": {
"node-type": "Audio/Source",
"format": "{volume}% ",
"format-muted": "",
"on-click-right": "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle",
"scroll-step": 5
}
```
# STYLE # STYLE
- *#wireplumber* - *#wireplumber*
+41
View File
@@ -23,6 +23,21 @@ The visual display elements for waybar use a CSS stylesheet, see *waybar-styles(
# BAR CONFIGURATION # BAR CONFIGURATION
*expand-center* ++
typeof: bool ++
default: false ++
Enables the modules-center to consume all left over space dynamically.
*expand-left* ++
typeof: bool ++
default: false ++
Enables the modules-left to consume all left over space dynamically.
*expand-right* ++
typeof: bool ++
default: false ++
Enables the modules-left to consume all left over space dynamically.
*layer* ++ *layer* ++
typeof: string ++ typeof: string ++
default: bottom ++ default: bottom ++
@@ -68,6 +83,11 @@ The visual display elements for waybar use a CSS stylesheet, see *waybar-styles(
typeof: integer ++ typeof: integer ++
Margins value without units. Margins value without units.
*no-center* ++
typeof: bool ++
default: false ++
Option to disable the center modules fully usefull together with expand-\*.
*spacing* ++ *spacing* ++
typeof: integer ++ typeof: integer ++
Size of gaps in between the different modules. Size of gaps in between the different modules.
@@ -181,6 +201,19 @@ A minimal *config* file could look like this:
} }
``` ```
# SIGNALS
Waybar accepts the following signals:
*SIGUSR1*
Toggles the bar visibility (hides if shown, shows if hidden)
*SIGUSR2*
Reloads (resets) the bar
*SIGINT*
Quits the bar
For example, to toggle the bar programmatically, you can invoke `killall -SIGUSR1 waybar`.
# MULTI OUTPUT CONFIGURATION # MULTI OUTPUT CONFIGURATION
## Limit a configuration to some outputs ## Limit a configuration to some outputs
@@ -278,6 +311,11 @@ A group may hide all but one element, showing them only on mouse hover. In order
default: "hidden" ++ default: "hidden" ++
Defines the CSS class to be applied to the hidden elements. Defines the CSS class to be applied to the hidden elements.
*click-to-reveal*: ++
typeof: bool ++
default: false ++
Whether left click should reveal the content rather than mouse over. Note that grouped modules may still process their own on-click events.
*transition-left-to-right*: ++ *transition-left-to-right*: ++
typeof: bool ++ typeof: bool ++
default: true ++ default: true ++
@@ -318,6 +356,9 @@ A group may hide all but one element, showing them only on mouse hover. In order
- *waybar-hyprland-submap(5)* - *waybar-hyprland-submap(5)*
- *waybar-hyprland-window(5)* - *waybar-hyprland-window(5)*
- *waybar-hyprland-workspaces(5)* - *waybar-hyprland-workspaces(5)*
- *waybar-niri-language(5)*
- *waybar-niri-window(5)*
- *waybar-niri-workspaces(5)*
- *waybar-idle-inhibitor(5)* - *waybar-idle-inhibitor(5)*
- *waybar-image(5)* - *waybar-image(5)*
- *waybar-inhibitor(5)* - *waybar-inhibitor(5)*
+23 -4
View File
@@ -1,6 +1,6 @@
project( project(
'waybar', 'cpp', 'c', 'waybar', 'cpp', 'c',
version: '0.10.3', version: '0.12.0',
license: 'MIT', license: 'MIT',
meson_version: '>= 0.59.0', meson_version: '>= 0.59.0',
default_options : [ default_options : [
@@ -69,7 +69,7 @@ is_openbsd = host_machine.system() == 'openbsd'
thread_dep = dependency('threads') thread_dep = dependency('threads')
fmt = dependency('fmt', version : ['>=8.1.1'], fallback : ['fmt', 'fmt_dep']) fmt = dependency('fmt', version : ['>=8.1.1'], fallback : ['fmt', 'fmt_dep'])
spdlog = dependency('spdlog', version : ['>=1.10.0'], fallback : ['spdlog', 'spdlog_dep'], default_options : ['external_fmt=enabled']) spdlog = dependency('spdlog', version : ['>=1.10.0'], fallback : ['spdlog', 'spdlog_dep'], default_options : ['external_fmt=enabled', 'std_format=disabled', 'tests=disabled'])
wayland_client = dependency('wayland-client') wayland_client = dependency('wayland-client')
wayland_cursor = dependency('wayland-cursor') wayland_cursor = dependency('wayland-cursor')
wayland_protos = dependency('wayland-protocols') wayland_protos = dependency('wayland-protocols')
@@ -106,7 +106,7 @@ if libsndio.found()
endif endif
endif endif
gtk_layer_shell = dependency('gtk-layer-shell-0', version: ['>=0.6.0'], gtk_layer_shell = dependency('gtk-layer-shell-0', version: ['>=0.9.0'],
default_options: ['introspection=false', 'vapi=false'], default_options: ['introspection=false', 'vapi=false'],
fallback: ['gtk-layer-shell', 'gtk_layer_shell']) fallback: ['gtk-layer-shell', 'gtk_layer_shell'])
systemd = dependency('systemd', required: get_option('systemd')) systemd = dependency('systemd', required: get_option('systemd'))
@@ -318,6 +318,25 @@ if true
) )
endif endif
if get_option('niri')
add_project_arguments('-DHAVE_NIRI', language: 'cpp')
src_files += files(
'src/modules/niri/backend.cpp',
'src/modules/niri/language.cpp',
'src/modules/niri/window.cpp',
'src/modules/niri/workspaces.cpp',
)
man_files += files(
'man/waybar-niri-language.5.scd',
'man/waybar-niri-window.5.scd',
'man/waybar-niri-workspaces.5.scd',
)
endif
if get_option('login-proxy')
add_project_arguments('-DHAVE_LOGIN_PROXY', language: 'cpp')
endif
if libnl.found() and libnlgen.found() if libnl.found() and libnlgen.found()
add_project_arguments('-DHAVE_LIBNL', language: 'cpp') add_project_arguments('-DHAVE_LIBNL', language: 'cpp')
src_files += files('src/modules/network.cpp') src_files += files('src/modules/network.cpp')
@@ -467,7 +486,7 @@ if get_option('experimental')
endif endif
cava = dependency('cava', cava = dependency('cava',
version : '>=0.10.2', version : '>=0.10.3',
required: get_option('cava'), required: get_option('cava'),
fallback : ['cava', 'cava_dep'], fallback : ['cava', 'cava_dep'],
not_found_message: 'cava is not found. Building waybar without cava') not_found_message: 'cava is not found. Building waybar without cava')
+2
View File
@@ -19,3 +19,5 @@ option('experimental', type : 'boolean', value : false, description: 'Enable exp
option('jack', type: 'feature', value: 'auto', description: 'Enable support for JACK') option('jack', type: 'feature', value: 'auto', description: 'Enable support for JACK')
option('wireplumber', type: 'feature', value: 'auto', description: 'Enable support for WirePlumber') option('wireplumber', type: 'feature', value: 'auto', description: 'Enable support for WirePlumber')
option('cava', type: 'feature', value: 'auto', description: 'Enable support for Cava') option('cava', type: 'feature', value: 'auto', description: 'Enable support for Cava')
option('niri', type: 'boolean', description: 'Enable support for niri')
option('login-proxy', type: 'boolean', description: 'Enable interfacing with dbus login interface')
+7 -2
View File
@@ -5,12 +5,12 @@
}: }:
let let
libcava = rec { libcava = rec {
version = "0.10.2"; version = "0.10.3";
src = pkgs.fetchFromGitHub { src = pkgs.fetchFromGitHub {
owner = "LukashonakV"; owner = "LukashonakV";
repo = "cava"; repo = "cava";
rev = version; rev = version;
hash = "sha256-jU7RQV2txruu/nUUl0TzjK4nai7G38J1rcTjO7UXumY="; hash = "sha256-ZDFbI69ECsUTjbhlw2kHRufZbQMu+FQSMmncCJ5pagg=";
}; };
}; };
in in
@@ -25,6 +25,11 @@ in
mesonFlags = lib.remove "-Dgtk-layer-shell=enabled" oldAttrs.mesonFlags; mesonFlags = lib.remove "-Dgtk-layer-shell=enabled" oldAttrs.mesonFlags;
# downstream patch should not affect upstream
patches = [];
# nixpkgs checks version, no need when building locally
nativeInstallCheckInputs = [];
buildInputs = (builtins.filter (p: p.pname != "wireplumber") oldAttrs.buildInputs) ++ [ buildInputs = (builtins.filter (p: p.pname != "wireplumber") oldAttrs.buildInputs) ++ [
pkgs.wireplumber pkgs.wireplumber
]; ];
+6 -2
View File
@@ -104,7 +104,11 @@
}, },
"tray": { "tray": {
// "icon-size": 21, // "icon-size": 21,
"spacing": 10 "spacing": 10,
// "icons": {
// "blueman": "bluetooth",
// "TelegramDesktop": "$HOME/.local/share/icons/hicolor/16x16/apps/telegram.png"
// }
}, },
"clock": { "clock": {
// "timezone": "America/New_York", // "timezone": "America/New_York",
@@ -189,7 +193,7 @@
"on-click": "pavucontrol" "on-click": "pavucontrol"
}, },
"custom/media": { "custom/media": {
"format": "{icon} {}", "format": "{icon} {text}",
"return-type": "json", "return-type": "json",
"max-length": 40, "max-length": 40,
"format-icons": { "format-icons": {
+1 -1
View File
@@ -17,7 +17,7 @@ void onclicked(GtkButton* button) {
} }
// You must // You must
const size_t wbcffi_version = 1; const size_t wbcffi_version = 2;
void* wbcffi_init(const wbcffi_init_info* init_info, const wbcffi_config_entry* config_entries, void* wbcffi_init(const wbcffi_init_info* init_info, const wbcffi_config_entry* config_entries,
size_t config_entries_len) { size_t config_entries_len) {
@@ -7,7 +7,7 @@
extern "C" { extern "C" {
#endif #endif
/// Waybar ABI version. 1 is the latest version /// Waybar ABI version. 2 is the latest version
extern const size_t wbcffi_version; extern const size_t wbcffi_version;
/// Private Waybar CFFI module /// Private Waybar CFFI module
@@ -35,7 +35,13 @@ typedef struct {
typedef struct { typedef struct {
/// Entry key /// Entry key
const char* key; const char* key;
/// Entry value as string. JSON object and arrays are serialized. /// Entry value
///
/// In ABI version 1, this may be either a bare string if the value is a
/// string, or the JSON representation of any other JSON object as a string.
///
/// From ABI version 2 onwards, this is always the JSON representation of the
/// value as a string.
const char* value; const char* value;
} wbcffi_config_entry; } wbcffi_config_entry;
+9
View File
@@ -154,6 +154,15 @@ void AAppIconLabel::updateAppIcon() {
update_app_icon_ = false; update_app_icon_ = false;
if (app_icon_name_.empty()) { if (app_icon_name_.empty()) {
image_.set_visible(false); image_.set_visible(false);
} else if (app_icon_name_.front() == '/') {
auto pixbuf = Gdk::Pixbuf::create_from_file(app_icon_name_);
int scaled_icon_size = app_icon_size_ * image_.get_scale_factor();
pixbuf = Gdk::Pixbuf::create_from_file(app_icon_name_, scaled_icon_size, scaled_icon_size);
auto surface = Gdk::Cairo::create_surface_from_pixbuf(pixbuf, image_.get_scale_factor(),
image_.get_window());
image_.set(surface);
image_.set_visible(true);
} else { } else {
image_.set_from_icon_name(app_icon_name_, Gtk::ICON_SIZE_INVALID); image_.set_from_icon_name(app_icon_name_, Gtk::ICON_SIZE_INVALID);
image_.set_visible(true); image_.set_visible(true);
+13 -1
View File
@@ -6,6 +6,8 @@
#include <iostream> #include <iostream>
#include <util/command.hpp> #include <util/command.hpp>
#include "config.hpp"
namespace waybar { namespace waybar {
ALabel::ALabel(const Json::Value& config, const std::string& name, const std::string& id, ALabel::ALabel(const Json::Value& config, const std::string& name, const std::string& id,
@@ -43,6 +45,8 @@ ALabel::ALabel(const Json::Value& config, const std::string& name, const std::st
if (config_["rotate"].isUInt()) { if (config_["rotate"].isUInt()) {
rotate = config["rotate"].asUInt(); rotate = config["rotate"].asUInt();
if (not(rotate == 0 || rotate == 90 || rotate == 180 || rotate == 270))
spdlog::warn("'rotate' is only supported in 90 degree increments {} is not valid.", rotate);
label_.set_angle(rotate); label_.set_angle(rotate);
} }
@@ -61,6 +65,14 @@ ALabel::ALabel(const Json::Value& config, const std::string& name, const std::st
try { try {
// Check that the file exists // Check that the file exists
std::string menuFile = config_["menu-file"].asString(); std::string menuFile = config_["menu-file"].asString();
// there might be "~" or "$HOME" in original path, try to expand it.
auto result = Config::tryExpandPath(menuFile, "");
if (result.empty()) {
throw std::runtime_error("Failed to expand file: " + menuFile);
}
menuFile = result.front();
// Read the menu descriptor file // Read the menu descriptor file
std::ifstream file(menuFile); std::ifstream file(menuFile);
if (!file.is_open()) { if (!file.is_open()) {
@@ -170,7 +182,7 @@ bool waybar::ALabel::handleToggle(GdkEventButton* const& e) {
return AModule::handleToggle(e); return AModule::handleToggle(e);
} }
void ALabel::handleGtkMenuEvent(GtkMenuItem* menuitem, gpointer data) { void ALabel::handleGtkMenuEvent(GtkMenuItem* /*menuitem*/, gpointer data) {
waybar::util::command::res res = waybar::util::command::exec((char*)data, "GtkMenu"); waybar::util::command::res res = waybar::util::command::exec((char*)data, "GtkMenu");
} }
+36 -4
View File
@@ -1,9 +1,13 @@
#include "AModule.hpp" #include "AModule.hpp"
#include <fmt/format.h> #include <fmt/format.h>
#include <spdlog/spdlog.h>
#include <util/command.hpp> #include <util/command.hpp>
#include "gdk/gdk.h"
#include "gdkmm/cursor.h"
namespace waybar { namespace waybar {
AModule::AModule(const Json::Value& config, const std::string& name, const std::string& id, AModule::AModule(const Json::Value& config, const std::string& name, const std::string& id,
@@ -11,6 +15,7 @@ AModule::AModule(const Json::Value& config, const std::string& name, const std::
: name_(name), : name_(name),
config_(config), config_(config),
isTooltip{config_["tooltip"].isBool() ? config_["tooltip"].asBool() : true}, isTooltip{config_["tooltip"].isBool() ? config_["tooltip"].asBool() : true},
isExpand{config_["expand"].isBool() ? config_["expand"].asBool() : false},
distance_scrolled_y_(0.0), distance_scrolled_y_(0.0),
distance_scrolled_x_(0.0) { distance_scrolled_x_(0.0) {
// Configure module action Map // Configure module action Map
@@ -64,6 +69,17 @@ AModule::AModule(const Json::Value& config, const std::string& name, const std::
event_box_.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK); event_box_.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
event_box_.signal_scroll_event().connect(sigc::mem_fun(*this, &AModule::handleScroll)); event_box_.signal_scroll_event().connect(sigc::mem_fun(*this, &AModule::handleScroll));
} }
// Respect user configuration of cursor
if (config_.isMember("cursor")) {
if (config_["cursor"].isBool() && config_["cursor"].asBool()) {
setCursor(Gdk::HAND2);
} else if (config_["cursor"].isInt()) {
setCursor(Gdk::CursorType(config_["cursor"].asInt()));
} else {
spdlog::warn("unknown cursor option configured on module {}", name_);
}
}
} }
AModule::~AModule() { AModule::~AModule() {
@@ -91,9 +107,20 @@ auto AModule::doAction(const std::string& name) -> void {
} }
void AModule::setCursor(Gdk::CursorType const& c) { void AModule::setCursor(Gdk::CursorType const& c) {
auto cursor = Gdk::Cursor::create(c);
auto gdk_window = event_box_.get_window(); auto gdk_window = event_box_.get_window();
gdk_window->set_cursor(cursor); if (gdk_window) {
auto cursor = Gdk::Cursor::create(c);
gdk_window->set_cursor(cursor);
} else {
// window may not be accessible yet, in this case,
// schedule another call for setting the cursor in 1 sec
Glib::signal_timeout().connect_seconds(
[this, c]() {
setCursor(c);
return false;
},
1);
}
} }
bool AModule::handleMouseEnter(GdkEventCrossing* const& e) { bool AModule::handleMouseEnter(GdkEventCrossing* const& e) {
@@ -101,9 +128,11 @@ bool AModule::handleMouseEnter(GdkEventCrossing* const& e) {
module->set_state_flags(Gtk::StateFlags::STATE_FLAG_PRELIGHT); module->set_state_flags(Gtk::StateFlags::STATE_FLAG_PRELIGHT);
} }
if (hasUserEvents_) { // Default behavior indicating event availability
if (hasUserEvents_ && !config_.isMember("cursor")) {
setCursor(Gdk::HAND2); setCursor(Gdk::HAND2);
} }
return false; return false;
} }
@@ -112,9 +141,11 @@ bool AModule::handleMouseLeave(GdkEventCrossing* const& e) {
module->unset_state_flags(Gtk::StateFlags::STATE_FLAG_PRELIGHT); module->unset_state_flags(Gtk::StateFlags::STATE_FLAG_PRELIGHT);
} }
if (hasUserEvents_) { // Default behavior indicating event availability
if (hasUserEvents_ && !config_.isMember("cursor")) {
setCursor(Gdk::ARROW); setCursor(Gdk::ARROW);
} }
return false; return false;
} }
@@ -243,6 +274,7 @@ bool AModule::handleScroll(GdkEventScroll* e) {
} }
bool AModule::tooltipEnabled() const { return isTooltip; } bool AModule::tooltipEnabled() const { return isTooltip; }
bool AModule::expandEnabled() const { return isExpand; }
AModule::operator Gtk::Widget&() { return event_box_; } AModule::operator Gtk::Widget&() { return event_box_; }
+45 -20
View File
@@ -37,19 +37,19 @@ const Bar::bar_mode_map Bar::PRESET_MODES = { //
.visible = true}}, .visible = true}},
{"hide", {"hide",
{// {//
.layer = bar_layer::TOP, .layer = bar_layer::OVERLAY,
.exclusive = false, .exclusive = false,
.passthrough = false, .passthrough = false,
.visible = true}}, .visible = true}},
{"invisible", {"invisible",
{// {//
.layer = std::nullopt, .layer = bar_layer::BOTTOM,
.exclusive = false, .exclusive = false,
.passthrough = true, .passthrough = true,
.visible = false}}, .visible = false}},
{"overlay", {"overlay",
{// {//
.layer = bar_layer::TOP, .layer = bar_layer::OVERLAY,
.exclusive = false, .exclusive = false,
.passthrough = true, .passthrough = true,
.visible = true}}}; .visible = true}}};
@@ -59,7 +59,7 @@ const std::string Bar::MODE_INVISIBLE = "invisible";
const std::string_view DEFAULT_BAR_ID = "bar-0"; const std::string_view DEFAULT_BAR_ID = "bar-0";
/* Deserializer for enum bar_layer */ /* Deserializer for enum bar_layer */
void from_json(const Json::Value& j, std::optional<bar_layer>& l) { void from_json(const Json::Value& j, bar_layer& l) {
if (j == "bottom") { if (j == "bottom") {
l = bar_layer::BOTTOM; l = bar_layer::BOTTOM;
} else if (j == "top") { } else if (j == "top") {
@@ -132,6 +132,7 @@ void from_json(const Json::Value& j, std::map<Key, Value>& m) {
waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config) waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
: output(w_output), : output(w_output),
config(w_config), config(w_config),
surface(nullptr),
window{Gtk::WindowType::WINDOW_TOPLEVEL}, window{Gtk::WindowType::WINDOW_TOPLEVEL},
x_global(0), x_global(0),
y_global(0), y_global(0),
@@ -316,13 +317,13 @@ void waybar::Bar::setMode(const std::string& mode) {
void waybar::Bar::setMode(const struct bar_mode& mode) { void waybar::Bar::setMode(const struct bar_mode& mode) {
auto* gtk_window = window.gobj(); auto* gtk_window = window.gobj();
if (mode.layer == bar_layer::BOTTOM) { auto layer = GTK_LAYER_SHELL_LAYER_BOTTOM;
gtk_layer_set_layer(gtk_window, GTK_LAYER_SHELL_LAYER_BOTTOM); if (mode.layer == bar_layer::TOP) {
} else if (mode.layer == bar_layer::TOP) { layer = GTK_LAYER_SHELL_LAYER_TOP;
gtk_layer_set_layer(gtk_window, GTK_LAYER_SHELL_LAYER_TOP);
} else if (mode.layer == bar_layer::OVERLAY) { } else if (mode.layer == bar_layer::OVERLAY) {
gtk_layer_set_layer(gtk_window, GTK_LAYER_SHELL_LAYER_OVERLAY); layer = GTK_LAYER_SHELL_LAYER_OVERLAY;
} }
gtk_layer_set_layer(gtk_window, layer);
if (mode.exclusive) { if (mode.exclusive) {
gtk_layer_auto_exclusive_zone_enable(gtk_window); gtk_layer_auto_exclusive_zone_enable(gtk_window);
@@ -339,6 +340,13 @@ void waybar::Bar::setMode(const struct bar_mode& mode) {
window.get_style_context()->add_class("hidden"); window.get_style_context()->add_class("hidden");
window.set_opacity(0); window.set_opacity(0);
} }
/*
* All the changes above require `wl_surface_commit`.
* gtk-layer-shell schedules a commit on the next frame event in GTK, but this could fail in
* certain scenarios, such as fully occluded bar.
*/
gtk_layer_try_force_commit(gtk_window);
wl_display_flush(Client::inst()->wl_display);
} }
void waybar::Bar::setPassThrough(bool passthrough) { void waybar::Bar::setPassThrough(bool passthrough) {
@@ -404,7 +412,8 @@ void waybar::Bar::onMap(GdkEventAny* /*unused*/) {
setPassThrough(passthrough_); setPassThrough(passthrough_);
} }
void waybar::Bar::setVisible(bool visible) { void waybar::Bar::setVisible(bool value) {
visible = value;
if (auto mode = config.get("mode", {}); mode.isString()) { if (auto mode = config.get("mode", {}); mode.isString()) {
setMode(visible ? config["mode"].asString() : MODE_INVISIBLE); setMode(visible ? config["mode"].asString() : MODE_INVISIBLE);
} else { } else {
@@ -525,13 +534,22 @@ void waybar::Bar::getModules(const Factory& factory, const std::string& pos,
auto waybar::Bar::setupWidgets() -> void { auto waybar::Bar::setupWidgets() -> void {
window.add(box_); window.add(box_);
box_.pack_start(left_, false, false);
if (config["fixed-center"].isBool() ? config["fixed-center"].asBool() : true) { bool expand_left = config["expand-left"].isBool() ? config["expand-left"].asBool() : false;
box_.set_center_widget(center_); bool expand_center = config["expand-center"].isBool() ? config["expand-center"].asBool() : false;
} else { bool expand_right = config["expand-right"].isBool() ? config["expand-right"].asBool() : false;
box_.pack_start(center_, true, false); bool no_center = config["no-center"].isBool() ? config["no-center"].asBool() : false;
box_.pack_start(left_, expand_left, expand_left);
if (!no_center) {
if (config["fixed-center"].isBool() ? config["fixed-center"].asBool() : true) {
box_.set_center_widget(center_);
} else {
spdlog::error("No fixed center_");
box_.pack_start(center_, true, expand_center);
}
} }
box_.pack_end(right_, false, false); box_.pack_end(right_, expand_right, expand_right);
// Convert to button code for every module that is used. // Convert to button code for every module that is used.
setupAltFormatKeyForModuleList("modules-left"); setupAltFormatKeyForModuleList("modules-left");
@@ -540,14 +558,21 @@ auto waybar::Bar::setupWidgets() -> void {
Factory factory(*this, config); Factory factory(*this, config);
getModules(factory, "modules-left"); getModules(factory, "modules-left");
getModules(factory, "modules-center"); if (!no_center) {
getModules(factory, "modules-center");
}
getModules(factory, "modules-right"); getModules(factory, "modules-right");
for (auto const& module : modules_left_) { for (auto const& module : modules_left_) {
left_.pack_start(*module, false, false); left_.pack_start(*module, module->expandEnabled(), module->expandEnabled());
} }
for (auto const& module : modules_center_) {
center_.pack_start(*module, false, false); if (!no_center) {
for (auto const& module : modules_center_) {
center_.pack_start(*module, false, false);
}
} }
std::reverse(modules_right_.begin(), modules_right_.end()); std::reverse(modules_right_.begin(), modules_right_.end());
for (auto const& module : modules_right_) { for (auto const& module : modules_right_) {
right_.pack_end(*module, false, false); right_.pack_end(*module, false, false);
+2 -1
View File
@@ -123,7 +123,8 @@ void waybar::Client::handleMonitorAdded(Glib::RefPtr<Gdk::Monitor> monitor) {
} }
void waybar::Client::handleMonitorRemoved(Glib::RefPtr<Gdk::Monitor> monitor) { void waybar::Client::handleMonitorRemoved(Glib::RefPtr<Gdk::Monitor> monitor) {
spdlog::debug("Output removed: {} {}", monitor->get_manufacturer().c_str(), monitor->get_model().c_str()); spdlog::debug("Output removed: {} {}", monitor->get_manufacturer().c_str(),
monitor->get_model().c_str());
/* This event can be triggered from wl_display_roundtrip called by GTK or our code. /* This event can be triggered from wl_display_roundtrip called by GTK or our code.
* Defer destruction of bars for the output to the next iteration of the event loop to avoid * Defer destruction of bars for the output to the next iteration of the event loop to avoid
* deleting objects referenced by currently executed code. * deleting objects referenced by currently executed code.
+20 -13
View File
@@ -21,7 +21,8 @@ const std::vector<std::string> Config::CONFIG_DIRS = {
const char *Config::CONFIG_PATH_ENV = "WAYBAR_CONFIG_DIR"; const char *Config::CONFIG_PATH_ENV = "WAYBAR_CONFIG_DIR";
std::optional<std::string> tryExpandPath(const std::string &base, const std::string &filename) { std::vector<std::string> Config::tryExpandPath(const std::string &base,
const std::string &filename) {
fs::path path; fs::path path;
if (!filename.empty()) { if (!filename.empty()) {
@@ -32,33 +33,35 @@ std::optional<std::string> tryExpandPath(const std::string &base, const std::str
spdlog::debug("Try expanding: {}", path.string()); spdlog::debug("Try expanding: {}", path.string());
std::vector<std::string> results;
wordexp_t p; wordexp_t p;
if (wordexp(path.c_str(), &p, 0) == 0) { if (wordexp(path.c_str(), &p, 0) == 0) {
if (access(*p.we_wordv, F_OK) == 0) { for (size_t i = 0; i < p.we_wordc; i++) {
std::string result = *p.we_wordv; if (access(p.we_wordv[i], F_OK) == 0) {
wordfree(&p); results.emplace_back(p.we_wordv[i]);
spdlog::debug("Found config file: {}", path.string()); spdlog::debug("Found config file: {}", p.we_wordv[i]);
return result; }
} }
wordfree(&p); wordfree(&p);
} }
return std::nullopt;
return results;
} }
std::optional<std::string> Config::findConfigPath(const std::vector<std::string> &names, std::optional<std::string> Config::findConfigPath(const std::vector<std::string> &names,
const std::vector<std::string> &dirs) { const std::vector<std::string> &dirs) {
if (const char *dir = std::getenv(Config::CONFIG_PATH_ENV)) { if (const char *dir = std::getenv(Config::CONFIG_PATH_ENV)) {
for (const auto &name : names) { for (const auto &name : names) {
if (auto res = tryExpandPath(dir, name); res) { if (auto res = tryExpandPath(dir, name); !res.empty()) {
return res; return res.front();
} }
} }
} }
for (const auto &dir : dirs) { for (const auto &dir : dirs) {
for (const auto &name : names) { for (const auto &name : names) {
if (auto res = tryExpandPath(dir, name); res) { if (auto res = tryExpandPath(dir, name); !res.empty()) {
return res; return res.front();
} }
} }
} }
@@ -91,11 +94,15 @@ void Config::resolveConfigIncludes(Json::Value &config, int depth) {
if (includes.isArray()) { if (includes.isArray()) {
for (const auto &include : includes) { for (const auto &include : includes) {
spdlog::info("Including resource file: {}", include.asString()); spdlog::info("Including resource file: {}", include.asString());
setupConfig(config, tryExpandPath(include.asString(), "").value_or(""), ++depth); for (const auto &match : tryExpandPath(include.asString(), "")) {
setupConfig(config, match, depth + 1);
}
} }
} else if (includes.isString()) { } else if (includes.isString()) {
spdlog::info("Including resource file: {}", includes.asString()); spdlog::info("Including resource file: {}", includes.asString());
setupConfig(config, tryExpandPath(includes.asString(), "").value_or(""), ++depth); for (const auto &match : tryExpandPath(includes.asString(), "")) {
setupConfig(config, match, depth + 1);
}
} }
} }
+17 -1
View File
@@ -36,6 +36,11 @@
#include "modules/hyprland/window.hpp" #include "modules/hyprland/window.hpp"
#include "modules/hyprland/workspaces.hpp" #include "modules/hyprland/workspaces.hpp"
#endif #endif
#ifdef HAVE_NIRI
#include "modules/niri/language.hpp"
#include "modules/niri/window.hpp"
#include "modules/niri/workspaces.hpp"
#endif
#if defined(__FreeBSD__) || defined(__linux__) #if defined(__FreeBSD__) || defined(__linux__)
#include "modules/battery.hpp" #include "modules/battery.hpp"
#endif #endif
@@ -135,7 +140,7 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name,
#endif #endif
#ifdef HAVE_PIPEWIRE #ifdef HAVE_PIPEWIRE
if (ref == "privacy") { if (ref == "privacy") {
return new waybar::modules::privacy::Privacy(id, config_[name], pos); return new waybar::modules::privacy::Privacy(id, config_[name], bar_.orientation, pos);
} }
#endif #endif
#ifdef HAVE_MPRIS #ifdef HAVE_MPRIS
@@ -205,6 +210,17 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name,
if (ref == "hyprland/workspaces") { if (ref == "hyprland/workspaces") {
return new waybar::modules::hyprland::Workspaces(id, bar_, config_[name]); return new waybar::modules::hyprland::Workspaces(id, bar_, config_[name]);
} }
#endif
#ifdef HAVE_NIRI
if (ref == "niri/language") {
return new waybar::modules::niri::Language(id, bar_, config_[name]);
}
if (ref == "niri/window") {
return new waybar::modules::niri::Window(id, bar_, config_[name]);
}
if (ref == "niri/workspaces") {
return new waybar::modules::niri::Workspaces(id, bar_, config_[name]);
}
#endif #endif
if (ref == "idle_inhibitor") { if (ref == "idle_inhibitor") {
return new waybar::modules::IdleInhibitor(id, bar_, config_[name]); return new waybar::modules::IdleInhibitor(id, bar_, config_[name]);
+29 -4
View File
@@ -9,7 +9,7 @@
namespace waybar { namespace waybar {
const Gtk::RevealerTransitionType getPreferredTransitionType(bool is_vertical) { Gtk::RevealerTransitionType getPreferredTransitionType(bool is_vertical) {
/* The transition direction of a drawer is not actually determined by the transition type, /* The transition direction of a drawer is not actually determined by the transition type,
* but rather by the order of 'box' and 'revealer_box': * but rather by the order of 'box' and 'revealer_box':
* 'REVEALER_TRANSITION_TYPE_SLIDE_LEFT' and 'REVEALER_TRANSITION_TYPE_SLIDE_RIGHT' * 'REVEALER_TRANSITION_TYPE_SLIDE_LEFT' and 'REVEALER_TRANSITION_TYPE_SLIDE_RIGHT'
@@ -62,6 +62,7 @@ Group::Group(const std::string& name, const std::string& id, const Json::Value&
const bool left_to_right = (drawer_config["transition-left-to-right"].isBool() const bool left_to_right = (drawer_config["transition-left-to-right"].isBool()
? drawer_config["transition-left-to-right"].asBool() ? drawer_config["transition-left-to-right"].asBool()
: true); : true);
click_to_reveal = drawer_config["click-to-reveal"].asBool();
auto transition_type = getPreferredTransitionType(vertical); auto transition_type = getPreferredTransitionType(vertical);
@@ -83,18 +84,42 @@ Group::Group(const std::string& name, const std::string& id, const Json::Value&
event_box_.add(box); event_box_.add(box);
} }
bool Group::handleMouseEnter(GdkEventCrossing* const& e) { void Group::show_group() {
box.set_state_flags(Gtk::StateFlags::STATE_FLAG_PRELIGHT); box.set_state_flags(Gtk::StateFlags::STATE_FLAG_PRELIGHT);
revealer.set_reveal_child(true); revealer.set_reveal_child(true);
}
void Group::hide_group() {
box.unset_state_flags(Gtk::StateFlags::STATE_FLAG_PRELIGHT);
revealer.set_reveal_child(false);
}
bool Group::handleMouseEnter(GdkEventCrossing* const& e) {
if (!click_to_reveal) {
show_group();
}
return false; return false;
} }
bool Group::handleMouseLeave(GdkEventCrossing* const& e) { bool Group::handleMouseLeave(GdkEventCrossing* const& e) {
box.unset_state_flags(Gtk::StateFlags::STATE_FLAG_PRELIGHT); if (!click_to_reveal && e->detail != GDK_NOTIFY_INFERIOR) {
revealer.set_reveal_child(false); hide_group();
}
return false; return false;
} }
bool Group::handleToggle(GdkEventButton* const& e) {
if (!click_to_reveal || e->button != 1) {
return false;
}
if ((box.get_state_flags() & Gtk::StateFlags::STATE_FLAG_PRELIGHT) != 0U) {
hide_group();
} else {
show_group();
}
return true;
}
auto Group::update() -> void { auto Group::update() -> void {
// noop // noop
} }
+4
View File
@@ -107,6 +107,10 @@ int main(int argc, char* argv[]) {
ret = client->main(argc, argv); ret = client->main(argc, argv);
} while (reload); } while (reload);
std::signal(SIGUSR1, SIG_IGN);
std::signal(SIGUSR2, SIG_IGN);
std::signal(SIGINT, SIG_IGN);
delete client; delete client;
return ret; return ret;
} catch (const std::exception& e) { } catch (const std::exception& e) {
+8
View File
@@ -112,6 +112,14 @@ bool waybar::modules::Backlight::handleScroll(GdkEventScroll *e) {
step = config_["scroll-step"].asDouble(); step = config_["scroll-step"].asDouble();
} }
double min_brightness = 0;
if (config_["min-brightness"].isDouble()) {
min_brightness = config_["min-brightness"].asDouble();
}
if (backend.get_scaled_brightness(preferred_device_) <= min_brightness &&
ct == util::ChangeType::Decrease) {
return true;
}
backend.set_brightness(preferred_device_, ct, step); backend.set_brightness(preferred_device_, ct, step);
return true; return true;
+11 -3
View File
@@ -273,14 +273,18 @@ waybar::modules::Battery::getInfos() {
// Scale these by the voltage to get μW/μWh. // Scale these by the voltage to get μW/μWh.
uint32_t current_now = 0; uint32_t current_now = 0;
int32_t _current_now_int = 0;
bool current_now_exists = false; bool current_now_exists = false;
if (fs::exists(bat / "current_now")) { if (fs::exists(bat / "current_now")) {
current_now_exists = true; current_now_exists = true;
std::ifstream(bat / "current_now") >> current_now; std::ifstream(bat / "current_now") >> _current_now_int;
} else if (fs::exists(bat / "current_avg")) { } else if (fs::exists(bat / "current_avg")) {
current_now_exists = true; current_now_exists = true;
std::ifstream(bat / "current_avg") >> current_now; std::ifstream(bat / "current_avg") >> _current_now_int;
} }
// Documentation ABI allows a negative value when discharging, positive
// value when charging.
current_now = std::abs(_current_now_int);
if (fs::exists(bat / "time_to_empty_now")) { if (fs::exists(bat / "time_to_empty_now")) {
time_to_empty_now_exists = true; time_to_empty_now_exists = true;
@@ -324,11 +328,15 @@ waybar::modules::Battery::getInfos() {
} }
uint32_t power_now = 0; uint32_t power_now = 0;
int32_t _power_now_int = 0;
bool power_now_exists = false; bool power_now_exists = false;
if (fs::exists(bat / "power_now")) { if (fs::exists(bat / "power_now")) {
power_now_exists = true; power_now_exists = true;
std::ifstream(bat / "power_now") >> power_now; std::ifstream(bat / "power_now") >> _power_now_int;
} }
// Some drivers (example: Qualcomm) exposes use a negative value when
// discharging, positive value when charging.
power_now = std::abs(_power_now_int);
uint32_t energy_now = 0; uint32_t energy_now = 0;
bool energy_now_exists = false; bool energy_now_exists = false;

Some files were not shown because too many files have changed in this diff Show More