Merge branch 'master' into amd_fix
commit
f743882baa
|
@ -8,6 +8,7 @@ env:
|
||||||
- distro: archlinux
|
- distro: archlinux
|
||||||
- distro: opensuse
|
- distro: opensuse
|
||||||
- distro: fedora
|
- distro: fedora
|
||||||
|
- distro: alpine
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- docker pull alexays/waybar:${distro}
|
- docker pull alexays/waybar:${distro}
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
FROM alpine:latest
|
||||||
|
|
||||||
|
RUN apk add --no-cache git meson alpine-sdk libinput-dev wayland-dev wayland-protocols mesa-dev libxkbcommon-dev eudev-dev pixman-dev gtkmm3-dev jsoncpp-dev libnl3-dev pulseaudio-dev libmpdclient-dev
|
|
@ -13,7 +13,7 @@ class ALabel : public IModule {
|
||||||
ALabel(const Json::Value &, const std::string &format, uint16_t interval = 0);
|
ALabel(const Json::Value &, const std::string &format, uint16_t interval = 0);
|
||||||
virtual ~ALabel();
|
virtual ~ALabel();
|
||||||
virtual auto update() -> void;
|
virtual auto update() -> void;
|
||||||
virtual std::string getIcon(uint16_t, const std::string &alt = "");
|
virtual std::string getIcon(uint16_t, const std::string &alt = "", uint16_t max = 0);
|
||||||
virtual operator Gtk::Widget &();
|
virtual operator Gtk::Widget &();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -31,7 +31,7 @@ class ALabel : public IModule {
|
||||||
|
|
||||||
virtual bool handleToggle(GdkEventButton *const &ev);
|
virtual bool handleToggle(GdkEventButton *const &ev);
|
||||||
virtual bool handleScroll(GdkEventScroll *);
|
virtual bool handleScroll(GdkEventScroll *);
|
||||||
virtual std::string getState(uint8_t value);
|
virtual std::string getState(uint8_t value, bool lesser = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<int> pid_;
|
std::vector<int> pid_;
|
||||||
|
|
|
@ -7,11 +7,13 @@
|
||||||
#include "modules/sway/window.hpp"
|
#include "modules/sway/window.hpp"
|
||||||
#include "modules/sway/workspaces.hpp"
|
#include "modules/sway/workspaces.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef NO_FILESYSTEM
|
||||||
#include "modules/battery.hpp"
|
#include "modules/battery.hpp"
|
||||||
|
#endif
|
||||||
#include "modules/cpu.hpp"
|
#include "modules/cpu.hpp"
|
||||||
#include "modules/idle_inhibitor.hpp"
|
#include "modules/idle_inhibitor.hpp"
|
||||||
#include "modules/memory.hpp"
|
#include "modules/memory.hpp"
|
||||||
#ifdef HAVE_DBUSMENU
|
#if defined(HAVE_DBUSMENU) && !defined(NO_FILESYSTEM)
|
||||||
#include "modules/sni/tray.hpp"
|
#include "modules/sni/tray.hpp"
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_LIBNL
|
#ifdef HAVE_LIBNL
|
||||||
|
|
|
@ -30,10 +30,10 @@ class Battery : public ALabel {
|
||||||
private:
|
private:
|
||||||
static inline const fs::path data_dir_ = "/sys/class/power_supply/";
|
static inline const fs::path data_dir_ = "/sys/class/power_supply/";
|
||||||
|
|
||||||
void getBatteries();
|
void getBatteries();
|
||||||
void worker();
|
void worker();
|
||||||
const std::string getAdapterStatus(uint8_t capacity) const;
|
const std::string getAdapterStatus(uint8_t capacity, uint32_t current_now) const;
|
||||||
const std::tuple<uint8_t, std::string> getInfos() const;
|
const std::tuple<uint8_t, uint32_t, std::string> getInfos() const;
|
||||||
|
|
||||||
util::SleeperThread thread_;
|
util::SleeperThread thread_;
|
||||||
util::SleeperThread thread_timer_;
|
util::SleeperThread thread_timer_;
|
||||||
|
|
|
@ -28,7 +28,6 @@ class Network : public ALabel {
|
||||||
static int handleScan(struct nl_msg*, void*);
|
static int handleScan(struct nl_msg*, void*);
|
||||||
|
|
||||||
void worker();
|
void worker();
|
||||||
void disconnected();
|
|
||||||
void createInfoSocket();
|
void createInfoSocket();
|
||||||
void createEventSocket();
|
void createEventSocket();
|
||||||
int getExternalInterface();
|
int getExternalInterface();
|
||||||
|
@ -37,27 +36,35 @@ class Network : public ALabel {
|
||||||
int netlinkResponse(void*, uint32_t, uint32_t groups = 0);
|
int netlinkResponse(void*, uint32_t, uint32_t groups = 0);
|
||||||
void parseEssid(struct nlattr**);
|
void parseEssid(struct nlattr**);
|
||||||
void parseSignal(struct nlattr**);
|
void parseSignal(struct nlattr**);
|
||||||
|
void parseFreq(struct nlattr**);
|
||||||
bool associatedOrJoined(struct nlattr**);
|
bool associatedOrJoined(struct nlattr**);
|
||||||
|
bool checkInterface(int if_index, std::string name);
|
||||||
|
int getPreferredIface();
|
||||||
auto getInfo() -> void;
|
auto getInfo() -> void;
|
||||||
|
bool wildcardMatch(const std::string& pattern, const std::string& text);
|
||||||
|
|
||||||
waybar::util::SleeperThread thread_;
|
waybar::util::SleeperThread thread_;
|
||||||
waybar::util::SleeperThread thread_timer_;
|
waybar::util::SleeperThread thread_timer_;
|
||||||
int ifid_;
|
int ifid_;
|
||||||
|
int last_ext_iface_;
|
||||||
sa_family_t family_;
|
sa_family_t family_;
|
||||||
struct sockaddr_nl nladdr_ = {0};
|
struct sockaddr_nl nladdr_ = {0};
|
||||||
struct nl_sock* sk_ = nullptr;
|
struct nl_sock* sock_ = nullptr;
|
||||||
struct nl_sock* info_sock_ = nullptr;
|
struct nl_sock* ev_sock_ = nullptr;
|
||||||
int efd_;
|
int efd_;
|
||||||
int ev_fd_;
|
int ev_fd_;
|
||||||
int nl80211_id_;
|
int nl80211_id_;
|
||||||
|
std::mutex mutex_;
|
||||||
|
|
||||||
std::string essid_;
|
std::string essid_;
|
||||||
std::string ifname_;
|
std::string ifname_;
|
||||||
std::string ipaddr_;
|
std::string ipaddr_;
|
||||||
std::string netmask_;
|
std::string netmask_;
|
||||||
int cidr_;
|
int cidr_;
|
||||||
|
bool linked_;
|
||||||
int32_t signal_strength_dbm_;
|
int32_t signal_strength_dbm_;
|
||||||
uint8_t signal_strength_;
|
uint8_t signal_strength_;
|
||||||
|
uint32_t frequency_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar::modules
|
} // namespace waybar::modules
|
||||||
|
|
|
@ -20,7 +20,7 @@ class Pulseaudio : public ALabel {
|
||||||
static void sinkInfoCb(pa_context*, const pa_sink_info*, int, void*);
|
static void sinkInfoCb(pa_context*, const pa_sink_info*, int, void*);
|
||||||
static void serverInfoCb(pa_context*, const pa_server_info*, void*);
|
static void serverInfoCb(pa_context*, const pa_server_info*, void*);
|
||||||
static void volumeModifyCb(pa_context*, int, void*);
|
static void volumeModifyCb(pa_context*, int, void*);
|
||||||
bool handleScroll(GdkEventScroll* e);
|
bool handleVolume(GdkEventScroll* e);
|
||||||
|
|
||||||
const std::string getPortIcon() const;
|
const std::string getPortIcon() const;
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ class Pulseaudio : public ALabel {
|
||||||
bool muted_;
|
bool muted_;
|
||||||
std::string port_name_;
|
std::string port_name_;
|
||||||
std::string desc_;
|
std::string desc_;
|
||||||
|
std::string monitor_;
|
||||||
bool scrolling_;
|
bool scrolling_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ class Item : public sigc::trackable {
|
||||||
std::string menu;
|
std::string menu;
|
||||||
DbusmenuGtkMenu* dbus_menu = nullptr;
|
DbusmenuGtkMenu* dbus_menu = nullptr;
|
||||||
Gtk::Menu* gtk_menu = nullptr;
|
Gtk::Menu* gtk_menu = nullptr;
|
||||||
bool item_is_menu;
|
bool item_is_menu = false;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void proxyReady(Glib::RefPtr<Gio::AsyncResult>& result);
|
void proxyReady(Glib::RefPtr<Gio::AsyncResult>& result);
|
||||||
|
@ -59,12 +59,12 @@ class Item : public sigc::trackable {
|
||||||
void updateImage();
|
void updateImage();
|
||||||
Glib::RefPtr<Gdk::Pixbuf> extractPixBuf(GVariant* variant);
|
Glib::RefPtr<Gdk::Pixbuf> extractPixBuf(GVariant* variant);
|
||||||
Glib::RefPtr<Gdk::Pixbuf> getIconByName(const std::string& name, int size);
|
Glib::RefPtr<Gdk::Pixbuf> getIconByName(const std::string& name, int size);
|
||||||
static void onMenuDestroyed(Item* self);
|
static void onMenuDestroyed(Item* self, GObject* old_menu_pointer);
|
||||||
bool makeMenu(GdkEventButton* const& ev);
|
void makeMenu(GdkEventButton* const& ev);
|
||||||
bool handleClick(GdkEventButton* const& /*ev*/);
|
bool handleClick(GdkEventButton* const& /*ev*/);
|
||||||
|
|
||||||
Glib::RefPtr<Gio::Cancellable> cancellable_;
|
|
||||||
Glib::RefPtr<Gio::DBus::Proxy> proxy_;
|
Glib::RefPtr<Gio::DBus::Proxy> proxy_;
|
||||||
|
Glib::RefPtr<Gio::Cancellable> cancellable_;
|
||||||
bool update_pending_;
|
bool update_pending_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
namespace waybar::modules::sway {
|
namespace waybar::modules::sway {
|
||||||
|
|
||||||
class Mode : public ALabel {
|
class Mode : public ALabel, public sigc::trackable {
|
||||||
public:
|
public:
|
||||||
Mode(const std::string&, const Json::Value&);
|
Mode(const std::string&, const Json::Value&);
|
||||||
~Mode() = default;
|
~Mode() = default;
|
||||||
|
|
|
@ -6,12 +6,12 @@
|
||||||
#include "bar.hpp"
|
#include "bar.hpp"
|
||||||
#include "client.hpp"
|
#include "client.hpp"
|
||||||
#include "modules/sway/ipc/client.hpp"
|
#include "modules/sway/ipc/client.hpp"
|
||||||
#include "util/sleeper_thread.hpp"
|
|
||||||
#include "util/json.hpp"
|
#include "util/json.hpp"
|
||||||
|
#include "util/sleeper_thread.hpp"
|
||||||
|
|
||||||
namespace waybar::modules::sway {
|
namespace waybar::modules::sway {
|
||||||
|
|
||||||
class Window : public ALabel {
|
class Window : public ALabel, public sigc::trackable {
|
||||||
public:
|
public:
|
||||||
Window(const std::string&, const waybar::Bar&, const Json::Value&);
|
Window(const std::string&, const waybar::Bar&, const Json::Value&);
|
||||||
~Window() = default;
|
~Window() = default;
|
||||||
|
@ -27,10 +27,11 @@ class Window : public ALabel {
|
||||||
const Bar& bar_;
|
const Bar& bar_;
|
||||||
waybar::util::SleeperThread thread_;
|
waybar::util::SleeperThread thread_;
|
||||||
Ipc ipc_;
|
Ipc ipc_;
|
||||||
|
std::mutex mutex_;
|
||||||
std::string window_;
|
std::string window_;
|
||||||
int windowId_;
|
int windowId_;
|
||||||
std::string app_id_;
|
std::string app_id_;
|
||||||
util::JsonParser parser_;
|
util::JsonParser parser_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar::modules::sway
|
} // namespace waybar::modules::sway
|
||||||
|
|
|
@ -7,12 +7,12 @@
|
||||||
#include "bar.hpp"
|
#include "bar.hpp"
|
||||||
#include "client.hpp"
|
#include "client.hpp"
|
||||||
#include "modules/sway/ipc/client.hpp"
|
#include "modules/sway/ipc/client.hpp"
|
||||||
#include "util/sleeper_thread.hpp"
|
|
||||||
#include "util/json.hpp"
|
#include "util/json.hpp"
|
||||||
|
#include "util/sleeper_thread.hpp"
|
||||||
|
|
||||||
namespace waybar::modules::sway {
|
namespace waybar::modules::sway {
|
||||||
|
|
||||||
class Workspaces : public IModule {
|
class Workspaces : public IModule, public sigc::trackable {
|
||||||
public:
|
public:
|
||||||
Workspaces(const std::string&, const waybar::Bar&, const Json::Value&);
|
Workspaces(const std::string&, const waybar::Bar&, const Json::Value&);
|
||||||
~Workspaces() = default;
|
~Workspaces() = default;
|
||||||
|
@ -27,10 +27,10 @@ class Workspaces : public IModule {
|
||||||
Gtk::Button& addButton(const Json::Value&);
|
Gtk::Button& addButton(const Json::Value&);
|
||||||
void onButtonReady(const Json::Value&, Gtk::Button&);
|
void onButtonReady(const Json::Value&, Gtk::Button&);
|
||||||
std::string getIcon(const std::string&, const Json::Value&);
|
std::string getIcon(const std::string&, const Json::Value&);
|
||||||
bool handleScroll(GdkEventScroll*);
|
|
||||||
const std::string getCycleWorkspace(std::vector<Json::Value>::iterator, bool prev) const;
|
const std::string getCycleWorkspace(std::vector<Json::Value>::iterator, bool prev) const;
|
||||||
uint16_t getWorkspaceIndex(const std::string& name) const;
|
uint16_t getWorkspaceIndex(const std::string& name) const;
|
||||||
std::string trimWorkspaceName(std::string);
|
std::string trimWorkspaceName(std::string);
|
||||||
|
bool handleScroll(GdkEventScroll*);
|
||||||
|
|
||||||
const Bar& bar_;
|
const Bar& bar_;
|
||||||
const Json::Value& config_;
|
const Json::Value& config_;
|
||||||
|
|
|
@ -4,11 +4,6 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include "ALabel.hpp"
|
#include "ALabel.hpp"
|
||||||
#include "util/sleeper_thread.hpp"
|
#include "util/sleeper_thread.hpp"
|
||||||
#ifdef FILESYSTEM_EXPERIMENTAL
|
|
||||||
#include <experimental/filesystem>
|
|
||||||
#else
|
|
||||||
#include <filesystem>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace waybar::modules {
|
namespace waybar::modules {
|
||||||
|
|
||||||
|
|
|
@ -5,15 +5,16 @@
|
||||||
namespace waybar::util {
|
namespace waybar::util {
|
||||||
|
|
||||||
struct JsonParser {
|
struct JsonParser {
|
||||||
JsonParser() : reader_(builder_.newCharReader()) {}
|
JsonParser() {}
|
||||||
|
|
||||||
const Json::Value parse(const std::string& data) const {
|
const Json::Value parse(const std::string& data) const {
|
||||||
Json::Value root(Json::objectValue);
|
Json::Value root(Json::objectValue);
|
||||||
if (data.empty()) {
|
if (data.empty()) {
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
std::string err;
|
std::unique_ptr<Json::CharReader> const reader(builder_.newCharReader());
|
||||||
bool res = reader_->parse(data.c_str(), data.c_str() + data.size(), &root, &err);
|
std::string err;
|
||||||
|
bool res = reader->parse(data.c_str(), data.c_str() + data.size(), &root, &err);
|
||||||
if (!res) throw std::runtime_error(err);
|
if (!res) throw std::runtime_error(err);
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
@ -21,8 +22,7 @@ struct JsonParser {
|
||||||
~JsonParser() = default;
|
~JsonParser() = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Json::CharReaderBuilder builder_;
|
Json::CharReaderBuilder builder_;
|
||||||
std::unique_ptr<Json::CharReader> const reader_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar::util
|
} // namespace waybar::util
|
||||||
|
|
11
meson.build
11
meson.build
|
@ -1,6 +1,6 @@
|
||||||
project(
|
project(
|
||||||
'waybar', 'cpp', 'c',
|
'waybar', 'cpp', 'c',
|
||||||
version: '0.6.2',
|
version: '0.6.4',
|
||||||
license: 'MIT',
|
license: 'MIT',
|
||||||
default_options : [
|
default_options : [
|
||||||
'cpp_std=c++17',
|
'cpp_std=c++17',
|
||||||
|
@ -12,7 +12,7 @@ project(
|
||||||
cpp_args = []
|
cpp_args = []
|
||||||
cpp_link_args = []
|
cpp_link_args = []
|
||||||
|
|
||||||
if false # libc++
|
if get_option('libcxx')
|
||||||
cpp_args += ['-stdlib=libc++']
|
cpp_args += ['-stdlib=libc++']
|
||||||
cpp_link_args += ['-stdlib=libc++', '-lc++abi']
|
cpp_link_args += ['-stdlib=libc++', '-lc++abi']
|
||||||
|
|
||||||
|
@ -34,7 +34,12 @@ else
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if not compiler.has_header('filesystem')
|
if not compiler.has_header('filesystem')
|
||||||
add_project_arguments('-DFILESYSTEM_EXPERIMENTAL', language: 'cpp')
|
if compiler.has_header('experimental/filesystem')
|
||||||
|
add_project_arguments('-DFILESYSTEM_EXPERIMENTAL', language: 'cpp')
|
||||||
|
else
|
||||||
|
add_project_arguments('-DNO_FILESYSTEM', language: 'cpp')
|
||||||
|
warning('No filesystem header found, some modules may not work')
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
add_global_arguments(cpp_args, language : 'cpp')
|
add_global_arguments(cpp_args, language : 'cpp')
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
option('libcxx', type : 'boolean', value : false, description : 'Build with Clang\'s libc++ instead of libstdc++ on Linux.')
|
||||||
option('libnl', type: 'feature', value: 'auto', description: 'Enable libnl support for network related features')
|
option('libnl', type: 'feature', value: 'auto', description: 'Enable libnl support for network related features')
|
||||||
option('libudev', type: 'feature', value: 'auto', description: 'Enable libudev support for udev related features')
|
option('libudev', type: 'feature', value: 'auto', description: 'Enable libudev support for udev related features')
|
||||||
option('pulseaudio', type: 'feature', value: 'auto', description: 'Enable support for pulseaudio')
|
option('pulseaudio', type: 'feature', value: 'auto', description: 'Enable support for pulseaudio')
|
||||||
|
|
|
@ -78,8 +78,9 @@
|
||||||
// "thermal-zone": 2,
|
// "thermal-zone": 2,
|
||||||
// "hwmon-path": "/sys/class/hwmon/hwmon2/temp1_input",
|
// "hwmon-path": "/sys/class/hwmon/hwmon2/temp1_input",
|
||||||
"critical-threshold": 80,
|
"critical-threshold": 80,
|
||||||
// "format-critical": "{temperatureC}°C ",
|
// "format-critical": "{temperatureC}°C {icon}",
|
||||||
"format": "{temperatureC}°C "
|
"format": "{temperatureC}°C {icon}",
|
||||||
|
"format-icons": ["", "", ""]
|
||||||
},
|
},
|
||||||
"backlight": {
|
"backlight": {
|
||||||
// "device": "acpi_video1",
|
// "device": "acpi_video1",
|
||||||
|
@ -93,6 +94,8 @@
|
||||||
"critical": 15
|
"critical": 15
|
||||||
},
|
},
|
||||||
"format": "{capacity}% {icon}",
|
"format": "{capacity}% {icon}",
|
||||||
|
"format-charging": "{capacity}% ",
|
||||||
|
"format-plugged": "{capacity}% ",
|
||||||
// "format-good": "", // An empty format will hide the module
|
// "format-good": "", // An empty format will hide the module
|
||||||
// "format-full": "",
|
// "format-full": "",
|
||||||
"format-icons": ["", "", "", "", ""]
|
"format-icons": ["", "", "", "", ""]
|
||||||
|
@ -101,16 +104,17 @@
|
||||||
"bat": "BAT2"
|
"bat": "BAT2"
|
||||||
},
|
},
|
||||||
"network": {
|
"network": {
|
||||||
// "interface": "wlp2s0", // (Optional) To force the use of this interface
|
// "interface": "wlp2*", // (Optional) To force the use of this interface
|
||||||
"format-wifi": "{essid} ({signalStrength}%) ",
|
"format-wifi": "{essid} ({signalStrength}%) ",
|
||||||
"format-ethernet": "{ifname}: {ipaddr}/{cidr} ",
|
"format-ethernet": "{ifname}: {ipaddr}/{cidr} ",
|
||||||
|
"format-linked": "{ifname} (No IP) ",
|
||||||
"format-disconnected": "Disconnected ⚠"
|
"format-disconnected": "Disconnected ⚠"
|
||||||
},
|
},
|
||||||
"pulseaudio": {
|
"pulseaudio": {
|
||||||
//"scroll-step": 1,
|
// "scroll-step": 1, // %, can be a float
|
||||||
"format": "{volume}% {icon}",
|
"format": "{volume}% {icon}",
|
||||||
"format-bluetooth": "{volume}% {icon}",
|
"format-bluetooth": "{volume}% {icon}",
|
||||||
"format-muted": "",
|
"format-muted": "",
|
||||||
"format-icons": {
|
"format-icons": {
|
||||||
"headphones": "",
|
"headphones": "",
|
||||||
"handsfree": "",
|
"handsfree": "",
|
||||||
|
@ -118,7 +122,7 @@
|
||||||
"phone": "",
|
"phone": "",
|
||||||
"portable": "",
|
"portable": "",
|
||||||
"car": "",
|
"car": "",
|
||||||
"default": ["", ""]
|
"default": ["", "", ""]
|
||||||
},
|
},
|
||||||
"on-click": "pavucontrol"
|
"on-click": "pavucontrol"
|
||||||
},
|
},
|
||||||
|
|
|
@ -32,8 +32,7 @@ window#waybar.termite {
|
||||||
}
|
}
|
||||||
|
|
||||||
window#waybar.chromium {
|
window#waybar.chromium {
|
||||||
background-color: #DEE1E6;
|
background-color: #000000;
|
||||||
color: #000000;
|
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,19 +44,11 @@ window#waybar.chromium {
|
||||||
border-bottom: 3px solid transparent;
|
border-bottom: 3px solid transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
window#waybar.chromium #workspaces button {
|
|
||||||
color: #3F3F3F;
|
|
||||||
}
|
|
||||||
|
|
||||||
#workspaces button.focused {
|
#workspaces button.focused {
|
||||||
background: #64727D;
|
background: #64727D;
|
||||||
border-bottom: 3px solid #ffffff;
|
border-bottom: 3px solid #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
window#waybar.chromium #workspaces button.focused {
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
#workspaces button.urgent {
|
#workspaces button.urgent {
|
||||||
background-color: #eb4d4b;
|
background-color: #eb4d4b;
|
||||||
}
|
}
|
||||||
|
@ -142,6 +133,7 @@ label:focus {
|
||||||
#custom-media {
|
#custom-media {
|
||||||
background: #66cc99;
|
background: #66cc99;
|
||||||
color: #2a5c45;
|
color: #2a5c45;
|
||||||
|
min-width: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.custom-spotify {
|
.custom-spotify {
|
||||||
|
|
|
@ -109,7 +109,7 @@ bool waybar::ALabel::handleScroll(GdkEventScroll* e) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string waybar::ALabel::getIcon(uint16_t percentage, const std::string& alt) {
|
std::string waybar::ALabel::getIcon(uint16_t percentage, const std::string& alt, uint16_t max) {
|
||||||
auto format_icons = config_["format-icons"];
|
auto format_icons = config_["format-icons"];
|
||||||
if (format_icons.isObject()) {
|
if (format_icons.isObject()) {
|
||||||
if (!alt.empty() && (format_icons[alt].isString() || format_icons[alt].isArray())) {
|
if (!alt.empty() && (format_icons[alt].isString() || format_icons[alt].isArray())) {
|
||||||
|
@ -120,7 +120,7 @@ std::string waybar::ALabel::getIcon(uint16_t percentage, const std::string& alt)
|
||||||
}
|
}
|
||||||
if (format_icons.isArray()) {
|
if (format_icons.isArray()) {
|
||||||
auto size = format_icons.size();
|
auto size = format_icons.size();
|
||||||
auto idx = std::clamp(percentage / (100 / size), 0U, size - 1);
|
auto idx = std::clamp(percentage / ((max == 0 ? 100 : max) / size), 0U, size - 1);
|
||||||
format_icons = format_icons[idx];
|
format_icons = format_icons[idx];
|
||||||
}
|
}
|
||||||
if (format_icons.isString()) {
|
if (format_icons.isString()) {
|
||||||
|
@ -129,7 +129,10 @@ std::string waybar::ALabel::getIcon(uint16_t percentage, const std::string& alt)
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string waybar::ALabel::getState(uint8_t value) {
|
std::string waybar::ALabel::getState(uint8_t value, bool lesser) {
|
||||||
|
if (!config_["states"].isObject()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
// Get current state
|
// Get current state
|
||||||
std::vector<std::pair<std::string, uint8_t>> states;
|
std::vector<std::pair<std::string, uint8_t>> states;
|
||||||
if (config_["states"].isObject()) {
|
if (config_["states"].isObject()) {
|
||||||
|
@ -140,10 +143,12 @@ std::string waybar::ALabel::getState(uint8_t value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Sort states
|
// Sort states
|
||||||
std::sort(states.begin(), states.end(), [](auto& a, auto& b) { return a.second < b.second; });
|
std::sort(states.begin(), states.end(), [&lesser](auto& a, auto& b) {
|
||||||
|
return lesser ? a.second < b.second : a.second > b.second;
|
||||||
|
});
|
||||||
std::string valid_state;
|
std::string valid_state;
|
||||||
for (auto const& state : states) {
|
for (auto const& state : states) {
|
||||||
if (value <= state.second && valid_state.empty()) {
|
if ((lesser ? value <= state.second : value >= state.second) && valid_state.empty()) {
|
||||||
label_.get_style_context()->add_class(state.first);
|
label_.get_style_context()->add_class(state.first);
|
||||||
valid_state = state.first;
|
valid_state = state.first;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -20,7 +20,6 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
|
||||||
height_ = 0;
|
height_ = 0;
|
||||||
width_ = 1;
|
width_ = 1;
|
||||||
}
|
}
|
||||||
window.set_size_request(width_, height_);
|
|
||||||
|
|
||||||
auto gtk_window = window.gobj();
|
auto gtk_window = window.gobj();
|
||||||
auto gtk_widget = GTK_WIDGET(gtk_window);
|
auto gtk_widget = GTK_WIDGET(gtk_window);
|
||||||
|
@ -43,8 +42,6 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
|
||||||
auto height = config["height"].isUInt() ? config["height"].asUInt() : height_;
|
auto height = config["height"].isUInt() ? config["height"].asUInt() : height_;
|
||||||
auto width = config["width"].isUInt() ? config["width"].asUInt() : width_;
|
auto width = config["width"].isUInt() ? config["width"].asUInt() : width_;
|
||||||
|
|
||||||
window.signal_configure_event().connect_notify(sigc::mem_fun(*this, &Bar::onConfigure));
|
|
||||||
|
|
||||||
std::size_t anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
|
std::size_t anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
|
||||||
if (config["position"] == "bottom") {
|
if (config["position"] == "bottom") {
|
||||||
anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
|
anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
|
||||||
|
@ -73,6 +70,9 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
|
||||||
wl_display_roundtrip(client->wl_display);
|
wl_display_roundtrip(client->wl_display);
|
||||||
|
|
||||||
setupWidgets();
|
setupWidgets();
|
||||||
|
|
||||||
|
window.set_size_request(width_, height_);
|
||||||
|
window.signal_configure_event().connect_notify(sigc::mem_fun(*this, &Bar::onConfigure));
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::Bar::setMarginsAndZone(uint32_t height, uint32_t width) {
|
void waybar::Bar::setMarginsAndZone(uint32_t height, uint32_t width) {
|
||||||
|
|
|
@ -153,6 +153,7 @@ void waybar::Client::handleName(void * data, struct zxdg_output_v1 * /*xdg_
|
||||||
wl_output_destroy(output->output);
|
wl_output_destroy(output->output);
|
||||||
zxdg_output_v1_destroy(output->xdg_output);
|
zxdg_output_v1_destroy(output->xdg_output);
|
||||||
} else {
|
} else {
|
||||||
|
wl_display_roundtrip(client->wl_display);
|
||||||
for (const auto &config : configs) {
|
for (const auto &config : configs) {
|
||||||
client->bars.emplace_back(std::make_unique<Bar>(output.get(), config));
|
client->bars.emplace_back(std::make_unique<Bar>(output.get(), config));
|
||||||
Glib::RefPtr<Gdk::Screen> screen = client->bars.back()->window.get_screen();
|
Glib::RefPtr<Gdk::Screen> screen = client->bars.back()->window.get_screen();
|
||||||
|
|
|
@ -7,9 +7,11 @@ waybar::IModule* waybar::Factory::makeModule(const std::string& name) const {
|
||||||
auto hash_pos = name.find('#');
|
auto hash_pos = name.find('#');
|
||||||
auto ref = name.substr(0, hash_pos);
|
auto ref = name.substr(0, hash_pos);
|
||||||
auto id = hash_pos != std::string::npos ? name.substr(hash_pos + 1) : "";
|
auto id = hash_pos != std::string::npos ? name.substr(hash_pos + 1) : "";
|
||||||
|
#ifndef NO_FILESYSTEM
|
||||||
if (ref == "battery") {
|
if (ref == "battery") {
|
||||||
return new waybar::modules::Battery(id, config_[name]);
|
return new waybar::modules::Battery(id, config_[name]);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#ifdef HAVE_SWAY
|
#ifdef HAVE_SWAY
|
||||||
if (ref == "sway/mode") {
|
if (ref == "sway/mode") {
|
||||||
return new waybar::modules::sway::Mode(id, config_[name]);
|
return new waybar::modules::sway::Mode(id, config_[name]);
|
||||||
|
@ -33,7 +35,7 @@ waybar::IModule* waybar::Factory::makeModule(const std::string& name) const {
|
||||||
if (ref == "clock") {
|
if (ref == "clock") {
|
||||||
return new waybar::modules::Clock(id, config_[name]);
|
return new waybar::modules::Clock(id, config_[name]);
|
||||||
}
|
}
|
||||||
#ifdef HAVE_DBUSMENU
|
#if defined(HAVE_DBUSMENU) && !defined(NO_FILESYSTEM)
|
||||||
if (ref == "tray") {
|
if (ref == "tray") {
|
||||||
return new waybar::modules::SNI::Tray(id, bar_, config_[name]);
|
return new waybar::modules::SNI::Tray(id, bar_, config_[name]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,21 +47,21 @@ void waybar::modules::Battery::worker() {
|
||||||
|
|
||||||
void waybar::modules::Battery::getBatteries() {
|
void waybar::modules::Battery::getBatteries() {
|
||||||
try {
|
try {
|
||||||
for (auto const& node : fs::directory_iterator(data_dir_)) {
|
for (auto& node : fs::directory_iterator(data_dir_)) {
|
||||||
if (!fs::is_directory(node)) {
|
if (!fs::is_directory(node)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto dir_name = node.path().filename();
|
auto dir_name = node.path().filename();
|
||||||
auto bat_defined = config_["bat"].isString();
|
auto bat_defined = config_["bat"].isString();
|
||||||
if (((bat_defined && dir_name == config_["bat"].asString()) || !bat_defined) &&
|
if (((bat_defined && dir_name == config_["bat"].asString()) || !bat_defined) &&
|
||||||
fs::exists(node / "capacity") && fs::exists(node / "uevent") &&
|
fs::exists(node.path() / "capacity") && fs::exists(node.path() / "uevent") &&
|
||||||
fs::exists(node / "status")) {
|
fs::exists(node.path() / "status")) {
|
||||||
batteries_.push_back(node);
|
batteries_.push_back(node.path());
|
||||||
}
|
}
|
||||||
auto adap_defined = config_["adapter"].isString();
|
auto adap_defined = config_["adapter"].isString();
|
||||||
if (((adap_defined && dir_name == config_["adapter"].asString()) || !adap_defined) &&
|
if (((adap_defined && dir_name == config_["adapter"].asString()) || !adap_defined) &&
|
||||||
fs::exists(node / "online")) {
|
fs::exists(node.path() / "online")) {
|
||||||
adapter_ = node;
|
adapter_ = node.path();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (fs::filesystem_error& e) {
|
} catch (fs::filesystem_error& e) {
|
||||||
|
@ -75,52 +75,69 @@ void waybar::modules::Battery::getBatteries() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::tuple<uint8_t, std::string> waybar::modules::Battery::getInfos() const {
|
const std::tuple<uint8_t, uint32_t, std::string> waybar::modules::Battery::getInfos() const {
|
||||||
try {
|
try {
|
||||||
uint16_t total = 0;
|
uint16_t total = 0;
|
||||||
|
uint32_t total_current = 0;
|
||||||
std::string status = "Unknown";
|
std::string status = "Unknown";
|
||||||
for (auto const& bat : batteries_) {
|
for (auto const& bat : batteries_) {
|
||||||
uint16_t capacity;
|
uint16_t capacity;
|
||||||
|
uint32_t current_now;
|
||||||
std::string _status;
|
std::string _status;
|
||||||
std::ifstream(bat / "capacity") >> capacity;
|
std::ifstream(bat / "capacity") >> capacity;
|
||||||
std::ifstream(bat / "status") >> _status;
|
std::ifstream(bat / "status") >> _status;
|
||||||
|
std::ifstream(bat / "current_now") >> current_now;
|
||||||
if (_status != "Unknown") {
|
if (_status != "Unknown") {
|
||||||
status = _status;
|
status = _status;
|
||||||
}
|
}
|
||||||
total += capacity;
|
total += capacity;
|
||||||
|
total_current += current_now;
|
||||||
|
}
|
||||||
|
if (!adapter_.empty() && status == "Discharging") {
|
||||||
|
bool online;
|
||||||
|
std::ifstream(adapter_ / "online") >> online;
|
||||||
|
if (online) {
|
||||||
|
status = "Plugged";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
uint16_t capacity = total / batteries_.size();
|
uint16_t capacity = total / batteries_.size();
|
||||||
return {capacity, status};
|
return {capacity, total_current, status};
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
std::cerr << e.what() << std::endl;
|
std::cerr << e.what() << std::endl;
|
||||||
return {0, "Unknown"};
|
return {0, 0, "Unknown"};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity) const {
|
const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity,
|
||||||
|
uint32_t current_now) const {
|
||||||
if (!adapter_.empty()) {
|
if (!adapter_.empty()) {
|
||||||
bool online;
|
bool online;
|
||||||
std::ifstream(adapter_ / "online") >> online;
|
std::ifstream(adapter_ / "online") >> online;
|
||||||
if (capacity == 100) {
|
if (capacity == 100) {
|
||||||
return "Full";
|
return "Full";
|
||||||
}
|
}
|
||||||
return online ? "Charging" : "Discharging";
|
if (online) {
|
||||||
|
return "Charging";
|
||||||
|
}
|
||||||
|
return "Discharging";
|
||||||
}
|
}
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
auto waybar::modules::Battery::update() -> void {
|
auto waybar::modules::Battery::update() -> void {
|
||||||
auto [capacity, status] = getInfos();
|
auto [capacity, current_now, status] = getInfos();
|
||||||
if (status == "Unknown") {
|
if (status == "Unknown") {
|
||||||
status = getAdapterStatus(capacity);
|
status = getAdapterStatus(capacity, current_now);
|
||||||
}
|
}
|
||||||
if (tooltipEnabled()) {
|
if (tooltipEnabled()) {
|
||||||
label_.set_tooltip_text(status);
|
label_.set_tooltip_text(status);
|
||||||
}
|
}
|
||||||
std::transform(status.begin(), status.end(), status.begin(), ::tolower);
|
std::transform(status.begin(), status.end(), status.begin(), ::tolower);
|
||||||
auto format = format_;
|
auto format = format_;
|
||||||
auto state = getState(capacity);
|
auto state = getState(capacity, true);
|
||||||
label_.get_style_context()->remove_class(old_status_);
|
if (!old_status_.empty()) {
|
||||||
|
label_.get_style_context()->remove_class(old_status_);
|
||||||
|
}
|
||||||
label_.get_style_context()->add_class(status);
|
label_.get_style_context()->add_class(status);
|
||||||
old_status_ = status;
|
old_status_ = status;
|
||||||
if (!state.empty() && config_["format-" + status + "-" + state].isString()) {
|
if (!state.empty() && config_["format-" + status + "-" + state].isString()) {
|
||||||
|
@ -134,7 +151,7 @@ auto waybar::modules::Battery::update() -> void {
|
||||||
event_box_.hide();
|
event_box_.hide();
|
||||||
} else {
|
} else {
|
||||||
event_box_.show();
|
event_box_.show();
|
||||||
label_.set_markup(
|
label_.set_markup(fmt::format(
|
||||||
fmt::format(format, fmt::arg("capacity", capacity), fmt::arg("icon", getIcon(capacity))));
|
format, fmt::arg("capacity", capacity), fmt::arg("icon", getIcon(capacity, state))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ std::thread waybar::modules::MPD::event_listener() {
|
||||||
try {
|
try {
|
||||||
if (connection_ == nullptr) {
|
if (connection_ == nullptr) {
|
||||||
// Retry periodically if no connection
|
// Retry periodically if no connection
|
||||||
update();
|
dp.emit();
|
||||||
std::this_thread::sleep_for(interval_);
|
std::this_thread::sleep_for(interval_);
|
||||||
} else {
|
} else {
|
||||||
waitForEvent();
|
waitForEvent();
|
||||||
|
|
|
@ -3,31 +3,27 @@
|
||||||
|
|
||||||
waybar::modules::Network::Network(const std::string &id, const Json::Value &config)
|
waybar::modules::Network::Network(const std::string &id, const Json::Value &config)
|
||||||
: ALabel(config, "{ifname}", 60),
|
: ALabel(config, "{ifname}", 60),
|
||||||
family_(AF_INET),
|
ifid_(-1),
|
||||||
|
last_ext_iface_(-1),
|
||||||
|
family_(config["family"] == "ipv6" ? AF_INET6 : AF_INET),
|
||||||
efd_(-1),
|
efd_(-1),
|
||||||
ev_fd_(-1),
|
ev_fd_(-1),
|
||||||
cidr_(-1),
|
cidr_(-1),
|
||||||
signal_strength_dbm_(0),
|
signal_strength_dbm_(0),
|
||||||
signal_strength_(0) {
|
signal_strength_(0),
|
||||||
|
frequency_(0) {
|
||||||
label_.set_name("network");
|
label_.set_name("network");
|
||||||
if (!id.empty()) {
|
if (!id.empty()) {
|
||||||
label_.get_style_context()->add_class(id);
|
label_.get_style_context()->add_class(id);
|
||||||
}
|
}
|
||||||
createInfoSocket();
|
createInfoSocket();
|
||||||
createEventSocket();
|
createEventSocket();
|
||||||
if (config_["interface"].isString()) {
|
auto default_iface = getPreferredIface();
|
||||||
ifid_ = if_nametoindex(config_["interface"].asCString());
|
if (default_iface != -1) {
|
||||||
ifname_ = config_["interface"].asString();
|
char ifname[IF_NAMESIZE];
|
||||||
if (ifid_ <= 0) {
|
if_indextoname(default_iface, ifname);
|
||||||
throw std::runtime_error("Can't found network interface");
|
ifname_ = ifname;
|
||||||
}
|
getInterfaceAddress();
|
||||||
} else {
|
|
||||||
ifid_ = getExternalInterface();
|
|
||||||
if (ifid_ > 0) {
|
|
||||||
char ifname[IF_NAMESIZE];
|
|
||||||
if_indextoname(ifid_, ifname);
|
|
||||||
ifname_ = ifname;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
dp.emit();
|
dp.emit();
|
||||||
worker();
|
worker();
|
||||||
|
@ -42,39 +38,42 @@ waybar::modules::Network::~Network() {
|
||||||
if (efd_ > -1) {
|
if (efd_ > -1) {
|
||||||
close(efd_);
|
close(efd_);
|
||||||
}
|
}
|
||||||
if (info_sock_ != nullptr) {
|
if (ev_sock_ != nullptr) {
|
||||||
nl_socket_drop_membership(info_sock_, RTMGRP_LINK);
|
nl_socket_drop_membership(ev_sock_, RTNLGRP_LINK);
|
||||||
nl_socket_drop_membership(info_sock_, RTMGRP_IPV4_IFADDR);
|
nl_socket_drop_membership(ev_sock_, RTNLGRP_IPV4_IFADDR);
|
||||||
nl_close(info_sock_);
|
nl_socket_drop_membership(ev_sock_, RTNLGRP_IPV6_IFADDR);
|
||||||
nl_socket_free(info_sock_);
|
nl_socket_drop_membership(ev_sock_, RTNLGRP_IPV4_ROUTE);
|
||||||
|
nl_socket_drop_membership(ev_sock_, RTNLGRP_IPV6_ROUTE);
|
||||||
|
nl_close(ev_sock_);
|
||||||
|
nl_socket_free(ev_sock_);
|
||||||
}
|
}
|
||||||
if (sk_ != nullptr) {
|
if (sock_ != nullptr) {
|
||||||
nl_close(sk_);
|
nl_close(sock_);
|
||||||
nl_socket_free(sk_);
|
nl_socket_free(sock_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::modules::Network::createInfoSocket() {
|
void waybar::modules::Network::createInfoSocket() {
|
||||||
info_sock_ = nl_socket_alloc();
|
ev_sock_ = nl_socket_alloc();
|
||||||
if (nl_connect(info_sock_, NETLINK_ROUTE) != 0) {
|
nl_socket_disable_seq_check(ev_sock_);
|
||||||
|
nl_socket_modify_cb(ev_sock_, NL_CB_VALID, NL_CB_CUSTOM, handleEvents, this);
|
||||||
|
nl_join_groups(ev_sock_, RTMGRP_LINK);
|
||||||
|
if (nl_connect(ev_sock_, NETLINK_ROUTE) != 0) {
|
||||||
throw std::runtime_error("Can't connect network socket");
|
throw std::runtime_error("Can't connect network socket");
|
||||||
}
|
}
|
||||||
if (nl_socket_add_membership(info_sock_, RTMGRP_LINK) != 0) {
|
nl_socket_add_membership(ev_sock_, RTNLGRP_LINK);
|
||||||
throw std::runtime_error("Can't add membership");
|
nl_socket_add_membership(ev_sock_, RTNLGRP_IPV4_IFADDR);
|
||||||
}
|
nl_socket_add_membership(ev_sock_, RTNLGRP_IPV6_IFADDR);
|
||||||
if (nl_socket_add_membership(info_sock_, RTMGRP_IPV4_IFADDR) != 0) {
|
nl_socket_add_membership(ev_sock_, RTNLGRP_IPV4_ROUTE);
|
||||||
throw std::runtime_error("Can't add membership");
|
nl_socket_add_membership(ev_sock_, RTNLGRP_IPV6_ROUTE);
|
||||||
}
|
|
||||||
nl_socket_disable_seq_check(info_sock_);
|
|
||||||
nl_socket_set_nonblocking(info_sock_);
|
|
||||||
nl_socket_modify_cb(info_sock_, NL_CB_VALID, NL_CB_CUSTOM, handleEvents, this);
|
|
||||||
efd_ = epoll_create1(EPOLL_CLOEXEC);
|
efd_ = epoll_create1(EPOLL_CLOEXEC);
|
||||||
if (efd_ < 0) {
|
if (efd_ < 0) {
|
||||||
throw std::runtime_error("Can't create epoll");
|
throw std::runtime_error("Can't create epoll");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ev_fd_ = eventfd(0, EFD_NONBLOCK);
|
ev_fd_ = eventfd(0, EFD_NONBLOCK);
|
||||||
struct epoll_event event = {0};
|
struct epoll_event event;
|
||||||
|
memset(&event, 0, sizeof(event));
|
||||||
event.events = EPOLLIN | EPOLLET;
|
event.events = EPOLLIN | EPOLLET;
|
||||||
event.data.fd = ev_fd_;
|
event.data.fd = ev_fd_;
|
||||||
if (epoll_ctl(efd_, EPOLL_CTL_ADD, ev_fd_, &event) == -1) {
|
if (epoll_ctl(efd_, EPOLL_CTL_ADD, ev_fd_, &event) == -1) {
|
||||||
|
@ -82,8 +81,9 @@ void waybar::modules::Network::createInfoSocket() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto fd = nl_socket_get_fd(info_sock_);
|
auto fd = nl_socket_get_fd(ev_sock_);
|
||||||
struct epoll_event event = {0};
|
struct epoll_event event;
|
||||||
|
memset(&event, 0, sizeof(event));
|
||||||
event.events = EPOLLIN | EPOLLET | EPOLLRDHUP;
|
event.events = EPOLLIN | EPOLLET | EPOLLRDHUP;
|
||||||
event.data.fd = fd;
|
event.data.fd = fd;
|
||||||
if (epoll_ctl(efd_, EPOLL_CTL_ADD, fd, &event) == -1) {
|
if (epoll_ctl(efd_, EPOLL_CTL_ADD, fd, &event) == -1) {
|
||||||
|
@ -93,14 +93,14 @@ void waybar::modules::Network::createInfoSocket() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::modules::Network::createEventSocket() {
|
void waybar::modules::Network::createEventSocket() {
|
||||||
sk_ = nl_socket_alloc();
|
sock_ = nl_socket_alloc();
|
||||||
if (genl_connect(sk_) != 0) {
|
if (genl_connect(sock_) != 0) {
|
||||||
throw std::runtime_error("Can't connect to netlink socket");
|
throw std::runtime_error("Can't connect to netlink socket");
|
||||||
}
|
}
|
||||||
if (nl_socket_modify_cb(sk_, NL_CB_VALID, NL_CB_CUSTOM, handleScan, this) < 0) {
|
if (nl_socket_modify_cb(sock_, NL_CB_VALID, NL_CB_CUSTOM, handleScan, this) < 0) {
|
||||||
throw std::runtime_error("Can't set callback");
|
throw std::runtime_error("Can't set callback");
|
||||||
}
|
}
|
||||||
nl80211_id_ = genl_ctrl_resolve(sk_, "nl80211");
|
nl80211_id_ = genl_ctrl_resolve(sock_, "nl80211");
|
||||||
if (nl80211_id_ < 0) {
|
if (nl80211_id_ < 0) {
|
||||||
throw std::runtime_error("Can't resolve nl80211 interface");
|
throw std::runtime_error("Can't resolve nl80211 interface");
|
||||||
}
|
}
|
||||||
|
@ -119,15 +119,13 @@ void waybar::modules::Network::worker() {
|
||||||
int ec = epoll_wait(efd_, events.data(), EPOLL_MAX, -1);
|
int ec = epoll_wait(efd_, events.data(), EPOLL_MAX, -1);
|
||||||
if (ec > 0) {
|
if (ec > 0) {
|
||||||
for (auto i = 0; i < ec; i++) {
|
for (auto i = 0; i < ec; i++) {
|
||||||
if (events[i].data.fd == nl_socket_get_fd(info_sock_)) {
|
if (events[i].data.fd == nl_socket_get_fd(ev_sock_)) {
|
||||||
nl_recvmsgs_default(info_sock_);
|
nl_recvmsgs_default(ev_sock_);
|
||||||
} else {
|
} else {
|
||||||
thread_.stop();
|
thread_.stop();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (ec == -1) {
|
|
||||||
thread_.stop();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -138,7 +136,7 @@ auto waybar::modules::Network::update() -> void {
|
||||||
if (config_["tooltip-format"].isString()) {
|
if (config_["tooltip-format"].isString()) {
|
||||||
tooltip_format = config_["tooltip-format"].asString();
|
tooltip_format = config_["tooltip-format"].asString();
|
||||||
}
|
}
|
||||||
if (ifid_ <= 0 || ipaddr_.empty()) {
|
if (ifid_ <= 0 || !linked_) {
|
||||||
if (config_["format-disconnected"].isString()) {
|
if (config_["format-disconnected"].isString()) {
|
||||||
default_format_ = config_["format-disconnected"].asString();
|
default_format_ = config_["format-disconnected"].asString();
|
||||||
}
|
}
|
||||||
|
@ -156,6 +154,14 @@ auto waybar::modules::Network::update() -> void {
|
||||||
tooltip_format = config_["tooltip-format-ethernet"].asString();
|
tooltip_format = config_["tooltip-format-ethernet"].asString();
|
||||||
}
|
}
|
||||||
connectiontype = "ethernet";
|
connectiontype = "ethernet";
|
||||||
|
} else if (ipaddr_.empty()) {
|
||||||
|
if (config_["format-linked"].isString()) {
|
||||||
|
default_format_ = config_["format-linked"].asString();
|
||||||
|
}
|
||||||
|
if (config_["tooltip-format-linked"].isString()) {
|
||||||
|
tooltip_format = config_["tooltip-format-linked"].asString();
|
||||||
|
}
|
||||||
|
connectiontype = "linked";
|
||||||
} else {
|
} else {
|
||||||
if (config_["format-wifi"].isString()) {
|
if (config_["format-wifi"].isString()) {
|
||||||
default_format_ = config_["format-wifi"].asString();
|
default_format_ = config_["format-wifi"].asString();
|
||||||
|
@ -179,6 +185,7 @@ auto waybar::modules::Network::update() -> void {
|
||||||
fmt::arg("netmask", netmask_),
|
fmt::arg("netmask", netmask_),
|
||||||
fmt::arg("ipaddr", ipaddr_),
|
fmt::arg("ipaddr", ipaddr_),
|
||||||
fmt::arg("cidr", cidr_),
|
fmt::arg("cidr", cidr_),
|
||||||
|
fmt::arg("frequency", frequency_),
|
||||||
fmt::arg("icon", getIcon(signal_strength_, connectiontype)));
|
fmt::arg("icon", getIcon(signal_strength_, connectiontype)));
|
||||||
label_.set_markup(text);
|
label_.set_markup(text);
|
||||||
if (tooltipEnabled()) {
|
if (tooltipEnabled()) {
|
||||||
|
@ -191,6 +198,7 @@ auto waybar::modules::Network::update() -> void {
|
||||||
fmt::arg("netmask", netmask_),
|
fmt::arg("netmask", netmask_),
|
||||||
fmt::arg("ipaddr", ipaddr_),
|
fmt::arg("ipaddr", ipaddr_),
|
||||||
fmt::arg("cidr", cidr_),
|
fmt::arg("cidr", cidr_),
|
||||||
|
fmt::arg("frequency", frequency_),
|
||||||
fmt::arg("icon", getIcon(signal_strength_, connectiontype)));
|
fmt::arg("icon", getIcon(signal_strength_, connectiontype)));
|
||||||
label_.set_tooltip_text(tooltip_text);
|
label_.set_tooltip_text(tooltip_text);
|
||||||
} else {
|
} else {
|
||||||
|
@ -199,21 +207,6 @@ auto waybar::modules::Network::update() -> void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::modules::Network::disconnected() {
|
|
||||||
essid_.clear();
|
|
||||||
signal_strength_dbm_ = 0;
|
|
||||||
signal_strength_ = 0;
|
|
||||||
ipaddr_.clear();
|
|
||||||
netmask_.clear();
|
|
||||||
cidr_ = 0;
|
|
||||||
if (!config_["interface"].isString()) {
|
|
||||||
ifname_.clear();
|
|
||||||
ifid_ = -1;
|
|
||||||
}
|
|
||||||
// Need to wait otherwise we'll have the same information
|
|
||||||
thread_.sleep_for(std::chrono::seconds(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Based on https://gist.github.com/Yawning/c70d804d4b8ae78cc698
|
// Based on https://gist.github.com/Yawning/c70d804d4b8ae78cc698
|
||||||
int waybar::modules::Network::getExternalInterface() {
|
int waybar::modules::Network::getExternalInterface() {
|
||||||
static const uint32_t route_buffer_size = 8192;
|
static const uint32_t route_buffer_size = 8192;
|
||||||
|
@ -333,6 +326,7 @@ int waybar::modules::Network::getExternalInterface() {
|
||||||
} while (true);
|
} while (true);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
last_ext_iface_ = ifidx;
|
||||||
return ifidx;
|
return ifidx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,26 +337,33 @@ void waybar::modules::Network::getInterfaceAddress() {
|
||||||
netmask_.clear();
|
netmask_.clear();
|
||||||
cidr_ = 0;
|
cidr_ = 0;
|
||||||
int success = getifaddrs(&ifaddr);
|
int success = getifaddrs(&ifaddr);
|
||||||
if (success == 0) {
|
if (success != 0) {
|
||||||
ifa = ifaddr;
|
return;
|
||||||
while (ifa != nullptr && ipaddr_.empty() && netmask_.empty()) {
|
|
||||||
if (ifa->ifa_addr != nullptr && ifa->ifa_addr->sa_family == family_) {
|
|
||||||
if (strcmp(ifa->ifa_name, ifname_.c_str()) == 0) {
|
|
||||||
ipaddr_ = inet_ntoa(((struct sockaddr_in *)ifa->ifa_addr)->sin_addr);
|
|
||||||
netmask_ = inet_ntoa(((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr);
|
|
||||||
cidrRaw = ((struct sockaddr_in *)(ifa->ifa_netmask))->sin_addr.s_addr;
|
|
||||||
unsigned int cidr = 0;
|
|
||||||
while (cidrRaw) {
|
|
||||||
cidr += cidrRaw & 1;
|
|
||||||
cidrRaw >>= 1;
|
|
||||||
}
|
|
||||||
cidr_ = cidr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ifa = ifa->ifa_next;
|
|
||||||
}
|
|
||||||
freeifaddrs(ifaddr);
|
|
||||||
}
|
}
|
||||||
|
ifa = ifaddr;
|
||||||
|
while (ifa != nullptr && ipaddr_.empty() && netmask_.empty()) {
|
||||||
|
if (ifa->ifa_addr != nullptr && ifa->ifa_addr->sa_family == family_ &&
|
||||||
|
ifa->ifa_name == ifname_) {
|
||||||
|
char ipaddr[INET6_ADDRSTRLEN];
|
||||||
|
ipaddr_ = inet_ntop(family_,
|
||||||
|
&reinterpret_cast<struct sockaddr_in *>(ifa->ifa_addr)->sin_addr,
|
||||||
|
ipaddr,
|
||||||
|
INET6_ADDRSTRLEN);
|
||||||
|
char netmask[INET6_ADDRSTRLEN];
|
||||||
|
auto net_addr = reinterpret_cast<struct sockaddr_in *>(ifa->ifa_netmask);
|
||||||
|
netmask_ = inet_ntop(family_, &net_addr->sin_addr, netmask, INET6_ADDRSTRLEN);
|
||||||
|
cidrRaw = net_addr->sin_addr.s_addr;
|
||||||
|
linked_ = ifa->ifa_flags & IFF_RUNNING;
|
||||||
|
unsigned int cidr = 0;
|
||||||
|
while (cidrRaw) {
|
||||||
|
cidr += cidrRaw & 1;
|
||||||
|
cidrRaw >>= 1;
|
||||||
|
}
|
||||||
|
cidr_ = cidr;
|
||||||
|
}
|
||||||
|
ifa = ifa->ifa_next;
|
||||||
|
}
|
||||||
|
freeifaddrs(ifaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
int waybar::modules::Network::netlinkRequest(void *req, uint32_t reqlen, uint32_t groups) {
|
int waybar::modules::Network::netlinkRequest(void *req, uint32_t reqlen, uint32_t groups) {
|
||||||
|
@ -370,8 +371,13 @@ int waybar::modules::Network::netlinkRequest(void *req, uint32_t reqlen, uint32_
|
||||||
sa.nl_family = AF_NETLINK;
|
sa.nl_family = AF_NETLINK;
|
||||||
sa.nl_groups = groups;
|
sa.nl_groups = groups;
|
||||||
struct iovec iov = {req, reqlen};
|
struct iovec iov = {req, reqlen};
|
||||||
struct msghdr msg = {&sa, sizeof(sa), &iov, 1, nullptr, 0, 0};
|
struct msghdr msg = {
|
||||||
return sendmsg(nl_socket_get_fd(info_sock_), &msg, 0);
|
.msg_name = &sa,
|
||||||
|
.msg_namelen = sizeof(sa),
|
||||||
|
.msg_iov = &iov,
|
||||||
|
.msg_iovlen = 1,
|
||||||
|
};
|
||||||
|
return sendmsg(nl_socket_get_fd(ev_sock_), &msg, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int waybar::modules::Network::netlinkResponse(void *resp, uint32_t resplen, uint32_t groups) {
|
int waybar::modules::Network::netlinkResponse(void *resp, uint32_t resplen, uint32_t groups) {
|
||||||
|
@ -379,56 +385,125 @@ int waybar::modules::Network::netlinkResponse(void *resp, uint32_t resplen, uint
|
||||||
sa.nl_family = AF_NETLINK;
|
sa.nl_family = AF_NETLINK;
|
||||||
sa.nl_groups = groups;
|
sa.nl_groups = groups;
|
||||||
struct iovec iov = {resp, resplen};
|
struct iovec iov = {resp, resplen};
|
||||||
struct msghdr msg = {&sa, sizeof(sa), &iov, 1, nullptr, 0, 0};
|
struct msghdr msg = {
|
||||||
auto ret = recvmsg(nl_socket_get_fd(info_sock_), &msg, 0);
|
.msg_name = &sa,
|
||||||
|
.msg_namelen = sizeof(sa),
|
||||||
|
.msg_iov = &iov,
|
||||||
|
.msg_iovlen = 1,
|
||||||
|
};
|
||||||
|
auto ret = recvmsg(nl_socket_get_fd(ev_sock_), &msg, 0);
|
||||||
if (msg.msg_flags & MSG_TRUNC) {
|
if (msg.msg_flags & MSG_TRUNC) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
|
bool waybar::modules::Network::checkInterface(int if_index, std::string name) {
|
||||||
int ret = 0;
|
if (config_["interface"].isString()) {
|
||||||
auto net = static_cast<waybar::modules::Network *>(data);
|
return config_["interface"].asString() == name ||
|
||||||
bool need_update = false;
|
wildcardMatch(config_["interface"].asString(), name);
|
||||||
for (nlmsghdr *nh = nlmsg_hdr(msg); NLMSG_OK(nh, ret); nh = NLMSG_NEXT(nh, ret)) {
|
}
|
||||||
if (nh->nlmsg_type == RTM_NEWADDR) {
|
auto external_iface = getExternalInterface();
|
||||||
need_update = true;
|
if (external_iface == -1) {
|
||||||
}
|
// Try with lastest working external iface
|
||||||
if (nh->nlmsg_type < RTM_NEWADDR) {
|
return last_ext_iface_ == if_index;
|
||||||
auto rtif = static_cast<struct ifinfomsg *>(NLMSG_DATA(nh));
|
}
|
||||||
if (rtif->ifi_index == static_cast<int>(net->ifid_)) {
|
return external_iface == if_index;
|
||||||
need_update = true;
|
}
|
||||||
if (!(rtif->ifi_flags & IFF_RUNNING)) {
|
|
||||||
net->disconnected();
|
int waybar::modules::Network::getPreferredIface() {
|
||||||
net->dp.emit();
|
if (config_["interface"].isString()) {
|
||||||
return NL_SKIP;
|
ifid_ = if_nametoindex(config_["interface"].asCString());
|
||||||
|
if (ifid_ > 0) {
|
||||||
|
ifname_ = config_["interface"].asString();
|
||||||
|
return ifid_;
|
||||||
|
} else {
|
||||||
|
// Try with wildcard
|
||||||
|
struct ifaddrs *ifaddr, *ifa;
|
||||||
|
int success = getifaddrs(&ifaddr);
|
||||||
|
if (success != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ifa = ifaddr;
|
||||||
|
ifid_ = -1;
|
||||||
|
while (ifa != nullptr) {
|
||||||
|
if (wildcardMatch(config_["interface"].asString(), ifa->ifa_name)) {
|
||||||
|
ifid_ = if_nametoindex(ifa->ifa_name);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
ifa = ifa->ifa_next;
|
||||||
}
|
}
|
||||||
|
freeifaddrs(ifaddr);
|
||||||
|
return ifid_;
|
||||||
}
|
}
|
||||||
if (need_update) break;
|
|
||||||
}
|
}
|
||||||
if (net->ifid_ <= 0 && !net->config_["interface"].isString()) {
|
ifid_ = getExternalInterface();
|
||||||
for (uint8_t i = 0; i < MAX_RETRY; i += 1) {
|
if (ifid_ > 0) {
|
||||||
net->ifid_ = net->getExternalInterface();
|
char ifname[IF_NAMESIZE];
|
||||||
if (net->ifid_ > 0) {
|
if_indextoname(ifid_, ifname);
|
||||||
break;
|
ifname_ = ifname;
|
||||||
}
|
return ifid_;
|
||||||
// Need to wait before get external interface
|
}
|
||||||
net->thread_.sleep_for(std::chrono::seconds(1));
|
return -1;
|
||||||
}
|
}
|
||||||
if (net->ifid_ > 0) {
|
|
||||||
char ifname[IF_NAMESIZE];
|
int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
|
||||||
if_indextoname(net->ifid_, ifname);
|
auto net = static_cast<waybar::modules::Network *>(data);
|
||||||
|
auto nh = nlmsg_hdr(msg);
|
||||||
|
std::lock_guard<std::mutex> lock(net->mutex_);
|
||||||
|
|
||||||
|
if (nh->nlmsg_type == RTM_NEWADDR) {
|
||||||
|
auto rtif = static_cast<struct ifinfomsg *>(NLMSG_DATA(nh));
|
||||||
|
char ifname[IF_NAMESIZE];
|
||||||
|
if_indextoname(rtif->ifi_index, ifname);
|
||||||
|
// Auto detected network can also be assigned here
|
||||||
|
if (net->checkInterface(rtif->ifi_index, ifname) && net->ifid_ == -1) {
|
||||||
|
net->linked_ = true;
|
||||||
net->ifname_ = ifname;
|
net->ifname_ = ifname;
|
||||||
need_update = true;
|
net->ifid_ = rtif->ifi_index;
|
||||||
|
net->dp.emit();
|
||||||
}
|
}
|
||||||
}
|
// Check for valid interface
|
||||||
if (need_update) {
|
if (rtif->ifi_index == static_cast<int>(net->ifid_)) {
|
||||||
if (net->ifid_ > 0) {
|
// Get Iface and WIFI info
|
||||||
net->getInfo();
|
net->thread_timer_.wake_up();
|
||||||
|
net->getInterfaceAddress();
|
||||||
|
net->dp.emit();
|
||||||
|
}
|
||||||
|
} else if (nh->nlmsg_type == RTM_DELADDR) {
|
||||||
|
auto rtif = static_cast<struct ifinfomsg *>(NLMSG_DATA(nh));
|
||||||
|
// Check for valid interface
|
||||||
|
if (rtif->ifi_index == static_cast<int>(net->ifid_)) {
|
||||||
|
net->ipaddr_.clear();
|
||||||
|
net->netmask_.clear();
|
||||||
|
net->cidr_ = 0;
|
||||||
|
net->dp.emit();
|
||||||
|
}
|
||||||
|
} else if (nh->nlmsg_type < RTM_NEWADDR) {
|
||||||
|
auto rtif = static_cast<struct ifinfomsg *>(NLMSG_DATA(nh));
|
||||||
|
char ifname[IF_NAMESIZE];
|
||||||
|
if_indextoname(rtif->ifi_index, ifname);
|
||||||
|
// Check for valid interface
|
||||||
|
if (net->checkInterface(rtif->ifi_index, ifname) && rtif->ifi_flags & IFF_RUNNING) {
|
||||||
|
net->linked_ = true;
|
||||||
|
net->ifname_ = ifname;
|
||||||
|
net->ifid_ = rtif->ifi_index;
|
||||||
|
net->dp.emit();
|
||||||
|
} else if (rtif->ifi_index == net->ifid_) {
|
||||||
|
net->linked_ = false;
|
||||||
|
net->ifname_.clear();
|
||||||
|
net->ifid_ = -1;
|
||||||
|
net->essid_.clear();
|
||||||
|
net->signal_strength_dbm_ = 0;
|
||||||
|
net->signal_strength_ = 0;
|
||||||
|
// Check for a new interface and get info
|
||||||
|
auto new_iface = net->getPreferredIface();
|
||||||
|
if (new_iface != -1) {
|
||||||
|
net->thread_timer_.wake_up();
|
||||||
|
net->getInterfaceAddress();
|
||||||
|
}
|
||||||
|
net->dp.emit();
|
||||||
}
|
}
|
||||||
net->dp.emit();
|
|
||||||
}
|
}
|
||||||
return NL_SKIP;
|
return NL_SKIP;
|
||||||
}
|
}
|
||||||
|
@ -464,7 +539,7 @@ int waybar::modules::Network::handleScan(struct nl_msg *msg, void *data) {
|
||||||
}
|
}
|
||||||
net->parseEssid(bss);
|
net->parseEssid(bss);
|
||||||
net->parseSignal(bss);
|
net->parseSignal(bss);
|
||||||
// TODO(someone): parse quality
|
net->parseFreq(bss);
|
||||||
return NL_SKIP;
|
return NL_SKIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -504,6 +579,13 @@ void waybar::modules::Network::parseSignal(struct nlattr **bss) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void waybar::modules::Network::parseFreq(struct nlattr **bss) {
|
||||||
|
if (bss[NL80211_BSS_FREQUENCY] != nullptr) {
|
||||||
|
// in MHz
|
||||||
|
frequency_ = nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool waybar::modules::Network::associatedOrJoined(struct nlattr **bss) {
|
bool waybar::modules::Network::associatedOrJoined(struct nlattr **bss) {
|
||||||
if (bss[NL80211_BSS_STATUS] == nullptr) {
|
if (bss[NL80211_BSS_STATUS] == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -520,7 +602,6 @@ bool waybar::modules::Network::associatedOrJoined(struct nlattr **bss) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto waybar::modules::Network::getInfo() -> void {
|
auto waybar::modules::Network::getInfo() -> void {
|
||||||
getInterfaceAddress();
|
|
||||||
struct nl_msg *nl_msg = nlmsg_alloc();
|
struct nl_msg *nl_msg = nlmsg_alloc();
|
||||||
if (nl_msg == nullptr) {
|
if (nl_msg == nullptr) {
|
||||||
return;
|
return;
|
||||||
|
@ -532,5 +613,44 @@ auto waybar::modules::Network::getInfo() -> void {
|
||||||
nlmsg_free(nl_msg);
|
nlmsg_free(nl_msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
nl_send_sync(sk_, nl_msg);
|
nl_send_sync(sock_, nl_msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://gist.github.com/rressi/92af77630faf055934c723ce93ae2495
|
||||||
|
bool waybar::modules::Network::wildcardMatch(const std::string &pattern, const std::string &text) {
|
||||||
|
auto P = int(pattern.size());
|
||||||
|
auto T = int(text.size());
|
||||||
|
|
||||||
|
auto p = 0, fallback_p = -1;
|
||||||
|
auto t = 0, fallback_t = -1;
|
||||||
|
|
||||||
|
while (t < T) {
|
||||||
|
// Wildcard match:
|
||||||
|
if (p < P && pattern[p] == '*') {
|
||||||
|
fallback_p = p++; // starting point after failures
|
||||||
|
fallback_t = t; // starting point after failures
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple match:
|
||||||
|
else if (p < P && (pattern[p] == '?' || pattern[p] == text[t])) {
|
||||||
|
p++;
|
||||||
|
t++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Failure, fall back just after last matched '*':
|
||||||
|
else if (fallback_p >= 0) {
|
||||||
|
p = fallback_p + 1; // position just after last matched '*"
|
||||||
|
t = ++fallback_t; // re-try to match text from here
|
||||||
|
}
|
||||||
|
|
||||||
|
// There were no '*' before, so we fail here:
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consume all '*' at the end of pattern:
|
||||||
|
while (p < P && pattern[p] == '*') p++;
|
||||||
|
|
||||||
|
return p == P;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ waybar::modules::Pulseaudio::Pulseaudio(const std::string &id, const Json::Value
|
||||||
// events are configured
|
// events are configured
|
||||||
if (!config["on-scroll-up"].isString() && !config["on-scroll-down"].isString()) {
|
if (!config["on-scroll-up"].isString() && !config["on-scroll-down"].isString()) {
|
||||||
event_box_.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
|
event_box_.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
|
||||||
event_box_.signal_scroll_event().connect(sigc::mem_fun(*this, &Pulseaudio::handleScroll));
|
event_box_.signal_scroll_event().connect(sigc::mem_fun(*this, &Pulseaudio::handleVolume));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,15 +71,15 @@ void waybar::modules::Pulseaudio::contextStateCb(pa_context *c, void *data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool waybar::modules::Pulseaudio::handleScroll(GdkEventScroll *e) {
|
bool waybar::modules::Pulseaudio::handleVolume(GdkEventScroll *e) {
|
||||||
// Avoid concurrent scroll event
|
// Avoid concurrent scroll event
|
||||||
bool direction_up = false;
|
|
||||||
uint16_t change = config_["scroll-step"].isUInt() ? config_["scroll-step"].asUInt() * 100 : 100;
|
|
||||||
pa_cvolume pa_volume = pa_volume_;
|
|
||||||
|
|
||||||
if (scrolling_) {
|
if (scrolling_) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
bool direction_up = false;
|
||||||
|
double volume_tick = (double)PA_VOLUME_NORM / 100;
|
||||||
|
pa_volume_t change = volume_tick;
|
||||||
|
pa_cvolume pa_volume = pa_volume_;
|
||||||
scrolling_ = true;
|
scrolling_ = true;
|
||||||
if (e->direction == GDK_SCROLL_UP) {
|
if (e->direction == GDK_SCROLL_UP) {
|
||||||
direction_up = true;
|
direction_up = true;
|
||||||
|
@ -98,6 +98,11 @@ bool waybar::modules::Pulseaudio::handleScroll(GdkEventScroll *e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isDouble returns true for integers as well, just in case
|
||||||
|
if (config_["scroll-step"].isDouble()) {
|
||||||
|
change = round(config_["scroll-step"].asDouble() * volume_tick);
|
||||||
|
}
|
||||||
|
|
||||||
if (direction_up) {
|
if (direction_up) {
|
||||||
if (volume_ + 1 < 100) {
|
if (volume_ + 1 < 100) {
|
||||||
pa_cvolume_inc(&pa_volume, change);
|
pa_cvolume_inc(&pa_volume, change);
|
||||||
|
@ -148,6 +153,7 @@ void waybar::modules::Pulseaudio::sinkInfoCb(pa_context * /*context*/, const pa_
|
||||||
pa->volume_ = std::round(volume * 100.0F);
|
pa->volume_ = std::round(volume * 100.0F);
|
||||||
pa->muted_ = i->mute != 0;
|
pa->muted_ = i->mute != 0;
|
||||||
pa->desc_ = i->description;
|
pa->desc_ = i->description;
|
||||||
|
pa->monitor_ = i->monitor_source_name;
|
||||||
pa->port_name_ = i->active_port != nullptr ? i->active_port->name : "Unknown";
|
pa->port_name_ = i->active_port != nullptr ? i->active_port->name : "Unknown";
|
||||||
pa->dp.emit();
|
pa->dp.emit();
|
||||||
}
|
}
|
||||||
|
@ -192,7 +198,7 @@ auto waybar::modules::Pulseaudio::update() -> void {
|
||||||
label_.get_style_context()->add_class("muted");
|
label_.get_style_context()->add_class("muted");
|
||||||
} else {
|
} else {
|
||||||
label_.get_style_context()->remove_class("muted");
|
label_.get_style_context()->remove_class("muted");
|
||||||
if (port_name_.find("a2dp_sink") != std::string::npos) {
|
if (monitor_.find("a2dp_sink") != std::string::npos) {
|
||||||
format =
|
format =
|
||||||
config_["format-bluetooth"].isString() ? config_["format-bluetooth"].asString() : format;
|
config_["format-bluetooth"].isString() ? config_["format-bluetooth"].asString() : format;
|
||||||
label_.get_style_context()->add_class("bluetooth");
|
label_.get_style_context()->add_class("bluetooth");
|
||||||
|
|
|
@ -130,8 +130,13 @@ std::tuple<std::string, std::string> Host::getBusNameAndObjectPath(const std::st
|
||||||
|
|
||||||
void Host::addRegisteredItem(std::string service) {
|
void Host::addRegisteredItem(std::string service) {
|
||||||
auto [bus_name, object_path] = getBusNameAndObjectPath(service);
|
auto [bus_name, object_path] = getBusNameAndObjectPath(service);
|
||||||
items_.emplace_back(new Item(bus_name, object_path, config_));
|
auto it = std::find_if(items_.begin(), items_.end(), [&bus_name, &object_path](const auto& item) {
|
||||||
on_add_(items_.back());
|
return bus_name == item->bus_name && object_path == item->object_path;
|
||||||
|
});
|
||||||
|
if (it == items_.end()) {
|
||||||
|
items_.emplace_back(new Item(bus_name, object_path, config_));
|
||||||
|
on_add_(items_.back());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace waybar::modules::SNI
|
|
@ -276,39 +276,38 @@ Glib::RefPtr<Gdk::Pixbuf> Item::getIconByName(const std::string& name, int reque
|
||||||
name.c_str(), tmp_size, Gtk::IconLookupFlags::ICON_LOOKUP_FORCE_SIZE);
|
name.c_str(), tmp_size, Gtk::IconLookupFlags::ICON_LOOKUP_FORCE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item::onMenuDestroyed(Item* self) {
|
void Item::onMenuDestroyed(Item* self, GObject* old_menu_pointer) {
|
||||||
self->gtk_menu = nullptr;
|
if (old_menu_pointer == reinterpret_cast<GObject*>(self->dbus_menu)) {
|
||||||
self->dbus_menu = nullptr;
|
self->gtk_menu = nullptr;
|
||||||
|
self->dbus_menu = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Item::makeMenu(GdkEventButton* const& ev) {
|
void Item::makeMenu(GdkEventButton* const& ev) {
|
||||||
if (gtk_menu == nullptr) {
|
if (gtk_menu == nullptr && !menu.empty()) {
|
||||||
if (!menu.empty()) {
|
dbus_menu = dbusmenu_gtkmenu_new(bus_name.data(), menu.data());
|
||||||
dbus_menu = dbusmenu_gtkmenu_new(bus_name.data(), menu.data());
|
if (dbus_menu != nullptr) {
|
||||||
if (dbus_menu != nullptr) {
|
g_object_ref_sink(G_OBJECT(dbus_menu));
|
||||||
g_object_ref_sink(G_OBJECT(dbus_menu));
|
g_object_weak_ref(G_OBJECT(dbus_menu), (GWeakNotify)onMenuDestroyed, this);
|
||||||
g_object_weak_ref(G_OBJECT(dbus_menu), (GWeakNotify)onMenuDestroyed, this);
|
gtk_menu = Glib::wrap(GTK_MENU(dbus_menu));
|
||||||
gtk_menu = Glib::wrap(GTK_MENU(dbus_menu));
|
gtk_menu->attach_to_widget(event_box);
|
||||||
gtk_menu->attach_to_widget(event_box);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (gtk_menu != nullptr) {
|
|
||||||
#if GTK_CHECK_VERSION(3, 22, 0)
|
|
||||||
gtk_menu->popup_at_pointer(reinterpret_cast<GdkEvent*>(ev));
|
|
||||||
#else
|
|
||||||
gtk_menu->popup(ev->button, ev->time);
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Item::handleClick(GdkEventButton* const& ev) {
|
bool Item::handleClick(GdkEventButton* const& ev) {
|
||||||
auto parameters = Glib::VariantContainerBase::create_tuple(
|
auto parameters = Glib::VariantContainerBase::create_tuple(
|
||||||
{Glib::Variant<int>::create(ev->x), Glib::Variant<int>::create(ev->y)});
|
{Glib::Variant<int>::create(ev->x), Glib::Variant<int>::create(ev->y)});
|
||||||
if ((ev->button == 1 && item_is_menu) || ev->button == 3) {
|
if ((ev->button == 1 && item_is_menu) || ev->button == 3) {
|
||||||
if (!makeMenu(ev)) {
|
makeMenu(ev);
|
||||||
|
if (gtk_menu != nullptr) {
|
||||||
|
#if GTK_CHECK_VERSION(3, 22, 0)
|
||||||
|
gtk_menu->popup_at_pointer(reinterpret_cast<GdkEvent*>(ev));
|
||||||
|
#else
|
||||||
|
gtk_menu->popup(ev->button, ev->time);
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
proxy_->call("ContextMenu", parameters);
|
proxy_->call("ContextMenu", parameters);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,11 +14,6 @@ Watcher::Watcher()
|
||||||
watcher_(sn_watcher_skeleton_new()) {}
|
watcher_(sn_watcher_skeleton_new()) {}
|
||||||
|
|
||||||
Watcher::~Watcher() {
|
Watcher::~Watcher() {
|
||||||
if (bus_name_id_ != 0) {
|
|
||||||
Gio::DBus::unown_name(bus_name_id_);
|
|
||||||
bus_name_id_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hosts_ != nullptr) {
|
if (hosts_ != nullptr) {
|
||||||
g_slist_free_full(hosts_, gfWatchFree);
|
g_slist_free_full(hosts_, gfWatchFree);
|
||||||
hosts_ = nullptr;
|
hosts_ = nullptr;
|
||||||
|
@ -28,7 +23,8 @@ Watcher::~Watcher() {
|
||||||
g_slist_free_full(items_, gfWatchFree);
|
g_slist_free_full(items_, gfWatchFree);
|
||||||
items_ = nullptr;
|
items_ = nullptr;
|
||||||
}
|
}
|
||||||
g_dbus_interface_skeleton_unexport(G_DBUS_INTERFACE_SKELETON(watcher_));
|
auto iface = G_DBUS_INTERFACE_SKELETON(watcher_);
|
||||||
|
g_dbus_interface_skeleton_unexport(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Watcher::busAcquired(const Glib::RefPtr<Gio::DBus::Connection>& conn, Glib::ustring name) {
|
void Watcher::busAcquired(const Glib::RefPtr<Gio::DBus::Connection>& conn, Glib::ustring name) {
|
||||||
|
|
|
@ -25,16 +25,23 @@ void Window::onEvent(const struct Ipc::ipc_response& res) { getTree(); }
|
||||||
|
|
||||||
void Window::onCmd(const struct Ipc::ipc_response& res) {
|
void Window::onCmd(const struct Ipc::ipc_response& res) {
|
||||||
try {
|
try {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
auto payload = parser_.parse(res.payload);
|
auto payload = parser_.parse(res.payload);
|
||||||
auto [nb, id, name, app_id] = getFocusedNode(payload);
|
auto [nb, id, name, app_id] = getFocusedNode(payload);
|
||||||
if (!app_id_.empty()) {
|
if (!app_id_.empty()) {
|
||||||
bar_.window.get_style_context()->remove_class(app_id_);
|
bar_.window.get_style_context()->remove_class(app_id_);
|
||||||
}
|
}
|
||||||
if (nb == 0) {
|
if (nb == 0) {
|
||||||
bar_.window.get_style_context()->add_class("empty");
|
bar_.window.get_style_context()->remove_class("solo");
|
||||||
|
if (!bar_.window.get_style_context()->has_class("empty")) {
|
||||||
|
bar_.window.get_style_context()->add_class("empty");
|
||||||
|
}
|
||||||
} else if (nb == 1) {
|
} else if (nb == 1) {
|
||||||
bar_.window.get_style_context()->add_class("solo");
|
bar_.window.get_style_context()->remove_class("empty");
|
||||||
if (!app_id.empty()) {
|
if (!bar_.window.get_style_context()->has_class("solo")) {
|
||||||
|
bar_.window.get_style_context()->add_class("solo");
|
||||||
|
}
|
||||||
|
if (!app_id.empty() && !bar_.window.get_style_context()->has_class(app_id)) {
|
||||||
bar_.window.get_style_context()->add_class(app_id);
|
bar_.window.get_style_context()->add_class(app_id);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -99,4 +106,4 @@ void Window::getTree() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace waybar::modules::sway
|
} // namespace waybar::modules::sway
|
||||||
|
|
|
@ -15,11 +15,22 @@ Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value
|
||||||
ipc_.signal_event.connect(sigc::mem_fun(*this, &Workspaces::onEvent));
|
ipc_.signal_event.connect(sigc::mem_fun(*this, &Workspaces::onEvent));
|
||||||
ipc_.signal_cmd.connect(sigc::mem_fun(*this, &Workspaces::onCmd));
|
ipc_.signal_cmd.connect(sigc::mem_fun(*this, &Workspaces::onCmd));
|
||||||
ipc_.sendCmd(IPC_GET_WORKSPACES);
|
ipc_.sendCmd(IPC_GET_WORKSPACES);
|
||||||
|
if (!config["disable-bar-scroll"].asBool()) {
|
||||||
|
auto &window = const_cast<Bar&>(bar_).window;
|
||||||
|
window.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
|
||||||
|
window.signal_scroll_event().connect(sigc::mem_fun(*this, &Workspaces::handleScroll));
|
||||||
|
}
|
||||||
// Launch worker
|
// Launch worker
|
||||||
worker();
|
worker();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::onEvent(const struct Ipc::ipc_response &res) { ipc_.sendCmd(IPC_GET_WORKSPACES); }
|
void Workspaces::onEvent(const struct Ipc::ipc_response &res) {
|
||||||
|
try {
|
||||||
|
ipc_.sendCmd(IPC_GET_WORKSPACES);
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
std::cerr << "Workspaces: " << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Workspaces::onCmd(const struct Ipc::ipc_response &res) {
|
void Workspaces::onCmd(const struct Ipc::ipc_response &res) {
|
||||||
if (res.type == IPC_GET_WORKSPACES) {
|
if (res.type == IPC_GET_WORKSPACES) {
|
||||||
|
@ -194,7 +205,11 @@ bool Workspaces::handleScroll(GdkEventScroll *e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ipc_.sendCmd(IPC_COMMAND, fmt::format("workspace \"{}\"", name));
|
try {
|
||||||
|
ipc_.sendCmd(IPC_COMMAND, fmt::format("workspace \"{}\"", name));
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
std::cerr << "Workspaces: " << e.what() << std::endl;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,7 +223,7 @@ const std::string Workspaces::getCycleWorkspace(std::vector<Json::Value>::iterat
|
||||||
else if (!prev && it != workspaces_.end())
|
else if (!prev && it != workspaces_.end())
|
||||||
++it;
|
++it;
|
||||||
if (!prev && it == workspaces_.end()) {
|
if (!prev && it == workspaces_.end()) {
|
||||||
return (*(++workspaces_.begin()))["name"].asString();
|
return (*(workspaces_.begin()))["name"].asString();
|
||||||
}
|
}
|
||||||
return (*it)["name"].asString();
|
return (*it)["name"].asString();
|
||||||
}
|
}
|
||||||
|
@ -235,4 +250,4 @@ void Workspaces::onButtonReady(const Json::Value &node, Gtk::Button &button) {
|
||||||
|
|
||||||
Workspaces::operator Gtk::Widget &() { return box_; }
|
Workspaces::operator Gtk::Widget &() { return box_; }
|
||||||
|
|
||||||
} // namespace waybar::modules::sway
|
} // namespace waybar::modules::sway
|
||||||
|
|
|
@ -8,11 +8,8 @@ waybar::modules::Temperature::Temperature(const std::string& id, const Json::Val
|
||||||
auto zone = config_["thermal-zone"].isInt() ? config_["thermal-zone"].asInt() : 0;
|
auto zone = config_["thermal-zone"].isInt() ? config_["thermal-zone"].asInt() : 0;
|
||||||
file_path_ = fmt::format("/sys/class/thermal/thermal_zone{}/temp", zone);
|
file_path_ = fmt::format("/sys/class/thermal/thermal_zone{}/temp", zone);
|
||||||
}
|
}
|
||||||
#ifdef FILESYSTEM_EXPERIMENTAL
|
std::ifstream temp(file_path_);
|
||||||
if (!std::experimental::filesystem::exists(file_path_)) {
|
if (!temp.is_open()) {
|
||||||
#else
|
|
||||||
if (!std::filesystem::exists(file_path_)) {
|
|
||||||
#endif
|
|
||||||
throw std::runtime_error("Can't open " + file_path_);
|
throw std::runtime_error("Can't open " + file_path_);
|
||||||
}
|
}
|
||||||
label_.set_name("temperature");
|
label_.set_name("temperature");
|
||||||
|
@ -35,8 +32,11 @@ auto waybar::modules::Temperature::update() -> void {
|
||||||
} else {
|
} else {
|
||||||
label_.get_style_context()->remove_class("critical");
|
label_.get_style_context()->remove_class("critical");
|
||||||
}
|
}
|
||||||
label_.set_markup(fmt::format(
|
auto max_temp = config_["critical-threshold"].isInt() ? config_["critical-threshold"].asInt() : 0;
|
||||||
format, fmt::arg("temperatureC", temperature_c), fmt::arg("temperatureF", temperature_f)));
|
label_.set_markup(fmt::format(format,
|
||||||
|
fmt::arg("temperatureC", temperature_c),
|
||||||
|
fmt::arg("temperatureF", temperature_f),
|
||||||
|
fmt::arg("icon", getIcon(temperature_c, "", max_temp))));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<uint16_t, uint16_t> waybar::modules::Temperature::getTemperature() {
|
std::tuple<uint16_t, uint16_t> waybar::modules::Temperature::getTemperature() {
|
||||||
|
|
Loading…
Reference in New Issue