Merge branch 'Alexays:master' into master
This commit is contained in:
@@ -1,14 +1,15 @@
|
|||||||
name: Build and Push Docker Image
|
name: Build and Push Docker Image
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
schedule:
|
schedule:
|
||||||
# run every night at midnight
|
# run monthly
|
||||||
- cron: '0 0 * * *'
|
- cron: '0 0 1 * *'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-and-push:
|
build-and-push:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.repository == 'Alexays/Waybar'
|
if: github.event_name != 'schedule' || 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:
|
||||||
|
|||||||
@@ -14,14 +14,14 @@ 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.25.0
|
uses: cross-platform-actions/action@v0.28.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: "14.1"
|
version: "14.2"
|
||||||
environment_variables: CPPFLAGS LDFLAGS
|
environment_variables: CPPFLAGS LDFLAGS
|
||||||
sync_files: runner-to-vm
|
sync_files: runner-to-vm
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
# vim: ft=Dockerfile
|
# vim: ft=Dockerfile
|
||||||
|
|
||||||
FROM debian:sid
|
FROM debian:sid-slim
|
||||||
|
|
||||||
RUN apt update && \
|
RUN apt update && \
|
||||||
apt install --no-install-recommends --no-install-suggests -y \
|
apt install --no-install-recommends --no-install-suggests -y \
|
||||||
|
|||||||
+1
-1
@@ -6,6 +6,6 @@ RUN export FEATURES="-ipc-sandbox -network-sandbox -pid-sandbox -sandbox -usersa
|
|||||||
emerge --sync && \
|
emerge --sync && \
|
||||||
eselect news read --quiet new 1>/dev/null 2>&1 && \
|
eselect news read --quiet new 1>/dev/null 2>&1 && \
|
||||||
emerge --verbose --update --deep --with-bdeps=y --backtrack=30 --newuse @world && \
|
emerge --verbose --update --deep --with-bdeps=y --backtrack=30 --newuse @world && \
|
||||||
USE="wayland gtk3 gtk -doc X pulseaudio minimal" emerge dev-vcs/git dev-libs/wayland dev-libs/wayland-protocols =dev-cpp/gtkmm-3.24.6 x11-libs/libxkbcommon \
|
USE="wayland gtk3 gtk -doc X pulseaudio minimal" emerge dev-vcs/git dev-libs/wayland dev-libs/wayland-protocols dev-cpp/gtkmm:3.0 x11-libs/libxkbcommon \
|
||||||
x11-libs/gtk+:3 dev-libs/libdbusmenu dev-libs/libnl sys-power/upower media-libs/libpulse dev-libs/libevdev media-libs/libmpdclient \
|
x11-libs/gtk+:3 dev-libs/libdbusmenu dev-libs/libnl sys-power/upower media-libs/libpulse dev-libs/libevdev media-libs/libmpdclient \
|
||||||
media-sound/sndio gui-libs/gtk-layer-shell app-text/scdoc media-sound/playerctl dev-libs/iniparser sci-libs/fftw
|
media-sound/sndio gui-libs/gtk-layer-shell app-text/scdoc media-sound/playerctl dev-libs/iniparser sci-libs/fftw
|
||||||
|
|||||||
@@ -20,8 +20,12 @@ debug-run: build-debug
|
|||||||
./build/waybar --log-level debug
|
./build/waybar --log-level debug
|
||||||
|
|
||||||
test:
|
test:
|
||||||
meson test -C build --no-rebuild --verbose --suite waybar
|
meson test -C build --verbose --suite waybar
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
|
|
||||||
|
test-detailed:
|
||||||
|
meson test -C build --verbose --print-errorlogs --test-args='--reporter console -s'
|
||||||
|
.PHONY: test-detailed
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf build
|
rm -rf build
|
||||||
|
|||||||
@@ -116,6 +116,36 @@ sudo apt install \
|
|||||||
libxkbregistry-dev
|
libxkbregistry-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
|
On Arch, you can use this command:
|
||||||
|
|
||||||
|
```
|
||||||
|
pacman -S \
|
||||||
|
gtkmm3 \
|
||||||
|
jsoncpp \
|
||||||
|
libsigc++ \
|
||||||
|
fmt \
|
||||||
|
wayland \
|
||||||
|
chrono-date \
|
||||||
|
spdlog \
|
||||||
|
gtk3 \
|
||||||
|
gobject-introspection \
|
||||||
|
libgirepository \
|
||||||
|
libpulse \
|
||||||
|
libnl \
|
||||||
|
libappindicator-gtk3 \
|
||||||
|
libdbusmenu-gtk3 \
|
||||||
|
libmpdclient \
|
||||||
|
sndio \
|
||||||
|
libevdev \
|
||||||
|
libxkbcommon \
|
||||||
|
upower \
|
||||||
|
meson \
|
||||||
|
cmake \
|
||||||
|
scdoc \
|
||||||
|
wayland-protocols \
|
||||||
|
glib2-devel
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
Contributions welcome!<br>
|
Contributions welcome!<br>
|
||||||
Have fun :)<br>
|
Have fun :)<br>
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
# Suppress common address sanitizer issues in dependencies, these are often non-fixable or not an issue.
|
||||||
|
# Use it like this (when in repo root): ASAN_OPTIONS="suppressions=./asan.supp" ./build/waybar
|
||||||
|
leak:libpangoft2-1.0.so.0
|
||||||
|
leak:libgtk-3.so.0
|
||||||
|
leak:libfontconfig.so.1
|
||||||
Generated
+6
-6
@@ -3,11 +3,11 @@
|
|||||||
"flake-compat": {
|
"flake-compat": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1733328505,
|
"lastModified": 1747046372,
|
||||||
"narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=",
|
"narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=",
|
||||||
"owner": "edolstra",
|
"owner": "edolstra",
|
||||||
"repo": "flake-compat",
|
"repo": "flake-compat",
|
||||||
"rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
|
"rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -18,11 +18,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1745391562,
|
"lastModified": 1759036355,
|
||||||
"narHash": "sha256-sPwcCYuiEopaafePqlG826tBhctuJsLx/mhKKM5Fmjo=",
|
"narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "8a2f738d9d1f1d986b5a4cd2fd2061a7127237d7",
|
"rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
@@ -65,7 +65,7 @@
|
|||||||
nativeBuildInputs =
|
nativeBuildInputs =
|
||||||
pkgs.waybar.nativeBuildInputs
|
pkgs.waybar.nativeBuildInputs
|
||||||
++ (with pkgs; [
|
++ (with pkgs; [
|
||||||
nixfmt-rfc-style
|
nixfmt
|
||||||
clang-tools
|
clang-tools
|
||||||
gdb
|
gdb
|
||||||
]);
|
]);
|
||||||
@@ -75,8 +75,7 @@
|
|||||||
formatter = genSystems (
|
formatter = genSystems (
|
||||||
pkgs:
|
pkgs:
|
||||||
pkgs.treefmt.withConfig {
|
pkgs.treefmt.withConfig {
|
||||||
settings = [
|
settings = {
|
||||||
{
|
|
||||||
formatter = {
|
formatter = {
|
||||||
clang-format = {
|
clang-format = {
|
||||||
options = [ "-i" ];
|
options = [ "-i" ];
|
||||||
@@ -90,13 +89,12 @@
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
nixfmt = {
|
nixfmt = {
|
||||||
command = lib.getExe pkgs.nixfmt-rfc-style;
|
command = lib.getExe pkgs.nixfmt;
|
||||||
includes = [ "*.nix" ];
|
includes = [ "*.nix" ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
tree-root-file = ".git/index";
|
tree-root-file = ".git/index";
|
||||||
}
|
};
|
||||||
];
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ class ALabel : public AModule {
|
|||||||
protected:
|
protected:
|
||||||
Gtk::Label label_;
|
Gtk::Label label_;
|
||||||
std::string format_;
|
std::string format_;
|
||||||
const std::chrono::seconds interval_;
|
const std::chrono::milliseconds interval_;
|
||||||
bool alt_ = false;
|
bool alt_ = false;
|
||||||
std::string default_format_;
|
std::string default_format_;
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -36,6 +36,7 @@ class AModule : public IModule {
|
|||||||
SCROLL_DIR getScrollDir(GdkEventScroll *e);
|
SCROLL_DIR getScrollDir(GdkEventScroll *e);
|
||||||
bool tooltipEnabled() const;
|
bool tooltipEnabled() const;
|
||||||
|
|
||||||
|
std::vector<int> pid_children_;
|
||||||
const std::string name_;
|
const std::string name_;
|
||||||
const Json::Value &config_;
|
const Json::Value &config_;
|
||||||
Gtk::EventBox event_box_;
|
Gtk::EventBox event_box_;
|
||||||
@@ -54,7 +55,6 @@ class AModule : public IModule {
|
|||||||
const bool isTooltip;
|
const bool isTooltip;
|
||||||
const bool isExpand;
|
const bool isExpand;
|
||||||
bool hasUserEvents_;
|
bool hasUserEvents_;
|
||||||
std::vector<int> pid_;
|
|
||||||
gdouble distance_scrolled_y_;
|
gdouble distance_scrolled_y_;
|
||||||
gdouble distance_scrolled_x_;
|
gdouble distance_scrolled_x_;
|
||||||
std::map<std::string, std::string> eventActionMap_;
|
std::map<std::string, std::string> eventActionMap_;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "AModule.hpp"
|
#include "AModule.hpp"
|
||||||
#include "group.hpp"
|
#include "group.hpp"
|
||||||
|
#include "util/kill_signal.hpp"
|
||||||
#include "xdg-output-unstable-v1-client-protocol.h"
|
#include "xdg-output-unstable-v1-client-protocol.h"
|
||||||
|
|
||||||
namespace waybar {
|
namespace waybar {
|
||||||
@@ -68,7 +69,11 @@ class Bar : public sigc::trackable {
|
|||||||
void setMode(const std::string &mode);
|
void setMode(const std::string &mode);
|
||||||
void setVisible(bool value);
|
void setVisible(bool value);
|
||||||
void toggle();
|
void toggle();
|
||||||
|
void show();
|
||||||
|
void hide();
|
||||||
void handleSignal(int);
|
void handleSignal(int);
|
||||||
|
util::KillSignalAction getOnSigusr1Action();
|
||||||
|
util::KillSignalAction getOnSigusr2Action();
|
||||||
|
|
||||||
struct waybar_output *output;
|
struct waybar_output *output;
|
||||||
Json::Value config;
|
Json::Value config;
|
||||||
@@ -118,6 +123,9 @@ class Bar : public sigc::trackable {
|
|||||||
std::unique_ptr<BarIpcClient> _ipc_client;
|
std::unique_ptr<BarIpcClient> _ipc_client;
|
||||||
#endif
|
#endif
|
||||||
std::vector<std::shared_ptr<waybar::AModule>> modules_all_;
|
std::vector<std::shared_ptr<waybar::AModule>> modules_all_;
|
||||||
|
|
||||||
|
waybar::util::KillSignalAction onSigusr1 = util::SIGNALACTION_DEFAULT_SIGUSR1;
|
||||||
|
waybar::util::KillSignalAction onSigusr2 = util::SIGNALACTION_DEFAULT_SIGUSR2;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar
|
} // namespace waybar
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ class Config {
|
|||||||
void setupConfig(Json::Value &dst, const std::string &config_file, int depth);
|
void setupConfig(Json::Value &dst, const std::string &config_file, int depth);
|
||||||
void resolveConfigIncludes(Json::Value &config, int depth);
|
void resolveConfigIncludes(Json::Value &config, int depth);
|
||||||
void mergeConfig(Json::Value &a_config_, Json::Value &b_config_);
|
void mergeConfig(Json::Value &a_config_, Json::Value &b_config_);
|
||||||
|
static std::vector<std::string> findIncludePath(
|
||||||
|
const std::string &name, const std::vector<std::string> &dirs = CONFIG_DIRS);
|
||||||
|
|
||||||
std::string config_file_;
|
std::string config_file_;
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ class Battery : public ALabel {
|
|||||||
std::tuple<uint8_t, float, std::string, float, uint16_t, float> getInfos();
|
std::tuple<uint8_t, float, std::string, float, uint16_t, float> getInfos();
|
||||||
const std::string formatTimeRemaining(float hoursRemaining);
|
const std::string formatTimeRemaining(float hoursRemaining);
|
||||||
void setBarClass(std::string&);
|
void setBarClass(std::string&);
|
||||||
|
void processEvents(std::string& state, std::string& status, uint8_t capacity);
|
||||||
|
|
||||||
int global_watch;
|
int global_watch;
|
||||||
std::map<fs::path, int> batteries_;
|
std::map<fs::path, int> batteries_;
|
||||||
@@ -43,6 +44,7 @@ class Battery : public ALabel {
|
|||||||
int global_watch_fd_;
|
int global_watch_fd_;
|
||||||
std::mutex battery_list_mutex_;
|
std::mutex battery_list_mutex_;
|
||||||
std::string old_status_;
|
std::string old_status_;
|
||||||
|
std::string last_event_;
|
||||||
bool warnFirstTime_{true};
|
bool warnFirstTime_{true};
|
||||||
const Bar& bar_;
|
const Bar& bar_;
|
||||||
|
|
||||||
|
|||||||
@@ -1,59 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "ALabel.hpp"
|
|
||||||
#include "util/sleeper_thread.hpp"
|
|
||||||
|
|
||||||
namespace cava {
|
|
||||||
extern "C" {
|
|
||||||
// Need sdl_glsl output feature to be enabled on libcava
|
|
||||||
#ifndef SDL_GLSL
|
|
||||||
#define SDL_GLSL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <cava/common.h>
|
|
||||||
|
|
||||||
#ifdef SDL_GLSL
|
|
||||||
#undef SDL_GLSL
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
} // namespace cava
|
|
||||||
|
|
||||||
namespace waybar::modules {
|
|
||||||
using namespace std::literals::chrono_literals;
|
|
||||||
|
|
||||||
class Cava final : public ALabel {
|
|
||||||
public:
|
|
||||||
Cava(const std::string&, const Json::Value&);
|
|
||||||
virtual ~Cava();
|
|
||||||
auto update() -> void override;
|
|
||||||
auto doAction(const std::string& name) -> void override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
util::SleeperThread thread_;
|
|
||||||
util::SleeperThread thread_fetch_input_;
|
|
||||||
|
|
||||||
struct cava::error_s error_{}; // cava errors
|
|
||||||
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_data audio_data_{}; // cava audio data
|
|
||||||
struct cava::cava_plan* plan_; //{new cava_plan{}};
|
|
||||||
// Cava API to read audio source
|
|
||||||
cava::ptr input_source_;
|
|
||||||
// Delay to handle audio source
|
|
||||||
std::chrono::milliseconds frame_time_milsec_{1s};
|
|
||||||
// Text to display
|
|
||||||
std::string text_{""};
|
|
||||||
int rePaint_{1};
|
|
||||||
std::chrono::seconds fetch_input_delay_{4};
|
|
||||||
std::chrono::seconds suspend_silence_delay_{0};
|
|
||||||
bool silence_{false};
|
|
||||||
bool hide_on_silence_{false};
|
|
||||||
std::string format_silent_{""};
|
|
||||||
int sleep_counter_{0};
|
|
||||||
// Cava method
|
|
||||||
void pause_resume();
|
|
||||||
// ModuleActionMap
|
|
||||||
static inline std::map<const std::string, void (waybar::modules::Cava::* const)()> actionMap_{
|
|
||||||
{"mode", &waybar::modules::Cava::pause_resume}};
|
|
||||||
};
|
|
||||||
} // namespace waybar::modules
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ALabel.hpp"
|
||||||
|
#include "cava_backend.hpp"
|
||||||
|
|
||||||
|
namespace waybar::modules::cava {
|
||||||
|
|
||||||
|
class Cava final : public ALabel, public sigc::trackable {
|
||||||
|
public:
|
||||||
|
Cava(const std::string&, const Json::Value&);
|
||||||
|
~Cava() = default;
|
||||||
|
auto onUpdate(const std::string& input) -> void;
|
||||||
|
auto onSilence() -> void;
|
||||||
|
auto doAction(const std::string& name) -> void override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<CavaBackend> backend_;
|
||||||
|
// Text to display
|
||||||
|
std::string label_text_{""};
|
||||||
|
bool hide_on_silence_{false};
|
||||||
|
std::string format_silent_{""};
|
||||||
|
int ascii_range_{0};
|
||||||
|
bool silence_{false};
|
||||||
|
// Cava method
|
||||||
|
void pause_resume();
|
||||||
|
// ModuleActionMap
|
||||||
|
static inline std::map<const std::string, void (waybar::modules::cava::Cava::* const)()>
|
||||||
|
actionMap_{{"mode", &waybar::modules::cava::Cava::pause_resume}};
|
||||||
|
};
|
||||||
|
} // namespace waybar::modules::cava
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <json/json.h>
|
||||||
|
#include <sigc++/sigc++.h>
|
||||||
|
|
||||||
|
#include "util/sleeper_thread.hpp"
|
||||||
|
|
||||||
|
namespace cava {
|
||||||
|
extern "C" {
|
||||||
|
// Need sdl_glsl output feature to be enabled on libcava
|
||||||
|
#ifndef SDL_GLSL
|
||||||
|
#define SDL_GLSL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <cava/common.h>
|
||||||
|
|
||||||
|
#ifdef SDL_GLSL
|
||||||
|
#undef SDL_GLSL
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} // namespace cava
|
||||||
|
|
||||||
|
namespace waybar::modules::cava {
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
|
||||||
|
class CavaBackend final {
|
||||||
|
public:
|
||||||
|
static std::shared_ptr<CavaBackend> inst(const Json::Value& config);
|
||||||
|
|
||||||
|
virtual ~CavaBackend();
|
||||||
|
// Methods
|
||||||
|
int getAsciiRange();
|
||||||
|
void doPauseResume();
|
||||||
|
void Update();
|
||||||
|
// Signal accessor
|
||||||
|
using type_signal_update = sigc::signal<void(const std::string&)>;
|
||||||
|
type_signal_update signal_update();
|
||||||
|
using type_signal_silence = sigc::signal<void()>;
|
||||||
|
type_signal_silence signal_silence();
|
||||||
|
|
||||||
|
private:
|
||||||
|
CavaBackend(const Json::Value& config);
|
||||||
|
util::SleeperThread thread_;
|
||||||
|
util::SleeperThread read_thread_;
|
||||||
|
// Cava API to read audio source
|
||||||
|
::cava::ptr input_source_;
|
||||||
|
|
||||||
|
struct ::cava::error_s error_{}; // cava errors
|
||||||
|
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_data audio_data_{}; // cava audio data
|
||||||
|
struct ::cava::cava_plan* plan_; //{new cava_plan{}};
|
||||||
|
|
||||||
|
std::chrono::seconds fetch_input_delay_{4};
|
||||||
|
// Delay to handle audio source
|
||||||
|
std::chrono::milliseconds frame_time_milsec_{1s};
|
||||||
|
|
||||||
|
int re_paint_{0};
|
||||||
|
bool silence_{false};
|
||||||
|
bool silence_prev_{false};
|
||||||
|
std::chrono::seconds suspend_silence_delay_{0};
|
||||||
|
int sleep_counter_{0};
|
||||||
|
std::string output_{};
|
||||||
|
// Methods
|
||||||
|
void invoke();
|
||||||
|
void execute();
|
||||||
|
bool isSilence();
|
||||||
|
void doUpdate(bool force = false);
|
||||||
|
|
||||||
|
// Signal
|
||||||
|
type_signal_update m_signal_update_;
|
||||||
|
type_signal_silence m_signal_silence_;
|
||||||
|
};
|
||||||
|
} // namespace waybar::modules::cava
|
||||||
+13
-11
@@ -42,35 +42,37 @@ class Clock final : public ALabel {
|
|||||||
int cldWnLen_{3}; // calendar week number length
|
int cldWnLen_{3}; // calendar week number length
|
||||||
const int cldMonColLen_{20}; // calendar month column length
|
const int cldMonColLen_{20}; // calendar month column length
|
||||||
WS cldWPos_{WS::HIDDEN}; // calendar week side to print
|
WS cldWPos_{WS::HIDDEN}; // calendar week side to print
|
||||||
months cldCurrShift_{0}; // calendar months shift
|
date::months cldCurrShift_{0}; // calendar months shift
|
||||||
int cldShift_{1}; // calendar months shift factor
|
int cldShift_{1}; // calendar months shift factor
|
||||||
year_month_day cldYearShift_; // calendar Year mode. Cached ymd
|
date::year_month_day cldYearShift_; // calendar Year mode. Cached ymd
|
||||||
std::string cldYearCached_; // calendar Year mode. Cached calendar
|
std::string cldYearCached_; // calendar Year mode. Cached calendar
|
||||||
year_month cldMonShift_; // calendar Month mode. Cached ym
|
date::year_month cldMonShift_; // calendar Month mode. Cached ym
|
||||||
std::string cldMonCached_; // calendar Month mode. Cached calendar
|
std::string cldMonCached_; // calendar Month mode. Cached calendar
|
||||||
day cldBaseDay_{0}; // calendar Cached day. Is used when today is changing(midnight)
|
date::day cldBaseDay_{0}; // calendar Cached day. Is used when today is changing(midnight)
|
||||||
std::string cldText_{""}; // calendar text to print
|
std::string cldText_{""}; // calendar text to print
|
||||||
|
bool iso8601Calendar_{false}; // whether the calendar is in ISO8601
|
||||||
CldMode cldMode_{CldMode::MONTH};
|
CldMode cldMode_{CldMode::MONTH};
|
||||||
auto get_calendar(const year_month_day& today, const year_month_day& ymd, const time_zone* tz)
|
auto get_calendar(const date::year_month_day& today, const date::year_month_day& ymd,
|
||||||
-> const std::string;
|
const date::time_zone* tz) -> const std::string;
|
||||||
|
|
||||||
// get local time zone
|
// get local time zone
|
||||||
auto local_zone() -> const time_zone*;
|
auto local_zone() -> const date::time_zone*;
|
||||||
|
|
||||||
// time zoned time in tooltip
|
// time zoned time in tooltip
|
||||||
const bool tzInTooltip_; // if need to print time zones text
|
const bool tzInTooltip_; // if need to print time zones text
|
||||||
std::vector<const time_zone*> tzList_; // time zones list
|
std::vector<const date::time_zone*> tzList_; // time zones list
|
||||||
int tzCurrIdx_; // current time zone index for tzList_
|
int tzCurrIdx_; // current time zone index for tzList_
|
||||||
std::string tzText_{""}; // time zones text to print
|
std::string tzText_{""}; // time zones text to print
|
||||||
|
std::string tzTooltipFormat_{""}; // optional timezone tooltip format
|
||||||
util::SleeperThread thread_;
|
util::SleeperThread thread_;
|
||||||
|
|
||||||
// ordinal date in tooltip
|
// ordinal date in tooltip
|
||||||
const bool ordInTooltip_;
|
const bool ordInTooltip_;
|
||||||
std::string ordText_{""};
|
std::string ordText_{""};
|
||||||
auto get_ordinal_date(const year_month_day& today) -> std::string;
|
auto get_ordinal_date(const date::year_month_day& today) -> std::string;
|
||||||
|
|
||||||
auto getTZtext(sys_seconds now) -> std::string;
|
auto getTZtext(date::sys_seconds now) -> std::string;
|
||||||
auto first_day_of_week() -> weekday;
|
auto first_day_of_week() -> date::weekday;
|
||||||
// Module actions
|
// Module actions
|
||||||
void cldModeSwitch();
|
void cldModeSwitch();
|
||||||
void cldShift_up();
|
void cldShift_up();
|
||||||
|
|||||||
@@ -0,0 +1,141 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
#include <gtkmm/button.h>
|
||||||
|
#include <gtkmm/image.h>
|
||||||
|
#include <gtkmm/label.h>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "AModule.hpp"
|
||||||
|
#include "bar.hpp"
|
||||||
|
#include "ext-workspace-v1-client-protocol.h"
|
||||||
|
|
||||||
|
namespace waybar::modules::ext {
|
||||||
|
|
||||||
|
class WorkspaceGroup;
|
||||||
|
class Workspace;
|
||||||
|
|
||||||
|
class WorkspaceManager final : public AModule {
|
||||||
|
public:
|
||||||
|
WorkspaceManager(const std::string &id, const waybar::Bar &bar, const Json::Value &config);
|
||||||
|
~WorkspaceManager() override;
|
||||||
|
void register_manager(wl_registry *registry, uint32_t name, uint32_t version);
|
||||||
|
void remove_workspace_group(uint32_t id);
|
||||||
|
void remove_workspace(uint32_t id);
|
||||||
|
void set_needs_sorting() { needs_sorting_ = true; }
|
||||||
|
|
||||||
|
// wl events
|
||||||
|
void handle_workspace_group(ext_workspace_group_handle_v1 *handle);
|
||||||
|
void handle_workspace(ext_workspace_handle_v1 *handle);
|
||||||
|
void handle_done();
|
||||||
|
void handle_finished();
|
||||||
|
|
||||||
|
// wl requests
|
||||||
|
void commit() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void update() override;
|
||||||
|
bool has_button(const Gtk::Button *button);
|
||||||
|
void sort_workspaces();
|
||||||
|
void clear_buttons();
|
||||||
|
void update_buttons();
|
||||||
|
|
||||||
|
static uint32_t group_global_id;
|
||||||
|
static uint32_t workspace_global_id;
|
||||||
|
uint32_t workspace_name = 0;
|
||||||
|
|
||||||
|
bool sort_by_id_ = false;
|
||||||
|
bool sort_by_name_ = true;
|
||||||
|
bool sort_by_coordinates_ = false;
|
||||||
|
bool all_outputs_ = false;
|
||||||
|
|
||||||
|
const waybar::Bar &bar_;
|
||||||
|
Gtk::Box box_;
|
||||||
|
|
||||||
|
ext_workspace_manager_v1 *ext_manager_ = nullptr;
|
||||||
|
std::vector<std::unique_ptr<WorkspaceGroup>> groups_;
|
||||||
|
std::vector<std::unique_ptr<Workspace>> workspaces_;
|
||||||
|
|
||||||
|
bool needs_sorting_ = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
class WorkspaceGroup {
|
||||||
|
public:
|
||||||
|
WorkspaceGroup(WorkspaceManager &manager, ext_workspace_group_handle_v1 *handle, uint32_t id);
|
||||||
|
~WorkspaceGroup();
|
||||||
|
|
||||||
|
u_int32_t id() const { return id_; }
|
||||||
|
bool has_output(const wl_output *output);
|
||||||
|
bool has_workspace(const ext_workspace_handle_v1 *workspace);
|
||||||
|
|
||||||
|
// wl events
|
||||||
|
void handle_capabilities(uint32_t capabilities);
|
||||||
|
void handle_output_enter(wl_output *output);
|
||||||
|
void handle_output_leave(wl_output *output);
|
||||||
|
void handle_workspace_enter(ext_workspace_handle_v1 *handle);
|
||||||
|
void handle_workspace_leave(ext_workspace_handle_v1 *handle);
|
||||||
|
void handle_removed();
|
||||||
|
|
||||||
|
private:
|
||||||
|
WorkspaceManager &workspaces_manager_;
|
||||||
|
ext_workspace_group_handle_v1 *ext_handle_;
|
||||||
|
uint32_t id_;
|
||||||
|
std::vector<wl_output *> outputs_;
|
||||||
|
std::vector<ext_workspace_handle_v1 *> workspaces_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Workspace {
|
||||||
|
public:
|
||||||
|
Workspace(const Json::Value &config, WorkspaceManager &manager, ext_workspace_handle_v1 *handle,
|
||||||
|
uint32_t id, const std::string &name);
|
||||||
|
~Workspace();
|
||||||
|
|
||||||
|
ext_workspace_handle_v1 *handle() const { return ext_handle_; }
|
||||||
|
u_int32_t id() const { return id_; }
|
||||||
|
std::string &workspace_id() { return workspace_id_; }
|
||||||
|
std::string &name() { return name_; }
|
||||||
|
std::vector<u_int32_t> &coordinates() { return coordinates_; }
|
||||||
|
Gtk::Button &button() { return button_; }
|
||||||
|
void update();
|
||||||
|
|
||||||
|
// wl events
|
||||||
|
void handle_id(const std::string &id);
|
||||||
|
void handle_name(const std::string &name);
|
||||||
|
void handle_coordinates(const std::vector<uint32_t> &coordinates);
|
||||||
|
void handle_state(uint32_t state);
|
||||||
|
void handle_capabilities(uint32_t capabilities);
|
||||||
|
void handle_removed();
|
||||||
|
|
||||||
|
// gdk events
|
||||||
|
bool handle_clicked(const GdkEventButton *button) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool has_state(uint32_t state) const { return (state_ & state) == state; }
|
||||||
|
std::string icon();
|
||||||
|
|
||||||
|
WorkspaceManager &workspace_manager_;
|
||||||
|
ext_workspace_handle_v1 *ext_handle_ = nullptr;
|
||||||
|
uint32_t id_;
|
||||||
|
uint32_t state_ = 0;
|
||||||
|
std::string workspace_id_;
|
||||||
|
std::string name_;
|
||||||
|
std::vector<uint32_t> coordinates_;
|
||||||
|
|
||||||
|
bool active_only_ = false;
|
||||||
|
bool ignore_hidden_ = true;
|
||||||
|
std::string format_;
|
||||||
|
bool with_icon_ = false;
|
||||||
|
static std::map<std::string, std::string> icon_map_;
|
||||||
|
std::string on_click_action_;
|
||||||
|
std::string on_click_middle_action_;
|
||||||
|
std::string on_click_right_action_;
|
||||||
|
|
||||||
|
Gtk::Button button_;
|
||||||
|
Gtk::Box content_;
|
||||||
|
Gtk::Label label_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar::modules::ext
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#include "ext-workspace-v1-client-protocol.h"
|
||||||
|
|
||||||
|
namespace waybar::modules::ext {
|
||||||
|
void add_registry_listener(void *data);
|
||||||
|
void add_workspace_listener(ext_workspace_handle_v1 *workspace_handle, void *data);
|
||||||
|
void add_workspace_group_listener(ext_workspace_group_handle_v1 *workspace_group_handle,
|
||||||
|
void *data);
|
||||||
|
ext_workspace_manager_v1 *workspace_manager_bind(wl_registry *registry, uint32_t name,
|
||||||
|
uint32_t version, void *data);
|
||||||
|
} // namespace waybar::modules::ext
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
#include <sys/statvfs.h>
|
||||||
|
|
||||||
|
#ifdef WANT_RFKILL
|
||||||
|
#include "util/rfkill.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gps.h>
|
||||||
|
|
||||||
|
#include "ALabel.hpp"
|
||||||
|
#include "util/sleeper_thread.hpp"
|
||||||
|
|
||||||
|
namespace waybar::modules {
|
||||||
|
|
||||||
|
class Gps : public ALabel {
|
||||||
|
public:
|
||||||
|
Gps(const std::string&, const Json::Value&);
|
||||||
|
virtual ~Gps();
|
||||||
|
auto update() -> void override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
#ifdef WANT_RFKILL
|
||||||
|
util::Rfkill rfkill_;
|
||||||
|
#endif
|
||||||
|
const std::string getFixModeName() const;
|
||||||
|
const std::string getFixModeString() const;
|
||||||
|
|
||||||
|
const std::string getFixStatusString() const;
|
||||||
|
|
||||||
|
util::SleeperThread thread_, gps_thread_;
|
||||||
|
gps_data_t gps_data_;
|
||||||
|
std::string state_;
|
||||||
|
|
||||||
|
bool hideDisconnected = true;
|
||||||
|
bool hideNoFix = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar::modules
|
||||||
@@ -17,9 +17,13 @@ class EventHandler {
|
|||||||
virtual ~EventHandler() = default;
|
virtual ~EventHandler() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// If you want to use the Hyprland IPC, simply use IPC::inst() to get the singleton instance.
|
||||||
|
/// Do not create multiple instances.
|
||||||
class IPC {
|
class IPC {
|
||||||
|
protected:
|
||||||
|
IPC(); // use IPC::inst() instead.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IPC();
|
|
||||||
~IPC();
|
~IPC();
|
||||||
static IPC& inst();
|
static IPC& inst();
|
||||||
|
|
||||||
@@ -42,8 +46,7 @@ class IPC {
|
|||||||
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
|
int socketfd_; // the hyprland socket file descriptor
|
||||||
bool running_ = true;
|
pid_t socketOwnerPid_;
|
||||||
|
bool running_ = true; // the ipcThread will stop running when this is false
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool modulesReady = false;
|
|
||||||
}; // namespace waybar::modules::hyprland
|
}; // namespace waybar::modules::hyprland
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "AAppIconLabel.hpp"
|
||||||
|
#include "bar.hpp"
|
||||||
|
#include "modules/hyprland/backend.hpp"
|
||||||
|
|
||||||
|
namespace waybar::modules::hyprland {
|
||||||
|
|
||||||
|
class WindowCount : public waybar::AAppIconLabel, public EventHandler {
|
||||||
|
public:
|
||||||
|
WindowCount(const std::string&, const waybar::Bar&, const Json::Value&);
|
||||||
|
~WindowCount() override;
|
||||||
|
|
||||||
|
auto update() -> void override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Workspace {
|
||||||
|
int id;
|
||||||
|
int windows;
|
||||||
|
bool hasfullscreen;
|
||||||
|
static auto parse(const Json::Value& value) -> Workspace;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto getActiveWorkspace(const std::string&) -> Workspace;
|
||||||
|
auto getActiveWorkspace() -> Workspace;
|
||||||
|
void onEvent(const std::string& ev) override;
|
||||||
|
void queryActiveWorkspace();
|
||||||
|
void setClass(const std::string&, bool enable);
|
||||||
|
|
||||||
|
bool separateOutputs_;
|
||||||
|
std::mutex mutex_;
|
||||||
|
const Bar& bar_;
|
||||||
|
Workspace workspace_;
|
||||||
|
IPC& m_ipc;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar::modules::hyprland
|
||||||
@@ -26,34 +26,48 @@ namespace waybar::modules::hyprland {
|
|||||||
|
|
||||||
class Workspaces;
|
class Workspaces;
|
||||||
|
|
||||||
|
struct WindowRepr {
|
||||||
|
std::string address;
|
||||||
|
std::string window_class;
|
||||||
|
std::string window_title;
|
||||||
|
std::string repr_rewrite;
|
||||||
|
bool isActive = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool empty() const { return address.empty(); }
|
||||||
|
void setActive(bool value) { isActive = value; }
|
||||||
|
};
|
||||||
|
|
||||||
class WindowCreationPayload {
|
class WindowCreationPayload {
|
||||||
public:
|
public:
|
||||||
WindowCreationPayload(std::string workspace_name, WindowAddress window_address,
|
WindowCreationPayload(std::string workspace_name, WindowAddress window_address,
|
||||||
std::string window_repr);
|
WindowRepr window_repr);
|
||||||
WindowCreationPayload(std::string workspace_name, WindowAddress window_address,
|
WindowCreationPayload(std::string workspace_name, WindowAddress window_address,
|
||||||
std::string window_class, std::string window_title);
|
std::string window_class, std::string window_title, bool is_active);
|
||||||
WindowCreationPayload(Json::Value const& client_data);
|
WindowCreationPayload(Json::Value const& client_data);
|
||||||
|
|
||||||
int incrementTimeSpentUncreated();
|
int incrementTimeSpentUncreated();
|
||||||
bool isEmpty(Workspaces& workspace_manager);
|
bool isEmpty(Workspaces& workspace_manager);
|
||||||
bool reprIsReady() const { return std::holds_alternative<Repr>(m_window); }
|
bool reprIsReady() const { return std::holds_alternative<Repr>(m_window); }
|
||||||
std::string repr(Workspaces& workspace_manager);
|
WindowRepr repr(Workspaces& workspace_manager);
|
||||||
|
void setActive(bool value) { m_isActive = value; }
|
||||||
|
|
||||||
std::string getWorkspaceName() const { return m_workspaceName; }
|
std::string getWorkspaceName() const { return m_workspaceName; }
|
||||||
WindowAddress getAddress() const { return m_windowAddress; }
|
WindowAddress getAddress() const { return m_windowAddress; }
|
||||||
|
|
||||||
void moveToWorksace(std::string& new_workspace_name);
|
void moveToWorkspace(std::string& new_workspace_name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void clearAddr();
|
void clearAddr();
|
||||||
void clearWorkspaceName();
|
void clearWorkspaceName();
|
||||||
|
|
||||||
using Repr = std::string;
|
using Repr = WindowRepr;
|
||||||
using ClassAndTitle = std::pair<std::string, std::string>;
|
using ClassAndTitle = std::pair<std::string, std::string>;
|
||||||
std::variant<Repr, ClassAndTitle> m_window;
|
std::variant<Repr, ClassAndTitle> m_window;
|
||||||
|
|
||||||
WindowAddress m_windowAddress;
|
WindowAddress m_windowAddress;
|
||||||
std::string m_workspaceName;
|
std::string m_workspaceName;
|
||||||
|
bool m_isActive = false;
|
||||||
|
|
||||||
int m_timeSpentUncreated = 0;
|
int m_timeSpentUncreated = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ class Workspace {
|
|||||||
bool isPersistentConfig() const { return m_isPersistentConfig; };
|
bool isPersistentConfig() const { return m_isPersistentConfig; };
|
||||||
bool isPersistentRule() const { return m_isPersistentRule; };
|
bool isPersistentRule() const { return m_isPersistentRule; };
|
||||||
bool isVisible() const { return m_isVisible; };
|
bool isVisible() const { return m_isVisible; };
|
||||||
bool isEmpty() const { return m_windows == 0; };
|
|
||||||
bool isUrgent() const { return m_isUrgent; };
|
bool isUrgent() const { return m_isUrgent; };
|
||||||
|
|
||||||
bool handleClicked(GdkEventButton* bt) const;
|
bool handleClicked(GdkEventButton* bt) const;
|
||||||
@@ -54,15 +53,18 @@ class Workspace {
|
|||||||
void setWindows(uint value) { m_windows = value; };
|
void setWindows(uint value) { m_windows = value; };
|
||||||
void setName(std::string const& value) { m_name = value; };
|
void setName(std::string const& value) { m_name = value; };
|
||||||
void setOutput(std::string const& value) { m_output = value; };
|
void setOutput(std::string const& value) { m_output = value; };
|
||||||
bool containsWindow(WindowAddress const& addr) const { return m_windowMap.contains(addr); }
|
bool containsWindow(WindowAddress const& addr) const {
|
||||||
void insertWindow(WindowCreationPayload create_window_paylod);
|
return std::ranges::any_of(m_windowMap,
|
||||||
std::string removeWindow(WindowAddress const& addr);
|
[&addr](const auto& window) { return window.address == addr; });
|
||||||
|
};
|
||||||
|
void insertWindow(WindowCreationPayload create_window_payload);
|
||||||
void initializeWindowMap(const Json::Value& clients_data);
|
void initializeWindowMap(const Json::Value& clients_data);
|
||||||
|
void setActiveWindow(WindowAddress const& addr);
|
||||||
|
|
||||||
bool onWindowOpened(WindowCreationPayload const& create_window_paylod);
|
bool onWindowOpened(WindowCreationPayload const& create_window_payload);
|
||||||
std::optional<std::string> closeWindow(WindowAddress const& addr);
|
std::optional<WindowRepr> closeWindow(WindowAddress const& addr);
|
||||||
|
|
||||||
void update(const std::string& format, const std::string& icon);
|
void update(const std::string& workspace_icon);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Workspaces& m_workspaceManager;
|
Workspaces& m_workspaceManager;
|
||||||
@@ -78,11 +80,17 @@ class Workspace {
|
|||||||
bool m_isUrgent = false;
|
bool m_isUrgent = false;
|
||||||
bool m_isVisible = false;
|
bool m_isVisible = false;
|
||||||
|
|
||||||
std::map<WindowAddress, std::string> m_windowMap;
|
std::vector<WindowRepr> m_windowMap;
|
||||||
|
|
||||||
Gtk::Button m_button;
|
Gtk::Button m_button;
|
||||||
Gtk::Box m_content;
|
Gtk::Box m_content;
|
||||||
Gtk::Label m_label;
|
Gtk::Label m_labelBefore;
|
||||||
|
Gtk::Label m_labelAfter;
|
||||||
|
|
||||||
|
bool isEmpty() const;
|
||||||
|
void updateTaskbar(const std::string& workspace_icon);
|
||||||
|
bool handleClick(const GdkEventButton* event_button, WindowAddress const& addr) const;
|
||||||
|
bool shouldSkipWindow(const WindowRepr& window_repr) const;
|
||||||
IPC& m_ipc;
|
IPC& m_ipc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <gtkmm/button.h>
|
#include <gtkmm/button.h>
|
||||||
|
#include <gtkmm/enums.h>
|
||||||
#include <gtkmm/label.h>
|
#include <gtkmm/label.h>
|
||||||
#include <json/value.h>
|
#include <json/value.h>
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@
|
|||||||
#include "modules/hyprland/windowcreationpayload.hpp"
|
#include "modules/hyprland/windowcreationpayload.hpp"
|
||||||
#include "modules/hyprland/workspace.hpp"
|
#include "modules/hyprland/workspace.hpp"
|
||||||
#include "util/enum.hpp"
|
#include "util/enum.hpp"
|
||||||
|
#include "util/icon_loader.hpp"
|
||||||
#include "util/regex_collection.hpp"
|
#include "util/regex_collection.hpp"
|
||||||
|
|
||||||
using WindowAddress = std::string;
|
using WindowAddress = std::string;
|
||||||
@@ -37,19 +39,36 @@ class Workspaces : public AModule, public EventHandler {
|
|||||||
auto showSpecial() const -> bool { return m_showSpecial; }
|
auto showSpecial() const -> bool { return m_showSpecial; }
|
||||||
auto activeOnly() const -> bool { return m_activeOnly; }
|
auto activeOnly() const -> bool { return m_activeOnly; }
|
||||||
auto specialVisibleOnly() const -> bool { return m_specialVisibleOnly; }
|
auto specialVisibleOnly() const -> bool { return m_specialVisibleOnly; }
|
||||||
|
auto persistentOnly() const -> bool { return m_persistentOnly; }
|
||||||
auto moveToMonitor() const -> bool { return m_moveToMonitor; }
|
auto moveToMonitor() const -> bool { return m_moveToMonitor; }
|
||||||
|
auto enableTaskbar() const -> bool { return m_enableTaskbar; }
|
||||||
|
auto taskbarWithIcon() const -> bool { return m_taskbarWithIcon; }
|
||||||
|
|
||||||
auto getBarOutput() const -> std::string { return m_bar.output->name; }
|
auto getBarOutput() const -> std::string { return m_bar.output->name; }
|
||||||
|
auto formatBefore() const -> std::string { return m_formatBefore; }
|
||||||
|
auto formatAfter() const -> std::string { return m_formatAfter; }
|
||||||
|
auto taskbarFormatBefore() const -> std::string { return m_taskbarFormatBefore; }
|
||||||
|
auto taskbarFormatAfter() const -> std::string { return m_taskbarFormatAfter; }
|
||||||
|
auto taskbarIconSize() const -> int { return m_taskbarIconSize; }
|
||||||
|
auto taskbarOrientation() const -> Gtk::Orientation { return m_taskbarOrientation; }
|
||||||
|
auto taskbarReverseDirection() const -> bool { return m_taskbarReverseDirection; }
|
||||||
|
auto onClickWindow() const -> std::string { return m_onClickWindow; }
|
||||||
|
auto getIgnoredWindows() const -> std::vector<std::regex> { return m_ignoreWindows; }
|
||||||
|
|
||||||
|
enum class ActiveWindowPosition { NONE, FIRST, LAST };
|
||||||
|
auto activeWindowPosition() const -> ActiveWindowPosition { return m_activeWindowPosition; }
|
||||||
|
|
||||||
std::string getRewrite(std::string window_class, std::string window_title);
|
std::string getRewrite(std::string window_class, std::string window_title);
|
||||||
std::string& getWindowSeparator() { return m_formatWindowSeparator; }
|
std::string& getWindowSeparator() { return m_formatWindowSeparator; }
|
||||||
bool isWorkspaceIgnored(std::string const& workspace_name);
|
bool isWorkspaceIgnored(std::string const& workspace_name);
|
||||||
|
|
||||||
bool windowRewriteConfigUsesTitle() const { return m_anyWindowRewriteRuleUsesTitle; }
|
bool windowRewriteConfigUsesTitle() const { return m_anyWindowRewriteRuleUsesTitle; }
|
||||||
|
const IconLoader& iconLoader() const { return m_iconLoader; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onEvent(const std::string& e) override;
|
void onEvent(const std::string& e) override;
|
||||||
void updateWindowCount();
|
void updateWindowCount();
|
||||||
|
void sortSpecialCentered();
|
||||||
void sortWorkspaces();
|
void sortWorkspaces();
|
||||||
void createWorkspace(Json::Value const& workspace_data,
|
void createWorkspace(Json::Value const& workspace_data,
|
||||||
Json::Value const& clients_data = Json::Value::nullRef);
|
Json::Value const& clients_data = Json::Value::nullRef);
|
||||||
@@ -68,6 +87,7 @@ class Workspaces : public AModule, public EventHandler {
|
|||||||
auto populateIgnoreWorkspacesConfig(const Json::Value& config) -> void;
|
auto populateIgnoreWorkspacesConfig(const Json::Value& config) -> void;
|
||||||
auto populateFormatWindowSeparatorConfig(const Json::Value& config) -> void;
|
auto populateFormatWindowSeparatorConfig(const Json::Value& config) -> void;
|
||||||
auto populateWindowRewriteConfig(const Json::Value& config) -> void;
|
auto populateWindowRewriteConfig(const Json::Value& config) -> void;
|
||||||
|
auto populateWorkspaceTaskbarConfig(const Json::Value& config) -> void;
|
||||||
|
|
||||||
void registerIpc();
|
void registerIpc();
|
||||||
|
|
||||||
@@ -90,6 +110,7 @@ class Workspaces : public AModule, public EventHandler {
|
|||||||
void onWindowMoved(std::string const& payload);
|
void onWindowMoved(std::string const& payload);
|
||||||
|
|
||||||
void onWindowTitleEvent(std::string const& payload);
|
void onWindowTitleEvent(std::string const& payload);
|
||||||
|
void onActiveWindowChanged(WindowAddress const& payload);
|
||||||
|
|
||||||
void onConfigReloaded();
|
void onConfigReloaded();
|
||||||
|
|
||||||
@@ -122,23 +143,26 @@ class Workspaces : public AModule, public EventHandler {
|
|||||||
bool m_showSpecial = false;
|
bool m_showSpecial = false;
|
||||||
bool m_activeOnly = false;
|
bool m_activeOnly = false;
|
||||||
bool m_specialVisibleOnly = false;
|
bool m_specialVisibleOnly = false;
|
||||||
|
bool m_persistentOnly = false;
|
||||||
bool m_moveToMonitor = false;
|
bool m_moveToMonitor = false;
|
||||||
Json::Value m_persistentWorkspaceConfig;
|
Json::Value m_persistentWorkspaceConfig;
|
||||||
|
|
||||||
// Map for windows stored in workspaces not present in the current bar.
|
// Map for windows stored in workspaces not present in the current bar.
|
||||||
// This happens when the user has multiple monitors (hence, multiple bars)
|
// This happens when the user has multiple monitors (hence, multiple bars)
|
||||||
// and doesn't share windows accross bars (a.k.a `all-outputs` = false)
|
// and doesn't share windows across bars (a.k.a `all-outputs` = false)
|
||||||
std::map<WindowAddress, std::string> m_orphanWindowMap;
|
std::map<WindowAddress, WindowRepr, std::less<>> m_orphanWindowMap;
|
||||||
|
|
||||||
enum class SortMethod { ID, NAME, NUMBER, DEFAULT };
|
enum class SortMethod { ID, NAME, NUMBER, SPECIAL_CENTERED, DEFAULT };
|
||||||
util::EnumParser<SortMethod> m_enumParser;
|
util::EnumParser<SortMethod> m_enumParser;
|
||||||
SortMethod m_sortBy = SortMethod::DEFAULT;
|
SortMethod m_sortBy = SortMethod::DEFAULT;
|
||||||
std::map<std::string, SortMethod> m_sortMap = {{"ID", SortMethod::ID},
|
std::map<std::string, SortMethod> m_sortMap = {{"ID", SortMethod::ID},
|
||||||
{"NAME", SortMethod::NAME},
|
{"NAME", SortMethod::NAME},
|
||||||
{"NUMBER", SortMethod::NUMBER},
|
{"NUMBER", SortMethod::NUMBER},
|
||||||
|
{"SPECIAL-CENTERED", SortMethod::SPECIAL_CENTERED},
|
||||||
{"DEFAULT", SortMethod::DEFAULT}};
|
{"DEFAULT", SortMethod::DEFAULT}};
|
||||||
|
|
||||||
std::string m_format;
|
std::string m_formatBefore;
|
||||||
|
std::string m_formatAfter;
|
||||||
|
|
||||||
std::map<std::string, std::string> m_iconsMap;
|
std::map<std::string, std::string> m_iconsMap;
|
||||||
util::RegexCollection m_windowRewriteRules;
|
util::RegexCollection m_windowRewriteRules;
|
||||||
@@ -154,7 +178,28 @@ class Workspaces : public AModule, public EventHandler {
|
|||||||
std::vector<std::string> m_workspacesToRemove;
|
std::vector<std::string> m_workspacesToRemove;
|
||||||
std::vector<WindowCreationPayload> m_windowsToCreate;
|
std::vector<WindowCreationPayload> m_windowsToCreate;
|
||||||
|
|
||||||
|
IconLoader m_iconLoader;
|
||||||
|
bool m_enableTaskbar = false;
|
||||||
|
bool m_updateActiveWindow = false;
|
||||||
|
bool m_taskbarWithIcon = false;
|
||||||
|
bool m_taskbarWithTitle = false;
|
||||||
|
std::string m_taskbarFormatBefore;
|
||||||
|
std::string m_taskbarFormatAfter;
|
||||||
|
int m_taskbarIconSize = 16;
|
||||||
|
Gtk::Orientation m_taskbarOrientation = Gtk::ORIENTATION_HORIZONTAL;
|
||||||
|
bool m_taskbarReverseDirection = false;
|
||||||
|
util::EnumParser<ActiveWindowPosition> m_activeWindowEnumParser;
|
||||||
|
ActiveWindowPosition m_activeWindowPosition = ActiveWindowPosition::NONE;
|
||||||
|
std::map<std::string, ActiveWindowPosition> m_activeWindowPositionMap = {
|
||||||
|
{"NONE", ActiveWindowPosition::NONE},
|
||||||
|
{"FIRST", ActiveWindowPosition::FIRST},
|
||||||
|
{"LAST", ActiveWindowPosition::LAST},
|
||||||
|
};
|
||||||
|
std::string m_onClickWindow;
|
||||||
|
std::string m_currentActiveWindowAddress;
|
||||||
|
|
||||||
std::vector<std::regex> m_ignoreWorkspaces;
|
std::vector<std::regex> m_ignoreWorkspaces;
|
||||||
|
std::vector<std::regex> m_ignoreWindows;
|
||||||
|
|
||||||
std::mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
const Bar& m_bar;
|
const Bar& m_bar;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class Image : public AModule {
|
|||||||
std::string path_;
|
std::string path_;
|
||||||
std::string tooltip_;
|
std::string tooltip_;
|
||||||
int size_;
|
int size_;
|
||||||
int interval_;
|
std::chrono::milliseconds interval_;
|
||||||
util::command::res output_;
|
util::command::res output_;
|
||||||
|
|
||||||
util::SleeperThread thread_;
|
util::SleeperThread thread_;
|
||||||
|
|||||||
+25
-24
@@ -9,6 +9,7 @@
|
|||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "ALabel.hpp"
|
#include "ALabel.hpp"
|
||||||
#include "util/sleeper_thread.hpp"
|
#include "util/sleeper_thread.hpp"
|
||||||
@@ -27,8 +28,8 @@ class Network : public ALabel {
|
|||||||
auto update() -> void override;
|
auto update() -> void override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const uint8_t MAX_RETRY = 5;
|
static const uint8_t MAX_RETRY{5};
|
||||||
static const uint8_t EPOLL_MAX = 200;
|
static const uint8_t EPOLL_MAX{200};
|
||||||
|
|
||||||
static int handleEvents(struct nl_msg*, void*);
|
static int handleEvents(struct nl_msg*, void*);
|
||||||
static int handleEventsDone(struct nl_msg*, void*);
|
static int handleEventsDone(struct nl_msg*, void*);
|
||||||
@@ -44,44 +45,44 @@ class Network : public ALabel {
|
|||||||
void parseFreq(struct nlattr**);
|
void parseFreq(struct nlattr**);
|
||||||
void parseBssid(struct nlattr**);
|
void parseBssid(struct nlattr**);
|
||||||
bool associatedOrJoined(struct nlattr**);
|
bool associatedOrJoined(struct nlattr**);
|
||||||
bool checkInterface(std::string name);
|
bool matchInterface(const std::string& ifname, const std::vector<std::string>& altnames,
|
||||||
|
std::string& matched) const;
|
||||||
auto getInfo() -> void;
|
auto getInfo() -> void;
|
||||||
const std::string getNetworkState() const;
|
const std::string getNetworkState() const;
|
||||||
void clearIface();
|
void clearIface();
|
||||||
bool wildcardMatch(const std::string& pattern, const std::string& text) const;
|
|
||||||
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_{-1};
|
||||||
ip_addr_pref addr_pref_;
|
ip_addr_pref addr_pref_{ip_addr_pref::IPV4};
|
||||||
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};
|
||||||
int efd_;
|
int efd_{-1};
|
||||||
int ev_fd_;
|
int ev_fd_{-1};
|
||||||
int nl80211_id_;
|
int nl80211_id_{-1};
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
|
|
||||||
bool want_route_dump_;
|
bool want_route_dump_{false};
|
||||||
bool want_link_dump_;
|
bool want_link_dump_{false};
|
||||||
bool want_addr_dump_;
|
bool want_addr_dump_{false};
|
||||||
bool dump_in_progress_;
|
bool dump_in_progress_{false};
|
||||||
bool is_p2p_;
|
bool is_p2p_{false};
|
||||||
|
|
||||||
unsigned long long bandwidth_down_total_;
|
unsigned long long bandwidth_down_total_{0};
|
||||||
unsigned long long bandwidth_up_total_;
|
unsigned long long bandwidth_up_total_{0};
|
||||||
|
|
||||||
std::string state_;
|
std::string state_;
|
||||||
std::string essid_;
|
std::string essid_;
|
||||||
std::string bssid_;
|
std::string bssid_;
|
||||||
bool carrier_;
|
bool carrier_{false};
|
||||||
std::string ifname_;
|
std::string ifname_;
|
||||||
std::string ipaddr_;
|
std::string ipaddr_;
|
||||||
std::string ipaddr6_;
|
std::string ipaddr6_;
|
||||||
std::string gwaddr_;
|
std::string gwaddr_;
|
||||||
std::string netmask_;
|
std::string netmask_;
|
||||||
std::string netmask6_;
|
std::string netmask6_;
|
||||||
int cidr_;
|
int cidr_{0};
|
||||||
int cidr6_;
|
int cidr6_{0};
|
||||||
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_;
|
||||||
@@ -90,9 +91,9 @@ class Network : public ALabel {
|
|||||||
util::SleeperThread thread_;
|
util::SleeperThread thread_;
|
||||||
util::SleeperThread thread_timer_;
|
util::SleeperThread thread_timer_;
|
||||||
#ifdef WANT_RFKILL
|
#ifdef WANT_RFKILL
|
||||||
util::Rfkill rfkill_;
|
util::Rfkill rfkill_{RFKILL_TYPE_WLAN};
|
||||||
#endif
|
#endif
|
||||||
float frequency_;
|
float frequency_{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar::modules
|
} // namespace waybar::modules
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ class Language : public ALabel, public EventHandler {
|
|||||||
|
|
||||||
std::vector<Layout> layouts_;
|
std::vector<Layout> layouts_;
|
||||||
unsigned current_idx_;
|
unsigned current_idx_;
|
||||||
|
std::string last_short_name_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar::modules::niri
|
} // namespace waybar::modules::niri
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ class Privacy : public AModule {
|
|||||||
uint iconSpacing = 4;
|
uint iconSpacing = 4;
|
||||||
uint iconSize = 20;
|
uint iconSize = 20;
|
||||||
uint transition_duration = 250;
|
uint transition_duration = 250;
|
||||||
|
std::set<std::pair<PrivacyNodeType, std::string>> ignore;
|
||||||
|
bool ignore_monitor = true;
|
||||||
|
|
||||||
std::shared_ptr<util::PipewireBackend::PipewireBackend> backend = nullptr;
|
std::shared_ptr<util::PipewireBackend::PipewireBackend> backend = nullptr;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ class Layout : public waybar::ALabel {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
const waybar::Bar &bar_;
|
const waybar::Bar &bar_;
|
||||||
|
std::string name_;
|
||||||
struct wl_output *output_; // stores the output this module belongs to
|
struct wl_output *output_; // stores the output this module belongs to
|
||||||
struct wl_output *focused_output_; // stores the currently focused output
|
struct wl_output *focused_output_; // stores the currently focused output
|
||||||
struct zriver_output_status_v1 *output_status_;
|
struct zriver_output_status_v1 *output_status_;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ class Tags : public waybar::AModule {
|
|||||||
void handle_view_tags(struct wl_array *tags);
|
void handle_view_tags(struct wl_array *tags);
|
||||||
void handle_urgent_tags(uint32_t tags);
|
void handle_urgent_tags(uint32_t tags);
|
||||||
|
|
||||||
|
void handle_show();
|
||||||
void handle_primary_clicked(uint32_t tag);
|
void handle_primary_clicked(uint32_t tag);
|
||||||
bool handle_button_press(GdkEventButton *event_button, uint32_t tag);
|
bool handle_button_press(GdkEventButton *event_button, uint32_t tag);
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ struct ToolTip {
|
|||||||
class Item : public sigc::trackable {
|
class Item : public sigc::trackable {
|
||||||
public:
|
public:
|
||||||
Item(const std::string&, const std::string&, const Json::Value&, const Bar&);
|
Item(const std::string&, const std::string&, const Json::Value&, const Bar&);
|
||||||
~Item() = default;
|
~Item();
|
||||||
|
|
||||||
std::string bus_name;
|
std::string bus_name;
|
||||||
std::string object_path;
|
std::string object_path;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ class Tray : public AModule {
|
|||||||
void onRemove(std::unique_ptr<Item>& item);
|
void onRemove(std::unique_ptr<Item>& item);
|
||||||
|
|
||||||
static inline std::size_t nb_hosts_ = 0;
|
static inline std::size_t nb_hosts_ = 0;
|
||||||
|
bool show_passive_ = false;
|
||||||
Gtk::Box box_;
|
Gtk::Box box_;
|
||||||
SNI::Watcher::singleton watcher_;
|
SNI::Watcher::singleton watcher_;
|
||||||
SNI::Host host_;
|
SNI::Host host_;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class Language : public ALabel, public sigc::trackable {
|
|||||||
auto update() -> void override;
|
auto update() -> void override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class DispayedShortFlag { None = 0, ShortName = 1, ShortDescription = 1 << 1 };
|
enum class DisplayedShortFlag { None = 0, ShortName = 1, ShortDescription = 1 << 1 };
|
||||||
|
|
||||||
struct Layout {
|
struct Layout {
|
||||||
std::string full_name;
|
std::string full_name;
|
||||||
@@ -58,7 +58,7 @@ class Language : public ALabel, public sigc::trackable {
|
|||||||
std::map<std::string, Layout> layouts_map_;
|
std::map<std::string, Layout> layouts_map_;
|
||||||
bool hide_single_;
|
bool hide_single_;
|
||||||
bool is_variant_displayed;
|
bool is_variant_displayed;
|
||||||
std::byte displayed_short_flag = static_cast<std::byte>(DispayedShortFlag::None);
|
std::byte displayed_short_flag = static_cast<std::byte>(DisplayedShortFlag::None);
|
||||||
|
|
||||||
util::JsonParser parser_;
|
util::JsonParser parser_;
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
|
|||||||
@@ -19,10 +19,11 @@ class Window : public AAppIconLabel, public sigc::trackable {
|
|||||||
auto update() -> void override;
|
auto update() -> void override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setClass(std::string classname, bool enable);
|
void setClass(const std::string& classname, bool enable);
|
||||||
void onEvent(const struct Ipc::ipc_response&);
|
void onEvent(const struct Ipc::ipc_response&);
|
||||||
void onCmd(const struct Ipc::ipc_response&);
|
void onCmd(const struct Ipc::ipc_response&);
|
||||||
std::tuple<std::size_t, int, int, std::string, std::string, std::string, std::string, std::string>
|
std::tuple<std::size_t, int, int, std::string, std::string, std::string, std::string, std::string,
|
||||||
|
std::string>
|
||||||
getFocusedNode(const Json::Value& nodes, std::string& output);
|
getFocusedNode(const Json::Value& nodes, std::string& output);
|
||||||
void getTree();
|
void getTree();
|
||||||
|
|
||||||
@@ -35,6 +36,7 @@ class Window : public AAppIconLabel, public sigc::trackable {
|
|||||||
std::string old_app_id_;
|
std::string old_app_id_;
|
||||||
std::size_t app_nb_;
|
std::size_t app_nb_;
|
||||||
std::string shell_;
|
std::string shell_;
|
||||||
|
std::string marks_;
|
||||||
int floating_count_;
|
int floating_count_;
|
||||||
util::JsonParser parser_;
|
util::JsonParser parser_;
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class Workspaces : public AModule, public sigc::trackable {
|
|||||||
std::vector<std::string> high_priority_named_;
|
std::vector<std::string> high_priority_named_;
|
||||||
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_formatWindowSeparator;
|
||||||
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_;
|
||||||
|
|||||||
@@ -19,12 +19,15 @@ class SystemdFailedUnits : public ALabel {
|
|||||||
std::string format_ok;
|
std::string format_ok;
|
||||||
|
|
||||||
bool update_pending;
|
bool update_pending;
|
||||||
uint32_t nr_failed_system, nr_failed_user;
|
std::string system_state, user_state, overall_state;
|
||||||
|
uint32_t nr_failed_system, nr_failed_user, nr_failed;
|
||||||
std::string last_status;
|
std::string last_status;
|
||||||
Glib::RefPtr<Gio::DBus::Proxy> system_proxy, user_proxy;
|
Glib::RefPtr<Gio::DBus::Proxy> system_proxy, user_proxy;
|
||||||
|
|
||||||
void notify_cb(const Glib::ustring &sender_name, const Glib::ustring &signal_name,
|
void notify_cb(const Glib::ustring &sender_name, const Glib::ustring &signal_name,
|
||||||
const Glib::VariantContainerBase &arguments);
|
const Glib::VariantContainerBase &arguments);
|
||||||
|
void RequestFailedUnits();
|
||||||
|
void RequestSystemState();
|
||||||
void updateData();
|
void updateData();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,122 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <json/json.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <list>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace waybar::modules::wayfire {
|
||||||
|
|
||||||
|
using EventHandler = std::function<void(const std::string& event)>;
|
||||||
|
|
||||||
|
struct State {
|
||||||
|
/*
|
||||||
|
┌───────────┐ ┌───────────┐
|
||||||
|
│ output #1 │ │ output #2 │
|
||||||
|
└─────┬─────┘ └─────┬─────┘
|
||||||
|
└─┐ └─────┐─ ─ ─ ─ ─ ─ ─ ─ ┐
|
||||||
|
┌───────┴───────┐ ┌───────┴──────┐ ┌───────┴───────┐
|
||||||
|
│ wset #1 │ │ wset #2 │ │ wset #3 │
|
||||||
|
│┌────────────┐ │ │┌────────────┐│ │┌────────────┐ │
|
||||||
|
││ workspaces │ │ ││ workspaces ││ ││ workspaces │ │
|
||||||
|
│└─┬──────────┘ │ │└────────────┘│ │└─┬──────────┘ │
|
||||||
|
│ │ ┌─────────┐│ └──────────────┘ │ │ ┌─────────┐│
|
||||||
|
│ ├─┤ view #1 ││ │ └─┤ view #3 ││
|
||||||
|
│ │ └─────────┘│ │ └─────────┘│
|
||||||
|
│ │ ┌─────────┐│ └───────────────┘
|
||||||
|
│ └─┤ view #2 ││
|
||||||
|
│ └─────────┘│
|
||||||
|
└───────────────┘
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct Output {
|
||||||
|
size_t id;
|
||||||
|
size_t w, h;
|
||||||
|
size_t wset_idx;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Workspace {
|
||||||
|
size_t num_views;
|
||||||
|
size_t num_sticky_views;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Wset {
|
||||||
|
std::optional<std::reference_wrapper<Output>> output;
|
||||||
|
std::vector<Workspace> wss;
|
||||||
|
size_t ws_w, ws_h, ws_x, ws_y;
|
||||||
|
size_t focused_view_id;
|
||||||
|
|
||||||
|
auto ws_idx() const { return ws_w * ws_y + ws_x; }
|
||||||
|
auto count_ws(const Json::Value& pos) -> Workspace&;
|
||||||
|
auto locate_ws(const Json::Value& geo) -> Workspace&;
|
||||||
|
auto locate_ws(const Json::Value& geo) const -> const Workspace&;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unordered_map<std::string, Output> outputs;
|
||||||
|
std::unordered_map<size_t, Wset> wsets;
|
||||||
|
std::unordered_map<size_t, Json::Value> views;
|
||||||
|
std::string focused_output_name;
|
||||||
|
size_t maybe_empty_focus_wset_idx = {};
|
||||||
|
size_t vswitch_sticky_view_id = {};
|
||||||
|
bool new_output_detected = {};
|
||||||
|
bool vswitching = {};
|
||||||
|
|
||||||
|
auto update_view(const Json::Value& view) -> void;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Sock {
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
Sock(int fd) : fd{fd} {}
|
||||||
|
~Sock() { close(fd); }
|
||||||
|
Sock(const Sock&) = delete;
|
||||||
|
auto operator=(const Sock&) = delete;
|
||||||
|
Sock(Sock&& rhs) noexcept {
|
||||||
|
fd = rhs.fd;
|
||||||
|
rhs.fd = -1;
|
||||||
|
}
|
||||||
|
auto& operator=(Sock&& rhs) noexcept {
|
||||||
|
fd = rhs.fd;
|
||||||
|
rhs.fd = -1;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class IPC {
|
||||||
|
static std::weak_ptr<IPC> instance;
|
||||||
|
Json::CharReaderBuilder reader_builder;
|
||||||
|
Json::StreamWriterBuilder writer_builder;
|
||||||
|
std::list<std::pair<std::string, std::reference_wrapper<const EventHandler>>> handlers;
|
||||||
|
std::mutex handlers_mutex;
|
||||||
|
State state;
|
||||||
|
std::mutex state_mutex;
|
||||||
|
|
||||||
|
IPC() { start(); }
|
||||||
|
|
||||||
|
static auto connect() -> Sock;
|
||||||
|
auto receive(Sock& sock) -> Json::Value;
|
||||||
|
auto start() -> void;
|
||||||
|
auto root_event_handler(const std::string& event, const Json::Value& data) -> void;
|
||||||
|
auto update_state_handler(const std::string& event, const Json::Value& data) -> void;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static auto get_instance() -> std::shared_ptr<IPC>;
|
||||||
|
auto send(const std::string& method, Json::Value&& data) -> Json::Value;
|
||||||
|
auto register_handler(const std::string& event, const EventHandler& handler) -> void;
|
||||||
|
auto unregister_handler(EventHandler& handler) -> void;
|
||||||
|
|
||||||
|
auto lock_state() -> std::lock_guard<std::mutex> { return std::lock_guard{state_mutex}; }
|
||||||
|
auto& get_outputs() const { return state.outputs; }
|
||||||
|
auto& get_wsets() const { return state.wsets; }
|
||||||
|
auto& get_views() const { return state.views; }
|
||||||
|
auto& get_focused_output_name() const { return state.focused_output_name; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar::modules::wayfire
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "AAppIconLabel.hpp"
|
||||||
|
#include "bar.hpp"
|
||||||
|
#include "modules/wayfire/backend.hpp"
|
||||||
|
|
||||||
|
namespace waybar::modules::wayfire {
|
||||||
|
|
||||||
|
class Window : public AAppIconLabel {
|
||||||
|
std::shared_ptr<IPC> ipc;
|
||||||
|
EventHandler handler;
|
||||||
|
|
||||||
|
const Bar& bar_;
|
||||||
|
std::string old_app_id_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Window(const std::string& id, const Bar& bar, const Json::Value& config);
|
||||||
|
~Window() override;
|
||||||
|
|
||||||
|
auto update() -> void override;
|
||||||
|
auto update_icon_label() -> void;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar::modules::wayfire
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gtkmm/button.h>
|
||||||
|
#include <json/json.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "AModule.hpp"
|
||||||
|
#include "bar.hpp"
|
||||||
|
#include "modules/wayfire/backend.hpp"
|
||||||
|
|
||||||
|
namespace waybar::modules::wayfire {
|
||||||
|
|
||||||
|
class Workspaces : public AModule {
|
||||||
|
std::shared_ptr<IPC> ipc;
|
||||||
|
EventHandler handler;
|
||||||
|
|
||||||
|
const Bar& bar_;
|
||||||
|
Gtk::Box box_;
|
||||||
|
std::vector<Gtk::Button> buttons_;
|
||||||
|
|
||||||
|
auto handleScroll(GdkEventScroll* e) -> bool override;
|
||||||
|
auto update() -> void override;
|
||||||
|
auto update_box() -> void;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Workspaces(const std::string& id, const Bar& bar, const Json::Value& config);
|
||||||
|
~Workspaces() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar::modules::wayfire
|
||||||
@@ -22,6 +22,8 @@ class Wireplumber : public ALabel {
|
|||||||
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);
|
||||||
|
static void updateSourceVolume(waybar::modules::Wireplumber* self, uint32_t id);
|
||||||
|
static void updateSourceName(waybar::modules::Wireplumber* self, uint32_t id); // NEW
|
||||||
static void onPluginActivated(WpObject* p, GAsyncResult* res, waybar::modules::Wireplumber* self);
|
static void onPluginActivated(WpObject* p, GAsyncResult* res, waybar::modules::Wireplumber* self);
|
||||||
static void onDefaultNodesApiLoaded(WpObject* p, GAsyncResult* res,
|
static void onDefaultNodesApiLoaded(WpObject* p, GAsyncResult* res,
|
||||||
waybar::modules::Wireplumber* self);
|
waybar::modules::Wireplumber* self);
|
||||||
@@ -46,7 +48,12 @@ 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_;
|
||||||
|
std::string source_name_;
|
||||||
gchar* type_;
|
gchar* type_;
|
||||||
|
uint32_t source_node_id_;
|
||||||
|
bool source_muted_;
|
||||||
|
double source_volume_;
|
||||||
|
gchar* default_source_name_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar::modules
|
} // namespace waybar::modules
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "bar.hpp"
|
#include "bar.hpp"
|
||||||
#include "client.hpp"
|
#include "client.hpp"
|
||||||
#include "giomm/desktopappinfo.h"
|
#include "giomm/desktopappinfo.h"
|
||||||
|
#include "util/icon_loader.hpp"
|
||||||
#include "util/json.hpp"
|
#include "util/json.hpp"
|
||||||
#include "wlr-foreign-toplevel-management-unstable-v1-client-protocol.h"
|
#include "wlr-foreign-toplevel-management-unstable-v1-client-protocol.h"
|
||||||
|
|
||||||
@@ -89,9 +90,6 @@ class Task {
|
|||||||
std::string state_string(bool = false) const;
|
std::string state_string(bool = false) const;
|
||||||
void set_minimize_hint();
|
void set_minimize_hint();
|
||||||
void on_button_size_allocated(Gtk::Allocation &alloc);
|
void on_button_size_allocated(Gtk::Allocation &alloc);
|
||||||
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,
|
|
||||||
Glib::RefPtr<Gio::DesktopAppInfo> app_info, int size);
|
|
||||||
void hide_if_ignored();
|
void hide_if_ignored();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -153,7 +151,7 @@ class Taskbar : public waybar::AModule {
|
|||||||
Gtk::Box box_;
|
Gtk::Box box_;
|
||||||
std::vector<TaskPtr> tasks_;
|
std::vector<TaskPtr> tasks_;
|
||||||
|
|
||||||
std::vector<Glib::RefPtr<Gtk::IconTheme>> icon_themes_;
|
IconLoader icon_loader_;
|
||||||
std::unordered_set<std::string> ignore_list_;
|
std::unordered_set<std::string> ignore_list_;
|
||||||
std::map<std::string, std::string> app_ids_replace_map_;
|
std::map<std::string, std::string> app_ids_replace_map_;
|
||||||
|
|
||||||
@@ -178,7 +176,7 @@ class Taskbar : public waybar::AModule {
|
|||||||
bool show_output(struct wl_output *) const;
|
bool show_output(struct wl_output *) const;
|
||||||
bool all_outputs() const;
|
bool all_outputs() const;
|
||||||
|
|
||||||
const std::vector<Glib::RefPtr<Gtk::IconTheme>> &icon_themes() const;
|
const IconLoader &icon_loader() const;
|
||||||
const std::unordered_set<std::string> &ignore_list() const;
|
const std::unordered_set<std::string> &ignore_list() const;
|
||||||
const std::map<std::string, std::string> &app_ids_replace_map() const;
|
const std::map<std::string, std::string> &app_ids_replace_map() const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,172 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <fmt/format.h>
|
|
||||||
#include <gtkmm/button.h>
|
|
||||||
#include <gtkmm/image.h>
|
|
||||||
#include <gtkmm/label.h>
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <map>
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "AModule.hpp"
|
|
||||||
#include "bar.hpp"
|
|
||||||
#include "ext-workspace-unstable-v1-client-protocol.h"
|
|
||||||
|
|
||||||
namespace waybar::modules::wlr {
|
|
||||||
|
|
||||||
class WorkspaceManager;
|
|
||||||
class WorkspaceGroup;
|
|
||||||
|
|
||||||
class Workspace {
|
|
||||||
public:
|
|
||||||
Workspace(const waybar::Bar &bar, const Json::Value &config, WorkspaceGroup &workspace_group,
|
|
||||||
zext_workspace_handle_v1 *workspace, uint32_t id, std::string name);
|
|
||||||
~Workspace();
|
|
||||||
auto update() -> void;
|
|
||||||
|
|
||||||
auto id() const -> uint32_t { return id_; }
|
|
||||||
auto is_active() const -> bool { return state_ & static_cast<uint32_t>(State::ACTIVE); }
|
|
||||||
auto is_urgent() const -> bool { return state_ & static_cast<uint32_t>(State::URGENT); }
|
|
||||||
auto is_hidden() const -> bool { return state_ & static_cast<uint32_t>(State::HIDDEN); }
|
|
||||||
auto is_empty() const -> bool { return state_ & static_cast<uint32_t>(State::EMPTY); }
|
|
||||||
auto is_persistent() const -> bool { return persistent_; }
|
|
||||||
// wlr stuff
|
|
||||||
auto handle_name(const std::string &name) -> void;
|
|
||||||
auto handle_coordinates(const std::vector<uint32_t> &coordinates) -> void;
|
|
||||||
auto handle_state(const std::vector<uint32_t> &state) -> void;
|
|
||||||
auto handle_remove() -> void;
|
|
||||||
auto make_persistent() -> void;
|
|
||||||
auto handle_duplicate() -> void;
|
|
||||||
|
|
||||||
auto handle_done() -> void;
|
|
||||||
auto handle_clicked(GdkEventButton *bt) -> bool;
|
|
||||||
auto show() -> void;
|
|
||||||
auto hide() -> void;
|
|
||||||
auto get_button_ref() -> Gtk::Button & { return button_; }
|
|
||||||
auto get_name() -> std::string & { return name_; }
|
|
||||||
auto get_coords() -> std::vector<uint32_t> & { return coordinates_; }
|
|
||||||
|
|
||||||
enum class State {
|
|
||||||
ACTIVE = (1 << 0),
|
|
||||||
URGENT = (1 << 1),
|
|
||||||
HIDDEN = (1 << 2),
|
|
||||||
EMPTY = (1 << 3),
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
auto get_icon() -> std::string;
|
|
||||||
|
|
||||||
const Bar &bar_;
|
|
||||||
const Json::Value &config_;
|
|
||||||
WorkspaceGroup &workspace_group_;
|
|
||||||
|
|
||||||
// wlr stuff
|
|
||||||
zext_workspace_handle_v1 *workspace_handle_;
|
|
||||||
uint32_t state_ = 0;
|
|
||||||
|
|
||||||
uint32_t id_;
|
|
||||||
std::string name_;
|
|
||||||
std::vector<uint32_t> coordinates_;
|
|
||||||
static std::map<std::string, std::string> icons_map_;
|
|
||||||
std::string format_;
|
|
||||||
bool with_icon_ = false;
|
|
||||||
bool persistent_ = false;
|
|
||||||
|
|
||||||
Gtk::Button button_;
|
|
||||||
Gtk::Box content_;
|
|
||||||
Gtk::Label label_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class WorkspaceGroup {
|
|
||||||
public:
|
|
||||||
WorkspaceGroup(const waybar::Bar &bar, Gtk::Box &box, const Json::Value &config,
|
|
||||||
WorkspaceManager &manager, zext_workspace_group_handle_v1 *workspace_group_handle,
|
|
||||||
uint32_t id);
|
|
||||||
~WorkspaceGroup();
|
|
||||||
auto update() -> void;
|
|
||||||
|
|
||||||
auto id() const -> uint32_t { return id_; }
|
|
||||||
auto is_visible() const -> bool;
|
|
||||||
auto remove_workspace(uint32_t id_) -> void;
|
|
||||||
auto active_only() const -> bool;
|
|
||||||
auto creation_delayed() const -> bool;
|
|
||||||
auto workspaces() -> std::vector<std::unique_ptr<Workspace>> & { return workspaces_; }
|
|
||||||
auto persistent_workspaces() -> std::vector<std::string> & { return persistent_workspaces_; }
|
|
||||||
|
|
||||||
auto sort_workspaces() -> void;
|
|
||||||
auto set_need_to_sort() -> void { need_to_sort = true; }
|
|
||||||
auto add_button(Gtk::Button &button) -> void;
|
|
||||||
auto remove_button(Gtk::Button &button) -> void;
|
|
||||||
auto fill_persistent_workspaces() -> void;
|
|
||||||
auto create_persistent_workspaces() -> void;
|
|
||||||
|
|
||||||
// wlr stuff
|
|
||||||
auto handle_workspace_create(zext_workspace_handle_v1 *workspace_handle) -> void;
|
|
||||||
auto handle_remove() -> void;
|
|
||||||
auto handle_output_enter(wl_output *output) -> void;
|
|
||||||
auto handle_output_leave() -> void;
|
|
||||||
auto handle_done() -> void;
|
|
||||||
auto commit() -> void;
|
|
||||||
|
|
||||||
private:
|
|
||||||
static uint32_t workspace_global_id;
|
|
||||||
const waybar::Bar &bar_;
|
|
||||||
Gtk::Box &box_;
|
|
||||||
const Json::Value &config_;
|
|
||||||
WorkspaceManager &workspace_manager_;
|
|
||||||
|
|
||||||
// wlr stuff
|
|
||||||
zext_workspace_group_handle_v1 *workspace_group_handle_;
|
|
||||||
wl_output *output_ = nullptr;
|
|
||||||
|
|
||||||
uint32_t id_;
|
|
||||||
std::vector<std::unique_ptr<Workspace>> workspaces_;
|
|
||||||
bool need_to_sort = false;
|
|
||||||
std::vector<std::string> persistent_workspaces_;
|
|
||||||
bool persistent_created_ = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
class WorkspaceManager : public AModule {
|
|
||||||
public:
|
|
||||||
WorkspaceManager(const std::string &id, const waybar::Bar &bar, const Json::Value &config);
|
|
||||||
~WorkspaceManager() override;
|
|
||||||
auto update() -> void override;
|
|
||||||
|
|
||||||
auto all_outputs() const -> bool { return all_outputs_; }
|
|
||||||
auto active_only() const -> bool { return active_only_; }
|
|
||||||
auto workspace_comparator() const
|
|
||||||
-> std::function<bool(std::unique_ptr<Workspace> &, std::unique_ptr<Workspace> &)>;
|
|
||||||
auto creation_delayed() const -> bool { return creation_delayed_; }
|
|
||||||
|
|
||||||
auto sort_workspaces() -> void;
|
|
||||||
auto remove_workspace_group(uint32_t id_) -> void;
|
|
||||||
|
|
||||||
// wlr stuff
|
|
||||||
auto register_manager(wl_registry *registry, uint32_t name, uint32_t version) -> void;
|
|
||||||
auto handle_workspace_group_create(zext_workspace_group_handle_v1 *workspace_group_handle)
|
|
||||||
-> void;
|
|
||||||
auto handle_done() -> void;
|
|
||||||
auto handle_finished() -> void;
|
|
||||||
auto commit() -> void;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const waybar::Bar &bar_;
|
|
||||||
Gtk::Box box_;
|
|
||||||
std::vector<std::unique_ptr<WorkspaceGroup>> groups_;
|
|
||||||
|
|
||||||
// wlr stuff
|
|
||||||
zext_workspace_manager_v1 *workspace_manager_ = nullptr;
|
|
||||||
|
|
||||||
static uint32_t group_global_id;
|
|
||||||
|
|
||||||
bool sort_by_name_ = true;
|
|
||||||
bool sort_by_coordinates_ = true;
|
|
||||||
bool sort_by_number_ = false;
|
|
||||||
bool all_outputs_ = false;
|
|
||||||
bool active_only_ = false;
|
|
||||||
bool creation_delayed_ = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace waybar::modules::wlr
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#include "ext-workspace-unstable-v1-client-protocol.h"
|
|
||||||
|
|
||||||
namespace waybar::modules::wlr {
|
|
||||||
void add_registry_listener(void *data);
|
|
||||||
void add_workspace_listener(zext_workspace_handle_v1 *workspace_handle, void *data);
|
|
||||||
void add_workspace_group_listener(zext_workspace_group_handle_v1 *workspace_group_handle,
|
|
||||||
void *data);
|
|
||||||
zext_workspace_manager_v1 *workspace_manager_bind(wl_registry *registry, uint32_t name,
|
|
||||||
uint32_t version, void *data);
|
|
||||||
} // namespace waybar::modules::wlr
|
|
||||||
@@ -11,6 +11,11 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#ifdef __OpenBSD__
|
||||||
|
#define SIGRTMIN SIGUSR1 - 1
|
||||||
|
#define SIGRTMAX SIGUSR1 + 1
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace waybar {
|
namespace waybar {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
namespace date {
|
namespace date {
|
||||||
#if HAVE_CHRONO_TIMEZONES
|
#if HAVE_CHRONO_TIMEZONES
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
using namespace std;
|
using std::format;
|
||||||
#else
|
#else
|
||||||
|
|
||||||
using system_clock = std::chrono::system_clock;
|
using system_clock = std::chrono::system_clock;
|
||||||
@@ -73,5 +73,3 @@ struct fmt::formatter<date::zoned_time<Duration, TimeZonePtr>> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace date;
|
|
||||||
|
|||||||
@@ -10,5 +10,7 @@ class DefaultGtkIconThemeWrapper {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
static bool has_icon(const std::string&);
|
static bool has_icon(const std::string&);
|
||||||
static Glib::RefPtr<Gdk::Pixbuf> load_icon(const char*, int, Gtk::IconLookupFlags);
|
static Glib::RefPtr<Gdk::Pixbuf> load_icon(
|
||||||
|
const char*, int, Gtk::IconLookupFlags,
|
||||||
|
Glib::RefPtr<Gtk::StyleContext> style = Glib::RefPtr<Gtk::StyleContext>());
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gdkmm/general.h>
|
||||||
|
#include <gio/gdesktopappinfo.h>
|
||||||
|
#include <giomm/desktopappinfo.h>
|
||||||
|
#include <glibmm/fileutils.h>
|
||||||
|
#include <gtkmm/image.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "util/gtk_icon.hpp"
|
||||||
|
|
||||||
|
class IconLoader {
|
||||||
|
private:
|
||||||
|
std::vector<Glib::RefPtr<Gtk::IconTheme>> custom_icon_themes_;
|
||||||
|
Glib::RefPtr<Gtk::IconTheme> default_icon_theme_ = Gtk::IconTheme::get_default();
|
||||||
|
static std::vector<std::string> search_prefix();
|
||||||
|
static Glib::RefPtr<Gio::DesktopAppInfo> get_app_info_by_name(const std::string &app_id);
|
||||||
|
static Glib::RefPtr<Gio::DesktopAppInfo> get_desktop_app_info(const std::string &app_id);
|
||||||
|
static Glib::RefPtr<Gdk::Pixbuf> load_icon_from_file(std::string const &icon_path, int size);
|
||||||
|
static std::string get_icon_name_from_icon_theme(const Glib::RefPtr<Gtk::IconTheme> &icon_theme,
|
||||||
|
const std::string &app_id);
|
||||||
|
static bool image_load_icon(Gtk::Image &image, const Glib::RefPtr<Gtk::IconTheme> &icon_theme,
|
||||||
|
Glib::RefPtr<Gio::DesktopAppInfo> app_info, int size);
|
||||||
|
|
||||||
|
public:
|
||||||
|
void add_custom_icon_theme(const std::string &theme_name);
|
||||||
|
bool image_load_icon(Gtk::Image &image, Glib::RefPtr<Gio::DesktopAppInfo> app_info,
|
||||||
|
int size) const;
|
||||||
|
static Glib::RefPtr<Gio::DesktopAppInfo> get_app_info_from_app_id_list(
|
||||||
|
const std::string &app_id_list);
|
||||||
|
};
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <json/value.h>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace waybar::util {
|
||||||
|
|
||||||
|
enum class KillSignalAction : std::uint8_t {
|
||||||
|
TOGGLE,
|
||||||
|
RELOAD,
|
||||||
|
SHOW,
|
||||||
|
HIDE,
|
||||||
|
NOOP,
|
||||||
|
};
|
||||||
|
const std::map<std::string, KillSignalAction> userKillSignalActions = {
|
||||||
|
{"TOGGLE", KillSignalAction::TOGGLE},
|
||||||
|
{"RELOAD", KillSignalAction::RELOAD},
|
||||||
|
{"SHOW", KillSignalAction::SHOW},
|
||||||
|
{"HIDE", KillSignalAction::HIDE},
|
||||||
|
{"NOOP", KillSignalAction::NOOP}};
|
||||||
|
|
||||||
|
const KillSignalAction SIGNALACTION_DEFAULT_SIGUSR1 = KillSignalAction::TOGGLE;
|
||||||
|
const KillSignalAction SIGNALACTION_DEFAULT_SIGUSR2 = KillSignalAction::RELOAD;
|
||||||
|
|
||||||
|
}; // namespace waybar::util
|
||||||
@@ -25,6 +25,7 @@ class PrivacyNodeInfo {
|
|||||||
std::string media_name;
|
std::string media_name;
|
||||||
std::string node_name;
|
std::string node_name;
|
||||||
std::string application_name;
|
std::string application_name;
|
||||||
|
bool is_monitor = false;
|
||||||
|
|
||||||
std::string pipewire_access_portal_app_id;
|
std::string pipewire_access_portal_app_id;
|
||||||
std::string application_icon_name;
|
std::string application_icon_name;
|
||||||
|
|||||||
@@ -6,14 +6,12 @@
|
|||||||
|
|
||||||
namespace waybar {
|
namespace waybar {
|
||||||
|
|
||||||
using namespace Gio;
|
|
||||||
|
|
||||||
enum class Appearance {
|
enum class Appearance {
|
||||||
UNKNOWN = 0,
|
UNKNOWN = 0,
|
||||||
DARK = 1,
|
DARK = 1,
|
||||||
LIGHT = 2,
|
LIGHT = 2,
|
||||||
};
|
};
|
||||||
class Portal : private DBus::Proxy {
|
class Portal : private Gio::DBus::Proxy {
|
||||||
public:
|
public:
|
||||||
Portal();
|
Portal();
|
||||||
void refreshAppearance();
|
void refreshAppearance();
|
||||||
|
|||||||
@@ -4,6 +4,6 @@
|
|||||||
|
|
||||||
namespace waybar::util {
|
namespace waybar::util {
|
||||||
|
|
||||||
// Get a signal emited with value true when entering sleep, and false when exiting
|
// Get a signal emitted with value true when entering sleep, and false when exiting
|
||||||
SafeSignal<bool>& prepare_for_sleep();
|
SafeSignal<bool>& prepare_for_sleep();
|
||||||
} // namespace waybar::util
|
} // namespace waybar::util
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include <sigc++/signal.h>
|
#include <sigc++/signal.h>
|
||||||
#include <sigc++/trackable.h>
|
#include <sigc++/trackable.h>
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
namespace waybar::util {
|
namespace waybar::util {
|
||||||
|
|
||||||
class Rfkill : public sigc::trackable {
|
class Rfkill : public sigc::trackable {
|
||||||
@@ -17,7 +19,7 @@ class Rfkill : public sigc::trackable {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
enum rfkill_type rfkill_type_;
|
enum rfkill_type rfkill_type_;
|
||||||
bool state_ = false;
|
std::atomic_bool state_ = false;
|
||||||
int fd_ = -1;
|
int fd_ = -1;
|
||||||
|
|
||||||
bool on_event(Glib::IOCondition cond);
|
bool on_event(Glib::IOCondition cond);
|
||||||
|
|||||||
@@ -23,3 +23,26 @@ inline std::string capitalize(const std::string& str) {
|
|||||||
[](unsigned char c) { return std::toupper(c); });
|
[](unsigned char c) { return std::toupper(c); });
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline std::string toLower(const std::string& str) {
|
||||||
|
std::string result = str;
|
||||||
|
std::transform(result.begin(), result.end(), result.begin(),
|
||||||
|
[](unsigned char c) { return std::tolower(c); });
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::vector<std::string> split(std::string_view s, std::string_view delimiter,
|
||||||
|
int max_splits = -1) {
|
||||||
|
std::vector<std::string> result;
|
||||||
|
size_t pos = 0;
|
||||||
|
size_t next_pos = 0;
|
||||||
|
while ((next_pos = s.find(delimiter, pos)) != std::string::npos) {
|
||||||
|
result.push_back(std::string(s.substr(pos, next_pos - pos)));
|
||||||
|
pos = next_pos + delimiter.size();
|
||||||
|
if (max_splits > 0 && result.size() == static_cast<size_t>(max_splits)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.push_back(std::string(s.substr(pos)));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ The *battery* module displays the current capacity and state (eg. charging) of y
|
|||||||
*menu-file*: ++
|
*menu-file*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
Location of the menu descriptor file. There need to be an element of type
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
GtkMenu with id *menu*
|
GtkMenu with id *menu*.
|
||||||
|
|
||||||
*menu-actions*: ++
|
*menu-actions*: ++
|
||||||
typeof: array ++
|
typeof: array ++
|
||||||
@@ -127,6 +127,10 @@ The *battery* module displays the current capacity and state (eg. charging) of y
|
|||||||
default: false ++
|
default: false ++
|
||||||
Enables this module to consume all left over space dynamically.
|
Enables this module to consume all left over space dynamically.
|
||||||
|
|
||||||
|
*events*: ++
|
||||||
|
typeof: object ++
|
||||||
|
Specifies commands to be executed on specific battery states. See *EVENTS* section below.
|
||||||
|
|
||||||
# FORMAT REPLACEMENTS
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
*{capacity}*: Capacity in percentage
|
*{capacity}*: Capacity in percentage
|
||||||
@@ -166,6 +170,19 @@ The *battery* module allows one to define custom formats based on up to two fact
|
|||||||
- The state can be addressed as a CSS class in the *style.css*. The name of the CSS class is the *<name>* of the state. Each class gets activated when the current capacity is equal to or below the configured *<value>*.
|
- The state can be addressed as a CSS class in the *style.css*. The name of the CSS class is the *<name>* of the state. Each class gets activated when the current capacity is equal to or below the configured *<value>*.
|
||||||
- Also each state can have its own *format*. Those can be configured via *format-<name>*. Or if you want to differentiate a bit more even as *format-<status>-<state>*. For more information see *custom-formats*.
|
- Also each state can have its own *format*. Those can be configured via *format-<name>*. Or if you want to differentiate a bit more even as *format-<status>-<state>*. For more information see *custom-formats*.
|
||||||
|
|
||||||
|
# EVENTS
|
||||||
|
|
||||||
|
Every entry in the *events* object consists of a *<event-name>* (typeof: *string*) and a *<command>* (typeof: *string*). ++
|
||||||
|
*<event-name>* can be in one of the following formats:
|
||||||
|
|
||||||
|
- *on-<status>-<state>*
|
||||||
|
- *on-<status>-<capacity>*
|
||||||
|
|
||||||
|
Where:
|
||||||
|
|
||||||
|
- *<status>* is either *charging* or *discharging*,
|
||||||
|
- *<state>* is the name of one of the states specified in the *states* object,
|
||||||
|
- *<capacity>* is a battery level value (between *0-100*).
|
||||||
|
|
||||||
|
|
||||||
# EXAMPLES
|
# EXAMPLES
|
||||||
@@ -178,6 +195,11 @@ The *battery* module allows one to define custom formats based on up to two fact
|
|||||||
"warning": 30,
|
"warning": 30,
|
||||||
"critical": 15
|
"critical": 15
|
||||||
},
|
},
|
||||||
|
"events": {
|
||||||
|
"on-discharging-warning": "notify-send -u normal 'Low Battery'",
|
||||||
|
"on-discharging-critical": "notify-send -u critical 'Very Low Battery'",
|
||||||
|
"on-charging-100": "notify-send -u normal 'Battery Full!'"
|
||||||
|
},
|
||||||
"format": "{capacity}% {icon}",
|
"format": "{capacity}% {icon}",
|
||||||
"format-icons": ["", "", "", "", ""],
|
"format-icons": ["", "", "", "", ""],
|
||||||
"max-length": 25
|
"max-length": 25
|
||||||
|
|||||||
@@ -39,6 +39,12 @@ $XDG_CONFIG_HOME/waybar/config ++
|
|||||||
:[ A list of timezones (as in *timezone*) to use for time display, changed using
|
:[ A list of timezones (as in *timezone*) to use for time display, changed using
|
||||||
the scroll wheel. Do not specify *timezone* option when *timezones* is specified.
|
the scroll wheel. Do not specify *timezone* option when *timezones* is specified.
|
||||||
"" represents the system's local timezone
|
"" represents the system's local timezone
|
||||||
|
|[ *timezone-tooltip-format*
|
||||||
|
:[ string
|
||||||
|
:[
|
||||||
|
:[ Format to use for displaying timezones in the tooltip. When set, this allows showing
|
||||||
|
timezone information (like timezone abbreviations) in the tooltip while keeping the
|
||||||
|
main display clean. Uses the same format options as *format*
|
||||||
|[ *locale*
|
|[ *locale*
|
||||||
:[ string
|
:[ string
|
||||||
:[
|
:[
|
||||||
@@ -126,6 +132,12 @@ View all valid format options in *strftime(3)* or have a look https://en.cpprefe
|
|||||||
:[ 1
|
:[ 1
|
||||||
:[ Value to scroll months/years forward/backward. Can be negative. Is
|
:[ Value to scroll months/years forward/backward. Can be negative. Is
|
||||||
configured under *on-scroll* option
|
configured under *on-scroll* option
|
||||||
|
|[ *iso8601*
|
||||||
|
:[ bool
|
||||||
|
:[ false
|
||||||
|
:[ When enabled, the calendar follows the ISO 8601 standard: weeks begin on
|
||||||
|
Monday, and the first week of the year is numbered 1. The default week format is
|
||||||
|
'{:%V}'.
|
||||||
|
|
||||||
3. Addressed by *clock: calendar: format*
|
3. Addressed by *clock: calendar: format*
|
||||||
[- *Option*
|
[- *Option*
|
||||||
@@ -229,6 +241,25 @@ View all valid format options in *strftime(3)* or have a look https://en.cpprefe
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
4. Show timezone in tooltip only
|
||||||
|
|
||||||
|
```
|
||||||
|
"clock": {
|
||||||
|
"interval": 60,
|
||||||
|
"format": "{:%H:%M}",
|
||||||
|
"timezone-tooltip-format": "{:%H:%M %Z}",
|
||||||
|
"timezones": [
|
||||||
|
"",
|
||||||
|
"America/Chicago",
|
||||||
|
"America/Los_Angeles",
|
||||||
|
"Europe/Paris",
|
||||||
|
"UTC"
|
||||||
|
],
|
||||||
|
"tooltip": true,
|
||||||
|
"tooltip-format": "{tz_list}"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
# STYLE
|
# STYLE
|
||||||
|
|
||||||
- *#clock*
|
- *#clock*
|
||||||
|
|||||||
@@ -11,9 +11,10 @@ The *cpu* module displays the current CPU utilization.
|
|||||||
# CONFIGURATION
|
# CONFIGURATION
|
||||||
|
|
||||||
*interval*: ++
|
*interval*: ++
|
||||||
typeof: integer ++
|
typeof: integer or float ++
|
||||||
default: 10 ++
|
default: 10 ++
|
||||||
The interval in which the information gets polled.
|
The interval in which the information gets polled. ++
|
||||||
|
Minimum value is 0.001 (1ms). Values smaller than 1ms will be set to 1ms.
|
||||||
|
|
||||||
*format*: ++
|
*format*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
|
|||||||
@@ -35,15 +35,17 @@ Addressed by *custom/<name>*
|
|||||||
See *return-type*
|
See *return-type*
|
||||||
|
|
||||||
*interval*: ++
|
*interval*: ++
|
||||||
typeof: integer ++
|
typeof: integer or float ++
|
||||||
The interval (in seconds) in which the information gets polled. ++
|
The interval (in seconds) in which the information gets polled. ++
|
||||||
|
Minimum value is 0.001 (1ms). Values smaller than 1ms will be set to 1ms. ++
|
||||||
Use *once* if you want to execute the module only on startup. ++
|
Use *once* if you want to execute the module only on startup. ++
|
||||||
You can update it manually with a signal. If no *interval* or *signal* is defined, it is assumed that the out script loops itself. ++
|
You can update it manually with a signal. If no *interval* or *signal* is defined, it is assumed that the out script loops itself. ++
|
||||||
If a *signal* is defined then the script will run once on startup and will only update with a signal.
|
If a *signal* is defined then the script will run once on startup and will only update with a signal.
|
||||||
|
|
||||||
*restart-interval*: ++
|
*restart-interval*: ++
|
||||||
typeof: integer ++
|
typeof: integer or float ++
|
||||||
The restart interval (in seconds). ++
|
The restart interval (in seconds). ++
|
||||||
|
Minimum value is 0.001 (1ms). Values smaller than 1ms will be set to 1ms. ++
|
||||||
Can't be used with the *interval* option, so only with continuous scripts. ++
|
Can't be used with the *interval* option, so only with continuous scripts. ++
|
||||||
Once the script exits, it'll be re-executed after the *restart-interval*.
|
Once the script exits, it'll be re-executed after the *restart-interval*.
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ The *workspaces* module displays the currently used workspaces in wayland compos
|
|||||||
|
|
||||||
# CONFIGURATION
|
# CONFIGURATION
|
||||||
|
|
||||||
Addressed by *wlr/workspaces*
|
Addressed by *ext/workspaces*
|
||||||
|
|
||||||
*format*: ++
|
*format*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
@@ -24,18 +24,18 @@ Addressed by *wlr/workspaces*
|
|||||||
*sort-by-name*: ++
|
*sort-by-name*: ++
|
||||||
typeof: bool ++
|
typeof: bool ++
|
||||||
default: true ++
|
default: true ++
|
||||||
Should workspaces be sorted by name.
|
Should workspaces be sorted by name. Workspace names will be sorted numerically when all names are numbers.
|
||||||
|
|
||||||
*sort-by-coordinates*: ++
|
*sort-by-coordinates*: ++
|
||||||
typeof: bool ++
|
typeof: bool ++
|
||||||
default: true ++
|
default: false ++
|
||||||
Should workspaces be sorted by coordinates. ++
|
Should workspaces be sorted by coordinates. ++
|
||||||
Note that if both *sort-by-name* and *sort-by-coordinates* are true sort-by name will be first. If both are false - sort by id will be performed.
|
Note that if both *sort-by-name* and *sort-by-coordinates* are true sort-by name will be first. If both are false - sort by id will be performed.
|
||||||
|
|
||||||
*sort-by-number*: ++
|
*sort-by-id*: ++
|
||||||
typeof: bool ++
|
typeof: bool ++
|
||||||
default: false ++
|
default: false ++
|
||||||
If set to true, workspace names will be sorted numerically. Takes precedence over any other sort-by option.
|
Should workspaces be sorted by ID. Workspace ID will be sorted numerically when all ID are numbers. Takes precedence over any other sort-by option.
|
||||||
|
|
||||||
*all-outputs*: ++
|
*all-outputs*: ++
|
||||||
typeof: bool ++
|
typeof: bool ++
|
||||||
@@ -47,9 +47,16 @@ Addressed by *wlr/workspaces*
|
|||||||
default: false ++
|
default: false ++
|
||||||
If set to true only active or urgent workspaces will be shown.
|
If set to true only active or urgent workspaces will be shown.
|
||||||
|
|
||||||
|
*ignore-hidden*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: true ++
|
||||||
|
If set to false hidden workspaces will be shown.
|
||||||
|
|
||||||
# FORMAT REPLACEMENTS
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
*{name}*: Name of workspace assigned by compositor
|
*{name}*: Name of workspace assigned by compositor.
|
||||||
|
|
||||||
|
*{id}*: ID of workspace assigned by compositor.
|
||||||
|
|
||||||
*{icon}*: Icon, as defined in *format-icons*.
|
*{icon}*: Icon, as defined in *format-icons*.
|
||||||
|
|
||||||
@@ -57,6 +64,8 @@ Addressed by *wlr/workspaces*
|
|||||||
|
|
||||||
*activate*: Switch to workspace.
|
*activate*: Switch to workspace.
|
||||||
|
|
||||||
|
*deactivate*: Deactivate the workspace.
|
||||||
|
|
||||||
*close*: Close the workspace.
|
*close*: Close the workspace.
|
||||||
|
|
||||||
# ICONS
|
# ICONS
|
||||||
@@ -69,18 +78,18 @@ In addition to workspace name matching, the following *format-icons* can be set.
|
|||||||
# EXAMPLES
|
# EXAMPLES
|
||||||
|
|
||||||
```
|
```
|
||||||
"wlr/workspaces": {
|
"ext/workspaces": {
|
||||||
"format": "{name}: {icon}",
|
"format": "{name}: {icon}",
|
||||||
|
"on-click": "activate",
|
||||||
"format-icons": {
|
"format-icons": {
|
||||||
"1": "",
|
"Workspace 1": "",
|
||||||
"2": "",
|
"Workspace 2": "",
|
||||||
"3": "",
|
"Workspace 3": "",
|
||||||
"4": "",
|
"Workspace 4": "",
|
||||||
"5": "",
|
|
||||||
"active": "",
|
"active": "",
|
||||||
"default": ""
|
"default": ""
|
||||||
},
|
},
|
||||||
"sort-by-number": true
|
"sort-by-id": true
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
waybar-gps(5) "waybar-gps" "User Manual"
|
||||||
|
|
||||||
|
# NAME
|
||||||
|
|
||||||
|
waybar - gps module
|
||||||
|
|
||||||
|
# DESCRIPTION
|
||||||
|
|
||||||
|
*gps* module for gpsd.
|
||||||
|
|
||||||
|
|
||||||
|
# FILES
|
||||||
|
|
||||||
|
$XDG_CONFIG_HOME/waybar/config ++
|
||||||
|
Per user configuration file
|
||||||
|
|
||||||
|
# ADDITIONAL FILES
|
||||||
|
|
||||||
|
libgps lives in:
|
||||||
|
|
||||||
|
. /usr/lib/libgps.so or /usr/lib64/libgps.so
|
||||||
|
. /usr/lib/pkgconfig/libgps.pc or /usr/lib64/pkgconfig/libgps.pc
|
||||||
|
. /usr/include/gps
|
||||||
|
|
||||||
|
# CONFIGURATION
|
||||||
|
|
||||||
|
*format*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: {glyph} ++
|
||||||
|
The text format.
|
||||||
|
|
||||||
|
*tooltip*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: true ++
|
||||||
|
Option to disable tooltip on hover.
|
||||||
|
|
||||||
|
*tooltip-format*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: Games running: {glyph} ++
|
||||||
|
The text format of the tooltip.
|
||||||
|
|
||||||
|
*interval*: ++
|
||||||
|
typeof: integer ++
|
||||||
|
default: 5 ++
|
||||||
|
The interval in which the GPS information gets polled (e.g. current speed).
|
||||||
|
Significant updates (e.g. the current fix mode) are updated immediately.
|
||||||
|
|
||||||
|
*hide-disconnected*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: true ++
|
||||||
|
Defines if the module should be hidden if there is no GPS receiver.
|
||||||
|
|
||||||
|
*hide-no-fix*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: false ++
|
||||||
|
Defines if the module should be hidden if there is no GPS fix.
|
||||||
|
|
||||||
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
|
*{mode}*: Fix mode
|
||||||
|
|
||||||
|
*{status}*: Technology used for GPS fix. Not all GPS receivers report this.
|
||||||
|
|
||||||
|
*{latitude}*: Latitude, decimal degrees. Can be NaN.
|
||||||
|
|
||||||
|
*{latitude_error}*: Latitude uncertainty, meters. Can be NaN.
|
||||||
|
|
||||||
|
*{longitude}*: Longitude, decimal degrees. Can be NaN.
|
||||||
|
|
||||||
|
*{longitude_error}*: Longitude uncertainty, meters. Can be NaN.
|
||||||
|
|
||||||
|
*{altitude_hae}*: Altitude, height above ellipsoid, meters. Can be NaN.
|
||||||
|
|
||||||
|
*{altitude_msl}*: Longitude, MSL, meters. Can be NaN.
|
||||||
|
|
||||||
|
*{altitude_error}*: Altitude uncertainty, meters. Can be NaN.
|
||||||
|
|
||||||
|
*{speed}*: Speed over ground, meters/sec. Can be NaN.
|
||||||
|
|
||||||
|
*{speed_error}*: Speed uncertainty, meters/sec. Can be NaN.
|
||||||
|
|
||||||
|
*{climb}*: Vertical speed, meters/sec. Can be NaN.
|
||||||
|
|
||||||
|
*{climb_error}*: Vertical speed uncertainty, meters/sec. Can be NaN.
|
||||||
|
|
||||||
|
*{satellites_visible}*: Number of satellites visible from the GPS receiver.
|
||||||
|
|
||||||
|
*{satellites_used}*: Number of satellites used for the GPS fix.
|
||||||
|
|
||||||
|
# EXAMPLES
|
||||||
|
|
||||||
|
```
|
||||||
|
"gps": {
|
||||||
|
"format": "{mode}",
|
||||||
|
"format-disabled": "", // an empty format will hide the module
|
||||||
|
"format-no-fix": "No fix",
|
||||||
|
"format-fix-3d": "{status}",
|
||||||
|
"tooltip-format": "{mode}",
|
||||||
|
"tooltip-format-no-fix": "{satellites_visible} satellites visible",
|
||||||
|
"tooltip-format-fix-2d": "{satellites_used}/{satellites_visible} satellites used",
|
||||||
|
"tooltip-format-fix-3d": "Altitude: {altitude_hae}m",
|
||||||
|
"hide-disconnected": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
# STYLE
|
||||||
|
|
||||||
|
- *#gps*
|
||||||
|
- *#gps.disabled* Applied when GPS is disabled.
|
||||||
|
- *#gps.fix-none* Applied when GPS is present, but there is no fix.
|
||||||
|
- *#gps.fix-2d* Applied when there is a 2D fix.
|
||||||
|
- *#gps.fix-3d* Applied when there is a 3D fix.
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
waybar-hyprland-windowcount(5)
|
||||||
|
|
||||||
|
# NAME
|
||||||
|
|
||||||
|
waybar - hyprland window count module
|
||||||
|
|
||||||
|
# DESCRIPTION
|
||||||
|
|
||||||
|
The *windowcount* module displays the number of windows in the current Hyprland workspace.
|
||||||
|
|
||||||
|
# CONFIGURATION
|
||||||
|
|
||||||
|
Addressed by *hyprland/windowcount*
|
||||||
|
|
||||||
|
*format*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: {} ++
|
||||||
|
The format for how information should be displayed. On {} the current workspace window count is displayed.
|
||||||
|
|
||||||
|
*format-empty*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Override the format when the workspace contains no windows window
|
||||||
|
|
||||||
|
*format-windowed*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Override the format when the workspace contains no fullscreen windows
|
||||||
|
|
||||||
|
*format-fullscreen*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Override the format when the workspace contains a fullscreen window
|
||||||
|
|
||||||
|
*separate-outputs*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: true ++
|
||||||
|
Show the active workspace window count of the monitor the bar belongs to, instead of the focused workspace.
|
||||||
|
|
||||||
|
# STYLE
|
||||||
|
|
||||||
|
- *#windowcount*
|
||||||
|
|
||||||
|
The following classes are applied to the entire Waybar rather than just the
|
||||||
|
windowcount widget:
|
||||||
|
|
||||||
|
- *window#waybar.empty* When no windows are in the workspace
|
||||||
|
- *window#waybar.fullscreen* When there is a fullscreen window in the workspace;
|
||||||
|
useful with Hyprland's *fullscreen, 1* mode
|
||||||
@@ -26,17 +26,77 @@ Addressed by *hyprland/workspaces*
|
|||||||
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. Values may use the placeholders {class} and {title} to use the window's original class and/or title respectively.
|
Keys are the rules, while the values are the methods of representation. Values may use the placeholders {class} and {title} to use the window's original class and/or title respectively.
|
||||||
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.
|
You may assign an empty value to a rule to have it ignored from generating any representation in workspaces. ++
|
||||||
|
This setting is ignored if *workspace-taskbar.enable* is set to true.
|
||||||
|
|
||||||
*window-rewrite-default*:
|
*window-rewrite-default*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
default: "?" ++
|
default: "?" ++
|
||||||
The default method of representation for a workspace's window. This will be used for windows whose classes do not match any of the rules in *window-rewrite*.
|
The default method of representation for a workspace's window. This will be used for windows whose classes do not match any of the rules in *window-rewrite*. ++
|
||||||
|
This setting is ignored if *workspace-taskbar.enable* is set to true.
|
||||||
|
|
||||||
*format-window-separator*: ++
|
*format-window-separator*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
default: " " ++
|
default: " " ++
|
||||||
The separator to be used between windows in a workspace.
|
The separator to be used between windows in a workspace. ++
|
||||||
|
This setting is ignored if *workspace-taskbar.enable* is set to true.
|
||||||
|
|
||||||
|
*workspace-taskbar*: ++
|
||||||
|
typeof: object ++
|
||||||
|
Contains settings for the workspace taskbar, an alternative mode for the workspaces module which displays the window icons as images instead of text.
|
||||||
|
|
||||||
|
*enable*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: false ++
|
||||||
|
Enables the workspace taskbar mode.
|
||||||
|
|
||||||
|
*update-active-window*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: false ++
|
||||||
|
If true, the active/focused window will have an 'active' class. Could cause higher CPU usage due to more frequent redraws.
|
||||||
|
|
||||||
|
*reverse-direction*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: false ++
|
||||||
|
If true, the taskbar windows will be added in reverse order (right to left if orientation is horizontal, bottom to top if vertical).
|
||||||
|
|
||||||
|
*active-window-position*: ++
|
||||||
|
typeof: "none" | "first" | "last" ++
|
||||||
|
default: "none" ++
|
||||||
|
If set to "first", the active window will be moved at the beginning of the taskbar. If set to "last", it will be moved at the end. It will only work if *update-active-window* is set to true.
|
||||||
|
|
||||||
|
*format*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: {icon} ++
|
||||||
|
Format to use for each window in the workspace taskbar. Available placeholders are {icon} and {title}.
|
||||||
|
|
||||||
|
*icon-size*: ++
|
||||||
|
typeof: int ++
|
||||||
|
default: 16 ++
|
||||||
|
Size of the icons in the workspace taskbar.
|
||||||
|
|
||||||
|
*icon-theme*: ++
|
||||||
|
typeof: string | array ++
|
||||||
|
default: [] ++
|
||||||
|
Icon theme to use for the workspace taskbar. If an array is provided, the first theme that is found for a given icon will be used. If no theme is found (or the array is empty), the default icon theme is used.
|
||||||
|
|
||||||
|
*orientation*: ++
|
||||||
|
typeof: "horizontal" | "vertical" ++
|
||||||
|
default: horizontal ++
|
||||||
|
Direction in which the workspace taskbar is displayed.
|
||||||
|
|
||||||
|
*ignore-list*: ++
|
||||||
|
typeof: array ++
|
||||||
|
default: [] ++
|
||||||
|
Regex patterns to match against window class or window title. If a window's class OR title matches any of the patterns, it will not be shown.
|
||||||
|
|
||||||
|
*on-click-window*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: "" ++
|
||||||
|
Command to run when a window is clicked. Available placeholders are: ++
|
||||||
|
- {address} Hyprland address of the clicked window. ++
|
||||||
|
- {button} Pressed button number, see https://api.gtkd.org/gdk.c.types.GdkEventButton.button.html. ++
|
||||||
|
See https://github.com/Alexays/Waybar/wiki/Module:-Hyprland#workspace-taskbars-example for a full example.
|
||||||
|
|
||||||
*show-special*: ++
|
*show-special*: ++
|
||||||
typeof: bool ++
|
typeof: bool ++
|
||||||
@@ -48,6 +108,11 @@ Addressed by *hyprland/workspaces*
|
|||||||
default: false ++
|
default: false ++
|
||||||
If this and show-special are to true, special workspaces will be shown only if visible.
|
If this and show-special are to true, special workspaces will be shown only if visible.
|
||||||
|
|
||||||
|
*persistent-only*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: false ++
|
||||||
|
If set to true, only persistent workspaces will be shown on bar.
|
||||||
|
|
||||||
*all-outputs*: ++
|
*all-outputs*: ++
|
||||||
typeof: bool ++
|
typeof: bool ++
|
||||||
default: false ++
|
default: false ++
|
||||||
@@ -76,6 +141,7 @@ Addressed by *hyprland/workspaces*
|
|||||||
If set to number, workspaces will sort by number.
|
If set to number, workspaces will sort by number.
|
||||||
If set to name, workspaces will sort by name.
|
If set to name, workspaces will sort by name.
|
||||||
If set to id, workspaces will sort by id.
|
If set to id, workspaces will sort by id.
|
||||||
|
If set to special-centered, workspaces will sort by default with special workspaces in the center.
|
||||||
If none of those, workspaces will sort with default behavior.
|
If none of those, workspaces will sort with default behavior.
|
||||||
|
|
||||||
*expand*: ++
|
*expand*: ++
|
||||||
@@ -178,3 +244,6 @@ Additional to workspace name matching, the following *format-icons* can be set.
|
|||||||
- *#workspaces button.special*
|
- *#workspaces button.special*
|
||||||
- *#workspaces button.urgent*
|
- *#workspaces button.urgent*
|
||||||
- *#workspaces button.hosting-monitor* (gets applied if workspace-monitor == waybar-monitor)
|
- *#workspaces button.hosting-monitor* (gets applied if workspace-monitor == waybar-monitor)
|
||||||
|
- *#workspaces .workspace-label*
|
||||||
|
- *#workspaces .taskbar-window* (each window in the taskbar, only if 'workspace-taskbar.enable' is true)
|
||||||
|
- *#workspaces .taskbar-window.active* (applied to the focused window, only if 'workspace-taskbar.update-active-window' is true)
|
||||||
|
|||||||
@@ -125,3 +125,9 @@ screensaver, also known as "presentation mode".
|
|||||||
"timeout": 30.5
|
"timeout": 30.5
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
# STYLE
|
||||||
|
|
||||||
|
- *#idle_inhibitor*
|
||||||
|
- *#idle_inhibitor.activated*
|
||||||
|
- *#idle_inhibitor.deactivated*
|
||||||
|
|||||||
@@ -24,8 +24,9 @@ The *image* module displays an image from a path.
|
|||||||
The width/height to render the image.
|
The width/height to render the image.
|
||||||
|
|
||||||
*interval*: ++
|
*interval*: ++
|
||||||
typeof: integer ++
|
typeof: integer or float ++
|
||||||
The interval (in seconds) to re-render the image. ++
|
The interval (in seconds) to re-render the image. ++
|
||||||
|
Minimum value is 0.001 (1ms). Values smaller than 1ms will be set to 1ms. ++
|
||||||
This is useful if the contents of *path* changes. ++
|
This is useful if the contents of *path* changes. ++
|
||||||
If no *interval* is defined, the image will only be rendered once.
|
If no *interval* is defined, the image will only be rendered once.
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ Addressed by *jack*
|
|||||||
The format of information displayed in the tooltip.
|
The format of information displayed in the tooltip.
|
||||||
|
|
||||||
*interval*: ++
|
*interval*: ++
|
||||||
typeof: integer ++
|
typeof: integer or float ++
|
||||||
default: 1 ++
|
default: 1 ++
|
||||||
The interval in which the information gets polled.
|
The interval in which the information gets polled.
|
||||||
|
|
||||||
|
|||||||
@@ -120,6 +120,8 @@ Addressed by *memory*
|
|||||||
|
|
||||||
*{swapAvail}*: Amount of available swap in GiB.
|
*{swapAvail}*: Amount of available swap in GiB.
|
||||||
|
|
||||||
|
*{swapState}*: Signals if swap is activated or not
|
||||||
|
|
||||||
# EXAMPLES
|
# EXAMPLES
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ waybar - menu property
|
|||||||
# OVERVIEW
|
# OVERVIEW
|
||||||
|
|
||||||
|
|
||||||
Some modules support a 'menu', which allows to have a popup menu whan a defined
|
Some modules support a 'menu', which allows to have a popup menu when a defined
|
||||||
click is done over the module.
|
click is done over the module.
|
||||||
|
|
||||||
# PROPERTIES
|
# PROPERTIES
|
||||||
@@ -110,7 +110,7 @@ Module config :
|
|||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkMenuItem" id="hibernat">
|
<object class="GtkMenuItem" id="hibernate">
|
||||||
<property name="label">Hibernate</property>
|
<property name="label">Hibernate</property>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
|
|||||||
@@ -204,6 +204,10 @@ Addressed by *mpd*
|
|||||||
|
|
||||||
*{queueLength}*: The length of the current queue.
|
*{queueLength}*: The length of the current queue.
|
||||||
|
|
||||||
|
*{uri}*: The URI of the song relative to the MPD music directory.
|
||||||
|
|
||||||
|
*{filename}* The last part of the URI.
|
||||||
|
|
||||||
*{stateIcon}*: The icon corresponding to the playing or paused status of the player (see *state-icons* option)
|
*{stateIcon}*: The icon corresponding to the playing or paused status of the player (see *state-icons* option)
|
||||||
|
|
||||||
*{consumeIcon}*: The icon corresponding the "consume" option (see *consume-icons* option)
|
*{consumeIcon}*: The icon corresponding the "consume" option (see *consume-icons* option)
|
||||||
|
|||||||
@@ -16,6 +16,11 @@ Addressed by *network*
|
|||||||
typeof: string ++
|
typeof: string ++
|
||||||
Use the defined interface instead of auto-detection. Accepts wildcard.
|
Use the defined interface instead of auto-detection. Accepts wildcard.
|
||||||
|
|
||||||
|
*rfkill*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: true ++
|
||||||
|
If enabled, the *disabled* format will be used when rfkill is blocking wlan interfaces.
|
||||||
|
|
||||||
*interval*: ++
|
*interval*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
default: 60 ++
|
default: 60 ++
|
||||||
@@ -49,7 +54,7 @@ Addressed by *network*
|
|||||||
|
|
||||||
*format-disabled*: ++
|
*format-disabled*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
This format is used when the displayed interface is disabled.
|
This format is used when rfkill is blocking wlan interfaces.
|
||||||
|
|
||||||
*format-icons*: ++
|
*format-icons*: ++
|
||||||
typeof: array/object ++
|
typeof: array/object ++
|
||||||
@@ -127,7 +132,7 @@ Addressed by *network*
|
|||||||
|
|
||||||
*tooltip-format-disabled*: ++
|
*tooltip-format-disabled*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
This format is used when the displayed interface is disabled.
|
This format is used when rfkill is blocking wlan interfaces.
|
||||||
|
|
||||||
*menu*: ++
|
*menu*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
@@ -171,7 +176,7 @@ Addressed by *network*
|
|||||||
|
|
||||||
*{signaldBm}*: Signal strength of the wireless network in dBm.
|
*{signaldBm}*: Signal strength of the wireless network in dBm.
|
||||||
|
|
||||||
*{frequency}*: Frequency of the wireless network in MHz.
|
*{frequency}*: Frequency of the wireless network in GHz.
|
||||||
|
|
||||||
*{bandwidthUpBits}*: Instant up speed in bits/seconds.
|
*{bandwidthUpBits}*: Instant up speed in bits/seconds.
|
||||||
|
|
||||||
|
|||||||
@@ -52,8 +52,8 @@ Addressed by *niri/language*
|
|||||||
|
|
||||||
```
|
```
|
||||||
"niri/language": {
|
"niri/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ı"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -61,3 +61,12 @@ Addressed by *niri/language*
|
|||||||
# STYLE
|
# STYLE
|
||||||
|
|
||||||
- *#language*
|
- *#language*
|
||||||
|
|
||||||
|
Additionally, a CSS class matching the current layout's short name is added to the widget. This
|
||||||
|
allows per-language styling, for example:
|
||||||
|
|
||||||
|
```
|
||||||
|
#language.us { color: #00ff00; }
|
||||||
|
#language.de { color: #ff0000; }
|
||||||
|
#language.fr { color: #0000ff; }
|
||||||
|
```
|
||||||
|
|||||||
@@ -70,6 +70,8 @@ Additional to workspace name matching, the following *format-icons* can be set.
|
|||||||
- *default*: Will be shown, when no string matches are found.
|
- *default*: Will be shown, when no string matches are found.
|
||||||
- *focused*: Will be shown, when workspace is focused.
|
- *focused*: Will be shown, when workspace is focused.
|
||||||
- *active*: Will be shown, when workspace is active on its output.
|
- *active*: Will be shown, when workspace is active on its output.
|
||||||
|
- *urgent*: Will be shown, when workspace has urgent windows.
|
||||||
|
- *empty*: Will be shown, when workspace is empty.
|
||||||
|
|
||||||
# EXAMPLES
|
# EXAMPLES
|
||||||
|
|
||||||
@@ -95,6 +97,7 @@ Additional to workspace name matching, the following *format-icons* can be set.
|
|||||||
- *#workspaces button*
|
- *#workspaces button*
|
||||||
- *#workspaces button.focused*: The single focused workspace.
|
- *#workspaces button.focused*: The single focused workspace.
|
||||||
- *#workspaces button.active*: The workspace is active (visible) on its output.
|
- *#workspaces button.active*: The workspace is active (visible) on its output.
|
||||||
|
- *#workspaces button.urgent*: The workspace has one or more urgent windows.
|
||||||
- *#workspaces button.empty*: The workspace is empty.
|
- *#workspaces button.empty*: The workspace is empty.
|
||||||
- *#workspaces button.current_output*: The workspace is from the same output as
|
- *#workspaces button.current_output*: The workspace is from the same output as
|
||||||
the bar that it is displayed on.
|
the bar that it is displayed on.
|
||||||
|
|||||||
@@ -37,6 +37,17 @@ the screen or playing audio.
|
|||||||
default: false ++
|
default: false ++
|
||||||
Enables this module to consume all left over space dynamically.
|
Enables this module to consume all left over space dynamically.
|
||||||
|
|
||||||
|
*ignore-monitor* ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: true ++
|
||||||
|
Ignore streams with *stream.monitor* property.
|
||||||
|
|
||||||
|
*ignore* ++
|
||||||
|
typeof: array of objects ++
|
||||||
|
default: [] ++
|
||||||
|
Additional streams to be ignored. See *IGNORE CONFIGURATION* for++
|
||||||
|
more information.
|
||||||
|
|
||||||
# MODULES CONFIGURATION
|
# MODULES CONFIGURATION
|
||||||
|
|
||||||
*type*: ++
|
*type*: ++
|
||||||
@@ -54,6 +65,14 @@ the screen or playing audio.
|
|||||||
default: 24 ++
|
default: 24 ++
|
||||||
The size of each icon in the tooltip.
|
The size of each icon in the tooltip.
|
||||||
|
|
||||||
|
# IGNORE CONFIGURATION
|
||||||
|
|
||||||
|
*type*: ++
|
||||||
|
typeof: string
|
||||||
|
|
||||||
|
*name*: ++
|
||||||
|
typeof: string
|
||||||
|
|
||||||
# EXAMPLES
|
# EXAMPLES
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -77,6 +96,17 @@ the screen or playing audio.
|
|||||||
"tooltip": true,
|
"tooltip": true,
|
||||||
"tooltip-icon-size": 24
|
"tooltip-icon-size": 24
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"ignore-monitor": true,
|
||||||
|
"ignore": [
|
||||||
|
{
|
||||||
|
"type": "audio-in",
|
||||||
|
"name": "cava"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "screenshare",
|
||||||
|
"name": "obs"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ Addressed by *river/layout*
|
|||||||
|
|
||||||
- *#layout*
|
- *#layout*
|
||||||
- *#layout.focused* Applied when the output this module's bar belongs to is focused.
|
- *#layout.focused* Applied when the output this module's bar belongs to is focused.
|
||||||
|
- *#layout.<layout>* Applied when the output this module's bar belongs uses this layout.
|
||||||
|
|
||||||
# SEE ALSO
|
# SEE ALSO
|
||||||
|
|
||||||
|
|||||||
@@ -89,6 +89,11 @@ Addressed by *sway/window*
|
|||||||
default: false ++
|
default: false ++
|
||||||
If the workspace itself is focused and the workspace contains nodes or floating_nodes, show the workspace name. If not set, text remains empty but styles according to nodes in the workspace are still applied.
|
If the workspace itself is focused and the workspace contains nodes or floating_nodes, show the workspace name. If not set, text remains empty but styles according to nodes in the workspace are still applied.
|
||||||
|
|
||||||
|
*show-hidden-marks*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: false ++
|
||||||
|
For the *{marks}* format replacement, include hidden marks that start with an underscore.
|
||||||
|
|
||||||
*rewrite*: ++
|
*rewrite*: ++
|
||||||
typeof: object ++
|
typeof: object ++
|
||||||
Rules to rewrite the module format output. See *rewrite rules*.
|
Rules to rewrite the module format output. See *rewrite rules*.
|
||||||
@@ -117,6 +122,8 @@ Addressed by *sway/window*
|
|||||||
*{shell}*: The shell of the focused window. It's 'xwayland' when the window is
|
*{shell}*: The shell of the focused window. It's 'xwayland' when the window is
|
||||||
running through xwayland, otherwise, it's 'xdg-shell'.
|
running through xwayland, otherwise, it's 'xdg-shell'.
|
||||||
|
|
||||||
|
*{marks}*: Marks of the window.
|
||||||
|
|
||||||
# REWRITE RULES
|
# REWRITE RULES
|
||||||
|
|
||||||
*rewrite* is an object where keys are regular expressions and values are
|
*rewrite* is an object where keys are regular expressions and values are
|
||||||
|
|||||||
@@ -31,6 +31,11 @@ Addressed by *sway/workspaces*
|
|||||||
default: false ++
|
default: false ++
|
||||||
If set to false, you can scroll to cycle through workspaces. If set to true this behaviour is disabled.
|
If set to false, you can scroll to cycle through workspaces. If set to true this behaviour is disabled.
|
||||||
|
|
||||||
|
*reverse-scroll*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: false ++
|
||||||
|
If set to false, scrolling up will switch to the previous workspace and scrolling down will switch to the next workspace. If set to true, the behavior will be reversed.
|
||||||
|
|
||||||
*disable-click*: ++
|
*disable-click*: ++
|
||||||
typeof: bool ++
|
typeof: bool ++
|
||||||
default: false ++
|
default: false ++
|
||||||
|
|||||||
@@ -62,6 +62,12 @@ Addressed by *systemd-failed-units*
|
|||||||
|
|
||||||
*{nr_failed}*: Number of total failed units.
|
*{nr_failed}*: Number of total failed units.
|
||||||
|
|
||||||
|
*{systemd_state}:* State of the systemd system session
|
||||||
|
|
||||||
|
*{user_state}:* State of the systemd user session
|
||||||
|
|
||||||
|
*{overall_state}:* Overall state of the systemd and user session. ("Ok" or "Degraded")
|
||||||
|
|
||||||
# EXAMPLES
|
# EXAMPLES
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ Addressed by *temperature*
|
|||||||
The threshold before it is considered critical (Celsius).
|
The threshold before it is considered critical (Celsius).
|
||||||
|
|
||||||
*interval*: ++
|
*interval*: ++
|
||||||
typeof: integer ++
|
typeof: integer or float ++
|
||||||
default: 10 ++
|
default: 10 ++
|
||||||
The interval in which the information gets polled.
|
The interval in which the information gets polled.
|
||||||
|
|
||||||
@@ -160,4 +160,5 @@ Addressed by *temperature*
|
|||||||
# STYLE
|
# STYLE
|
||||||
|
|
||||||
- *#temperature*
|
- *#temperature*
|
||||||
|
- *#temperature.warning*
|
||||||
- *#temperature.critical*
|
- *#temperature.critical*
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
waybar-wayfire-window(5)
|
||||||
|
|
||||||
|
# NAME
|
||||||
|
|
||||||
|
waybar - wayfire window module
|
||||||
|
|
||||||
|
# DESCRIPTION
|
||||||
|
|
||||||
|
The *window* module displays the title of the currently focused window in wayfire.
|
||||||
|
|
||||||
|
# CONFIGURATION
|
||||||
|
|
||||||
|
Addressed by *wayfire/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*.
|
||||||
|
|
||||||
|
*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 "wayfire 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
|
||||||
|
|
||||||
|
```
|
||||||
|
"wayfire/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
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
waybar-wayfire-workspaces(5)
|
||||||
|
|
||||||
|
# NAME
|
||||||
|
|
||||||
|
waybar - wayfire workspaces module
|
||||||
|
|
||||||
|
# DESCRIPTION
|
||||||
|
|
||||||
|
The *workspaces* module displays the currently used workspaces in wayfire.
|
||||||
|
|
||||||
|
# CONFIGURATION
|
||||||
|
|
||||||
|
Addressed by *wayfire/workspaces*
|
||||||
|
|
||||||
|
*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
|
||||||
|
|
||||||
|
*{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.
|
||||||
|
|
||||||
|
# EXAMPLES
|
||||||
|
|
||||||
|
```
|
||||||
|
"wayfire/workspaces": {
|
||||||
|
"format": "{icon}",
|
||||||
|
"format-icons": {
|
||||||
|
"1": "",
|
||||||
|
"2": "",
|
||||||
|
"3": "",
|
||||||
|
"4": "",
|
||||||
|
"5": "",
|
||||||
|
"focused": "",
|
||||||
|
"default": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Style
|
||||||
|
|
||||||
|
- *#workspaces button*
|
||||||
|
- *#workspaces button.focused*: The single focused workspace.
|
||||||
|
- *#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.
|
||||||
+51
-4
@@ -86,7 +86,7 @@ The visual display elements for waybar use a CSS stylesheet, see *waybar-styles(
|
|||||||
*no-center* ++
|
*no-center* ++
|
||||||
typeof: bool ++
|
typeof: bool ++
|
||||||
default: false ++
|
default: false ++
|
||||||
Option to disable the center modules fully usefull together with expand-\*.
|
Option to disable the center modules fully useful together with expand-\*.
|
||||||
|
|
||||||
*spacing* ++
|
*spacing* ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
@@ -151,6 +151,20 @@ The visual display elements for waybar use a CSS stylesheet, see *waybar-styles(
|
|||||||
default: *false* ++
|
default: *false* ++
|
||||||
Option to enable reloading the css style if a modification is detected on the style sheet file or any imported css files.
|
Option to enable reloading the css style if a modification is detected on the style sheet file or any imported css files.
|
||||||
|
|
||||||
|
*on-sigusr1* ++
|
||||||
|
typeof: string ++
|
||||||
|
default: *toggle* ++
|
||||||
|
Action that is performed when receiving SIGUSR1 kill signal. ++
|
||||||
|
Possible values: *show*, *hide*, *toggle*, *reload*, *noop*. ++
|
||||||
|
Default value: *toggle*.
|
||||||
|
|
||||||
|
*on-sigusr2* ++
|
||||||
|
typeof: string ++
|
||||||
|
default: *reload* ++
|
||||||
|
Action that is performed when receiving SIGUSR2 kill signal. ++
|
||||||
|
Possible values: *show*, *hide*, *toggle*, *reload*, *noop*. ++
|
||||||
|
Default value: *reload*.
|
||||||
|
|
||||||
# MODULE FORMAT
|
# MODULE FORMAT
|
||||||
|
|
||||||
You can use PangoMarkupFormat (See https://developer.gnome.org/pango/stable/PangoMarkupFormat.html#PangoMarkupFormat).
|
You can use PangoMarkupFormat (See https://developer.gnome.org/pango/stable/PangoMarkupFormat.html#PangoMarkupFormat).
|
||||||
@@ -206,14 +220,36 @@ A minimal *config* file could look like this:
|
|||||||
Waybar accepts the following signals:
|
Waybar accepts the following signals:
|
||||||
|
|
||||||
*SIGUSR1*
|
*SIGUSR1*
|
||||||
Toggles the bar visibility (hides if shown, shows if hidden)
|
By default toggles the bar visibility (hides if shown, shows if hidden)
|
||||||
*SIGUSR2*
|
*SIGUSR2*
|
||||||
Reloads (resets) the bar
|
By default reloads (resets) the bar
|
||||||
*SIGINT*
|
*SIGINT*
|
||||||
Quits the bar
|
Quits the bar
|
||||||
|
|
||||||
For example, to toggle the bar programmatically, you can invoke `killall -SIGUSR1 waybar`.
|
For example, to toggle the bar programmatically, you can invoke `killall -SIGUSR1 waybar`.
|
||||||
|
|
||||||
|
## User signal configuration
|
||||||
|
|
||||||
|
Config parameters *on-sigusr1* and *on-sigusr2* change what happens when bars receive
|
||||||
|
*SIGUSR1* and *SIGUSR2* signals.
|
||||||
|
|
||||||
|
This means that commands `killall -SIGUSR1 waybar` and `killall -SIGUSR2 waybar`
|
||||||
|
can perform user-configured action.
|
||||||
|
|
||||||
|
It also means that if an external script has the PID of the bar then it can
|
||||||
|
perform more complex `show`/`hide`/`reload` logic for each instance of Waybar.
|
||||||
|
One can find the PID e.g. by doing `pgrep -a waybar` which could then match
|
||||||
|
by config name or other parameters.
|
||||||
|
|
||||||
|
## Kill parameter meanings
|
||||||
|
|
||||||
|
*show* Switches state to visible (per bar).
|
||||||
|
*hide* Switches state to hidden (per bar).
|
||||||
|
*toggle* Switches state between visible and hidden (per bar).
|
||||||
|
*reload* Reloads all waybars of current waybar process (basically equivalent to
|
||||||
|
restarting with updated config which sets initial visibility values).
|
||||||
|
*noop* Does nothing when the kill signal is received.
|
||||||
|
|
||||||
# MULTI OUTPUT CONFIGURATION
|
# MULTI OUTPUT CONFIGURATION
|
||||||
|
|
||||||
## Limit a configuration to some outputs
|
## Limit a configuration to some outputs
|
||||||
@@ -272,6 +308,17 @@ When positioning Waybar on the left or right side of the screen, sometimes it's
|
|||||||
|
|
||||||
Valid options for the "rotate" property are: 0, 90, 180, and 270.
|
Valid options for the "rotate" property are: 0, 90, 180, and 270.
|
||||||
|
|
||||||
|
## Swapping icon and label
|
||||||
|
|
||||||
|
If a module displays both a label and an icon, it might be desirable to swap them (for instance, for panels on the left or right of the screen, or for user adopting a right-to-left script). This can be achieved with the "swap-icon-label" property, taking a boolean. Example:
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"sway/window": {
|
||||||
|
"swap-icon-label": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Grouping modules
|
## Grouping modules
|
||||||
|
|
||||||
Module groups allow stacking modules in any direction. By default, when the bar is positioned on the top or bottom of the screen, modules in a group are stacked vertically. Likewise, when positioned on the left or right, modules in a group are stacked horizontally. This can be changed with the "orientation" property.
|
Module groups allow stacking modules in any direction. By default, when the bar is positioned on the top or bottom of the screen, modules in a group are stacked vertically. Likewise, when positioned on the left or right, modules in a group are stacked horizontally. This can be changed with the "orientation" property.
|
||||||
@@ -390,4 +437,4 @@ A group may hide all but one element, showing them only on mouse hover. In order
|
|||||||
# SEE ALSO
|
# SEE ALSO
|
||||||
|
|
||||||
*sway-output(5)*
|
*sway-output(5)*
|
||||||
*waybar-styles(5)"
|
*waybar-styles(5)*
|
||||||
|
|||||||
+34
-15
@@ -1,6 +1,6 @@
|
|||||||
project(
|
project(
|
||||||
'waybar', 'cpp', 'c',
|
'waybar', 'cpp', 'c',
|
||||||
version: '0.12.0',
|
version: '0.14.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', 'std_format=disabled', 'tests=disabled'])
|
spdlog = dependency('spdlog', version : ['>=1.15.2'], fallback : ['spdlog', 'spdlog_dep'], default_options : ['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')
|
||||||
@@ -93,6 +93,7 @@ libmpdclient = dependency('libmpdclient', required: get_option('mpd'))
|
|||||||
xkbregistry = dependency('xkbregistry')
|
xkbregistry = dependency('xkbregistry')
|
||||||
libjack = dependency('jack', required: get_option('jack'))
|
libjack = dependency('jack', required: get_option('jack'))
|
||||||
libwireplumber = dependency('wireplumber-0.5', required: get_option('wireplumber'))
|
libwireplumber = dependency('wireplumber-0.5', required: get_option('wireplumber'))
|
||||||
|
libgps = dependency('libgps', required: get_option('gps'))
|
||||||
|
|
||||||
libsndio = compiler.find_library('sndio', required: get_option('sndio'))
|
libsndio = compiler.find_library('sndio', required: get_option('sndio'))
|
||||||
if libsndio.found()
|
if libsndio.found()
|
||||||
@@ -182,6 +183,7 @@ src_files = files(
|
|||||||
'src/util/sanitize_str.cpp',
|
'src/util/sanitize_str.cpp',
|
||||||
'src/util/rewrite_string.cpp',
|
'src/util/rewrite_string.cpp',
|
||||||
'src/util/gtk_icon.cpp',
|
'src/util/gtk_icon.cpp',
|
||||||
|
'src/util/icon_loader.cpp',
|
||||||
'src/util/regex_collection.cpp',
|
'src/util/regex_collection.cpp',
|
||||||
'src/util/css_reload_helper.cpp'
|
'src/util/css_reload_helper.cpp'
|
||||||
)
|
)
|
||||||
@@ -275,6 +277,17 @@ if true
|
|||||||
man_files += files('man/waybar-wlr-taskbar.5.scd')
|
man_files += files('man/waybar-wlr-taskbar.5.scd')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if wayland_protos.version().version_compare('>=1.39')
|
||||||
|
add_project_arguments('-DHAVE_EXT_WORKSPACES', language: 'cpp')
|
||||||
|
src_files += files(
|
||||||
|
'src/modules/ext/workspace_manager.cpp',
|
||||||
|
'src/modules/ext/workspace_manager_binding.cpp',
|
||||||
|
)
|
||||||
|
man_files += files(
|
||||||
|
'man/waybar-ext-workspaces.5.scd',
|
||||||
|
)
|
||||||
|
endif
|
||||||
|
|
||||||
if true
|
if true
|
||||||
add_project_arguments('-DHAVE_RIVER', language: 'cpp')
|
add_project_arguments('-DHAVE_RIVER', language: 'cpp')
|
||||||
src_files += files(
|
src_files += files(
|
||||||
@@ -306,6 +319,7 @@ if true
|
|||||||
'src/modules/hyprland/language.cpp',
|
'src/modules/hyprland/language.cpp',
|
||||||
'src/modules/hyprland/submap.cpp',
|
'src/modules/hyprland/submap.cpp',
|
||||||
'src/modules/hyprland/window.cpp',
|
'src/modules/hyprland/window.cpp',
|
||||||
|
'src/modules/hyprland/windowcount.cpp',
|
||||||
'src/modules/hyprland/workspace.cpp',
|
'src/modules/hyprland/workspace.cpp',
|
||||||
'src/modules/hyprland/workspaces.cpp',
|
'src/modules/hyprland/workspaces.cpp',
|
||||||
'src/modules/hyprland/windowcreationpayload.cpp',
|
'src/modules/hyprland/windowcreationpayload.cpp',
|
||||||
@@ -333,6 +347,15 @@ if get_option('niri')
|
|||||||
)
|
)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if true
|
||||||
|
add_project_arguments('-DHAVE_WAYFIRE', language: 'cpp')
|
||||||
|
src_files += files(
|
||||||
|
'src/modules/wayfire/backend.cpp',
|
||||||
|
'src/modules/wayfire/window.cpp',
|
||||||
|
'src/modules/wayfire/workspaces.cpp',
|
||||||
|
)
|
||||||
|
endif
|
||||||
|
|
||||||
if get_option('login-proxy')
|
if get_option('login-proxy')
|
||||||
add_project_arguments('-DHAVE_LOGIN_PROXY', language: 'cpp')
|
add_project_arguments('-DHAVE_LOGIN_PROXY', language: 'cpp')
|
||||||
endif
|
endif
|
||||||
@@ -474,17 +497,6 @@ else
|
|||||||
man_files += files('man/waybar-clock.5.scd')
|
man_files += files('man/waybar-clock.5.scd')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if get_option('experimental')
|
|
||||||
add_project_arguments('-DHAVE_WLR_WORKSPACES', language: 'cpp')
|
|
||||||
src_files += files(
|
|
||||||
'src/modules/wlr/workspace_manager.cpp',
|
|
||||||
'src/modules/wlr/workspace_manager_binding.cpp',
|
|
||||||
)
|
|
||||||
man_files += files(
|
|
||||||
'man/waybar-wlr-workspaces.5.scd',
|
|
||||||
)
|
|
||||||
endif
|
|
||||||
|
|
||||||
cava = dependency('cava',
|
cava = dependency('cava',
|
||||||
version : '>=0.10.4',
|
version : '>=0.10.4',
|
||||||
required: get_option('cava'),
|
required: get_option('cava'),
|
||||||
@@ -493,10 +505,16 @@ cava = dependency('cava',
|
|||||||
|
|
||||||
if cava.found()
|
if cava.found()
|
||||||
add_project_arguments('-DHAVE_LIBCAVA', language: 'cpp')
|
add_project_arguments('-DHAVE_LIBCAVA', language: 'cpp')
|
||||||
src_files += files('src/modules/cava.cpp')
|
src_files += files('src/modules/cava/cava.cpp', 'src/modules/cava/cava_backend.cpp')
|
||||||
man_files += files('man/waybar-cava.5.scd')
|
man_files += files('man/waybar-cava.5.scd')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if libgps.found()
|
||||||
|
add_project_arguments('-DHAVE_LIBGPS', language: 'cpp')
|
||||||
|
src_files += files('src/modules/gps.cpp')
|
||||||
|
man_files += files('man/waybar-gps.5.scd')
|
||||||
|
endif
|
||||||
|
|
||||||
subdir('protocol')
|
subdir('protocol')
|
||||||
|
|
||||||
app_resources = []
|
app_resources = []
|
||||||
@@ -535,7 +553,8 @@ executable(
|
|||||||
libsndio,
|
libsndio,
|
||||||
tz_dep,
|
tz_dep,
|
||||||
xkbregistry,
|
xkbregistry,
|
||||||
cava
|
cava,
|
||||||
|
libgps
|
||||||
],
|
],
|
||||||
include_directories: inc_dirs,
|
include_directories: inc_dirs,
|
||||||
install: true,
|
install: true,
|
||||||
|
|||||||
@@ -21,3 +21,4 @@ option('wireplumber', type: 'feature', value: 'auto', description: 'Enable suppo
|
|||||||
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('niri', type: 'boolean', description: 'Enable support for niri')
|
||||||
option('login-proxy', type: 'boolean', description: 'Enable interfacing with dbus login interface')
|
option('login-proxy', type: 'boolean', description: 'Enable interfacing with dbus login interface')
|
||||||
|
option('gps', type: 'feature', value: 'auto', description: 'Enable support for gps')
|
||||||
|
|||||||
+4
-1
@@ -30,8 +30,11 @@ in
|
|||||||
# nixpkgs checks version, no need when building locally
|
# nixpkgs checks version, no need when building locally
|
||||||
nativeInstallCheckInputs = [ ];
|
nativeInstallCheckInputs = [ ];
|
||||||
|
|
||||||
buildInputs = (builtins.filter (p: p.pname != "wireplumber") oldAttrs.buildInputs) ++ [
|
buildInputs =
|
||||||
|
(builtins.filter (p: p.pname != "wireplumber" && p.pname != "gps") oldAttrs.buildInputs)
|
||||||
|
++ [
|
||||||
pkgs.wireplumber
|
pkgs.wireplumber
|
||||||
|
pkgs.gpsd
|
||||||
];
|
];
|
||||||
|
|
||||||
postUnpack = ''
|
postUnpack = ''
|
||||||
|
|||||||
@@ -1,306 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<protocol name="ext_workspace_unstable_v1">
|
|
||||||
<copyright>
|
|
||||||
Copyright © 2019 Christopher Billington
|
|
||||||
Copyright © 2020 Ilia Bozhinov
|
|
||||||
|
|
||||||
Permission to use, copy, modify, distribute, and sell this
|
|
||||||
software and its documentation for any purpose is hereby granted
|
|
||||||
without fee, provided that the above copyright notice appear in
|
|
||||||
all copies and that both that copyright notice and this permission
|
|
||||||
notice appear in supporting documentation, and that the name of
|
|
||||||
the copyright holders not be used in advertising or publicity
|
|
||||||
pertaining to distribution of the software without specific,
|
|
||||||
written prior permission. The copyright holders make no
|
|
||||||
representations about the suitability of this software for any
|
|
||||||
purpose. It is provided "as is" without express or implied
|
|
||||||
warranty.
|
|
||||||
|
|
||||||
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
|
||||||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
|
||||||
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
|
||||||
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
|
||||||
THIS SOFTWARE.
|
|
||||||
</copyright>
|
|
||||||
|
|
||||||
<interface name="zext_workspace_manager_v1" version="1">
|
|
||||||
<description summary="list and control workspaces">
|
|
||||||
Workspaces, also called virtual desktops, are groups of surfaces. A
|
|
||||||
compositor with a concept of workspaces may only show some such groups of
|
|
||||||
surfaces (those of 'active' workspaces) at a time. 'Activating' a
|
|
||||||
workspace is a request for the compositor to display that workspace's
|
|
||||||
surfaces as normal, whereas the compositor may hide or otherwise
|
|
||||||
de-emphasise surfaces that are associated only with 'inactive' workspaces.
|
|
||||||
Workspaces are grouped by which sets of outputs they correspond to, and
|
|
||||||
may contain surfaces only from those outputs. In this way, it is possible
|
|
||||||
for each output to have its own set of workspaces, or for all outputs (or
|
|
||||||
any other arbitrary grouping) to share workspaces. Compositors may
|
|
||||||
optionally conceptually arrange each group of workspaces in an
|
|
||||||
N-dimensional grid.
|
|
||||||
|
|
||||||
The purpose of this protocol is to enable the creation of taskbars and
|
|
||||||
docks by providing them with a list of workspaces and their properties,
|
|
||||||
and allowing them to activate and deactivate workspaces.
|
|
||||||
|
|
||||||
After a client binds the zext_workspace_manager_v1, each workspace will be
|
|
||||||
sent via the workspace event.
|
|
||||||
</description>
|
|
||||||
|
|
||||||
<event name="workspace_group">
|
|
||||||
<description summary="a workspace group has been created">
|
|
||||||
This event is emitted whenever a new workspace group has been created.
|
|
||||||
|
|
||||||
All initial details of the workspace group (workspaces, outputs) will be
|
|
||||||
sent immediately after this event via the corresponding events in
|
|
||||||
zext_workspace_group_handle_v1.
|
|
||||||
</description>
|
|
||||||
<arg name="workspace_group" type="new_id" interface="zext_workspace_group_handle_v1"/>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<request name="commit">
|
|
||||||
<description summary="all requests about the workspaces have been sent">
|
|
||||||
The client must send this request after it has finished sending other
|
|
||||||
requests. The compositor must process a series of requests preceding a
|
|
||||||
commit request atomically.
|
|
||||||
|
|
||||||
This allows changes to the workspace properties to be seen as atomic,
|
|
||||||
even if they happen via multiple events, and even if they involve
|
|
||||||
multiple zext_workspace_handle_v1 objects, for example, deactivating one
|
|
||||||
workspace and activating another.
|
|
||||||
</description>
|
|
||||||
</request>
|
|
||||||
|
|
||||||
<event name="done">
|
|
||||||
<description summary="all information about the workspace groups has been sent">
|
|
||||||
This event is sent after all changes in all workspace groups have been
|
|
||||||
sent.
|
|
||||||
|
|
||||||
This allows changes to one or more zext_workspace_group_handle_v1
|
|
||||||
properties to be seen as atomic, even if they happen via multiple
|
|
||||||
events. In particular, an output moving from one workspace group to
|
|
||||||
another sends an output_enter event and an output_leave event to the two
|
|
||||||
zext_workspace_group_handle_v1 objects in question. The compositor sends
|
|
||||||
the done event only after updating the output information in both
|
|
||||||
workspace groups.
|
|
||||||
</description>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="finished">
|
|
||||||
<description summary="the compositor has finished with the workspace_manager">
|
|
||||||
This event indicates that the compositor is done sending events to the
|
|
||||||
zext_workspace_manager_v1. The server will destroy the object
|
|
||||||
immediately after sending this request, so it will become invalid and
|
|
||||||
the client should free any resources associated with it.
|
|
||||||
</description>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<request name="stop">
|
|
||||||
<description summary="stop sending events">
|
|
||||||
Indicates the client no longer wishes to receive events for new
|
|
||||||
workspace groups. However the compositor may emit further workspace
|
|
||||||
events, until the finished event is emitted.
|
|
||||||
|
|
||||||
The client must not send any more requests after this one.
|
|
||||||
</description>
|
|
||||||
</request>
|
|
||||||
</interface>
|
|
||||||
|
|
||||||
<interface name="zext_workspace_group_handle_v1" version="1">
|
|
||||||
<description summary="a workspace group assigned to a set of outputs">
|
|
||||||
A zext_workspace_group_handle_v1 object represents a a workspace group
|
|
||||||
that is assigned a set of outputs and contains a number of workspaces.
|
|
||||||
|
|
||||||
The set of outputs assigned to the workspace group is conveyed to the client via
|
|
||||||
output_enter and output_leave events, and its workspaces are conveyed with
|
|
||||||
workspace events.
|
|
||||||
|
|
||||||
For example, a compositor which has a set of workspaces for each output may
|
|
||||||
advertise a workspace group (and its workspaces) per output, whereas a compositor
|
|
||||||
where a workspace spans all outputs may advertise a single workspace group for all
|
|
||||||
outputs.
|
|
||||||
</description>
|
|
||||||
|
|
||||||
<event name="output_enter">
|
|
||||||
<description summary="output assigned to workspace group">
|
|
||||||
This event is emitted whenever an output is assigned to the workspace
|
|
||||||
group.
|
|
||||||
</description>
|
|
||||||
<arg name="output" type="object" interface="wl_output"/>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="output_leave">
|
|
||||||
<description summary="output removed from workspace group">
|
|
||||||
This event is emitted whenever an output is removed from the workspace
|
|
||||||
group.
|
|
||||||
</description>
|
|
||||||
<arg name="output" type="object" interface="wl_output"/>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="workspace">
|
|
||||||
<description summary="workspace added to workspace group">
|
|
||||||
This event is emitted whenever a new workspace has been created.
|
|
||||||
|
|
||||||
All initial details of the workspace (name, coordinates, state) will
|
|
||||||
be sent immediately after this event via the corresponding events in
|
|
||||||
zext_workspace_handle_v1.
|
|
||||||
</description>
|
|
||||||
<arg name="workspace" type="new_id" interface="zext_workspace_handle_v1"/>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="remove">
|
|
||||||
<description summary="this workspace group has been destroyed">
|
|
||||||
This event means the zext_workspace_group_handle_v1 has been destroyed.
|
|
||||||
It is guaranteed there won't be any more events for this
|
|
||||||
zext_workspace_group_handle_v1. The zext_workspace_group_handle_v1 becomes
|
|
||||||
inert so any requests will be ignored except the destroy request.
|
|
||||||
|
|
||||||
The compositor must remove all workspaces belonging to a workspace group
|
|
||||||
before removing the workspace group.
|
|
||||||
</description>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<request name="create_workspace">
|
|
||||||
<description summary="create a new workspace">
|
|
||||||
Request that the compositor create a new workspace with the given name.
|
|
||||||
|
|
||||||
There is no guarantee that the compositor will create a new workspace,
|
|
||||||
or that the created workspace will have the provided name.
|
|
||||||
</description>
|
|
||||||
<arg name="workspace" type="string"/>
|
|
||||||
</request>
|
|
||||||
|
|
||||||
<request name="destroy" type="destructor">
|
|
||||||
<description summary="destroy the zext_workspace_handle_v1 object">
|
|
||||||
Destroys the zext_workspace_handle_v1 object.
|
|
||||||
|
|
||||||
This request should be called either when the client does not want to
|
|
||||||
use the workspace object any more or after the remove event to finalize
|
|
||||||
the destruction of the object.
|
|
||||||
</description>
|
|
||||||
</request>
|
|
||||||
</interface>
|
|
||||||
|
|
||||||
<interface name="zext_workspace_handle_v1" version="1">
|
|
||||||
<description summary="a workspace handing a group of surfaces">
|
|
||||||
A zext_workspace_handle_v1 object represents a a workspace that handles a
|
|
||||||
group of surfaces.
|
|
||||||
|
|
||||||
Each workspace has a name, conveyed to the client with the name event; a
|
|
||||||
list of states, conveyed to the client with the state event; and
|
|
||||||
optionally a set of coordinates, conveyed to the client with the
|
|
||||||
coordinates event. The client may request that the compositor activate or
|
|
||||||
deactivate the workspace.
|
|
||||||
|
|
||||||
Each workspace can belong to only a single workspace group.
|
|
||||||
Depepending on the compositor policy, there might be workspaces with
|
|
||||||
the same name in different workspace groups, but these workspaces are still
|
|
||||||
separate (e.g. one of them might be active while the other is not).
|
|
||||||
</description>
|
|
||||||
|
|
||||||
<event name="name">
|
|
||||||
<description summary="workspace name changed">
|
|
||||||
This event is emitted immediately after the zext_workspace_handle_v1 is
|
|
||||||
created and whenever the name of the workspace changes.
|
|
||||||
</description>
|
|
||||||
<arg name="name" type="string"/>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="coordinates">
|
|
||||||
<description summary="workspace coordinates changed">
|
|
||||||
This event is used to organize workspaces into an N-dimensional grid
|
|
||||||
within a workspace group, and if supported, is emitted immediately after
|
|
||||||
the zext_workspace_handle_v1 is created and whenever the coordinates of
|
|
||||||
the workspace change. Compositors may not send this event if they do not
|
|
||||||
conceptually arrange workspaces in this way. If compositors simply
|
|
||||||
number workspaces, without any geometric interpretation, they may send
|
|
||||||
1D coordinates, which clients should not interpret as implying any
|
|
||||||
geometry. Sending an empty array means that the compositor no longer
|
|
||||||
orders the workspace geometrically.
|
|
||||||
|
|
||||||
Coordinates have an arbitrary number of dimensions N with an uint32
|
|
||||||
position along each dimension. By convention if N > 1, the first
|
|
||||||
dimension is X, the second Y, the third Z, and so on. The compositor may
|
|
||||||
chose to utilize these events for a more novel workspace layout
|
|
||||||
convention, however. No guarantee is made about the grid being filled or
|
|
||||||
bounded; there may be a workspace at coordinate 1 and another at
|
|
||||||
coordinate 1000 and none in between. Within a workspace group, however,
|
|
||||||
workspaces must have unique coordinates of equal dimensionality.
|
|
||||||
</description>
|
|
||||||
<arg name="coordinates" type="array"/>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="state">
|
|
||||||
<description summary="the state of the workspace changed">
|
|
||||||
This event is emitted immediately after the zext_workspace_handle_v1 is
|
|
||||||
created and each time the workspace state changes, either because of a
|
|
||||||
compositor action or because of a request in this protocol.
|
|
||||||
</description>
|
|
||||||
<arg name="state" type="array"/>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<enum name="state">
|
|
||||||
<description summary="types of states on the workspace">
|
|
||||||
The different states that a workspace can have.
|
|
||||||
</description>
|
|
||||||
|
|
||||||
<entry name="active" value="0" summary="the workspace is active"/>
|
|
||||||
<entry name="urgent" value="1" summary="the workspace requests attention"/>
|
|
||||||
<entry name="hidden" value="2">
|
|
||||||
<description summary="the workspace is not visible">
|
|
||||||
The workspace is not visible in its workspace group, and clients
|
|
||||||
attempting to visualize the compositor workspace state should not
|
|
||||||
display such workspaces.
|
|
||||||
</description>
|
|
||||||
</entry>
|
|
||||||
</enum>
|
|
||||||
|
|
||||||
<event name="remove">
|
|
||||||
<description summary="this workspace has been destroyed">
|
|
||||||
This event means the zext_workspace_handle_v1 has been destroyed. It is
|
|
||||||
guaranteed there won't be any more events for this
|
|
||||||
zext_workspace_handle_v1. The zext_workspace_handle_v1 becomes inert so
|
|
||||||
any requests will be ignored except the destroy request.
|
|
||||||
</description>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<request name="destroy" type="destructor">
|
|
||||||
<description summary="destroy the zext_workspace_handle_v1 object">
|
|
||||||
Destroys the zext_workspace_handle_v1 object.
|
|
||||||
|
|
||||||
This request should be called either when the client does not want to
|
|
||||||
use the workspace object any more or after the remove event to finalize
|
|
||||||
the destruction of the object.
|
|
||||||
</description>
|
|
||||||
</request>
|
|
||||||
|
|
||||||
<request name="activate">
|
|
||||||
<description summary="activate the workspace">
|
|
||||||
Request that this workspace be activated.
|
|
||||||
|
|
||||||
There is no guarantee the workspace will be actually activated, and
|
|
||||||
behaviour may be compositor-dependent. For example, activating a
|
|
||||||
workspace may or may not deactivate all other workspaces in the same
|
|
||||||
group.
|
|
||||||
</description>
|
|
||||||
</request>
|
|
||||||
|
|
||||||
<request name="deactivate">
|
|
||||||
<description summary="activate the workspace">
|
|
||||||
Request that this workspace be deactivated.
|
|
||||||
|
|
||||||
There is no guarantee the workspace will be actually deactivated.
|
|
||||||
</description>
|
|
||||||
</request>
|
|
||||||
|
|
||||||
<request name="remove">
|
|
||||||
<description summary="remove the workspace">
|
|
||||||
Request that this workspace be removed.
|
|
||||||
|
|
||||||
There is no guarantee the workspace will be actually removed.
|
|
||||||
</description>
|
|
||||||
</request>
|
|
||||||
</interface>
|
|
||||||
</protocol>
|
|
||||||
@@ -26,12 +26,17 @@ client_protocols = [
|
|||||||
[wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'],
|
[wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'],
|
||||||
[wl_protocol_dir, 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml'],
|
[wl_protocol_dir, 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml'],
|
||||||
['wlr-foreign-toplevel-management-unstable-v1.xml'],
|
['wlr-foreign-toplevel-management-unstable-v1.xml'],
|
||||||
['ext-workspace-unstable-v1.xml'],
|
|
||||||
['river-status-unstable-v1.xml'],
|
['river-status-unstable-v1.xml'],
|
||||||
['river-control-unstable-v1.xml'],
|
['river-control-unstable-v1.xml'],
|
||||||
['dwl-ipc-unstable-v2.xml'],
|
['dwl-ipc-unstable-v2.xml'],
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if wayland_protos.version().version_compare('>=1.39')
|
||||||
|
client_protocols += [
|
||||||
|
[wl_protocol_dir, 'staging/ext-workspace/ext-workspace-v1.xml']
|
||||||
|
]
|
||||||
|
endif
|
||||||
|
|
||||||
client_protos_src = []
|
client_protos_src = []
|
||||||
client_protos_headers = []
|
client_protos_headers = []
|
||||||
|
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ class PlayerManager:
|
|||||||
logger.debug(f"Metadata changed for player {player.props.player_name}")
|
logger.debug(f"Metadata changed for player {player.props.player_name}")
|
||||||
player_name = player.props.player_name
|
player_name = player.props.player_name
|
||||||
artist = player.get_artist()
|
artist = player.get_artist()
|
||||||
|
artist = artist.replace("&", "&")
|
||||||
title = player.get_title()
|
title = player.get_title()
|
||||||
title = title.replace("&", "&")
|
title = title.replace("&", "&")
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -63,7 +63,7 @@ button:hover {
|
|||||||
background: rgba(0, 0, 0, 0.2);
|
background: rgba(0, 0, 0, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#workspaces button.focused {
|
#workspaces button.focused, #workspaces button.active {
|
||||||
background-color: #64727D;
|
background-color: #64727D;
|
||||||
box-shadow: inset 0 -3px #ffffff;
|
box-shadow: inset 0 -3px #ffffff;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=Highly customizable Wayland bar for Sway and Wlroots based compositors.
|
Description=Highly customizable Wayland bar for Sway and Wlroots based compositors
|
||||||
Documentation=https://github.com/Alexays/Waybar/wiki/
|
Documentation=https://github.com/Alexays/Waybar/wiki/
|
||||||
PartOf=graphical-session.target
|
PartOf=graphical-session.target
|
||||||
After=graphical-session.target
|
After=graphical-session.target
|
||||||
|
|||||||
@@ -63,7 +63,8 @@ std::optional<std::string> getDesktopFilePath(const std::string& app_identifier,
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto data_dirs = Glib::get_system_data_dirs();
|
auto data_dirs = Glib::get_system_data_dirs();
|
||||||
|
data_dirs.insert(data_dirs.begin(), Glib::get_user_data_dir());
|
||||||
for (const auto& data_dir : data_dirs) {
|
for (const auto& data_dir : data_dirs) {
|
||||||
const auto data_app_dir = data_dir + "/applications/";
|
const auto data_app_dir = data_dir + "/applications/";
|
||||||
auto desktop_file_suffix = app_identifier + ".desktop";
|
auto desktop_file_suffix = app_identifier + ".desktop";
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "AIconLabel.hpp"
|
#include "AIconLabel.hpp"
|
||||||
|
|
||||||
#include <gdkmm/pixbuf.h>
|
#include <gdkmm/pixbuf.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
namespace waybar {
|
namespace waybar {
|
||||||
|
|
||||||
@@ -17,14 +18,39 @@ AIconLabel::AIconLabel(const Json::Value &config, const std::string &name, const
|
|||||||
box_.get_style_context()->add_class(id);
|
box_.get_style_context()->add_class(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int rot = 0;
|
||||||
|
|
||||||
|
if (config_["rotate"].isUInt()) {
|
||||||
|
rot = config["rotate"].asUInt() % 360;
|
||||||
|
if ((rot % 90) != 00) rot = 0;
|
||||||
|
rot /= 90;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rot % 2) == 0)
|
||||||
box_.set_orientation(Gtk::Orientation::ORIENTATION_HORIZONTAL);
|
box_.set_orientation(Gtk::Orientation::ORIENTATION_HORIZONTAL);
|
||||||
|
else
|
||||||
|
box_.set_orientation(Gtk::Orientation::ORIENTATION_VERTICAL);
|
||||||
box_.set_name(name);
|
box_.set_name(name);
|
||||||
|
|
||||||
int spacing = config_["icon-spacing"].isInt() ? config_["icon-spacing"].asInt() : 8;
|
int spacing = config_["icon-spacing"].isInt() ? config_["icon-spacing"].asInt() : 8;
|
||||||
box_.set_spacing(spacing);
|
box_.set_spacing(spacing);
|
||||||
|
|
||||||
|
bool swap_icon_label = false;
|
||||||
|
if (config_["swap-icon-label"].isNull()) {
|
||||||
|
} else if (config_["swap-icon-label"].isBool()) {
|
||||||
|
swap_icon_label = config_["swap-icon-label"].asBool();
|
||||||
|
} else {
|
||||||
|
spdlog::warn("'swap-icon-label' must be a bool, found '{}'. Using default value (false).",
|
||||||
|
config_["swap-icon-label"].asString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rot == 0 || rot == 3) ^ swap_icon_label) {
|
||||||
box_.add(image_);
|
box_.add(image_);
|
||||||
box_.add(label_);
|
box_.add(label_);
|
||||||
|
} else {
|
||||||
|
box_.add(label_);
|
||||||
|
box_.add(image_);
|
||||||
|
}
|
||||||
|
|
||||||
event_box_.add(box_);
|
event_box_.add(box_);
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-4
@@ -17,10 +17,17 @@ ALabel::ALabel(const Json::Value& config, const std::string& name, const std::st
|
|||||||
config["format-alt"].isString() || config["menu"].isString() || enable_click,
|
config["format-alt"].isString() || config["menu"].isString() || enable_click,
|
||||||
enable_scroll),
|
enable_scroll),
|
||||||
format_(config_["format"].isString() ? config_["format"].asString() : format),
|
format_(config_["format"].isString() ? config_["format"].asString() : format),
|
||||||
|
|
||||||
|
// Leave the default option outside of the std::max(1L, ...), because the zero value
|
||||||
|
// (default) is used in modules/custom.cpp to make the difference between
|
||||||
|
// two types of custom scripts. Fixes #4521.
|
||||||
interval_(config_["interval"] == "once"
|
interval_(config_["interval"] == "once"
|
||||||
? std::chrono::seconds::max()
|
? std::chrono::milliseconds::max()
|
||||||
: std::chrono::seconds(
|
: std::chrono::milliseconds(
|
||||||
config_["interval"].isUInt() ? config_["interval"].asUInt() : interval)),
|
(config_["interval"].isNumeric()
|
||||||
|
? std::max(1L, // Minimum 1ms due to millisecond precision
|
||||||
|
static_cast<long>(config_["interval"].asDouble()) * 1000)
|
||||||
|
: 1000 * (long)interval))),
|
||||||
default_format_(format_) {
|
default_format_(format_) {
|
||||||
label_.set_name(name);
|
label_.set_name(name);
|
||||||
if (!id.empty()) {
|
if (!id.empty()) {
|
||||||
@@ -200,7 +207,7 @@ std::string ALabel::getState(uint8_t value, bool lesser) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Sort states
|
// Sort states
|
||||||
std::sort(states.begin(), states.end(), [&lesser](auto& a, auto& b) {
|
std::ranges::sort(states.begin(), states.end(), [&lesser](auto& a, auto& b) {
|
||||||
return lesser ? a.second < b.second : a.second > b.second;
|
return lesser ? a.second < b.second : a.second > b.second;
|
||||||
});
|
});
|
||||||
std::string valid_state;
|
std::string valid_state;
|
||||||
|
|||||||
+10
-6
@@ -83,7 +83,7 @@ AModule::AModule(const Json::Value& config, const std::string& name, const std::
|
|||||||
}
|
}
|
||||||
|
|
||||||
AModule::~AModule() {
|
AModule::~AModule() {
|
||||||
for (const auto& pid : pid_) {
|
for (const auto& pid : pid_children_) {
|
||||||
if (pid != -1) {
|
if (pid != -1) {
|
||||||
killpg(pid, SIGTERM);
|
killpg(pid, SIGTERM);
|
||||||
}
|
}
|
||||||
@@ -93,15 +93,15 @@ AModule::~AModule() {
|
|||||||
auto AModule::update() -> void {
|
auto AModule::update() -> void {
|
||||||
// Run user-provided update handler if configured
|
// Run user-provided update handler if configured
|
||||||
if (config_["on-update"].isString()) {
|
if (config_["on-update"].isString()) {
|
||||||
pid_.push_back(util::command::forkExec(config_["on-update"].asString()));
|
pid_children_.push_back(util::command::forkExec(config_["on-update"].asString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Get mapping between event name and module action name
|
// Get mapping between event name and module action name
|
||||||
// Then call overrided doAction in order to call appropriate module action
|
// Then call overridden doAction in order to call appropriate module action
|
||||||
auto AModule::doAction(const std::string& name) -> void {
|
auto AModule::doAction(const std::string& name) -> void {
|
||||||
if (!name.empty()) {
|
if (!name.empty()) {
|
||||||
const std::map<std::string, std::string>::const_iterator& recA{eventActionMap_.find(name)};
|
const std::map<std::string, std::string>::const_iterator& recA{eventActionMap_.find(name)};
|
||||||
// Call overrided action if derrived class has implemented it
|
// Call overridden action if derived class has implemented it
|
||||||
if (recA != eventActionMap_.cend() && name != recA->second) this->doAction(recA->second);
|
if (recA != eventActionMap_.cend() && name != recA->second) this->doAction(recA->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -172,6 +172,10 @@ bool AModule::handleUserEvent(GdkEventButton* const& e) {
|
|||||||
// Popup the menu
|
// Popup the menu
|
||||||
gtk_widget_show_all(GTK_WIDGET(menu_));
|
gtk_widget_show_all(GTK_WIDGET(menu_));
|
||||||
gtk_menu_popup_at_pointer(GTK_MENU(menu_), reinterpret_cast<GdkEvent*>(e));
|
gtk_menu_popup_at_pointer(GTK_MENU(menu_), reinterpret_cast<GdkEvent*>(e));
|
||||||
|
// Manually reset prelight to make sure the module doesn't stay in a hover state
|
||||||
|
if (auto* module = event_box_.get_child(); module != nullptr) {
|
||||||
|
module->unset_state_flags(Gtk::StateFlags::STATE_FLAG_PRELIGHT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Second call user scripts
|
// Second call user scripts
|
||||||
@@ -182,7 +186,7 @@ bool AModule::handleUserEvent(GdkEventButton* const& e) {
|
|||||||
format.clear();
|
format.clear();
|
||||||
}
|
}
|
||||||
if (!format.empty()) {
|
if (!format.empty()) {
|
||||||
pid_.push_back(util::command::forkExec(format));
|
pid_children_.push_back(util::command::forkExec(format));
|
||||||
}
|
}
|
||||||
dp.emit();
|
dp.emit();
|
||||||
return true;
|
return true;
|
||||||
@@ -267,7 +271,7 @@ bool AModule::handleScroll(GdkEventScroll* e) {
|
|||||||
this->AModule::doAction(eventName);
|
this->AModule::doAction(eventName);
|
||||||
// Second call user scripts
|
// Second call user scripts
|
||||||
if (config_[eventName].isString())
|
if (config_[eventName].isString())
|
||||||
pid_.push_back(util::command::forkExec(config_[eventName].asString()));
|
pid_children_.push_back(util::command::forkExec(config_[eventName].asString()));
|
||||||
|
|
||||||
dp.emit();
|
dp.emit();
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
+52
-5
@@ -8,6 +8,8 @@
|
|||||||
#include "client.hpp"
|
#include "client.hpp"
|
||||||
#include "factory.hpp"
|
#include "factory.hpp"
|
||||||
#include "group.hpp"
|
#include "group.hpp"
|
||||||
|
#include "util/enum.hpp"
|
||||||
|
#include "util/kill_signal.hpp"
|
||||||
|
|
||||||
#ifdef HAVE_SWAY
|
#ifdef HAVE_SWAY
|
||||||
#include "modules/sway/bar.hpp"
|
#include "modules/sway/bar.hpp"
|
||||||
@@ -277,6 +279,32 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
waybar::util::EnumParser<util::KillSignalAction> m_signalActionEnumParser;
|
||||||
|
const auto& configSigusr1 = config["on-sigusr1"];
|
||||||
|
if (configSigusr1.isString()) {
|
||||||
|
auto strSigusr1 = configSigusr1.asString();
|
||||||
|
try {
|
||||||
|
onSigusr1 =
|
||||||
|
m_signalActionEnumParser.parseStringToEnum(strSigusr1, util::userKillSignalActions);
|
||||||
|
} catch (const std::invalid_argument& e) {
|
||||||
|
onSigusr1 = util::SIGNALACTION_DEFAULT_SIGUSR1;
|
||||||
|
spdlog::warn(
|
||||||
|
"Invalid string representation for on-sigusr1. Falling back to default mode (toggle).");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const auto& configSigusr2 = config["on-sigusr2"];
|
||||||
|
if (configSigusr2.isString()) {
|
||||||
|
auto strSigusr2 = configSigusr2.asString();
|
||||||
|
try {
|
||||||
|
onSigusr2 =
|
||||||
|
m_signalActionEnumParser.parseStringToEnum(strSigusr2, util::userKillSignalActions);
|
||||||
|
} catch (const std::invalid_argument& e) {
|
||||||
|
onSigusr2 = util::SIGNALACTION_DEFAULT_SIGUSR2;
|
||||||
|
spdlog::warn(
|
||||||
|
"Invalid string representation for on-sigusr2. Falling back to default mode (reload).");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setupWidgets();
|
setupWidgets();
|
||||||
window.show_all();
|
window.show_all();
|
||||||
|
|
||||||
@@ -405,7 +433,18 @@ void waybar::Bar::onMap(GdkEventAny* /*unused*/) {
|
|||||||
/*
|
/*
|
||||||
* Obtain a pointer to the custom layer surface for modules that require it (idle_inhibitor).
|
* Obtain a pointer to the custom layer surface for modules that require it (idle_inhibitor).
|
||||||
*/
|
*/
|
||||||
auto* gdk_window = window.get_window()->gobj();
|
auto gdk_window_ref = window.get_window();
|
||||||
|
if (!gdk_window_ref) {
|
||||||
|
spdlog::warn("Failed to get GDK window during onMap, deferring surface initialization");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* gdk_window = gdk_window_ref->gobj();
|
||||||
|
if (!gdk_window) {
|
||||||
|
spdlog::warn("GDK window object is null during onMap, deferring surface initialization");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
surface = gdk_wayland_window_get_wl_surface(gdk_window);
|
surface = gdk_wayland_window_get_wl_surface(gdk_window);
|
||||||
configureGlobalOffset(gdk_window_get_width(gdk_window), gdk_window_get_height(gdk_window));
|
configureGlobalOffset(gdk_window_get_width(gdk_window), gdk_window_get_height(gdk_window));
|
||||||
|
|
||||||
@@ -422,6 +461,8 @@ void waybar::Bar::setVisible(bool value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void waybar::Bar::toggle() { setVisible(!visible); }
|
void waybar::Bar::toggle() { setVisible(!visible); }
|
||||||
|
void waybar::Bar::show() { setVisible(true); }
|
||||||
|
void waybar::Bar::hide() { setVisible(false); }
|
||||||
|
|
||||||
// Converting string to button code rn as to avoid doing it later
|
// Converting string to button code rn as to avoid doing it later
|
||||||
void waybar::Bar::setupAltFormatKeyForModule(const std::string& module_name) {
|
void waybar::Bar::setupAltFormatKeyForModule(const std::string& module_name) {
|
||||||
@@ -479,6 +520,9 @@ void waybar::Bar::handleSignal(int signal) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
waybar::util::KillSignalAction waybar::Bar::getOnSigusr1Action() { return this->onSigusr1; }
|
||||||
|
waybar::util::KillSignalAction waybar::Bar::getOnSigusr2Action() { return this->onSigusr2; }
|
||||||
|
|
||||||
void waybar::Bar::getModules(const Factory& factory, const std::string& pos,
|
void waybar::Bar::getModules(const Factory& factory, const std::string& pos,
|
||||||
waybar::Group* group = nullptr) {
|
waybar::Group* group = nullptr) {
|
||||||
auto module_list = group != nullptr ? config[pos]["modules"] : config[pos];
|
auto module_list = group != nullptr ? config[pos]["modules"] : config[pos];
|
||||||
@@ -496,7 +540,11 @@ void waybar::Bar::getModules(const Factory& factory, const std::string& pos,
|
|||||||
auto vertical = (group != nullptr ? group->getBox().get_orientation()
|
auto vertical = (group != nullptr ? group->getBox().get_orientation()
|
||||||
: box_.get_orientation()) == Gtk::ORIENTATION_VERTICAL;
|
: box_.get_orientation()) == Gtk::ORIENTATION_VERTICAL;
|
||||||
|
|
||||||
auto* group_module = new waybar::Group(id_name, class_name, config[ref], vertical);
|
auto group_config = config[ref];
|
||||||
|
if (group_config["modules"].isNull()) {
|
||||||
|
spdlog::warn("Group definition '{}' has not been found, group will be hidden", ref);
|
||||||
|
}
|
||||||
|
auto* group_module = new waybar::Group(id_name, class_name, group_config, vertical);
|
||||||
getModules(factory, ref, group_module);
|
getModules(factory, ref, group_module);
|
||||||
module = group_module;
|
module = group_module;
|
||||||
} else {
|
} else {
|
||||||
@@ -545,7 +593,6 @@ auto waybar::Bar::setupWidgets() -> void {
|
|||||||
if (config["fixed-center"].isBool() ? config["fixed-center"].asBool() : true) {
|
if (config["fixed-center"].isBool() ? config["fixed-center"].asBool() : true) {
|
||||||
box_.set_center_widget(center_);
|
box_.set_center_widget(center_);
|
||||||
} else {
|
} else {
|
||||||
spdlog::error("No fixed center_");
|
|
||||||
box_.pack_start(center_, true, expand_center);
|
box_.pack_start(center_, true, expand_center);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -569,13 +616,13 @@ auto waybar::Bar::setupWidgets() -> void {
|
|||||||
|
|
||||||
if (!no_center) {
|
if (!no_center) {
|
||||||
for (auto const& module : modules_center_) {
|
for (auto const& module : modules_center_) {
|
||||||
center_.pack_start(*module, false, false);
|
center_.pack_start(*module, module->expandEnabled(), module->expandEnabled());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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, module->expandEnabled(), module->expandEnabled());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-6
@@ -86,7 +86,7 @@ void waybar::Client::handleOutputDone(void *data, struct zxdg_output_v1 * /*xdg_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
std::cerr << e.what() << '\n';
|
spdlog::warn("caught exception in zxdg_output_v1_listener::done: {}", e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +97,7 @@ void waybar::Client::handleOutputName(void *data, struct zxdg_output_v1 * /*xdg_
|
|||||||
auto &output = client->getOutput(data);
|
auto &output = client->getOutput(data);
|
||||||
output.name = name;
|
output.name = name;
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
std::cerr << e.what() << '\n';
|
spdlog::warn("caught exception in zxdg_output_v1_listener::name: {}", e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,13 +106,13 @@ void waybar::Client::handleOutputDescription(void *data, struct zxdg_output_v1 *
|
|||||||
auto *client = waybar::Client::inst();
|
auto *client = waybar::Client::inst();
|
||||||
try {
|
try {
|
||||||
auto &output = client->getOutput(data);
|
auto &output = client->getOutput(data);
|
||||||
const char *open_paren = strrchr(description, '(');
|
|
||||||
|
|
||||||
// Description format: "identifier (name)"
|
// Description format: "identifier (name)"
|
||||||
size_t identifier_length = open_paren - description;
|
auto s = std::string(description);
|
||||||
output.identifier = std::string(description, identifier_length - 1);
|
auto pos = s.find(" (");
|
||||||
|
output.identifier = pos != std::string::npos ? s.substr(0, pos) : s;
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
std::cerr << e.what() << '\n';
|
spdlog::warn("caught exception in zxdg_output_v1_listener::description: {}", e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,15 +151,19 @@ void waybar::Client::handleDeferredMonitorRemoval(Glib::RefPtr<Gdk::Monitor> mon
|
|||||||
|
|
||||||
const std::string waybar::Client::getStyle(const std::string &style,
|
const std::string waybar::Client::getStyle(const std::string &style,
|
||||||
std::optional<Appearance> appearance = std::nullopt) {
|
std::optional<Appearance> appearance = std::nullopt) {
|
||||||
|
auto gtk_settings = Gtk::Settings::get_default();
|
||||||
std::optional<std::string> css_file;
|
std::optional<std::string> css_file;
|
||||||
|
|
||||||
if (style.empty()) {
|
if (style.empty()) {
|
||||||
std::vector<std::string> search_files;
|
std::vector<std::string> search_files;
|
||||||
switch (appearance.value_or(portal->getAppearance())) {
|
switch (appearance.value_or(portal->getAppearance())) {
|
||||||
case waybar::Appearance::LIGHT:
|
case waybar::Appearance::LIGHT:
|
||||||
search_files.emplace_back("style-light.css");
|
search_files.emplace_back("style-light.css");
|
||||||
|
gtk_settings->property_gtk_application_prefer_dark_theme() = false;
|
||||||
break;
|
break;
|
||||||
case waybar::Appearance::DARK:
|
case waybar::Appearance::DARK:
|
||||||
search_files.emplace_back("style-dark.css");
|
search_files.emplace_back("style-dark.css");
|
||||||
|
gtk_settings->property_gtk_application_prefer_dark_theme() = true;
|
||||||
break;
|
break;
|
||||||
case waybar::Appearance::UNKNOWN:
|
case waybar::Appearance::UNKNOWN:
|
||||||
break;
|
break;
|
||||||
@@ -169,9 +173,11 @@ const std::string waybar::Client::getStyle(const std::string &style,
|
|||||||
} else {
|
} else {
|
||||||
css_file = style;
|
css_file = style;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!css_file) {
|
if (!css_file) {
|
||||||
throw std::runtime_error("Missing required resource files");
|
throw std::runtime_error("Missing required resource files");
|
||||||
}
|
}
|
||||||
|
|
||||||
spdlog::info("Using CSS file {}", css_file.value());
|
spdlog::info("Using CSS file {}", css_file.value());
|
||||||
return css_file.value();
|
return css_file.value();
|
||||||
};
|
};
|
||||||
|
|||||||
+49
-2
@@ -2,7 +2,11 @@
|
|||||||
|
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#ifndef __OpenBSD__
|
||||||
#include <wordexp.h>
|
#include <wordexp.h>
|
||||||
|
#else
|
||||||
|
#include <glob.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@@ -34,6 +38,7 @@ std::vector<std::string> Config::tryExpandPath(const std::string &base,
|
|||||||
spdlog::debug("Try expanding: {}", path.string());
|
spdlog::debug("Try expanding: {}", path.string());
|
||||||
|
|
||||||
std::vector<std::string> results;
|
std::vector<std::string> results;
|
||||||
|
#ifndef __OpenBSD__
|
||||||
wordexp_t p;
|
wordexp_t p;
|
||||||
if (wordexp(path.c_str(), &p, 0) == 0) {
|
if (wordexp(path.c_str(), &p, 0) == 0) {
|
||||||
for (size_t i = 0; i < p.we_wordc; i++) {
|
for (size_t i = 0; i < p.we_wordc; i++) {
|
||||||
@@ -44,6 +49,18 @@ std::vector<std::string> Config::tryExpandPath(const std::string &base,
|
|||||||
}
|
}
|
||||||
wordfree(&p);
|
wordfree(&p);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
glob_t p;
|
||||||
|
if (glob(path.c_str(), 0, NULL, &p) == 0) {
|
||||||
|
for (size_t i = 0; i < p.gl_pathc; i++) {
|
||||||
|
if (access(p.gl_pathv[i], F_OK) == 0) {
|
||||||
|
results.emplace_back(p.gl_pathv[i]);
|
||||||
|
spdlog::debug("Found config file: {}", p.gl_pathv[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
globfree(&p);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
@@ -89,20 +106,50 @@ void Config::setupConfig(Json::Value &dst, const std::string &config_file, int d
|
|||||||
mergeConfig(dst, tmp_config);
|
mergeConfig(dst, tmp_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> Config::findIncludePath(const std::string &name,
|
||||||
|
const std::vector<std::string> &dirs) {
|
||||||
|
auto match1 = tryExpandPath(name, "");
|
||||||
|
if (!match1.empty()) {
|
||||||
|
return match1;
|
||||||
|
}
|
||||||
|
if (const char *dir = std::getenv(Config::CONFIG_PATH_ENV)) {
|
||||||
|
if (auto res = tryExpandPath(dir, name); !res.empty()) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const auto &dir : dirs) {
|
||||||
|
if (auto res = tryExpandPath(dir, name); !res.empty()) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void Config::resolveConfigIncludes(Json::Value &config, int depth) {
|
void Config::resolveConfigIncludes(Json::Value &config, int depth) {
|
||||||
Json::Value includes = config["include"];
|
Json::Value includes = config["include"];
|
||||||
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());
|
||||||
for (const auto &match : tryExpandPath(include.asString(), "")) {
|
auto matches = findIncludePath(include.asString());
|
||||||
|
if (!matches.empty()) {
|
||||||
|
for (const auto &match : matches) {
|
||||||
setupConfig(config, match, depth + 1);
|
setupConfig(config, match, depth + 1);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
spdlog::warn("Unable to find resource file: {}", include.asString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (includes.isString()) {
|
} else if (includes.isString()) {
|
||||||
spdlog::info("Including resource file: {}", includes.asString());
|
spdlog::info("Including resource file: {}", includes.asString());
|
||||||
for (const auto &match : tryExpandPath(includes.asString(), "")) {
|
auto matches = findIncludePath(includes.asString());
|
||||||
|
if (!matches.empty()) {
|
||||||
|
for (const auto &match : matches) {
|
||||||
setupConfig(config, match, depth + 1);
|
setupConfig(config, match, depth + 1);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
spdlog::warn("Unable to find resource file: {}", includes.asString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+31
-7
@@ -17,8 +17,8 @@
|
|||||||
#ifdef HAVE_WLR_TASKBAR
|
#ifdef HAVE_WLR_TASKBAR
|
||||||
#include "modules/wlr/taskbar.hpp"
|
#include "modules/wlr/taskbar.hpp"
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_WLR_WORKSPACES
|
#ifdef HAVE_EXT_WORKSPACES
|
||||||
#include "modules/wlr/workspace_manager.hpp"
|
#include "modules/ext/workspace_manager.hpp"
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_RIVER
|
#ifdef HAVE_RIVER
|
||||||
#include "modules/river/layout.hpp"
|
#include "modules/river/layout.hpp"
|
||||||
@@ -34,6 +34,7 @@
|
|||||||
#include "modules/hyprland/language.hpp"
|
#include "modules/hyprland/language.hpp"
|
||||||
#include "modules/hyprland/submap.hpp"
|
#include "modules/hyprland/submap.hpp"
|
||||||
#include "modules/hyprland/window.hpp"
|
#include "modules/hyprland/window.hpp"
|
||||||
|
#include "modules/hyprland/windowcount.hpp"
|
||||||
#include "modules/hyprland/workspaces.hpp"
|
#include "modules/hyprland/workspaces.hpp"
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_NIRI
|
#ifdef HAVE_NIRI
|
||||||
@@ -41,6 +42,10 @@
|
|||||||
#include "modules/niri/window.hpp"
|
#include "modules/niri/window.hpp"
|
||||||
#include "modules/niri/workspaces.hpp"
|
#include "modules/niri/workspaces.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_WAYFIRE
|
||||||
|
#include "modules/wayfire/window.hpp"
|
||||||
|
#include "modules/wayfire/workspaces.hpp"
|
||||||
|
#endif
|
||||||
#if defined(__FreeBSD__) || defined(__linux__)
|
#if defined(__FreeBSD__) || defined(__linux__)
|
||||||
#include "modules/battery.hpp"
|
#include "modules/battery.hpp"
|
||||||
#endif
|
#endif
|
||||||
@@ -104,11 +109,14 @@
|
|||||||
#include "modules/wireplumber.hpp"
|
#include "modules/wireplumber.hpp"
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_LIBCAVA
|
#ifdef HAVE_LIBCAVA
|
||||||
#include "modules/cava.hpp"
|
#include "modules/cava/cava.hpp"
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_SYSTEMD_MONITOR
|
#ifdef HAVE_SYSTEMD_MONITOR
|
||||||
#include "modules/systemd_failed_units.hpp"
|
#include "modules/systemd_failed_units.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_LIBGPS
|
||||||
|
#include "modules/gps.hpp"
|
||||||
|
#endif
|
||||||
#include "modules/cffi.hpp"
|
#include "modules/cffi.hpp"
|
||||||
#include "modules/custom.hpp"
|
#include "modules/custom.hpp"
|
||||||
#include "modules/image.hpp"
|
#include "modules/image.hpp"
|
||||||
@@ -170,9 +178,9 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name,
|
|||||||
return new waybar::modules::wlr::Taskbar(id, bar_, config_[name]);
|
return new waybar::modules::wlr::Taskbar(id, bar_, config_[name]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_WLR_WORKSPACES
|
#ifdef HAVE_EXT_WORKSPACES
|
||||||
if (ref == "wlr/workspaces") {
|
if (ref == "ext/workspaces") {
|
||||||
return new waybar::modules::wlr::WorkspaceManager(id, bar_, config_[name]);
|
return new waybar::modules::ext::WorkspaceManager(id, bar_, config_[name]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_RIVER
|
#ifdef HAVE_RIVER
|
||||||
@@ -201,6 +209,9 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name,
|
|||||||
if (ref == "hyprland/window") {
|
if (ref == "hyprland/window") {
|
||||||
return new waybar::modules::hyprland::Window(id, bar_, config_[name]);
|
return new waybar::modules::hyprland::Window(id, bar_, config_[name]);
|
||||||
}
|
}
|
||||||
|
if (ref == "hyprland/windowcount") {
|
||||||
|
return new waybar::modules::hyprland::WindowCount(id, bar_, config_[name]);
|
||||||
|
}
|
||||||
if (ref == "hyprland/language") {
|
if (ref == "hyprland/language") {
|
||||||
return new waybar::modules::hyprland::Language(id, bar_, config_[name]);
|
return new waybar::modules::hyprland::Language(id, bar_, config_[name]);
|
||||||
}
|
}
|
||||||
@@ -221,6 +232,14 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name,
|
|||||||
if (ref == "niri/workspaces") {
|
if (ref == "niri/workspaces") {
|
||||||
return new waybar::modules::niri::Workspaces(id, bar_, config_[name]);
|
return new waybar::modules::niri::Workspaces(id, bar_, config_[name]);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_WAYFIRE
|
||||||
|
if (ref == "wayfire/window") {
|
||||||
|
return new waybar::modules::wayfire::Window(id, bar_, config_[name]);
|
||||||
|
}
|
||||||
|
if (ref == "wayfire/workspaces") {
|
||||||
|
return new waybar::modules::wayfire::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]);
|
||||||
@@ -324,13 +343,18 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name,
|
|||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_LIBCAVA
|
#ifdef HAVE_LIBCAVA
|
||||||
if (ref == "cava") {
|
if (ref == "cava") {
|
||||||
return new waybar::modules::Cava(id, config_[name]);
|
return new waybar::modules::cava::Cava(id, config_[name]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_SYSTEMD_MONITOR
|
#ifdef HAVE_SYSTEMD_MONITOR
|
||||||
if (ref == "systemd-failed-units") {
|
if (ref == "systemd-failed-units") {
|
||||||
return new waybar::modules::SystemdFailedUnits(id, config_[name]);
|
return new waybar::modules::SystemdFailedUnits(id, config_[name]);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_LIBGPS
|
||||||
|
if (ref == "gps") {
|
||||||
|
return new waybar::modules::Gps(id, config_[name]);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
if (ref == "temperature") {
|
if (ref == "temperature") {
|
||||||
return new waybar::modules::Temperature(id, config_[name]);
|
return new waybar::modules::Temperature(id, config_[name]);
|
||||||
|
|||||||
+125
-57
@@ -1,3 +1,4 @@
|
|||||||
|
#include <fcntl.h>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
@@ -6,27 +7,134 @@
|
|||||||
#include <list>
|
#include <list>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
#include "bar.hpp"
|
||||||
#include "client.hpp"
|
#include "client.hpp"
|
||||||
|
#include "util/SafeSignal.hpp"
|
||||||
|
|
||||||
std::mutex reap_mtx;
|
std::mutex reap_mtx;
|
||||||
std::list<pid_t> reap;
|
std::list<pid_t> reap;
|
||||||
volatile bool reload;
|
|
||||||
|
|
||||||
void* signalThread(void* args) {
|
static int signal_pipe_write_fd;
|
||||||
int err;
|
|
||||||
int signum;
|
// Write a single signal to `signal_pipe_write_fd`.
|
||||||
sigset_t mask;
|
// This function is set as a signal handler, so it must be async-signal-safe.
|
||||||
sigemptyset(&mask);
|
static void writeSignalToPipe(int signum) {
|
||||||
sigaddset(&mask, SIGCHLD);
|
ssize_t amt = write(signal_pipe_write_fd, &signum, sizeof(int));
|
||||||
|
|
||||||
|
// There's not much we can safely do inside of a signal handler.
|
||||||
|
// Let's just ignore any errors.
|
||||||
|
(void)amt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This initializes `signal_pipe_write_fd`, and sets up signal handlers.
|
||||||
|
//
|
||||||
|
// This function will run forever, emitting every `SIGUSR1`, `SIGUSR2`,
|
||||||
|
// `SIGINT`, `SIGCHLD`, and `SIGRTMIN + 1`...`SIGRTMAX` signal received
|
||||||
|
// to `signal_handler`.
|
||||||
|
static void catchSignals(waybar::SafeSignal<int>& signal_handler) {
|
||||||
|
int fd[2];
|
||||||
|
pipe(fd);
|
||||||
|
|
||||||
|
int signal_pipe_read_fd = fd[0];
|
||||||
|
signal_pipe_write_fd = fd[1];
|
||||||
|
|
||||||
|
// This pipe should be able to buffer ~thousands of signals. If it fills up,
|
||||||
|
// we'll drop signals instead of blocking.
|
||||||
|
|
||||||
|
// We can't allow the write end to block because we'll be writing to it in a
|
||||||
|
// signal handler, which could interrupt the loop that's reading from it and
|
||||||
|
// deadlock.
|
||||||
|
|
||||||
|
fcntl(signal_pipe_write_fd, F_SETFL, O_NONBLOCK);
|
||||||
|
|
||||||
|
std::signal(SIGUSR1, writeSignalToPipe);
|
||||||
|
std::signal(SIGUSR2, writeSignalToPipe);
|
||||||
|
std::signal(SIGINT, writeSignalToPipe);
|
||||||
|
std::signal(SIGCHLD, writeSignalToPipe);
|
||||||
|
|
||||||
|
for (int sig = SIGRTMIN + 1; sig <= SIGRTMAX; ++sig) {
|
||||||
|
std::signal(sig, writeSignalToPipe);
|
||||||
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
err = sigwait(&mask, &signum);
|
int signum;
|
||||||
if (err != 0) {
|
ssize_t amt = read(signal_pipe_read_fd, &signum, sizeof(int));
|
||||||
spdlog::error("sigwait failed: {}", strerror(errno));
|
if (amt < 0) {
|
||||||
|
spdlog::error("read from signal pipe failed with error {}, closing thread", strerror(errno));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (amt != sizeof(int)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signal_handler.emit(signum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
waybar::util::KillSignalAction getActionForBar(waybar::Bar* bar, int signal) {
|
||||||
|
switch (signal) {
|
||||||
|
case SIGUSR1:
|
||||||
|
return bar->getOnSigusr1Action();
|
||||||
|
case SIGUSR2:
|
||||||
|
return bar->getOnSigusr2Action();
|
||||||
|
default:
|
||||||
|
return waybar::util::KillSignalAction::NOOP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleUserSignal(int signal, bool& reload) {
|
||||||
|
int i = 0;
|
||||||
|
for (auto& bar : waybar::Client::inst()->bars) {
|
||||||
|
switch (getActionForBar(bar.get(), signal)) {
|
||||||
|
case waybar::util::KillSignalAction::HIDE:
|
||||||
|
spdlog::debug("Visibility 'hide' for bar ", i);
|
||||||
|
bar->hide();
|
||||||
|
break;
|
||||||
|
case waybar::util::KillSignalAction::SHOW:
|
||||||
|
spdlog::debug("Visibility 'show' for bar ", i);
|
||||||
|
bar->show();
|
||||||
|
break;
|
||||||
|
case waybar::util::KillSignalAction::TOGGLE:
|
||||||
|
spdlog::debug("Visibility 'toggle' for bar ", i);
|
||||||
|
bar->toggle();
|
||||||
|
break;
|
||||||
|
case waybar::util::KillSignalAction::RELOAD:
|
||||||
|
spdlog::info("Reloading...");
|
||||||
|
reload = true;
|
||||||
|
waybar::Client::inst()->reset();
|
||||||
|
return;
|
||||||
|
case waybar::util::KillSignalAction::NOOP:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must be called on the main thread.
|
||||||
|
//
|
||||||
|
// If this signal should restart or close the bar, this function will write
|
||||||
|
// `true` or `false`, respectively, into `reload`.
|
||||||
|
static void handleSignalMainThread(int signum, bool& reload) {
|
||||||
|
if (signum >= SIGRTMIN + 1 && signum <= SIGRTMAX) {
|
||||||
|
for (auto& bar : waybar::Client::inst()->bars) {
|
||||||
|
bar->handleSignal(signum);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (signum) {
|
switch (signum) {
|
||||||
|
case SIGUSR1:
|
||||||
|
handleUserSignal(SIGUSR1, reload);
|
||||||
|
break;
|
||||||
|
case SIGUSR2:
|
||||||
|
handleUserSignal(SIGUSR2, reload);
|
||||||
|
break;
|
||||||
|
case SIGINT:
|
||||||
|
spdlog::info("Quitting.");
|
||||||
|
reload = false;
|
||||||
|
waybar::Client::inst()->reset();
|
||||||
|
break;
|
||||||
case SIGCHLD:
|
case SIGCHLD:
|
||||||
spdlog::debug("Received SIGCHLD in signalThread");
|
spdlog::debug("Received SIGCHLD in signalThread");
|
||||||
if (!reap.empty()) {
|
if (!reap.empty()) {
|
||||||
@@ -45,61 +153,21 @@ void* signalThread(void* args) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void startSignalThread() {
|
|
||||||
int err;
|
|
||||||
sigset_t mask;
|
|
||||||
sigemptyset(&mask);
|
|
||||||
sigaddset(&mask, SIGCHLD);
|
|
||||||
|
|
||||||
// Block SIGCHLD so it can be handled by the signal thread
|
|
||||||
// Any threads created by this one (the main thread) should not
|
|
||||||
// modify their signal mask to unblock SIGCHLD
|
|
||||||
err = pthread_sigmask(SIG_BLOCK, &mask, nullptr);
|
|
||||||
if (err != 0) {
|
|
||||||
spdlog::error("pthread_sigmask failed in startSignalThread: {}", strerror(err));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_t thread_id;
|
|
||||||
err = pthread_create(&thread_id, nullptr, signalThread, nullptr);
|
|
||||||
if (err != 0) {
|
|
||||||
spdlog::error("pthread_create failed in startSignalThread: {}", strerror(err));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
try {
|
try {
|
||||||
auto* client = waybar::Client::inst();
|
auto* client = waybar::Client::inst();
|
||||||
|
|
||||||
std::signal(SIGUSR1, [](int /*signal*/) {
|
bool reload;
|
||||||
for (auto& bar : waybar::Client::inst()->bars) {
|
|
||||||
bar->toggle();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
std::signal(SIGUSR2, [](int /*signal*/) {
|
waybar::SafeSignal<int> posix_signal_received;
|
||||||
spdlog::info("Reloading...");
|
posix_signal_received.connect([&](int signum) { handleSignalMainThread(signum, reload); });
|
||||||
reload = true;
|
|
||||||
waybar::Client::inst()->reset();
|
|
||||||
});
|
|
||||||
|
|
||||||
std::signal(SIGINT, [](int /*signal*/) {
|
std::thread signal_thread([&]() { catchSignals(posix_signal_received); });
|
||||||
spdlog::info("Quitting.");
|
|
||||||
reload = false;
|
|
||||||
waybar::Client::inst()->reset();
|
|
||||||
});
|
|
||||||
|
|
||||||
for (int sig = SIGRTMIN + 1; sig <= SIGRTMAX; ++sig) {
|
// Every `std::thread` must be joined or detached.
|
||||||
std::signal(sig, [](int sig) {
|
// This thread should run forever, so detach it.
|
||||||
for (auto& bar : waybar::Client::inst()->bars) {
|
signal_thread.detach();
|
||||||
bar->handleSignal(sig);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
startSignalThread();
|
|
||||||
|
|
||||||
auto ret = 0;
|
auto ret = 0;
|
||||||
do {
|
do {
|
||||||
|
|||||||
@@ -38,10 +38,20 @@ auto waybar::modules::Backlight::update() -> void {
|
|||||||
event_box_.show();
|
event_box_.show();
|
||||||
const uint8_t percent =
|
const uint8_t percent =
|
||||||
best->get_max() == 0 ? 100 : round(best->get_actual() * 100.0f / best->get_max());
|
best->get_max() == 0 ? 100 : round(best->get_actual() * 100.0f / best->get_max());
|
||||||
std::string desc = fmt::format(fmt::runtime(format_), fmt::arg("percent", percent),
|
|
||||||
|
// Get the state and apply state-specific format if available
|
||||||
|
auto state = getState(percent);
|
||||||
|
std::string current_format = format_;
|
||||||
|
if (!state.empty()) {
|
||||||
|
std::string state_format_name = "format-" + state;
|
||||||
|
if (config_[state_format_name].isString()) {
|
||||||
|
current_format = config_[state_format_name].asString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string desc = fmt::format(fmt::runtime(current_format), fmt::arg("percent", percent),
|
||||||
fmt::arg("icon", getIcon(percent)));
|
fmt::arg("icon", getIcon(percent)));
|
||||||
label_.set_markup(desc);
|
label_.set_markup(desc);
|
||||||
getState(percent);
|
|
||||||
if (tooltipEnabled()) {
|
if (tooltipEnabled()) {
|
||||||
std::string tooltip_format;
|
std::string tooltip_format;
|
||||||
if (config_["tooltip-format"].isString()) {
|
if (config_["tooltip-format"].isString()) {
|
||||||
|
|||||||
+35
-6
@@ -1,14 +1,16 @@
|
|||||||
#include "modules/battery.hpp"
|
#include "modules/battery.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
|
#include "util/command.hpp"
|
||||||
#if defined(__FreeBSD__)
|
#if defined(__FreeBSD__)
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
#endif
|
#endif
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
waybar::modules::Battery::Battery(const std::string& id, const Bar& bar, const Json::Value& config)
|
waybar::modules::Battery::Battery(const std::string& id, const Bar& bar, const Json::Value& config)
|
||||||
: ALabel(config, "battery", id, "{capacity}%", 60), bar_(bar) {
|
: ALabel(config, "battery", id, "{capacity}%", 60), last_event_(""), bar_(bar) {
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
battery_watch_fd_ = inotify_init1(IN_CLOEXEC);
|
battery_watch_fd_ = inotify_init1(IN_CLOEXEC);
|
||||||
if (battery_watch_fd_ == -1) {
|
if (battery_watch_fd_ == -1) {
|
||||||
@@ -26,6 +28,7 @@ waybar::modules::Battery::Battery(const std::string& id, const Bar& bar, const J
|
|||||||
throw std::runtime_error("Could not watch for battery plug/unplug");
|
throw std::runtime_error("Could not watch for battery plug/unplug");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
spdlog::debug("battery: worker interval is {}", interval_.count());
|
||||||
worker();
|
worker();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -677,18 +680,22 @@ auto waybar::modules::Battery::update() -> void {
|
|||||||
}
|
}
|
||||||
auto status_pretty = status;
|
auto status_pretty = status;
|
||||||
// Transform to lowercase and replace space with dash
|
// Transform to lowercase and replace space with dash
|
||||||
std::transform(status.begin(), status.end(), status.begin(),
|
std::ranges::transform(status.begin(), status.end(), status.begin(),
|
||||||
[](char ch) { return ch == ' ' ? '-' : std::tolower(ch); });
|
[](char ch) { return ch == ' ' ? '-' : std::tolower(ch); });
|
||||||
auto format = format_;
|
auto format = format_;
|
||||||
auto state = getState(capacity, true);
|
auto state = getState(capacity, true);
|
||||||
|
processEvents(state, status, capacity);
|
||||||
setBarClass(state);
|
setBarClass(state);
|
||||||
auto time_remaining_formatted = formatTimeRemaining(time_remaining);
|
auto time_remaining_formatted = formatTimeRemaining(time_remaining);
|
||||||
if (tooltipEnabled()) {
|
if (tooltipEnabled()) {
|
||||||
std::string tooltip_text_default;
|
std::string tooltip_text_default;
|
||||||
std::string tooltip_format = "{timeTo}";
|
std::string tooltip_format = "{timeTo}";
|
||||||
if (time_remaining != 0) {
|
if (time_remaining != 0) {
|
||||||
std::string time_to = std::string("Time to ") + ((time_remaining > 0) ? "empty" : "full");
|
if (time_remaining > 0) {
|
||||||
tooltip_text_default = time_to + ": " + time_remaining_formatted;
|
tooltip_text_default = std::string("Empty in ") + time_remaining_formatted;
|
||||||
|
} else {
|
||||||
|
tooltip_text_default = std::string("Full in ") + time_remaining_formatted;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
tooltip_text_default = status_pretty;
|
tooltip_text_default = status_pretty;
|
||||||
}
|
}
|
||||||
@@ -701,7 +708,7 @@ auto waybar::modules::Battery::update() -> void {
|
|||||||
} else if (config_["tooltip-format"].isString()) {
|
} else if (config_["tooltip-format"].isString()) {
|
||||||
tooltip_format = config_["tooltip-format"].asString();
|
tooltip_format = config_["tooltip-format"].asString();
|
||||||
}
|
}
|
||||||
label_.set_tooltip_text(
|
label_.set_tooltip_markup(
|
||||||
fmt::format(fmt::runtime(tooltip_format), fmt::arg("timeTo", tooltip_text_default),
|
fmt::format(fmt::runtime(tooltip_format), fmt::arg("timeTo", tooltip_text_default),
|
||||||
fmt::arg("power", power), fmt::arg("capacity", capacity),
|
fmt::arg("power", power), fmt::arg("capacity", capacity),
|
||||||
fmt::arg("time", time_remaining_formatted), fmt::arg("cycles", cycles),
|
fmt::arg("time", time_remaining_formatted), fmt::arg("cycles", cycles),
|
||||||
@@ -767,3 +774,25 @@ void waybar::modules::Battery::setBarClass(std::string& state) {
|
|||||||
bar_.window.get_style_context()->add_class(new_class);
|
bar_.window.get_style_context()->add_class(new_class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void waybar::modules::Battery::processEvents(std::string& state, std::string& status,
|
||||||
|
uint8_t capacity) {
|
||||||
|
// There are no events specified, skip
|
||||||
|
auto events = config_["events"];
|
||||||
|
if (!events.isObject() || events.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::string event_name = fmt::format("on-{}-{}", status == "discharging" ? status : "charging",
|
||||||
|
state.empty() ? std::to_string(capacity) : state);
|
||||||
|
if (last_event_ != event_name) {
|
||||||
|
spdlog::debug("battery: triggering event {}", event_name);
|
||||||
|
if (events[event_name].isString()) {
|
||||||
|
std::string exec = events[event_name].asString();
|
||||||
|
// Execute the command if it is not empty
|
||||||
|
if (!exec.empty()) {
|
||||||
|
util::command::exec(exec, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
last_event_ = event_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user