Merge branch 'Alexays:master' into master
This commit is contained in:
commit
8e2a742042
|
@ -16,4 +16,5 @@ jobs:
|
||||||
with:
|
with:
|
||||||
source: "."
|
source: "."
|
||||||
extensions: "hpp,h,cpp,c"
|
extensions: "hpp,h,cpp,c"
|
||||||
clangFormatVersion: 16
|
style: "file:.clang-format"
|
||||||
|
clangFormatVersion: 18
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
- Sway (Workspaces, Binding mode, Focused window name)
|
- Sway (Workspaces, Binding mode, Focused window name)
|
||||||
- River (Mapping mode, Tags, Focused window name)
|
- River (Mapping mode, Tags, Focused window name)
|
||||||
- Hyprland (Window Icons, Workspaces, Focused window name)
|
- Hyprland (Window Icons, Workspaces, Focused window name)
|
||||||
|
- Niri (Workspaces, Focused window name, Language)
|
||||||
- DWL (Tags, Focused window name) [requires dwl ipc patch](https://github.com/djpohly/dwl/wiki/ipc)
|
- DWL (Tags, Focused window name) [requires dwl ipc patch](https://github.com/djpohly/dwl/wiki/ipc)
|
||||||
- Tray [#21](https://github.com/Alexays/Waybar/issues/21)
|
- Tray [#21](https://github.com/Alexays/Waybar/issues/21)
|
||||||
- Local time
|
- Local time
|
||||||
|
|
|
@ -18,11 +18,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1722185531,
|
"lastModified": 1724819573,
|
||||||
"narHash": "sha256-veKR07psFoJjINLC8RK4DiLniGGMgF3QMlS4tb74S6k=",
|
"narHash": "sha256-GnR7/ibgIH1vhoy8cYdmXE6iyZqKqFxQSVkFgosBh6w=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "52ec9ac3b12395ad677e8b62106f0b98c1f8569d",
|
"rev": "71e91c409d1e654808b2621f28a327acfdad8dc2",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
@ -51,8 +51,8 @@ class Clock final : public ALabel {
|
||||||
day cldBaseDay_{0}; // calendar Cached day. Is used when today is changing(midnight)
|
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
|
||||||
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 year_month_day& today, const year_month_day& ymd,
|
||||||
-> const std::string;
|
const time_zone* tz) -> const std::string;
|
||||||
|
|
||||||
// get local time zone
|
// get local time zone
|
||||||
auto local_zone() -> const time_zone*;
|
auto local_zone() -> const time_zone*;
|
||||||
|
|
|
@ -61,8 +61,8 @@ class Workspaces : public AModule, public EventHandler {
|
||||||
// Config
|
// Config
|
||||||
void parseConfig(const Json::Value& config);
|
void parseConfig(const Json::Value& config);
|
||||||
auto populateIconsMap(const Json::Value& formatIcons) -> void;
|
auto populateIconsMap(const Json::Value& formatIcons) -> void;
|
||||||
static auto populateBoolConfig(const Json::Value& config, const std::string& key, bool& member)
|
static auto populateBoolConfig(const Json::Value& config, const std::string& key,
|
||||||
-> void;
|
bool& member) -> void;
|
||||||
auto populateSortByConfig(const Json::Value& config) -> void;
|
auto populateSortByConfig(const Json::Value& config) -> void;
|
||||||
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;
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include "util/json.hpp"
|
||||||
|
|
||||||
|
namespace waybar::modules::niri {
|
||||||
|
|
||||||
|
class EventHandler {
|
||||||
|
public:
|
||||||
|
virtual void onEvent(const Json::Value& ev) = 0;
|
||||||
|
virtual ~EventHandler() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IPC {
|
||||||
|
public:
|
||||||
|
IPC() { startIPC(); }
|
||||||
|
|
||||||
|
void registerForIPC(const std::string& ev, EventHandler* ev_handler);
|
||||||
|
void unregisterForIPC(EventHandler* handler);
|
||||||
|
|
||||||
|
static Json::Value send(const Json::Value& request);
|
||||||
|
|
||||||
|
// The data members are only safe to access while dataMutex_ is locked.
|
||||||
|
std::lock_guard<std::mutex> lockData() { return std::lock_guard(dataMutex_); }
|
||||||
|
const std::vector<Json::Value>& workspaces() const { return workspaces_; }
|
||||||
|
const std::vector<Json::Value>& windows() const { return windows_; }
|
||||||
|
const std::vector<std::string>& keyboardLayoutNames() const { return keyboardLayoutNames_; }
|
||||||
|
unsigned keyboardLayoutCurrent() const { return keyboardLayoutCurrent_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void startIPC();
|
||||||
|
static int connectToSocket();
|
||||||
|
void parseIPC(const std::string&);
|
||||||
|
|
||||||
|
std::mutex dataMutex_;
|
||||||
|
std::vector<Json::Value> workspaces_;
|
||||||
|
std::vector<Json::Value> windows_;
|
||||||
|
std::vector<std::string> keyboardLayoutNames_;
|
||||||
|
unsigned keyboardLayoutCurrent_;
|
||||||
|
|
||||||
|
util::JsonParser parser_;
|
||||||
|
std::mutex callbackMutex_;
|
||||||
|
std::list<std::pair<std::string, EventHandler*>> callbacks_;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::unique_ptr<IPC> gIPC;
|
||||||
|
|
||||||
|
}; // namespace waybar::modules::niri
|
|
@ -0,0 +1,38 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "ALabel.hpp"
|
||||||
|
#include "bar.hpp"
|
||||||
|
#include "modules/niri/backend.hpp"
|
||||||
|
|
||||||
|
namespace waybar::modules::niri {
|
||||||
|
|
||||||
|
class Language : public ALabel, public EventHandler {
|
||||||
|
public:
|
||||||
|
Language(const std::string &, const Bar &, const Json::Value &);
|
||||||
|
~Language() override;
|
||||||
|
void update() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateFromIPC();
|
||||||
|
void onEvent(const Json::Value &ev) override;
|
||||||
|
void doUpdate();
|
||||||
|
|
||||||
|
struct Layout {
|
||||||
|
std::string full_name;
|
||||||
|
std::string short_name;
|
||||||
|
std::string variant;
|
||||||
|
std::string short_description;
|
||||||
|
};
|
||||||
|
|
||||||
|
static Layout getLayout(const std::string &fullName);
|
||||||
|
|
||||||
|
std::mutex mutex_;
|
||||||
|
const Bar &bar_;
|
||||||
|
|
||||||
|
std::vector<Layout> layouts_;
|
||||||
|
unsigned current_idx_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar::modules::niri
|
|
@ -0,0 +1,28 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gtkmm/button.h>
|
||||||
|
#include <json/value.h>
|
||||||
|
|
||||||
|
#include "AAppIconLabel.hpp"
|
||||||
|
#include "bar.hpp"
|
||||||
|
#include "modules/niri/backend.hpp"
|
||||||
|
|
||||||
|
namespace waybar::modules::niri {
|
||||||
|
|
||||||
|
class Window : public AAppIconLabel, public EventHandler {
|
||||||
|
public:
|
||||||
|
Window(const std::string &, const Bar &, const Json::Value &);
|
||||||
|
~Window() override;
|
||||||
|
void update() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void onEvent(const Json::Value &ev) override;
|
||||||
|
void doUpdate();
|
||||||
|
void setClass(const std::string &className, bool enable);
|
||||||
|
|
||||||
|
const Bar &bar_;
|
||||||
|
|
||||||
|
std::string oldAppId_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar::modules::niri
|
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gtkmm/button.h>
|
||||||
|
#include <json/value.h>
|
||||||
|
|
||||||
|
#include "AModule.hpp"
|
||||||
|
#include "bar.hpp"
|
||||||
|
#include "modules/niri/backend.hpp"
|
||||||
|
|
||||||
|
namespace waybar::modules::niri {
|
||||||
|
|
||||||
|
class Workspaces : public AModule, public EventHandler {
|
||||||
|
public:
|
||||||
|
Workspaces(const std::string &, const Bar &, const Json::Value &);
|
||||||
|
~Workspaces() override;
|
||||||
|
void update() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void onEvent(const Json::Value &ev) override;
|
||||||
|
void doUpdate();
|
||||||
|
Gtk::Button &addButton(const Json::Value &ws);
|
||||||
|
std::string getIcon(const std::string &value, const Json::Value &ws);
|
||||||
|
|
||||||
|
const Bar &bar_;
|
||||||
|
Gtk::Box box_;
|
||||||
|
// Map from niri workspace id to button.
|
||||||
|
std::unordered_map<uint64_t, Gtk::Button> buttons_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar::modules::niri
|
|
@ -622,8 +622,8 @@ inline auto convertInto(std::string const &source, bool &target) -> ParserResult
|
||||||
}
|
}
|
||||||
#ifdef CLARA_CONFIG_OPTIONAL_TYPE
|
#ifdef CLARA_CONFIG_OPTIONAL_TYPE
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline auto convertInto(std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T> &target)
|
inline auto convertInto(std::string const &source,
|
||||||
-> ParserResult {
|
CLARA_CONFIG_OPTIONAL_TYPE<T> &target) -> ParserResult {
|
||||||
T temp;
|
T temp;
|
||||||
auto result = convertInto(source, temp);
|
auto result = convertInto(source, temp);
|
||||||
if (result) target = std::move(temp);
|
if (result) target = std::move(temp);
|
||||||
|
@ -751,8 +751,8 @@ class ParserBase {
|
||||||
public:
|
public:
|
||||||
virtual ~ParserBase() = default;
|
virtual ~ParserBase() = default;
|
||||||
virtual auto validate() const -> Result { return Result::ok(); }
|
virtual auto validate() const -> Result { return Result::ok(); }
|
||||||
virtual auto parse(std::string const &exeName, TokenStream const &tokens) const
|
virtual auto parse(std::string const &exeName,
|
||||||
-> InternalParseResult = 0;
|
TokenStream const &tokens) const -> InternalParseResult = 0;
|
||||||
virtual auto cardinality() const -> size_t { return 1; }
|
virtual auto cardinality() const -> size_t { return 1; }
|
||||||
|
|
||||||
auto parse(Args const &args) const -> InternalParseResult {
|
auto parse(Args const &args) const -> InternalParseResult {
|
||||||
|
@ -1098,8 +1098,8 @@ struct Parser : ParserBase {
|
||||||
|
|
||||||
using ParserBase::parse;
|
using ParserBase::parse;
|
||||||
|
|
||||||
auto parse(std::string const &exeName, TokenStream const &tokens) const
|
auto parse(std::string const &exeName,
|
||||||
-> InternalParseResult override {
|
TokenStream const &tokens) const -> InternalParseResult override {
|
||||||
struct ParserInfo {
|
struct ParserInfo {
|
||||||
ParserBase const *parser = nullptr;
|
ParserBase const *parser = nullptr;
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
|
|
|
@ -38,7 +38,7 @@ The *backlight* module displays the current backlight level.
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
Positive value to rotate the text label.
|
Positive value to rotate the text label (in 90 degree increments).
|
||||||
|
|
||||||
*states*: ++
|
*states*: ++
|
||||||
typeof: object ++
|
typeof: object ++
|
||||||
|
|
|
@ -69,7 +69,7 @@ The *battery* module displays the current capacity and state (eg. charging) of y
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer++
|
typeof: integer++
|
||||||
Positive value to rotate the text label.
|
Positive value to rotate the text label (in 90 degree increments).
|
||||||
|
|
||||||
*on-click*: ++
|
*on-click*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
|
|
|
@ -54,7 +54,7 @@ Addressed by *bluetooth*
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
Positive value to rotate the text label.
|
Positive value to rotate the text label (in 90 degree increments).
|
||||||
|
|
||||||
*max-length*: ++
|
*max-length*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
|
|
|
@ -51,7 +51,7 @@ $XDG_CONFIG_HOME/waybar/config ++
|
||||||
|[ *rotate*
|
|[ *rotate*
|
||||||
:[ integer
|
:[ integer
|
||||||
:[
|
:[
|
||||||
:[ Positive value to rotate the text label
|
:[ Positive value to rotate the text label (in 90 degree increments)
|
||||||
|[ *on-click*
|
|[ *on-click*
|
||||||
:[ string
|
:[ string
|
||||||
:[
|
:[
|
||||||
|
|
|
@ -43,7 +43,7 @@ The *cpu* module displays the current CPU utilization.
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
Positive value to rotate the text label.
|
Positive value to rotate the text label (in 90 degree increments).
|
||||||
|
|
||||||
*states*: ++
|
*states*: ++
|
||||||
typeof: object ++
|
typeof: object ++
|
||||||
|
|
|
@ -64,7 +64,7 @@ Addressed by *custom/<name>*
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
Positive value to rotate the text label.
|
Positive value to rotate the text label (in 90 degree increments).
|
||||||
|
|
||||||
*max-length*: ++
|
*max-length*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
|
|
|
@ -29,7 +29,7 @@ Addressed by *disk*
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
Positive value to rotate the text label.
|
Positive value to rotate the text label (in 90 degree increments).
|
||||||
|
|
||||||
*states*: ++
|
*states*: ++
|
||||||
typeof: object ++
|
typeof: object ++
|
||||||
|
|
|
@ -19,7 +19,7 @@ Addressed by *dwl/window*
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
Positive value to rotate the text label.
|
Positive value to rotate the text label (in 90 degree increments).
|
||||||
|
|
||||||
*max-length*: ++
|
*max-length*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
|
|
|
@ -19,7 +19,7 @@ Addressed by *hyprland/submap*
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
Positive value to rotate the text label.
|
Positive value to rotate the text label (in 90 degree increments).
|
||||||
|
|
||||||
*max-length*: ++
|
*max-length*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
|
|
|
@ -21,7 +21,7 @@ screensaver, also known as "presentation mode".
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
Positive value to rotate the text label.
|
Positive value to rotate the text label (in 90 degree increments).
|
||||||
|
|
||||||
*max-length*: ++
|
*max-length*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
|
|
|
@ -25,7 +25,7 @@ See *systemd-inhibit*(1) for more information.
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
Positive value to rotate the text label.
|
Positive value to rotate the text label (in 90 degree increments).
|
||||||
|
|
||||||
*max-length*: ++
|
*max-length*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
|
|
|
@ -51,7 +51,7 @@ Addressed by *jack*
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
Positive value to rotate the text label.
|
Positive value to rotate the text label (in 90 degree increments).
|
||||||
|
|
||||||
*max-length*: ++
|
*max-length*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
|
|
|
@ -29,7 +29,7 @@ Addressed by *memory*
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
Positive value to rotate the text label.
|
Positive value to rotate the text label (in 90 degree increments).
|
||||||
|
|
||||||
*states*: ++
|
*states*: ++
|
||||||
typeof: object ++
|
typeof: object ++
|
||||||
|
|
|
@ -91,7 +91,7 @@ Addressed by *mpd*
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
Positive value to rotate the text label.
|
Positive value to rotate the text label (in 90 degree increments).
|
||||||
|
|
||||||
*max-length*: ++
|
*max-length*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
|
|
|
@ -107,7 +107,7 @@ The *mpris* module displays currently playing media via libplayerctl.
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
Positive value to rotate the text label.
|
Positive value to rotate the text label (in 90 degree increments).
|
||||||
|
|
||||||
*max-length*: ++
|
*max-length*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
|
|
|
@ -58,7 +58,7 @@ Addressed by *network*
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
Positive value to rotate the text label.
|
Positive value to rotate the text label (in 90 degree increments).
|
||||||
|
|
||||||
*max-length*: ++
|
*max-length*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
waybar-niri-language(5)
|
||||||
|
|
||||||
|
# NAME
|
||||||
|
|
||||||
|
waybar - niri language module
|
||||||
|
|
||||||
|
# DESCRIPTION
|
||||||
|
|
||||||
|
The *language* module displays the currently selected language in niri.
|
||||||
|
|
||||||
|
# CONFIGURATION
|
||||||
|
|
||||||
|
Addressed by *niri/language*
|
||||||
|
|
||||||
|
*format*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: {} ++
|
||||||
|
The format, how information should be displayed.
|
||||||
|
|
||||||
|
*format-<lang>* ++
|
||||||
|
typeof: string++
|
||||||
|
Provide an alternative name to display per language where <lang> is the language of your choosing. Can be passed multiple times with multiple languages as shown by the example below.
|
||||||
|
|
||||||
|
*menu*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Action that popups the menu.
|
||||||
|
|
||||||
|
*menu-file*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Location of the menu descriptor file. There need to be an element of type GtkMenu with id *menu*
|
||||||
|
|
||||||
|
*menu-actions*: ++
|
||||||
|
typeof: array ++
|
||||||
|
The actions corresponding to the buttons of the menu.
|
||||||
|
|
||||||
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
|
*{short}*: Short name of layout (e.g. "us"). Equals to {}.
|
||||||
|
|
||||||
|
*{shortDescription}*: Short description of layout (e.g. "en").
|
||||||
|
|
||||||
|
*{long}*: Long name of layout (e.g. "English (Dvorak)").
|
||||||
|
|
||||||
|
*{variant}*: Variant of layout (e.g. "dvorak").
|
||||||
|
|
||||||
|
# EXAMPLES
|
||||||
|
|
||||||
|
```
|
||||||
|
"niri/language": {
|
||||||
|
"format": "Lang: {long}"
|
||||||
|
"format-en": "AMERICA, HELL YEAH!"
|
||||||
|
"format-tr": "As bayrakları"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# STYLE
|
||||||
|
|
||||||
|
- *#language*
|
|
@ -0,0 +1,81 @@
|
||||||
|
waybar-niri-window(5)
|
||||||
|
|
||||||
|
# NAME
|
||||||
|
|
||||||
|
waybar - niri window module
|
||||||
|
|
||||||
|
# DESCRIPTION
|
||||||
|
|
||||||
|
The *window* module displays the title of the currently focused window in niri.
|
||||||
|
|
||||||
|
# CONFIGURATION
|
||||||
|
|
||||||
|
Addressed by *niri/window*
|
||||||
|
|
||||||
|
*format*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: {title} ++
|
||||||
|
The format, how information should be displayed. On {} the current window title is displayed.
|
||||||
|
|
||||||
|
*rewrite*: ++
|
||||||
|
typeof: object ++
|
||||||
|
Rules to rewrite window title. See *rewrite rules*.
|
||||||
|
|
||||||
|
*separate-outputs*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
Show the active window of the monitor the bar belongs to, instead of the focused window.
|
||||||
|
|
||||||
|
*icon*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: false ++
|
||||||
|
Option to hide the application icon.
|
||||||
|
|
||||||
|
*icon-size*: ++
|
||||||
|
typeof: integer ++
|
||||||
|
default: 24 ++
|
||||||
|
Option to change the size of the application icon.
|
||||||
|
|
||||||
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
|
See the output of "niri msg windows" for examples
|
||||||
|
|
||||||
|
*{title}*: The current title of the focused window.
|
||||||
|
|
||||||
|
*{app_id}*: The current app ID of the focused window.
|
||||||
|
|
||||||
|
# REWRITE RULES
|
||||||
|
|
||||||
|
*rewrite* is an object where keys are regular expressions and values are
|
||||||
|
rewrite rules if the expression matches. Rules may contain references to
|
||||||
|
captures of the expression.
|
||||||
|
|
||||||
|
Regular expression and replacement follow ECMA-script rules.
|
||||||
|
|
||||||
|
If no expression matches, the title is left unchanged.
|
||||||
|
|
||||||
|
Invalid expressions (e.g., mismatched parentheses) are skipped.
|
||||||
|
|
||||||
|
# EXAMPLES
|
||||||
|
|
||||||
|
```
|
||||||
|
"niri/window": {
|
||||||
|
"format": "{}",
|
||||||
|
"rewrite": {
|
||||||
|
"(.*) - Mozilla Firefox": "🌎 $1",
|
||||||
|
"(.*) - zsh": "> [$1]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# STYLE
|
||||||
|
|
||||||
|
- *#window*
|
||||||
|
- *window#waybar.empty #window* When no windows are on the workspace
|
||||||
|
|
||||||
|
The following classes are applied to the entire Waybar rather than just the
|
||||||
|
window widget:
|
||||||
|
|
||||||
|
- *window#waybar.empty* When no windows are in the workspace
|
||||||
|
- *window#waybar.solo* When only one window is on the workspace
|
||||||
|
- *window#waybar.<app-id>* Where *app-id* is the app ID of the only window on
|
||||||
|
the workspace
|
|
@ -0,0 +1,97 @@
|
||||||
|
waybar-niri-workspaces(5)
|
||||||
|
|
||||||
|
# NAME
|
||||||
|
|
||||||
|
waybar - niri workspaces module
|
||||||
|
|
||||||
|
# DESCRIPTION
|
||||||
|
|
||||||
|
The *workspaces* module displays the currently used workspaces in niri.
|
||||||
|
|
||||||
|
# CONFIGURATION
|
||||||
|
|
||||||
|
Addressed by *niri/workspaces*
|
||||||
|
|
||||||
|
*all-outputs*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: false ++
|
||||||
|
If set to false, workspaces will only be shown on the output they are on. If set to true all workspaces will be shown on every output.
|
||||||
|
|
||||||
|
*format*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: {value} ++
|
||||||
|
The format, how information should be displayed.
|
||||||
|
|
||||||
|
*format-icons*: ++
|
||||||
|
typeof: array ++
|
||||||
|
Based on the workspace name, index and state, the corresponding icon gets selected. See *icons*.
|
||||||
|
|
||||||
|
*disable-click*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: false ++
|
||||||
|
If set to false, you can click to change workspace. If set to true this behaviour is disabled.
|
||||||
|
|
||||||
|
*disable-markup*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: false ++
|
||||||
|
If set to true, button label will escape pango markup.
|
||||||
|
|
||||||
|
*current-only*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: false ++
|
||||||
|
If set to true, only the active or focused workspace will be shown.
|
||||||
|
|
||||||
|
*on-update*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Command to execute when the module is updated.
|
||||||
|
|
||||||
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
|
*{value}*: Name of the workspace, or index for unnamed workspaces,
|
||||||
|
as defined by niri.
|
||||||
|
|
||||||
|
*{name}*: Name of the workspace for named workspaces.
|
||||||
|
|
||||||
|
*{icon}*: Icon, as defined in *format-icons*.
|
||||||
|
|
||||||
|
*{index}*: Index of the workspace on its output.
|
||||||
|
|
||||||
|
*{output}*: Output where the workspace is located.
|
||||||
|
|
||||||
|
# ICONS
|
||||||
|
|
||||||
|
Additional to workspace name matching, the following *format-icons* can be set.
|
||||||
|
|
||||||
|
- *default*: Will be shown, when no string matches are found.
|
||||||
|
- *focused*: Will be shown, when workspace is focused.
|
||||||
|
- *active*: Will be shown, when workspace is active on its output.
|
||||||
|
|
||||||
|
# EXAMPLES
|
||||||
|
|
||||||
|
```
|
||||||
|
"niri/workspaces": {
|
||||||
|
"format": "{icon}",
|
||||||
|
"format-icons": {
|
||||||
|
// Named workspaces
|
||||||
|
// (you need to configure them in niri)
|
||||||
|
"browser": "",
|
||||||
|
"discord": "",
|
||||||
|
"chat": "<b></b>",
|
||||||
|
|
||||||
|
// Icons by state
|
||||||
|
"active": "",
|
||||||
|
"default": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Style
|
||||||
|
|
||||||
|
- *#workspaces button*
|
||||||
|
- *#workspaces button.focused*: The single focused workspace.
|
||||||
|
- *#workspaces button.active*: The workspace is active (visible) on its output.
|
||||||
|
- *#workspaces button.empty*: The workspace is empty.
|
||||||
|
- *#workspaces button.current_output*: The workspace is from the same output as
|
||||||
|
the bar that it is displayed on.
|
||||||
|
- *#workspaces button#niri-workspace-<name>*: Workspaces named this, or index
|
||||||
|
for unnamed workspaces.
|
|
@ -40,7 +40,7 @@ Additionally, you can control the volume by scrolling *up* or *down* while the c
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
Positive value to rotate the text label.
|
Positive value to rotate the text label (in 90 degree increments).
|
||||||
|
|
||||||
*states*: ++
|
*states*: ++
|
||||||
typeof: object ++
|
typeof: object ++
|
||||||
|
|
|
@ -21,7 +21,7 @@ Addressed by *river/layout*
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
Positive value to rotate the text label.
|
Positive value to rotate the text label (in 90 degree increments).
|
||||||
|
|
||||||
*max-length*: ++
|
*max-length*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
|
|
|
@ -19,7 +19,7 @@ Addressed by *river/mode*
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
Positive value to rotate the text label.
|
Positive value to rotate the text label (in 90 degree increments).
|
||||||
|
|
||||||
*max-length*: ++
|
*max-length*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
|
|
|
@ -19,7 +19,7 @@ Addressed by *river/window*
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
Positive value to rotate the text label.
|
Positive value to rotate the text label (in 90 degree increments).
|
||||||
|
|
||||||
*max-length*: ++
|
*max-length*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
|
|
|
@ -20,7 +20,7 @@ cursor is over the module, and clicking on the module toggles mute.
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
Positive value to rotate the text label.
|
Positive value to rotate the text label (in 90 degree increments).
|
||||||
|
|
||||||
*max-length*: ++
|
*max-length*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
|
|
|
@ -19,7 +19,7 @@ Addressed by *sway/mode*
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
Positive value to rotate the text label.
|
Positive value to rotate the text label (in 90 degree increments).
|
||||||
|
|
||||||
*max-length*: ++
|
*max-length*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
|
|
|
@ -19,7 +19,7 @@ Addressed by *sway/window*
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
Positive value to rotate the text label.
|
Positive value to rotate the text label (in 90 degree increments).
|
||||||
|
|
||||||
*max-length*: ++
|
*max-length*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
|
|
|
@ -60,7 +60,7 @@ Addressed by *temperature*
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
Positive value to rotate the text label.
|
Positive value to rotate the text label (in 90 degree increments).
|
||||||
|
|
||||||
*max-length*: ++
|
*max-length*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
|
|
|
@ -31,7 +31,7 @@ The *wireplumber* module displays the current volume reported by WirePlumber.
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
Positive value to rotate the text label.
|
Positive value to rotate the text label (in 90 degree increments).
|
||||||
|
|
||||||
*states*: ++
|
*states*: ++
|
||||||
typeof: object ++
|
typeof: object ++
|
||||||
|
|
|
@ -323,6 +323,9 @@ A group may hide all but one element, showing them only on mouse hover. In order
|
||||||
- *waybar-hyprland-submap(5)*
|
- *waybar-hyprland-submap(5)*
|
||||||
- *waybar-hyprland-window(5)*
|
- *waybar-hyprland-window(5)*
|
||||||
- *waybar-hyprland-workspaces(5)*
|
- *waybar-hyprland-workspaces(5)*
|
||||||
|
- *waybar-niri-language(5)*
|
||||||
|
- *waybar-niri-window(5)*
|
||||||
|
- *waybar-niri-workspaces(5)*
|
||||||
- *waybar-idle-inhibitor(5)*
|
- *waybar-idle-inhibitor(5)*
|
||||||
- *waybar-image(5)*
|
- *waybar-image(5)*
|
||||||
- *waybar-inhibitor(5)*
|
- *waybar-inhibitor(5)*
|
||||||
|
|
19
meson.build
19
meson.build
|
@ -1,6 +1,6 @@
|
||||||
project(
|
project(
|
||||||
'waybar', 'cpp', 'c',
|
'waybar', 'cpp', 'c',
|
||||||
version: '0.10.4',
|
version: '0.11.0',
|
||||||
license: 'MIT',
|
license: 'MIT',
|
||||||
meson_version: '>= 0.59.0',
|
meson_version: '>= 0.59.0',
|
||||||
default_options : [
|
default_options : [
|
||||||
|
@ -69,7 +69,7 @@ is_openbsd = host_machine.system() == 'openbsd'
|
||||||
|
|
||||||
thread_dep = dependency('threads')
|
thread_dep = dependency('threads')
|
||||||
fmt = dependency('fmt', version : ['>=8.1.1'], fallback : ['fmt', 'fmt_dep'])
|
fmt = dependency('fmt', version : ['>=8.1.1'], fallback : ['fmt', 'fmt_dep'])
|
||||||
spdlog = dependency('spdlog', version : ['>=1.10.0'], fallback : ['spdlog', 'spdlog_dep'], default_options : ['external_fmt=enabled'])
|
spdlog = dependency('spdlog', version : ['>=1.10.0'], fallback : ['spdlog', 'spdlog_dep'], default_options : ['external_fmt=enabled', 'std_format=disabled', 'tests=disabled'])
|
||||||
wayland_client = dependency('wayland-client')
|
wayland_client = dependency('wayland-client')
|
||||||
wayland_cursor = dependency('wayland-cursor')
|
wayland_cursor = dependency('wayland-cursor')
|
||||||
wayland_protos = dependency('wayland-protocols')
|
wayland_protos = dependency('wayland-protocols')
|
||||||
|
@ -318,6 +318,21 @@ if true
|
||||||
)
|
)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if get_option('niri')
|
||||||
|
add_project_arguments('-DHAVE_NIRI', language: 'cpp')
|
||||||
|
src_files += files(
|
||||||
|
'src/modules/niri/backend.cpp',
|
||||||
|
'src/modules/niri/language.cpp',
|
||||||
|
'src/modules/niri/window.cpp',
|
||||||
|
'src/modules/niri/workspaces.cpp',
|
||||||
|
)
|
||||||
|
man_files += files(
|
||||||
|
'man/waybar-niri-language.5.scd',
|
||||||
|
'man/waybar-niri-window.5.scd',
|
||||||
|
'man/waybar-niri-workspaces.5.scd',
|
||||||
|
)
|
||||||
|
endif
|
||||||
|
|
||||||
if libnl.found() and libnlgen.found()
|
if libnl.found() and libnlgen.found()
|
||||||
add_project_arguments('-DHAVE_LIBNL', language: 'cpp')
|
add_project_arguments('-DHAVE_LIBNL', language: 'cpp')
|
||||||
src_files += files('src/modules/network.cpp')
|
src_files += files('src/modules/network.cpp')
|
||||||
|
|
|
@ -19,3 +19,4 @@ option('experimental', type : 'boolean', value : false, description: 'Enable exp
|
||||||
option('jack', type: 'feature', value: 'auto', description: 'Enable support for JACK')
|
option('jack', type: 'feature', value: 'auto', description: 'Enable support for JACK')
|
||||||
option('wireplumber', type: 'feature', value: 'auto', description: 'Enable support for WirePlumber')
|
option('wireplumber', type: 'feature', value: 'auto', description: 'Enable support for WirePlumber')
|
||||||
option('cava', type: 'feature', value: 'auto', description: 'Enable support for Cava')
|
option('cava', type: 'feature', value: 'auto', description: 'Enable support for Cava')
|
||||||
|
option('niri', type: 'boolean', description: 'Enable support for niri')
|
||||||
|
|
|
@ -45,6 +45,8 @@ ALabel::ALabel(const Json::Value& config, const std::string& name, const std::st
|
||||||
|
|
||||||
if (config_["rotate"].isUInt()) {
|
if (config_["rotate"].isUInt()) {
|
||||||
rotate = config["rotate"].asUInt();
|
rotate = config["rotate"].asUInt();
|
||||||
|
if (not(rotate == 0 || rotate == 90 || rotate == 180 || rotate == 270))
|
||||||
|
spdlog::warn("'rotate' is only supported in 90 degree increments {} is not valid.", rotate);
|
||||||
label_.set_angle(rotate);
|
label_.set_angle(rotate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,11 @@
|
||||||
#include "modules/hyprland/window.hpp"
|
#include "modules/hyprland/window.hpp"
|
||||||
#include "modules/hyprland/workspaces.hpp"
|
#include "modules/hyprland/workspaces.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_NIRI
|
||||||
|
#include "modules/niri/language.hpp"
|
||||||
|
#include "modules/niri/window.hpp"
|
||||||
|
#include "modules/niri/workspaces.hpp"
|
||||||
|
#endif
|
||||||
#if defined(__FreeBSD__) || defined(__linux__)
|
#if defined(__FreeBSD__) || defined(__linux__)
|
||||||
#include "modules/battery.hpp"
|
#include "modules/battery.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
@ -205,6 +210,17 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name,
|
||||||
if (ref == "hyprland/workspaces") {
|
if (ref == "hyprland/workspaces") {
|
||||||
return new waybar::modules::hyprland::Workspaces(id, bar_, config_[name]);
|
return new waybar::modules::hyprland::Workspaces(id, bar_, config_[name]);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NIRI
|
||||||
|
if (ref == "niri/language") {
|
||||||
|
return new waybar::modules::niri::Language(id, bar_, config_[name]);
|
||||||
|
}
|
||||||
|
if (ref == "niri/window") {
|
||||||
|
return new waybar::modules::niri::Window(id, bar_, config_[name]);
|
||||||
|
}
|
||||||
|
if (ref == "niri/workspaces") {
|
||||||
|
return new waybar::modules::niri::Workspaces(id, bar_, config_[name]);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
if (ref == "idle_inhibitor") {
|
if (ref == "idle_inhibitor") {
|
||||||
return new waybar::modules::IdleInhibitor(id, bar_, config_[name]);
|
return new waybar::modules::IdleInhibitor(id, bar_, config_[name]);
|
||||||
|
|
|
@ -49,8 +49,8 @@ auto getBoolProperty(GDBusProxy* proxy, const char* property_name) -> bool {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto getOptionalStringProperty(GDBusProxy* proxy, const char* property_name)
|
auto getOptionalStringProperty(GDBusProxy* proxy,
|
||||||
-> std::optional<std::string> {
|
const char* property_name) -> std::optional<std::string> {
|
||||||
auto gvar = g_dbus_proxy_get_cached_property(proxy, property_name);
|
auto gvar = g_dbus_proxy_get_cached_property(proxy, property_name);
|
||||||
if (gvar) {
|
if (gvar) {
|
||||||
std::string property_value = g_variant_get_string(gvar, NULL);
|
std::string property_value = g_variant_get_string(gvar, NULL);
|
||||||
|
@ -345,8 +345,8 @@ auto waybar::modules::Bluetooth::onInterfaceAddedOrRemoved(GDBusObjectManager* m
|
||||||
|
|
||||||
auto waybar::modules::Bluetooth::onInterfaceProxyPropertiesChanged(
|
auto waybar::modules::Bluetooth::onInterfaceProxyPropertiesChanged(
|
||||||
GDBusObjectManagerClient* manager, GDBusObjectProxy* object_proxy, GDBusProxy* interface_proxy,
|
GDBusObjectManagerClient* manager, GDBusObjectProxy* object_proxy, GDBusProxy* interface_proxy,
|
||||||
GVariant* changed_properties, const gchar* const* invalidated_properties, gpointer user_data)
|
GVariant* changed_properties, const gchar* const* invalidated_properties,
|
||||||
-> void {
|
gpointer user_data) -> void {
|
||||||
std::string interface_name = g_dbus_proxy_get_interface_name(interface_proxy);
|
std::string interface_name = g_dbus_proxy_get_interface_name(interface_proxy);
|
||||||
std::string object_path = g_dbus_object_get_object_path(G_DBUS_OBJECT(object_proxy));
|
std::string object_path = g_dbus_object_get_object_path(G_DBUS_OBJECT(object_proxy));
|
||||||
|
|
||||||
|
@ -395,8 +395,8 @@ auto waybar::modules::Bluetooth::getDeviceBatteryPercentage(GDBusObject* object)
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto waybar::modules::Bluetooth::getDeviceProperties(GDBusObject* object, DeviceInfo& device_info)
|
auto waybar::modules::Bluetooth::getDeviceProperties(GDBusObject* object,
|
||||||
-> bool {
|
DeviceInfo& device_info) -> bool {
|
||||||
GDBusProxy* proxy_device = G_DBUS_PROXY(g_dbus_object_get_interface(object, "org.bluez.Device1"));
|
GDBusProxy* proxy_device = G_DBUS_PROXY(g_dbus_object_get_interface(object, "org.bluez.Device1"));
|
||||||
|
|
||||||
if (proxy_device != NULL) {
|
if (proxy_device != NULL) {
|
||||||
|
@ -462,9 +462,8 @@ auto waybar::modules::Bluetooth::findCurController() -> std::optional<Controller
|
||||||
return controller_info;
|
return controller_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto waybar::modules::Bluetooth::findConnectedDevices(const std::string& cur_controller_path,
|
auto waybar::modules::Bluetooth::findConnectedDevices(
|
||||||
std::vector<DeviceInfo>& connected_devices)
|
const std::string& cur_controller_path, std::vector<DeviceInfo>& connected_devices) -> void {
|
||||||
-> void {
|
|
||||||
GList* objects = g_dbus_object_manager_get_objects(manager_.get());
|
GList* objects = g_dbus_object_manager_get_objects(manager_.get());
|
||||||
for (GList* l = objects; l != NULL; l = l->next) {
|
for (GList* l = objects; l != NULL; l = l->next) {
|
||||||
GDBusObject* object = G_DBUS_OBJECT(l->data);
|
GDBusObject* object = G_DBUS_OBJECT(l->data);
|
||||||
|
|
|
@ -198,8 +198,8 @@ const unsigned cldRowsInMonth(const year_month& ym, const weekday& firstdow) {
|
||||||
return 2u + ceil<weeks>((weekday{ym / 1} - firstdow) + ((ym / last).day() - day{0})).count();
|
return 2u + ceil<weeks>((weekday{ym / 1} - firstdow) + ((ym / last).day() - day{0})).count();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto cldGetWeekForLine(const year_month& ym, const weekday& firstdow, const unsigned line)
|
auto cldGetWeekForLine(const year_month& ym, const weekday& firstdow,
|
||||||
-> const year_month_weekday {
|
const unsigned line) -> const year_month_weekday {
|
||||||
unsigned index{line - 2};
|
unsigned index{line - 2};
|
||||||
if (weekday{ym / 1} == firstdow) ++index;
|
if (weekday{ym / 1} == firstdow) ++index;
|
||||||
return ym / firstdow[index];
|
return ym / firstdow[index];
|
||||||
|
|
|
@ -590,8 +590,8 @@ auto Workspaces::populateIconsMap(const Json::Value &formatIcons) -> void {
|
||||||
m_iconsMap.emplace("", "");
|
m_iconsMap.emplace("", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Workspaces::populateBoolConfig(const Json::Value &config, const std::string &key, bool &member)
|
auto Workspaces::populateBoolConfig(const Json::Value &config, const std::string &key,
|
||||||
-> void {
|
bool &member) -> void {
|
||||||
const auto &configValue = config[key];
|
const auto &configValue = config[key];
|
||||||
if (configValue.isBool()) {
|
if (configValue.isBool()) {
|
||||||
member = configValue.asBool();
|
member = configValue.asBool();
|
||||||
|
|
|
@ -42,7 +42,6 @@ void waybar::modules::Image::refresh(int sig) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto waybar::modules::Image::update() -> void {
|
auto waybar::modules::Image::update() -> void {
|
||||||
Glib::RefPtr<Gdk::Pixbuf> pixbuf;
|
|
||||||
if (config_["path"].isString()) {
|
if (config_["path"].isString()) {
|
||||||
path_ = config_["path"].asString();
|
path_ = config_["path"].asString();
|
||||||
} else if (config_["exec"].isString()) {
|
} else if (config_["exec"].isString()) {
|
||||||
|
@ -51,19 +50,24 @@ auto waybar::modules::Image::update() -> void {
|
||||||
} else {
|
} else {
|
||||||
path_ = "";
|
path_ = "";
|
||||||
}
|
}
|
||||||
if (Glib::file_test(path_, Glib::FILE_TEST_EXISTS))
|
|
||||||
pixbuf = Gdk::Pixbuf::create_from_file(path_, size_, size_);
|
|
||||||
else
|
|
||||||
pixbuf = {};
|
|
||||||
|
|
||||||
if (pixbuf) {
|
if (Glib::file_test(path_, Glib::FILE_TEST_EXISTS)) {
|
||||||
|
Glib::RefPtr<Gdk::Pixbuf> pixbuf;
|
||||||
|
|
||||||
|
int scaled_icon_size = size_ * image_.get_scale_factor();
|
||||||
|
pixbuf = Gdk::Pixbuf::create_from_file(path_, scaled_icon_size, scaled_icon_size);
|
||||||
|
|
||||||
|
auto surface = Gdk::Cairo::create_surface_from_pixbuf(pixbuf, image_.get_scale_factor(),
|
||||||
|
image_.get_window());
|
||||||
|
image_.set(surface);
|
||||||
|
image_.show();
|
||||||
|
|
||||||
if (tooltipEnabled() && !tooltip_.empty()) {
|
if (tooltipEnabled() && !tooltip_.empty()) {
|
||||||
if (box_.get_tooltip_markup() != tooltip_) {
|
if (box_.get_tooltip_markup() != tooltip_) {
|
||||||
box_.set_tooltip_markup(tooltip_);
|
box_.set_tooltip_markup(tooltip_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
image_.set(pixbuf);
|
|
||||||
image_.show();
|
|
||||||
box_.get_style_context()->remove_class("empty");
|
box_.get_style_context()->remove_class("empty");
|
||||||
} else {
|
} else {
|
||||||
image_.clear();
|
image_.clear();
|
||||||
|
|
|
@ -0,0 +1,261 @@
|
||||||
|
#include "modules/niri/backend.hpp"
|
||||||
|
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#include "giomm/datainputstream.h"
|
||||||
|
#include "giomm/dataoutputstream.h"
|
||||||
|
#include "giomm/unixinputstream.h"
|
||||||
|
#include "giomm/unixoutputstream.h"
|
||||||
|
|
||||||
|
namespace waybar::modules::niri {
|
||||||
|
|
||||||
|
int IPC::connectToSocket() {
|
||||||
|
const char *socket_path = getenv("NIRI_SOCKET");
|
||||||
|
|
||||||
|
if (socket_path == nullptr) {
|
||||||
|
spdlog::warn("Niri is not running, niri IPC will not be available.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
int socketfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
|
||||||
|
if (socketfd == -1) {
|
||||||
|
throw std::runtime_error("socketfd failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
addr.sun_family = AF_UNIX;
|
||||||
|
|
||||||
|
strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
|
||||||
|
|
||||||
|
addr.sun_path[sizeof(addr.sun_path) - 1] = 0;
|
||||||
|
|
||||||
|
int l = sizeof(struct sockaddr_un);
|
||||||
|
|
||||||
|
if (connect(socketfd, (struct sockaddr *)&addr, l) == -1) {
|
||||||
|
close(socketfd);
|
||||||
|
throw std::runtime_error("unable to connect");
|
||||||
|
}
|
||||||
|
|
||||||
|
return socketfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPC::startIPC() {
|
||||||
|
// will start IPC and relay events to parseIPC
|
||||||
|
|
||||||
|
std::thread([&]() {
|
||||||
|
int socketfd;
|
||||||
|
try {
|
||||||
|
socketfd = connectToSocket();
|
||||||
|
} catch (std::exception &e) {
|
||||||
|
spdlog::error("Niri IPC: failed to start, reason: {}", e.what());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (socketfd == -1) return;
|
||||||
|
|
||||||
|
spdlog::info("Niri IPC starting");
|
||||||
|
|
||||||
|
auto unix_istream = Gio::UnixInputStream::create(socketfd, true);
|
||||||
|
auto unix_ostream = Gio::UnixOutputStream::create(socketfd, false);
|
||||||
|
auto istream = Gio::DataInputStream::create(unix_istream);
|
||||||
|
auto ostream = Gio::DataOutputStream::create(unix_ostream);
|
||||||
|
|
||||||
|
if (!ostream->put_string("\"EventStream\"\n") || !ostream->flush()) {
|
||||||
|
spdlog::error("Niri IPC: failed to start event stream");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
if (!istream->read_line(line) || line != R"({"Ok":"Handled"})") {
|
||||||
|
spdlog::error("Niri IPC: failed to start event stream");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (istream->read_line(line)) {
|
||||||
|
spdlog::debug("Niri IPC: received {}", line);
|
||||||
|
|
||||||
|
try {
|
||||||
|
parseIPC(line);
|
||||||
|
} catch (std::exception &e) {
|
||||||
|
spdlog::warn("Failed to parse IPC message: {}, reason: {}", line, e.what());
|
||||||
|
} catch (...) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
|
}
|
||||||
|
}).detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPC::parseIPC(const std::string &line) {
|
||||||
|
const auto ev = parser_.parse(line);
|
||||||
|
const auto members = ev.getMemberNames();
|
||||||
|
if (members.size() != 1) throw std::runtime_error("Event must have a single member");
|
||||||
|
|
||||||
|
{
|
||||||
|
auto lock = lockData();
|
||||||
|
|
||||||
|
if (const auto &payload = ev["WorkspacesChanged"]) {
|
||||||
|
workspaces_.clear();
|
||||||
|
const auto &values = payload["workspaces"];
|
||||||
|
std::copy(values.begin(), values.end(), std::back_inserter(workspaces_));
|
||||||
|
|
||||||
|
std::sort(workspaces_.begin(), workspaces_.end(), [](const auto &a, const auto &b) {
|
||||||
|
const auto &aOutput = a["output"].asString();
|
||||||
|
const auto &bOutput = b["output"].asString();
|
||||||
|
const auto aIdx = a["idx"].asUInt();
|
||||||
|
const auto bIdx = b["idx"].asUInt();
|
||||||
|
if (aOutput == bOutput) return aIdx < bIdx;
|
||||||
|
return aOutput < bOutput;
|
||||||
|
});
|
||||||
|
} else if (const auto &payload = ev["WorkspaceActivated"]) {
|
||||||
|
const auto id = payload["id"].asUInt64();
|
||||||
|
const auto focused = payload["focused"].asBool();
|
||||||
|
auto it = std::find_if(workspaces_.begin(), workspaces_.end(),
|
||||||
|
[id](const auto &ws) { return ws["id"].asUInt64() == id; });
|
||||||
|
if (it != workspaces_.end()) {
|
||||||
|
const auto &ws = *it;
|
||||||
|
const auto &output = ws["output"].asString();
|
||||||
|
for (auto &ws : workspaces_) {
|
||||||
|
const auto got_activated = (ws["id"].asUInt64() == id);
|
||||||
|
if (ws["output"] == output) ws["is_active"] = got_activated;
|
||||||
|
|
||||||
|
if (focused) ws["is_focused"] = got_activated;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
spdlog::error("Activated unknown workspace");
|
||||||
|
}
|
||||||
|
} else if (const auto &payload = ev["WorkspaceActiveWindowChanged"]) {
|
||||||
|
const auto workspaceId = payload["workspace_id"].asUInt64();
|
||||||
|
auto it = std::find_if(workspaces_.begin(), workspaces_.end(), [workspaceId](const auto &ws) {
|
||||||
|
return ws["id"].asUInt64() == workspaceId;
|
||||||
|
});
|
||||||
|
if (it != workspaces_.end()) {
|
||||||
|
auto &ws = *it;
|
||||||
|
ws["active_window_id"] = payload["active_window_id"];
|
||||||
|
} else {
|
||||||
|
spdlog::error("Active window changed on unknown workspace");
|
||||||
|
}
|
||||||
|
} else if (const auto &payload = ev["KeyboardLayoutsChanged"]) {
|
||||||
|
const auto &layouts = payload["keyboard_layouts"];
|
||||||
|
const auto &names = layouts["names"];
|
||||||
|
keyboardLayoutCurrent_ = layouts["current_idx"].asUInt();
|
||||||
|
|
||||||
|
keyboardLayoutNames_.clear();
|
||||||
|
for (const auto &fullName : names) keyboardLayoutNames_.push_back(fullName.asString());
|
||||||
|
} else if (const auto &payload = ev["KeyboardLayoutSwitched"]) {
|
||||||
|
keyboardLayoutCurrent_ = payload["idx"].asUInt();
|
||||||
|
} else if (const auto &payload = ev["WindowsChanged"]) {
|
||||||
|
windows_.clear();
|
||||||
|
const auto &values = payload["windows"];
|
||||||
|
std::copy(values.begin(), values.end(), std::back_inserter(windows_));
|
||||||
|
} else if (const auto &payload = ev["WindowOpenedOrChanged"]) {
|
||||||
|
const auto &window = payload["window"];
|
||||||
|
const auto id = window["id"].asUInt64();
|
||||||
|
auto it = std::find_if(windows_.begin(), windows_.end(),
|
||||||
|
[id](const auto &win) { return win["id"].asUInt64() == id; });
|
||||||
|
if (it == windows_.end()) {
|
||||||
|
windows_.push_back(window);
|
||||||
|
|
||||||
|
if (window["is_focused"].asBool()) {
|
||||||
|
for (auto &win : windows_) {
|
||||||
|
win["is_focused"] = win["id"].asUInt64() == id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*it = window;
|
||||||
|
}
|
||||||
|
} else if (const auto &payload = ev["WindowClosed"]) {
|
||||||
|
const auto id = payload["id"].asUInt64();
|
||||||
|
auto it = std::find_if(windows_.begin(), windows_.end(),
|
||||||
|
[id](const auto &win) { return win["id"].asUInt64() == id; });
|
||||||
|
if (it != windows_.end()) {
|
||||||
|
windows_.erase(it);
|
||||||
|
} else {
|
||||||
|
spdlog::error("Unknown window closed");
|
||||||
|
}
|
||||||
|
} else if (const auto &payload = ev["WindowFocusChanged"]) {
|
||||||
|
const auto focused = !payload["id"].isNull();
|
||||||
|
const auto id = payload["id"].asUInt64();
|
||||||
|
for (auto &win : windows_) {
|
||||||
|
win["is_focused"] = focused && win["id"].asUInt64() == id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_lock lock(callbackMutex_);
|
||||||
|
|
||||||
|
for (auto &[eventname, handler] : callbacks_) {
|
||||||
|
if (eventname == members[0]) {
|
||||||
|
handler->onEvent(ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPC::registerForIPC(const std::string &ev, EventHandler *ev_handler) {
|
||||||
|
if (ev_handler == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_lock lock(callbackMutex_);
|
||||||
|
callbacks_.emplace_back(ev, ev_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPC::unregisterForIPC(EventHandler *ev_handler) {
|
||||||
|
if (ev_handler == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_lock lock(callbackMutex_);
|
||||||
|
|
||||||
|
for (auto it = callbacks_.begin(); it != callbacks_.end();) {
|
||||||
|
auto &[eventname, handler] = *it;
|
||||||
|
if (handler == ev_handler) {
|
||||||
|
it = callbacks_.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Json::Value IPC::send(const Json::Value &request) {
|
||||||
|
int socketfd = connectToSocket();
|
||||||
|
if (socketfd == -1) throw std::runtime_error("Niri is not running");
|
||||||
|
|
||||||
|
auto unix_istream = Gio::UnixInputStream::create(socketfd, true);
|
||||||
|
auto unix_ostream = Gio::UnixOutputStream::create(socketfd, false);
|
||||||
|
auto istream = Gio::DataInputStream::create(unix_istream);
|
||||||
|
auto ostream = Gio::DataOutputStream::create(unix_ostream);
|
||||||
|
|
||||||
|
// Niri needs the request on a single line.
|
||||||
|
Json::StreamWriterBuilder builder;
|
||||||
|
builder["indentation"] = "";
|
||||||
|
std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
|
||||||
|
std::ostringstream oss;
|
||||||
|
writer->write(request, &oss);
|
||||||
|
oss << '\n';
|
||||||
|
|
||||||
|
if (!ostream->put_string(oss.str()) || !ostream->flush())
|
||||||
|
throw std::runtime_error("error writing to niri socket");
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
if (!istream->read_line(line)) throw std::runtime_error("error reading from niri socket");
|
||||||
|
|
||||||
|
std::istringstream iss(std::move(line));
|
||||||
|
Json::Value response;
|
||||||
|
iss >> response;
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace waybar::modules::niri
|
|
@ -0,0 +1,136 @@
|
||||||
|
#include "modules/niri/language.hpp"
|
||||||
|
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
#include <xkbcommon/xkbregistry.h>
|
||||||
|
|
||||||
|
#include "util/string.hpp"
|
||||||
|
|
||||||
|
namespace waybar::modules::niri {
|
||||||
|
|
||||||
|
Language::Language(const std::string &id, const Bar &bar, const Json::Value &config)
|
||||||
|
: ALabel(config, "language", id, "{}", 0, true), bar_(bar) {
|
||||||
|
label_.hide();
|
||||||
|
|
||||||
|
if (!gIPC) gIPC = std::make_unique<IPC>();
|
||||||
|
|
||||||
|
gIPC->registerForIPC("KeyboardLayoutsChanged", this);
|
||||||
|
gIPC->registerForIPC("KeyboardLayoutSwitched", this);
|
||||||
|
|
||||||
|
updateFromIPC();
|
||||||
|
dp.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
Language::~Language() {
|
||||||
|
gIPC->unregisterForIPC(this);
|
||||||
|
// wait for possible event handler to finish
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Language::updateFromIPC() {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
auto ipcLock = gIPC->lockData();
|
||||||
|
|
||||||
|
layouts_.clear();
|
||||||
|
for (const auto &fullName : gIPC->keyboardLayoutNames()) layouts_.push_back(getLayout(fullName));
|
||||||
|
|
||||||
|
current_idx_ = gIPC->keyboardLayoutCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Language::doUpdate - update workspaces in UI thread.
|
||||||
|
*
|
||||||
|
* Note: some member fields are modified by both UI thread and event listener thread, use mutex_ to
|
||||||
|
* protect these member fields, and lock should released before calling ALabel::update().
|
||||||
|
*/
|
||||||
|
void Language::doUpdate() {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
|
||||||
|
if (layouts_.size() <= current_idx_) {
|
||||||
|
spdlog::error("niri language layout index out of bounds");
|
||||||
|
label_.hide();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto &layout = layouts_[current_idx_];
|
||||||
|
|
||||||
|
spdlog::debug("niri language update with full name {}", layout.full_name);
|
||||||
|
spdlog::debug("niri language update with short name {}", layout.short_name);
|
||||||
|
spdlog::debug("niri language update with short description {}", layout.short_description);
|
||||||
|
spdlog::debug("niri language update with variant {}", layout.variant);
|
||||||
|
|
||||||
|
std::string layoutName = std::string{};
|
||||||
|
if (config_.isMember("format-" + layout.short_description + "-" + layout.variant)) {
|
||||||
|
const auto propName = "format-" + layout.short_description + "-" + layout.variant;
|
||||||
|
layoutName = fmt::format(fmt::runtime(format_), config_[propName].asString());
|
||||||
|
} else if (config_.isMember("format-" + layout.short_description)) {
|
||||||
|
const auto propName = "format-" + layout.short_description;
|
||||||
|
layoutName = fmt::format(fmt::runtime(format_), config_[propName].asString());
|
||||||
|
} else {
|
||||||
|
layoutName = trim(fmt::format(fmt::runtime(format_), fmt::arg("long", layout.full_name),
|
||||||
|
fmt::arg("short", layout.short_name),
|
||||||
|
fmt::arg("shortDescription", layout.short_description),
|
||||||
|
fmt::arg("variant", layout.variant)));
|
||||||
|
}
|
||||||
|
|
||||||
|
spdlog::debug("niri language formatted layout name {}", layoutName);
|
||||||
|
|
||||||
|
if (!format_.empty()) {
|
||||||
|
label_.show();
|
||||||
|
label_.set_markup(layoutName);
|
||||||
|
} else {
|
||||||
|
label_.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Language::update() {
|
||||||
|
doUpdate();
|
||||||
|
ALabel::update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Language::onEvent(const Json::Value &ev) {
|
||||||
|
if (ev["KeyboardLayoutsChanged"]) {
|
||||||
|
updateFromIPC();
|
||||||
|
} else if (ev["KeyboardLayoutSwitched"]) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
auto ipcLock = gIPC->lockData();
|
||||||
|
current_idx_ = gIPC->keyboardLayoutCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
dp.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
Language::Layout Language::getLayout(const std::string &fullName) {
|
||||||
|
auto *const context = rxkb_context_new(RXKB_CONTEXT_LOAD_EXOTIC_RULES);
|
||||||
|
rxkb_context_parse_default_ruleset(context);
|
||||||
|
|
||||||
|
rxkb_layout *layout = rxkb_layout_first(context);
|
||||||
|
while (layout != nullptr) {
|
||||||
|
std::string nameOfLayout = rxkb_layout_get_description(layout);
|
||||||
|
|
||||||
|
if (nameOfLayout != fullName) {
|
||||||
|
layout = rxkb_layout_next(layout);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto name = std::string(rxkb_layout_get_name(layout));
|
||||||
|
const auto *variantPtr = rxkb_layout_get_variant(layout);
|
||||||
|
std::string variant = variantPtr == nullptr ? "" : std::string(variantPtr);
|
||||||
|
|
||||||
|
const auto *descriptionPtr = rxkb_layout_get_brief(layout);
|
||||||
|
std::string description = descriptionPtr == nullptr ? "" : std::string(descriptionPtr);
|
||||||
|
|
||||||
|
Layout info = Layout{nameOfLayout, name, variant, description};
|
||||||
|
|
||||||
|
rxkb_context_unref(context);
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
rxkb_context_unref(context);
|
||||||
|
|
||||||
|
spdlog::debug("niri language didn't find matching layout for {}", fullName);
|
||||||
|
|
||||||
|
return Layout{"", "", "", ""};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace waybar::modules::niri
|
|
@ -0,0 +1,109 @@
|
||||||
|
#include "modules/niri/window.hpp"
|
||||||
|
|
||||||
|
#include <gtkmm/button.h>
|
||||||
|
#include <gtkmm/label.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
|
#include "util/rewrite_string.hpp"
|
||||||
|
#include "util/sanitize_str.hpp"
|
||||||
|
|
||||||
|
namespace waybar::modules::niri {
|
||||||
|
|
||||||
|
Window::Window(const std::string &id, const Bar &bar, const Json::Value &config)
|
||||||
|
: AAppIconLabel(config, "window", id, "{title}", 0, true), bar_(bar) {
|
||||||
|
if (!gIPC) gIPC = std::make_unique<IPC>();
|
||||||
|
|
||||||
|
gIPC->registerForIPC("WindowsChanged", this);
|
||||||
|
gIPC->registerForIPC("WindowOpenedOrChanged", this);
|
||||||
|
gIPC->registerForIPC("WindowClosed", this);
|
||||||
|
gIPC->registerForIPC("WindowFocusChanged", this);
|
||||||
|
|
||||||
|
dp.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
Window::~Window() { gIPC->unregisterForIPC(this); }
|
||||||
|
|
||||||
|
void Window::onEvent(const Json::Value &ev) { dp.emit(); }
|
||||||
|
|
||||||
|
void Window::doUpdate() {
|
||||||
|
auto ipcLock = gIPC->lockData();
|
||||||
|
|
||||||
|
const auto &windows = gIPC->windows();
|
||||||
|
const auto &workspaces = gIPC->workspaces();
|
||||||
|
|
||||||
|
const auto separateOutputs = config_["separate-outputs"].asBool();
|
||||||
|
const auto ws_it = std::find_if(workspaces.cbegin(), workspaces.cend(), [&](const auto &ws) {
|
||||||
|
if (separateOutputs) {
|
||||||
|
return ws["is_active"].asBool() && ws["output"].asString() == bar_.output->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ws["is_focused"].asBool();
|
||||||
|
});
|
||||||
|
|
||||||
|
std::vector<Json::Value>::const_iterator it;
|
||||||
|
if (ws_it == workspaces.cend() || (*ws_it)["active_window_id"].isNull()) {
|
||||||
|
it = windows.cend();
|
||||||
|
} else {
|
||||||
|
const auto id = (*ws_it)["active_window_id"].asUInt64();
|
||||||
|
it = std::find_if(windows.cbegin(), windows.cend(),
|
||||||
|
[id](const auto &win) { return win["id"].asUInt64() == id; });
|
||||||
|
}
|
||||||
|
|
||||||
|
setClass("empty", ws_it == workspaces.cend() || (*ws_it)["active_window_id"].isNull());
|
||||||
|
|
||||||
|
if (it != windows.cend()) {
|
||||||
|
const auto &window = *it;
|
||||||
|
|
||||||
|
const auto title = window["title"].asString();
|
||||||
|
const auto appId = window["app_id"].asString();
|
||||||
|
const auto sanitizedTitle = waybar::util::sanitize_string(title);
|
||||||
|
const auto sanitizedAppId = waybar::util::sanitize_string(appId);
|
||||||
|
|
||||||
|
label_.show();
|
||||||
|
label_.set_markup(waybar::util::rewriteString(
|
||||||
|
fmt::format(fmt::runtime(format_), fmt::arg("title", sanitizedTitle),
|
||||||
|
fmt::arg("app_id", sanitizedAppId)),
|
||||||
|
config_["rewrite"]));
|
||||||
|
|
||||||
|
updateAppIconName(appId, "");
|
||||||
|
|
||||||
|
if (tooltipEnabled()) label_.set_tooltip_text(title);
|
||||||
|
|
||||||
|
const auto id = window["id"].asUInt64();
|
||||||
|
const auto workspaceId = window["workspace_id"].asUInt64();
|
||||||
|
const auto isSolo = std::none_of(windows.cbegin(), windows.cend(), [&](const auto &win) {
|
||||||
|
return win["id"].asUInt64() != id && win["workspace_id"].asUInt64() == workspaceId;
|
||||||
|
});
|
||||||
|
setClass("solo", isSolo);
|
||||||
|
if (!appId.empty()) setClass(appId, isSolo);
|
||||||
|
|
||||||
|
if (oldAppId_ != appId) {
|
||||||
|
if (!oldAppId_.empty()) setClass(oldAppId_, false);
|
||||||
|
oldAppId_ = appId;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
label_.hide();
|
||||||
|
updateAppIconName("", "");
|
||||||
|
setClass("solo", false);
|
||||||
|
if (!oldAppId_.empty()) setClass(oldAppId_, false);
|
||||||
|
oldAppId_.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::update() {
|
||||||
|
doUpdate();
|
||||||
|
AAppIconLabel::update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::setClass(const std::string &className, bool enable) {
|
||||||
|
auto styleContext = bar_.window.get_style_context();
|
||||||
|
if (enable) {
|
||||||
|
if (!styleContext->has_class(className)) {
|
||||||
|
styleContext->add_class(className);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
styleContext->remove_class(className);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace waybar::modules::niri
|
|
@ -0,0 +1,186 @@
|
||||||
|
#include "modules/niri/workspaces.hpp"
|
||||||
|
|
||||||
|
#include <gtkmm/button.h>
|
||||||
|
#include <gtkmm/label.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
|
namespace waybar::modules::niri {
|
||||||
|
|
||||||
|
Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value &config)
|
||||||
|
: AModule(config, "workspaces", id, false, false), bar_(bar), box_(bar.orientation, 0) {
|
||||||
|
box_.set_name("workspaces");
|
||||||
|
if (!id.empty()) {
|
||||||
|
box_.get_style_context()->add_class(id);
|
||||||
|
}
|
||||||
|
box_.get_style_context()->add_class(MODULE_CLASS);
|
||||||
|
event_box_.add(box_);
|
||||||
|
|
||||||
|
if (!gIPC) gIPC = std::make_unique<IPC>();
|
||||||
|
|
||||||
|
gIPC->registerForIPC("WorkspacesChanged", this);
|
||||||
|
gIPC->registerForIPC("WorkspaceActivated", this);
|
||||||
|
gIPC->registerForIPC("WorkspaceActiveWindowChanged", this);
|
||||||
|
|
||||||
|
dp.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
Workspaces::~Workspaces() { gIPC->unregisterForIPC(this); }
|
||||||
|
|
||||||
|
void Workspaces::onEvent(const Json::Value &ev) { dp.emit(); }
|
||||||
|
|
||||||
|
void Workspaces::doUpdate() {
|
||||||
|
auto ipcLock = gIPC->lockData();
|
||||||
|
|
||||||
|
const auto alloutputs = config_["all-outputs"].asBool();
|
||||||
|
std::vector<Json::Value> my_workspaces;
|
||||||
|
const auto &workspaces = gIPC->workspaces();
|
||||||
|
std::copy_if(workspaces.cbegin(), workspaces.cend(), std::back_inserter(my_workspaces),
|
||||||
|
[&](const auto &ws) {
|
||||||
|
if (alloutputs) return true;
|
||||||
|
return ws["output"].asString() == bar_.output->name;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Remove buttons for removed workspaces.
|
||||||
|
for (auto it = buttons_.begin(); it != buttons_.end();) {
|
||||||
|
auto ws = std::find_if(my_workspaces.begin(), my_workspaces.end(),
|
||||||
|
[it](const auto &ws) { return ws["id"].asUInt64() == it->first; });
|
||||||
|
if (ws == my_workspaces.end()) {
|
||||||
|
it = buttons_.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add buttons for new workspaces, update existing ones.
|
||||||
|
for (const auto &ws : my_workspaces) {
|
||||||
|
auto bit = buttons_.find(ws["id"].asUInt64());
|
||||||
|
auto &button = bit == buttons_.end() ? addButton(ws) : bit->second;
|
||||||
|
auto style_context = button.get_style_context();
|
||||||
|
|
||||||
|
if (ws["is_focused"].asBool())
|
||||||
|
style_context->add_class("focused");
|
||||||
|
else
|
||||||
|
style_context->remove_class("focused");
|
||||||
|
|
||||||
|
if (ws["is_active"].asBool())
|
||||||
|
style_context->add_class("active");
|
||||||
|
else
|
||||||
|
style_context->remove_class("active");
|
||||||
|
|
||||||
|
if (ws["output"]) {
|
||||||
|
if (ws["output"].asString() == bar_.output->name)
|
||||||
|
style_context->add_class("current_output");
|
||||||
|
else
|
||||||
|
style_context->remove_class("current_output");
|
||||||
|
} else {
|
||||||
|
style_context->remove_class("current_output");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ws["active_window_id"].isNull())
|
||||||
|
style_context->add_class("empty");
|
||||||
|
else
|
||||||
|
style_context->remove_class("empty");
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
if (ws["name"]) {
|
||||||
|
name = ws["name"].asString();
|
||||||
|
} else {
|
||||||
|
name = std::to_string(ws["idx"].asUInt());
|
||||||
|
}
|
||||||
|
button.set_name("niri-workspace-" + name);
|
||||||
|
|
||||||
|
if (config_["format"].isString()) {
|
||||||
|
auto format = config_["format"].asString();
|
||||||
|
name = fmt::format(fmt::runtime(format), fmt::arg("icon", getIcon(name, ws)),
|
||||||
|
fmt::arg("value", name), fmt::arg("name", ws["name"].asString()),
|
||||||
|
fmt::arg("index", ws["idx"].asUInt()),
|
||||||
|
fmt::arg("output", ws["output"].asString()));
|
||||||
|
}
|
||||||
|
if (!config_["disable-markup"].asBool()) {
|
||||||
|
static_cast<Gtk::Label *>(button.get_children()[0])->set_markup(name);
|
||||||
|
} else {
|
||||||
|
button.set_label(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config_["current-only"].asBool()) {
|
||||||
|
const auto *property = alloutputs ? "is_focused" : "is_active";
|
||||||
|
if (ws[property].asBool())
|
||||||
|
button.show();
|
||||||
|
else
|
||||||
|
button.hide();
|
||||||
|
} else {
|
||||||
|
button.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Refresh the button order.
|
||||||
|
for (auto it = my_workspaces.cbegin(); it != my_workspaces.cend(); ++it) {
|
||||||
|
const auto &ws = *it;
|
||||||
|
|
||||||
|
auto pos = ws["idx"].asUInt() - 1;
|
||||||
|
if (alloutputs) pos = it - my_workspaces.cbegin();
|
||||||
|
|
||||||
|
auto &button = buttons_[ws["id"].asUInt64()];
|
||||||
|
box_.reorder_child(button, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Workspaces::update() {
|
||||||
|
doUpdate();
|
||||||
|
AModule::update();
|
||||||
|
}
|
||||||
|
|
||||||
|
Gtk::Button &Workspaces::addButton(const Json::Value &ws) {
|
||||||
|
std::string name;
|
||||||
|
if (ws["name"]) {
|
||||||
|
name = ws["name"].asString();
|
||||||
|
} else {
|
||||||
|
name = std::to_string(ws["idx"].asUInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto pair = buttons_.emplace(ws["id"].asUInt64(), name);
|
||||||
|
auto &&button = pair.first->second;
|
||||||
|
box_.pack_start(button, false, false, 0);
|
||||||
|
button.set_relief(Gtk::RELIEF_NONE);
|
||||||
|
if (!config_["disable-click"].asBool()) {
|
||||||
|
const auto id = ws["id"].asUInt64();
|
||||||
|
button.signal_pressed().connect([=] {
|
||||||
|
try {
|
||||||
|
// {"Action":{"FocusWorkspace":{"reference":{"Id":1}}}}
|
||||||
|
Json::Value request(Json::objectValue);
|
||||||
|
auto &action = (request["Action"] = Json::Value(Json::objectValue));
|
||||||
|
auto &focusWorkspace = (action["FocusWorkspace"] = Json::Value(Json::objectValue));
|
||||||
|
auto &reference = (focusWorkspace["reference"] = Json::Value(Json::objectValue));
|
||||||
|
reference["Id"] = id;
|
||||||
|
|
||||||
|
IPC::send(request);
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
spdlog::error("Error switching workspace: {}", e.what());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Workspaces::getIcon(const std::string &value, const Json::Value &ws) {
|
||||||
|
const auto &icons = config_["format-icons"];
|
||||||
|
if (!icons) return value;
|
||||||
|
|
||||||
|
if (ws["is_focused"].asBool() && icons["focused"]) return icons["focused"].asString();
|
||||||
|
|
||||||
|
if (ws["is_active"].asBool() && icons["active"]) return icons["active"].asString();
|
||||||
|
|
||||||
|
if (ws["name"]) {
|
||||||
|
const auto &name = ws["name"].asString();
|
||||||
|
if (icons[name]) return icons[name].asString();
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto idx = ws["idx"].asString();
|
||||||
|
if (icons[idx]) return icons[idx].asString();
|
||||||
|
|
||||||
|
if (icons["default"]) return icons["default"].asString();
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace waybar::modules::niri
|
|
@ -204,7 +204,7 @@ void PowerProfilesDaemon::setPropCb(Glib::RefPtr<Gio::AsyncResult>& r) {
|
||||||
auto _ = powerProfilesProxy_->call_finish(r);
|
auto _ = powerProfilesProxy_->call_finish(r);
|
||||||
dp.emit();
|
dp.emit();
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
spdlog::error("Failed to set the the active power profile: {}", e.what());
|
spdlog::error("Failed to set the active power profile: {}", e.what());
|
||||||
} catch (const Glib::Error& e) {
|
} catch (const Glib::Error& e) {
|
||||||
spdlog::error("Failed to set the active power profile: {}", std::string(e.what()));
|
spdlog::error("Failed to set the active power profile: {}", std::string(e.what()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,9 +104,11 @@ void Item::proxyReady(Glib::RefPtr<Gio::AsyncResult>& result) {
|
||||||
this->updateImage();
|
this->updateImage();
|
||||||
|
|
||||||
} catch (const Glib::Error& err) {
|
} catch (const Glib::Error& err) {
|
||||||
spdlog::error("Failed to create DBus Proxy for {} {}: {}", bus_name, object_path, err.what());
|
spdlog::error("Failed to create DBus Proxy for {} {}: {}", bus_name, object_path,
|
||||||
|
std::string(err.what()));
|
||||||
} catch (const std::exception& err) {
|
} catch (const std::exception& err) {
|
||||||
spdlog::error("Failed to create DBus Proxy for {} {}: {}", bus_name, object_path, err.what());
|
spdlog::error("Failed to create DBus Proxy for {} {}: {}", bus_name, object_path,
|
||||||
|
std::string(err.what()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,14 +126,15 @@ ToolTip get_variant<ToolTip>(const Glib::VariantBase& value) {
|
||||||
result.text = get_variant<Glib::ustring>(container.get_child(2));
|
result.text = get_variant<Glib::ustring>(container.get_child(2));
|
||||||
auto description = get_variant<Glib::ustring>(container.get_child(3));
|
auto description = get_variant<Glib::ustring>(container.get_child(3));
|
||||||
if (!description.empty()) {
|
if (!description.empty()) {
|
||||||
result.text = fmt::format("<b>{}</b>\n{}", result.text, description);
|
result.text = fmt::format("<b>{}</b>\n{}", std::string(result.text), std::string(description));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item::setProperty(const Glib::ustring& name, Glib::VariantBase& value) {
|
void Item::setProperty(const Glib::ustring& name, Glib::VariantBase& value) {
|
||||||
try {
|
try {
|
||||||
spdlog::trace("Set tray item property: {}.{} = {}", id.empty() ? bus_name : id, name, value);
|
spdlog::trace("Set tray item property: {}.{} = {}", id.empty() ? bus_name : id,
|
||||||
|
std::string(name), get_variant<std::string>(value));
|
||||||
|
|
||||||
if (name == "Category") {
|
if (name == "Category") {
|
||||||
category = get_variant<std::string>(value);
|
category = get_variant<std::string>(value);
|
||||||
|
@ -176,10 +179,12 @@ void Item::setProperty(const Glib::ustring& name, Glib::VariantBase& value) {
|
||||||
}
|
}
|
||||||
} catch (const Glib::Error& err) {
|
} catch (const Glib::Error& err) {
|
||||||
spdlog::warn("Failed to set tray item property: {}.{}, value = {}, err = {}",
|
spdlog::warn("Failed to set tray item property: {}.{}, value = {}, err = {}",
|
||||||
id.empty() ? bus_name : id, name, value, err.what());
|
id.empty() ? bus_name : id, std::string(name), get_variant<std::string>(value),
|
||||||
|
std::string(err.what()));
|
||||||
} catch (const std::exception& err) {
|
} catch (const std::exception& err) {
|
||||||
spdlog::warn("Failed to set tray item property: {}.{}, value = {}, err = {}",
|
spdlog::warn("Failed to set tray item property: {}.{}, value = {}, err = {}",
|
||||||
id.empty() ? bus_name : id, name, value, err.what());
|
id.empty() ? bus_name : id, std::string(name), get_variant<std::string>(value),
|
||||||
|
std::string(err.what()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,9 +226,9 @@ void Item::processUpdatedProperties(Glib::RefPtr<Gio::AsyncResult>& _result) {
|
||||||
|
|
||||||
this->updateImage();
|
this->updateImage();
|
||||||
} catch (const Glib::Error& err) {
|
} catch (const Glib::Error& err) {
|
||||||
spdlog::warn("Failed to update properties: {}", err.what());
|
spdlog::warn("Failed to update properties: {}", std::string(err.what()));
|
||||||
} catch (const std::exception& err) {
|
} catch (const std::exception& err) {
|
||||||
spdlog::warn("Failed to update properties: {}", err.what());
|
spdlog::warn("Failed to update properties: {}", std::string(err.what()));
|
||||||
}
|
}
|
||||||
update_pending_.clear();
|
update_pending_.clear();
|
||||||
}
|
}
|
||||||
|
@ -245,7 +250,7 @@ static const std::map<std::string_view, std::set<std::string_view>> signal2props
|
||||||
|
|
||||||
void Item::onSignal(const Glib::ustring& sender_name, const Glib::ustring& signal_name,
|
void Item::onSignal(const Glib::ustring& sender_name, const Glib::ustring& signal_name,
|
||||||
const Glib::VariantContainerBase& arguments) {
|
const Glib::VariantContainerBase& arguments) {
|
||||||
spdlog::trace("Tray item '{}' got signal {}", id, signal_name);
|
spdlog::trace("Tray item '{}' got signal {}", id, std::string(signal_name));
|
||||||
auto changed = signal2props.find(signal_name.raw());
|
auto changed = signal2props.find(signal_name.raw());
|
||||||
if (changed != signal2props.end()) {
|
if (changed != signal2props.end()) {
|
||||||
if (update_pending_.empty()) {
|
if (update_pending_.empty()) {
|
||||||
|
|
|
@ -384,10 +384,11 @@ void UPower::setDisplayDevice() {
|
||||||
displayDevice = upDevice;
|
displayDevice = upDevice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Unref current upDevice
|
// Unref current upDevice if it exists
|
||||||
if (displayDevice.upDevice != NULL) g_object_unref(thisPtr->upDevice_.upDevice);
|
if (displayDevice.upDevice != NULL) {
|
||||||
// Reassign new upDevice
|
if (thisPtr->upDevice_.upDevice != NULL) g_object_unref(thisPtr->upDevice_.upDevice);
|
||||||
thisPtr->upDevice_ = displayDevice;
|
thisPtr->upDevice_ = displayDevice;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
this);
|
this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,8 +118,8 @@ auto WorkspaceManager::sort_workspaces() -> void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto WorkspaceManager::register_manager(wl_registry *registry, uint32_t name, uint32_t version)
|
auto WorkspaceManager::register_manager(wl_registry *registry, uint32_t name,
|
||||||
-> void {
|
uint32_t version) -> void {
|
||||||
if (workspace_manager_) {
|
if (workspace_manager_) {
|
||||||
spdlog::warn("Register workspace manager again although already registered!");
|
spdlog::warn("Register workspace manager again although already registered!");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
[wrap-file]
|
[wrap-file]
|
||||||
directory = Catch2-3.5.1
|
directory = Catch2-3.7.0
|
||||||
source_url = https://github.com/catchorg/Catch2/archive/v3.5.1.tar.gz
|
source_url = https://github.com/catchorg/Catch2/archive/v3.7.0.tar.gz
|
||||||
source_filename = Catch2-3.5.1.tar.gz
|
source_filename = Catch2-3.7.0.tar.gz
|
||||||
source_hash = 49c3ca7a68f1c8ec71307736bc6ed14fec21631707e1be9af45daf4037e75a08
|
source_hash = 5b10cd536fa3818112a82820ce0787bd9f2a906c618429e7c4dea639983c8e88
|
||||||
# source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/catch2_3.4.0-1/Catch2-3.4.0.tar.gz
|
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/catch2_3.7.0-1/Catch2-3.7.0.tar.gz
|
||||||
# wrapdb_version = 3.4.0-1
|
wrapdb_version = 3.7.0-1
|
||||||
|
|
||||||
[provide]
|
[provide]
|
||||||
catch2 = catch2_dep
|
catch2 = catch2_dep
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
[wrap-file]
|
[wrap-file]
|
||||||
directory = fmt-9.1.0
|
directory = fmt-11.0.1
|
||||||
source_url = https://github.com/fmtlib/fmt/archive/9.1.0.tar.gz
|
source_url = https://github.com/fmtlib/fmt/archive/11.0.1.tar.gz
|
||||||
source_filename = fmt-9.1.0.tar.gz
|
source_filename = fmt-11.0.1.tar.gz
|
||||||
source_hash = 5dea48d1fcddc3ec571ce2058e13910a0d4a6bab4cc09a809d8b1dd1c88ae6f2
|
source_hash = 7d009f7f89ac84c0a83f79ed602463d092fbf66763766a907c97fd02b100f5e9
|
||||||
patch_filename = fmt_9.1.0-2_patch.zip
|
patch_filename = fmt_11.0.1-1_patch.zip
|
||||||
patch_url = https://wrapdb.mesonbuild.com/v2/fmt_9.1.0-2/get_patch
|
patch_url = https://wrapdb.mesonbuild.com/v2/fmt_11.0.1-1/get_patch
|
||||||
patch_hash = 23e8c4829f3e63f509b5643fe6bb87cbed39eae9594c451b338475d14d051967
|
patch_hash = 0a8b93d1ee6d84a82d3872a9bfb4c3977d8a53f7f484d42d1f7ed63ed496d549
|
||||||
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/fmt_9.1.0-2/fmt-9.1.0.tar.gz
|
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/fmt_11.0.1-1/fmt-11.0.1.tar.gz
|
||||||
wrapdb_version = 9.1.0-2
|
wrapdb_version = 11.0.1-1
|
||||||
|
|
||||||
[provide]
|
[provide]
|
||||||
fmt = fmt_dep
|
fmt = fmt_dep
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[wrap-file]
|
[wrap-file]
|
||||||
directory = gtk-layer-shell-0.8.2
|
directory = gtk-layer-shell-0.9.0
|
||||||
source_filename = gtk-layer-shell-0.8.2.tar.gz
|
source_filename = gtk-layer-shell-0.9.0.tar.gz
|
||||||
source_hash = 254dd246303127c5d5236ea640f01a82e35d2d652a48d139dd669c832a0f0dce
|
source_hash = 3809e5565d9ed02e44bb73787ff218523e8760fef65830afe60ea7322e22da1c
|
||||||
source_url = https://github.com/wmww/gtk-layer-shell/archive/v0.8.2/gtk-layer-shell-0.8.2.tar.gz
|
source_url = https://github.com/wmww/gtk-layer-shell/archive/v0.9.0/gtk-layer-shell-0.9.0.tar.gz
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
[wrap-file]
|
[wrap-file]
|
||||||
directory = spdlog-1.12.0
|
directory = spdlog-1.14.1
|
||||||
source_url = https://github.com/gabime/spdlog/archive/refs/tags/v1.12.0.tar.gz
|
source_url = https://github.com/gabime/spdlog/archive/refs/tags/v1.14.1.tar.gz
|
||||||
source_filename = spdlog-1.12.0.tar.gz
|
source_filename = spdlog-1.14.1.tar.gz
|
||||||
source_hash = 4dccf2d10f410c1e2feaff89966bfc49a1abb29ef6f08246335b110e001e09a9
|
source_hash = 1586508029a7d0670dfcb2d97575dcdc242d3868a259742b69f100801ab4e16b
|
||||||
patch_filename = spdlog_1.12.0-2_patch.zip
|
patch_filename = spdlog_1.14.1-1_patch.zip
|
||||||
patch_url = https://wrapdb.mesonbuild.com/v2/spdlog_1.12.0-2/get_patch
|
patch_url = https://wrapdb.mesonbuild.com/v2/spdlog_1.14.1-1/get_patch
|
||||||
patch_hash = 9596972d1eb2e0a69cea4a53273ca7bbbcb9b2fa872cd734864fc7232dc2d573
|
patch_hash = ae878e732330ea1048f90d7e117c40c0cd2a6fb8ae5492c7955818ce3aaade6c
|
||||||
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/spdlog_1.12.0-2/spdlog-1.12.0.tar.gz
|
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/spdlog_1.14.1-1/spdlog-1.14.1.tar.gz
|
||||||
wrapdb_version = 1.12.0-2
|
wrapdb_version = 1.14.1-1
|
||||||
|
|
||||||
[provide]
|
[provide]
|
||||||
spdlog = spdlog_dep
|
spdlog = spdlog_dep
|
||||||
|
|
Loading…
Reference in New Issue