Compare commits

..

11 Commits
0.2.1 ... 0.2.2

Author SHA1 Message Date
2b05b8e69a chore: v0.2.2 2018-11-23 12:03:23 +01:00
ad7400d5ce refactor(ALabel): add interval 2018-11-23 11:57:37 +01:00
36652158ad refactor(tray): more cpp binding 2018-11-23 10:46:58 +01:00
8db94f7efd revert(ALabel): ref on format 2018-11-22 16:50:42 +01:00
aaaa17d94f fix(config): remove duplicate tray 2018-11-22 16:21:46 +01:00
0b1b0eb1a7 feat(tray): multiple hosts 2018-11-22 16:20:49 +01:00
f00be0b552 refactor(tray): remove useless variable 2018-11-22 15:51:55 +01:00
ba79b4d397 refactor(tray): cleanup and fixes 2018-11-22 15:47:23 +01:00
bd62c4cbc5 feat(Label): use set_markup 2018-11-21 20:49:09 +01:00
b3559328f1 fix(window): ellipsize 2018-11-20 23:24:33 +01:00
69fceb1c92 fix(tray): sigsev on click when multiple icons is available 2018-11-16 12:01:03 +01:00
25 changed files with 281 additions and 329 deletions

View File

@ -7,7 +7,7 @@ namespace waybar {
class ALabel : public IModule { class ALabel : public IModule {
public: public:
ALabel(const Json::Value&, const std::string format); ALabel(const Json::Value&, const std::string format, uint16_t interval = 0);
virtual ~ALabel() = default; virtual ~ALabel() = default;
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 = "");
@ -19,6 +19,7 @@ class ALabel : public IModule {
const Json::Value& config_; const Json::Value& config_;
std::string format_; std::string format_;
std::mutex mutex_; std::mutex mutex_;
const std::chrono::seconds interval_;
private: private:
bool handleToggle(GdkEventButton* const& ev); bool handleToggle(GdkEventButton* const& ev);

View File

@ -26,6 +26,7 @@ class Bar {
std::string output_name; std::string output_name;
uint32_t wl_name; uint32_t wl_name;
bool visible = true; bool visible = true;
uint32_t nb_tray_hosts = 0;
private: private:
static void handleLogicalPosition(void *, struct zxdg_output_v1 *, int32_t, static void handleLogicalPosition(void *, struct zxdg_output_v1 *, int32_t,
int32_t); int32_t);

View File

@ -1,9 +1,9 @@
#pragma once #pragma once
#ifdef FILESYSTEM_EXPERIMENTAL #ifdef FILESYSTEM_EXPERIMENTAL
#include <experimental/filesystem> #include <experimental/filesystem>
#else #else
#include <filesystem> #include <filesystem>
#endif #endif
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
@ -30,8 +30,8 @@ class Battery : public ALabel {
static inline const fs::path data_dir_ = "/sys/class/power_supply/"; static inline const fs::path data_dir_ = "/sys/class/power_supply/";
void worker(); void worker();
std::tuple<uint16_t, std::string> getInfos(); const std::tuple<uint8_t, std::string> getInfos() const;
std::string getState(uint16_t); const std::string getState(uint8_t) const;
util::SleeperThread thread_; util::SleeperThread thread_;
util::SleeperThread thread_timer_; util::SleeperThread thread_timer_;

View File

@ -0,0 +1,41 @@
#pragma once
#include <gtkmm.h>
#include <json/json.h>
#include <tuple>
#include <dbus-status-notifier-watcher.h>
#include "modules/sni/item.hpp"
namespace waybar::modules::SNI {
class Host {
public:
Host(const std::size_t id, const Json::Value&,
const std::function<void(std::unique_ptr<Item>&)>&,
const std::function<void(std::unique_ptr<Item>&)>&);
~Host();
private:
void busAcquired(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring);
void nameAppeared(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring, const Glib::ustring&);
void nameVanished(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring);
static void proxyReady(GObject*, GAsyncResult*, gpointer);
static void registerHost(GObject*, GAsyncResult*, gpointer);
static void itemRegistered(SnWatcher*, const gchar*, gpointer);
static void itemUnregistered(SnWatcher*, const gchar*, gpointer);
std::tuple<std::string, std::string> getBusNameAndObjectPath(const std::string);
void addRegisteredItem(std::string service);
std::vector<std::unique_ptr<Item>> items_;
const std::string bus_name_;
const std::string object_path_;
std::size_t bus_name_id_;
std::size_t watcher_id_;
GCancellable* cancellable_ = nullptr;
SnWatcher* watcher_ = nullptr;
const Json::Value &config_;
const std::function<void(std::unique_ptr<Item>&)> on_add_;
const std::function<void(std::unique_ptr<Item>&)> on_remove_;
};
}

View File

@ -3,26 +3,27 @@
#include <dbus-status-notifier-item.h> #include <dbus-status-notifier-item.h>
#include <gtkmm.h> #include <gtkmm.h>
#include <json/json.h> #include <json/json.h>
#include <libdbusmenu-gtk/dbusmenu-gtk.h>
#ifdef FILESYSTEM_EXPERIMENTAL #ifdef FILESYSTEM_EXPERIMENTAL
#include <experimental/filesystem> #include <experimental/filesystem>
#else #else
#include <filesystem> #include <filesystem>
#endif #endif
namespace waybar::modules::SNI { namespace waybar::modules::SNI {
class Item { class Item {
public: public:
Item(std::string, std::string, Glib::Dispatcher*, Json::Value); Item(std::string, std::string, const Json::Value&);
~Item() = default;
std::string bus_name; std::string bus_name;
std::string object_path; std::string object_path;
Gtk::EventBox event_box;
int icon_size; int icon_size;
int effective_icon_size; int effective_icon_size;
Gtk::Image *image; Gtk::Image image;
Gtk::Menu *gtk_menu = nullptr; Gtk::EventBox event_box;
std::string category; std::string category;
std::string id; std::string id;
std::string status; std::string status;
@ -36,24 +37,23 @@ public:
std::string attention_movie_name; std::string attention_movie_name;
std::string icon_theme_path; std::string icon_theme_path;
std::string menu; std::string menu;
DbusmenuGtkMenu *dbus_menu = nullptr;
Gtk::Menu *gtk_menu = nullptr;
bool item_is_menu; bool item_is_menu;
private: private:
static void proxyReady(GObject *obj, GAsyncResult *res, gpointer data); static void proxyReady(GObject *obj, GAsyncResult *res, gpointer data);
static void getAll(GObject *obj, GAsyncResult *res, gpointer data); static void getAll(GObject *obj, GAsyncResult *res, gpointer data);
static void handleActivate(GObject *, GAsyncResult *, gpointer);
static void handleSecondaryActivate(GObject *, GAsyncResult *, gpointer);
void updateImage(); void updateImage();
void updateMenu();
Glib::RefPtr<Gdk::Pixbuf> extractPixBuf(GVariant *variant); Glib::RefPtr<Gdk::Pixbuf> extractPixBuf(GVariant *variant);
Glib::RefPtr<Gdk::Pixbuf> getIconByName(std::string name, int size); Glib::RefPtr<Gdk::Pixbuf> getIconByName(std::string name, int size);
static void onMenuDestroyed(Item *self);
bool makeMenu(GdkEventButton *const &ev);
bool handleClick(GdkEventButton *const & /*ev*/); bool handleClick(GdkEventButton *const & /*ev*/);
Glib::Dispatcher *dp_;
GCancellable *cancellable_ = nullptr; GCancellable *cancellable_ = nullptr;
SnItem *proxy_ = nullptr; SnItem *proxy_ = nullptr;
Json::Value config_;
}; };
} // namespace waybar::modules::SNI } // namespace waybar::modules::SNI

View File

@ -1,38 +0,0 @@
#pragma once
#include <gtkmm.h>
#include <json/json.h>
#include <tuple>
#include <dbus-status-notifier-watcher.h>
#include "modules/sni/sni.hpp"
namespace waybar::modules::SNI {
class Host {
public:
Host(Glib::Dispatcher*, const Json::Value&);
std::vector<Item> items;
private:
static void busAcquired(GDBusConnection*, const gchar*, gpointer);
static void nameAppeared(GDBusConnection*, const gchar*, const gchar*,
gpointer);
static void nameVanished(GDBusConnection*, const gchar*, gpointer);
static void proxyReady(GObject*, GAsyncResult*, gpointer);
static void registerHost(GObject*, GAsyncResult*, gpointer);
static void itemRegistered(SnWatcher*, const gchar*, gpointer);
static void itemUnregistered(SnWatcher*, const gchar*, gpointer);
std::tuple<std::string, std::string> getBusNameAndObjectPath(const gchar*);
void addRegisteredItem(const gchar* service);
uint32_t bus_name_id_;
uint32_t watcher_id_;
std::string bus_name_;
std::string object_path_;
Glib::Dispatcher* dp_;
GCancellable* cancellable_ = nullptr;
SnWatcher* watcher_ = nullptr;
const Json::Value &config_;
};
}

View File

@ -2,19 +2,23 @@
#include <fmt/format.h> #include <fmt/format.h>
#include <thread> #include <thread>
#include "bar.hpp"
#include "util/json.hpp" #include "util/json.hpp"
#include "IModule.hpp" #include "IModule.hpp"
#include "modules/sni/snw.hpp" #include "modules/sni/watcher.hpp"
#include "modules/sni/snh.hpp" #include "modules/sni/host.hpp"
namespace waybar::modules::SNI { namespace waybar::modules::SNI {
class Tray : public IModule { class Tray : public IModule {
public: public:
Tray(const Json::Value&); Tray(Bar& bar, const Json::Value&);
auto update() -> void; auto update() -> void;
operator Gtk::Widget &(); operator Gtk::Widget &();
private: private:
void onAdd(std::unique_ptr<Item>& item);
void onRemove(std::unique_ptr<Item>& item);
std::thread thread_; std::thread thread_;
const Json::Value& config_; const Json::Value& config_;
Gtk::Box box_; Gtk::Box box_;

View File

@ -8,7 +8,7 @@ namespace waybar::modules::SNI {
class Watcher { class Watcher {
public: public:
Watcher(); Watcher();
~Watcher(); ~Watcher() = default;
private: private:
typedef enum { GF_WATCH_TYPE_HOST, GF_WATCH_TYPE_ITEM } GfWatchType; typedef enum { GF_WATCH_TYPE_HOST, GF_WATCH_TYPE_ITEM } GfWatchType;
@ -22,7 +22,7 @@ private:
guint watch_id; guint watch_id;
} GfWatch; } GfWatch;
static void busAcquired(GDBusConnection *, const gchar *, gpointer); void busAcquired(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring);
static gboolean handleRegisterHost(Watcher *, GDBusMethodInvocation *, static gboolean handleRegisterHost(Watcher *, GDBusMethodInvocation *,
const gchar *); const gchar *);
static gboolean handleRegisterItem(Watcher *, GDBusMethodInvocation *, static gboolean handleRegisterItem(Watcher *, GDBusMethodInvocation *,

View File

@ -1,6 +1,6 @@
project( project(
'waybar', 'cpp', 'c', 'waybar', 'cpp', 'c',
version: '0.2.1', version: '0.2.2',
license: 'MIT', license: 'MIT',
default_options : [ default_options : [
'cpp_std=c++17', 'cpp_std=c++17',
@ -83,9 +83,9 @@ if dbusmenu_gtk.found()
add_project_arguments('-DHAVE_DBUSMENU', language: 'cpp') add_project_arguments('-DHAVE_DBUSMENU', language: 'cpp')
src_files += files( src_files += files(
'src/modules/sni/tray.cpp', 'src/modules/sni/tray.cpp',
'src/modules/sni/snw.cpp', 'src/modules/sni/watcher.cpp',
'src/modules/sni/snh.cpp', 'src/modules/sni/host.cpp',
'src/modules/sni/sni.cpp' 'src/modules/sni/item.cpp'
) )
endif endif

View File

@ -1,78 +1,47 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" <!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node> <node>
<interface name="org.kde.StatusNotifierItem"> <interface name='org.kde.StatusNotifierItem'>
<annotation name="org.gtk.GDBus.C.Name" value="Item" /> <annotation name="org.gtk.GDBus.C.Name" value="Item" />
<property name="Category" type="s" access="read"/> <method name='ContextMenu'>
<property name="Id" type="s" access="read"/> <arg type='i' direction='in' name='x'/>
<property name="Title" type="s" access="read"/> <arg type='i' direction='in' name='y'/>
<property name="Status" type="s" access="read"/>
<property name="WindowId" type="i" access="read"/>
<property name="Menu" type="o" access="read" />
<!-- main icon -->
<!-- names are preferred over pixmaps -->
<property name="IconName" type="s" access="read" />
<property name="IconThemePath" type="s" access="read" />
<!-- struct containing width, height and image data-->
<!-- implementation has been dropped as of now -->
<property name="IconPixmap" type="a(iiay)" access="read" />
<!-- not used in ayatana code, no test case so far -->
<property name="OverlayIconName" type="s" access="read"/>
<property name="OverlayIconPixmap" type="a(iiay)" access="read" />
<!-- Requesting attention icon -->
<property name="AttentionIconName" type="s" access="read"/>
<!--same definition as image-->
<property name="AttentionIconPixmap" type="a(iiay)" access="read" />
<!-- tooltip data -->
<!-- unimplemented as of now -->
<!--(iiay) is an image-->
<property name="ToolTip" type="(sa(iiay)ss)" access="read" />
<!-- interaction: actually, we do not use them. -->
<method name="Activate">
<arg name="x" type="i" direction="in"/>
<arg name="y" type="i" direction="in"/>
</method> </method>
<method name="SecondaryActivate"> <method name='Activate'>
<arg name="x" type="i" direction="in"/> <arg type='i' direction='in' name='x'/>
<arg name="y" type="i" direction="in"/> <arg type='i' direction='in' name='y'/>
</method> </method>
<method name="Scroll"> <method name='SecondaryActivate'>
<arg name="delta" type="i" direction="in"/> <arg type='i' direction='in' name='x'/>
<arg name="dir" type="s" direction="in"/> <arg type='i' direction='in' name='y'/>
</method> </method>
<method name='Scroll'>
<!-- Signals: the client wants to change something in the status--> <arg type='i' direction='in' name='delta'/>
<signal name="NewTitle"></signal> <arg type='s' direction='in' name='orientation'/>
<signal name="NewIcon"></signal> </method>
<signal name="NewIconThemePath"> <signal name='NewTitle'/>
<arg type="s" name="icon_theme_path" direction="out" /> <signal name='NewIcon'/>
<signal name='NewAttentionIcon'/>
<signal name='NewOverlayIcon'/>
<signal name='NewToolTip'/>
<signal name='NewStatus'>
<arg type='s' name='status'/>
</signal> </signal>
<signal name="NewAttentionIcon"></signal> <property name='Category' type='s' access='read'/>
<signal name="NewOverlayIcon"></signal> <property name='Id' type='s' access='read'/>
<signal name="NewToolTip"></signal> <property name='Title' type='s' access='read'/>
<signal name="NewStatus"> <property name='Status' type='s' access='read'/>
<arg name="status" type="s" /> <property name='WindowId' type='u' access='read'/>
</signal> <property name='IconThemePath' type='s' access='read'/>
<property name='IconName' type='s' access='read'/>
<!-- ayatana labels --> <property name='IconPixmap' type='a(iiay)' access='read'/>
<!-- These are commented out because GDBusProxy would otherwise require them, <property name='OverlayIconName' type='s' access='read'/>
but they are not available for KDE indicators <property name='OverlayIconPixmap' type='a(iiay)' access='read'/>
--> <property name='AttentionIconName' type='s' access='read'/>
<!--<signal name="XAyatanaNewLabel"> <property name='AttentionIconPixmap' type='a(iiay)' access='read'/>
<arg type="s" name="label" direction="out" /> <property name='AttentionMovieName' type='s' access='read'/>
<arg type="s" name="guide" direction="out" /> <property name='ToolTip' type='(sa(iiay)ss)' access='read'/>
</signal> <property name='Menu' type='o' access='read'/>
<property name="XAyatanaLabel" type="s" access="read" /> <property name='ItemIsMenu' type='b' access='read'/>
<property name="XAyatanaLabelGuide" type="s" access="read" />--> </interface>
</interface>
</node> </node>

View File

@ -24,10 +24,7 @@
// } // }
// }, // },
"sway/mode": { "sway/mode": {
"format": "{}" "format": "<span style=\"italic\">{}</span>"
},
"sway/window": {
"max-length": 50
}, },
"tray": { "tray": {
// "icon-size": 21, // "icon-size": 21,

View File

@ -3,10 +3,11 @@
#include <iostream> #include <iostream>
waybar::ALabel::ALabel(const Json::Value& config, const std::string format) waybar::ALabel::ALabel(const Json::Value& config, const std::string format, uint16_t interval)
: config_(config), : config_(config),
format_(config_["format"].isString() ? config_["format"].asString() : format), format_(config_["format"].isString() ? config_["format"].asString() : format),
default_format_(format_) interval_(std::chrono::seconds(config_["interval"].isUInt()
? config_["interval"].asUInt() : interval)), default_format_(format_)
{ {
event_box_.add(label_); event_box_.add(label_);
if (config_["max-length"].isUInt()) { if (config_["max-length"].isUInt()) {

View File

@ -33,7 +33,7 @@ waybar::IModule* waybar::Factory::makeModule(const std::string &name) const
} }
#ifdef HAVE_DBUSMENU #ifdef HAVE_DBUSMENU
if (ref == "tray") { if (ref == "tray") {
return new waybar::modules::SNI::Tray(config_[name]); return new waybar::modules::SNI::Tray(bar_, config_[name]);
} }
#endif #endif
#ifdef HAVE_LIBNL #ifdef HAVE_LIBNL

View File

@ -1,7 +1,7 @@
#include "modules/battery.hpp" #include "modules/battery.hpp"
waybar::modules::Battery::Battery(const Json::Value& config) waybar::modules::Battery::Battery(const Json::Value& config)
: ALabel(config, "{capacity}%") : ALabel(config, "{capacity}%", 60)
{ {
try { try {
if (config_["bat"].isString()) { if (config_["bat"].isString()) {
@ -46,9 +46,8 @@ void waybar::modules::Battery::worker()
{ {
// Trigger first values // Trigger first values
update(); update();
uint32_t interval = config_["interval"].isUInt() ? config_["interval"].asUInt() : 60; thread_timer_ = [this] {
thread_timer_ = [this, interval] { thread_.sleep_for(interval_);
thread_.sleep_for(chrono::seconds(interval));
dp.emit(); dp.emit();
}; };
thread_ = [this] { thread_ = [this] {
@ -63,7 +62,7 @@ void waybar::modules::Battery::worker()
}; };
} }
std::tuple<uint16_t, std::string> waybar::modules::Battery::getInfos() const std::tuple<uint8_t, std::string> waybar::modules::Battery::getInfos() const
{ {
try { try {
uint16_t total = 0; uint16_t total = 0;
@ -86,10 +85,10 @@ std::tuple<uint16_t, std::string> waybar::modules::Battery::getInfos()
} }
} }
std::string waybar::modules::Battery::getState(uint16_t capacity) const std::string waybar::modules::Battery::getState(uint8_t capacity) const
{ {
// Get current state // Get current state
std::vector<std::pair<std::string, uint16_t>> states; std::vector<std::pair<std::string, uint8_t>> states;
if (config_["states"].isObject()) { if (config_["states"].isObject()) {
for (auto it = config_["states"].begin(); it != config_["states"].end(); ++it) { for (auto it = config_["states"].begin(); it != config_["states"].end(); ++it) {
if (it->isUInt() && it.key().isString()) { if (it->isUInt() && it.key().isString()) {
@ -101,16 +100,16 @@ std::string waybar::modules::Battery::getState(uint16_t capacity)
std::sort(states.begin(), states.end(), [](auto &a, auto &b) { std::sort(states.begin(), states.end(), [](auto &a, auto &b) {
return a.second < b.second; return a.second < b.second;
}); });
std::string validState = ""; std::string valid_state;
for (auto state : states) { for (auto state : states) {
if (capacity <= state.second && validState.empty()) { if (capacity <= state.second && valid_state.empty()) {
label_.get_style_context()->add_class(state.first); label_.get_style_context()->add_class(state.first);
validState = state.first; valid_state = state.first;
} else { } else {
label_.get_style_context()->remove_class(state.first); label_.get_style_context()->remove_class(state.first);
} }
} }
return validState; return valid_state;
} }
auto waybar::modules::Battery::update() -> void auto waybar::modules::Battery::update() -> void
@ -136,7 +135,7 @@ auto waybar::modules::Battery::update() -> void
} else { } else {
event_box_.show(); event_box_.show();
label_.set_name("battery"); label_.set_name("battery");
label_.set_text(fmt::format(format, fmt::arg("capacity", capacity), label_.set_markup(fmt::format(format, fmt::arg("capacity", capacity),
fmt::arg("icon", getIcon(capacity)))); fmt::arg("icon", getIcon(capacity))));
} }
} }

View File

@ -1,21 +1,22 @@
#include "modules/clock.hpp" #include "modules/clock.hpp"
waybar::modules::Clock::Clock(const Json::Value& config) waybar::modules::Clock::Clock(const Json::Value& config)
: ALabel(config, "{:%H:%M}") : ALabel(config, "{:%H:%M}", 60)
{ {
label_.set_name("clock"); label_.set_name("clock");
uint32_t interval = config_["interval"].isUInt() ? config_["interval"].asUInt() : 60; thread_ = [this] {
thread_ = [this, interval] {
auto now = waybar::chrono::clock::now(); auto now = waybar::chrono::clock::now();
dp.emit(); dp.emit();
auto timeout = std::chrono::floor<std::chrono::seconds>(now auto timeout = std::chrono::floor<std::chrono::seconds>(now + interval_);
+ std::chrono::seconds(interval)); auto time_s = std::chrono::time_point_cast<std::chrono::seconds>(timeout);
thread_.sleep_until(timeout); auto sub_m =
std::chrono::duration_cast<std::chrono::seconds>(time_s.time_since_epoch()).count() % 60;
thread_.sleep_until(timeout - std::chrono::seconds(sub_m - 1));
}; };
} }
auto waybar::modules::Clock::update() -> void auto waybar::modules::Clock::update() -> void
{ {
auto localtime = fmt::localtime(std::time(nullptr)); auto localtime = fmt::localtime(std::time(nullptr));
label_.set_text(fmt::format(format_, localtime)); label_.set_markup(fmt::format(format_, localtime));
} }

View File

@ -1,13 +1,12 @@
#include "modules/cpu.hpp" #include "modules/cpu.hpp"
waybar::modules::Cpu::Cpu(const Json::Value& config) waybar::modules::Cpu::Cpu(const Json::Value& config)
: ALabel(config, "{usage}%") : ALabel(config, "{usage}%", 10)
{ {
label_.set_name("cpu"); label_.set_name("cpu");
uint32_t interval = config_["interval"].isUInt() ? config_["interval"].asUInt() : 10; thread_ = [this] {
thread_ = [this, interval] {
dp.emit(); dp.emit();
thread_.sleep_for(chrono::seconds(interval)); thread_.sleep_for(interval_);
}; };
} }
@ -18,7 +17,7 @@ auto waybar::modules::Cpu::update() -> void
auto cpu_load = getCpuLoad(); auto cpu_load = getCpuLoad();
auto [cpu_usage, tooltip] = getCpuUsage(); auto [cpu_usage, tooltip] = getCpuUsage();
label_.set_tooltip_text(tooltip); label_.set_tooltip_text(tooltip);
label_.set_text(fmt::format(format_, label_.set_markup(fmt::format(format_,
fmt::arg("load", cpu_load), fmt::arg("usage", cpu_usage))); fmt::arg("load", cpu_load), fmt::arg("usage", cpu_usage)));
} catch (const std::exception& e) { } catch (const std::exception& e) {
std::cerr << e.what() << std::endl; std::cerr << e.what() << std::endl;

View File

@ -7,7 +7,7 @@ waybar::modules::Custom::Custom(const std::string name,
if (!config_["exec"].isString()) { if (!config_["exec"].isString()) {
throw std::runtime_error(name_ + " has no exec path."); throw std::runtime_error(name_ + " has no exec path.");
} }
if (config_["interval"].isUInt()) { if (interval_.count() > 0) {
delayWorker(); delayWorker();
} else { } else {
continuousWorker(); continuousWorker();
@ -16,8 +16,7 @@ waybar::modules::Custom::Custom(const std::string name,
void waybar::modules::Custom::delayWorker() void waybar::modules::Custom::delayWorker()
{ {
auto interval = config_["interval"].asUInt(); thread_ = [this] {
thread_ = [this, interval] {
bool can_update = true; bool can_update = true;
if (config_["exec-if"].isString()) { if (config_["exec-if"].isString()) {
auto res = waybar::util::command::exec(config_["exec-if"].asString()); auto res = waybar::util::command::exec(config_["exec-if"].asString());
@ -31,7 +30,7 @@ void waybar::modules::Custom::delayWorker()
output_ = waybar::util::command::exec(config_["exec"].asString()); output_ = waybar::util::command::exec(config_["exec"].asString());
dp.emit(); dp.emit();
} }
thread_.sleep_for(chrono::seconds(interval)); thread_.sleep_for(interval_);
}; };
} }
@ -80,7 +79,7 @@ auto waybar::modules::Custom::update() -> void
} }
auto str = fmt::format(format_, text_); auto str = fmt::format(format_, text_);
label_.set_text(str); label_.set_markup(str);
if (text_ == tooltip_) { if (text_ == tooltip_) {
label_.set_tooltip_text(str); label_.set_tooltip_text(str);
} else { } else {

View File

@ -1,12 +1,11 @@
#include "modules/memory.hpp" #include "modules/memory.hpp"
waybar::modules::Memory::Memory(const Json::Value& config) waybar::modules::Memory::Memory(const Json::Value& config)
: ALabel(config, "{}%") : ALabel(config, "{}%", 30)
{ {
uint32_t interval = config_["interval"].isUInt() ? config_["interval"].asUInt() : 30; thread_ = [this] {
thread_ = [this, interval] {
dp.emit(); dp.emit();
thread_.sleep_for(chrono::seconds(interval)); thread_.sleep_for(interval_);
}; };
} }
@ -15,7 +14,7 @@ auto waybar::modules::Memory::update() -> void
parseMeminfo(); parseMeminfo();
if (memtotal_ > 0 && memfree_ >= 0) { if (memtotal_ > 0 && memfree_ >= 0) {
int used_ram_percentage = 100 * (memtotal_ - memfree_) / memtotal_; int used_ram_percentage = 100 * (memtotal_ - memfree_) / memtotal_;
label_.set_text(fmt::format(format_, used_ram_percentage)); label_.set_markup(fmt::format(format_, used_ram_percentage));
auto used_ram_gigabytes = (memtotal_ - memfree_) / std::pow(1024, 2); auto used_ram_gigabytes = (memtotal_ - memfree_) / std::pow(1024, 2);
label_.set_tooltip_text(fmt::format("{:.{}f}Gb used", used_ram_gigabytes, 1)); label_.set_tooltip_text(fmt::format("{:.{}f}Gb used", used_ram_gigabytes, 1));
label_.set_name("memory"); label_.set_name("memory");

View File

@ -1,7 +1,7 @@
#include "modules/network.hpp" #include "modules/network.hpp"
waybar::modules::Network::Network(const Json::Value& config) waybar::modules::Network::Network(const Json::Value& config)
: ALabel(config, "{ifname}"), family_(AF_INET), : ALabel(config, "{ifname}", 60), family_(AF_INET),
signal_strength_dbm_(0), signal_strength_(0) signal_strength_dbm_(0), signal_strength_(0)
{ {
sock_fd_ = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); sock_fd_ = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
@ -85,9 +85,8 @@ void waybar::modules::Network::worker()
dp.emit(); dp.emit();
} }
}; };
uint32_t interval = config_["interval"].isUInt() ? config_["interval"].asUInt() : 60; thread_timer_ = [this] {
thread_timer_ = [this, interval] { thread_.sleep_for(interval_);
thread_.sleep_for(std::chrono::seconds(interval));
if (ifid_ > 0) { if (ifid_ > 0) {
getInfo(); getInfo();
dp.emit(); dp.emit();
@ -112,7 +111,7 @@ auto waybar::modules::Network::update() -> void
} }
label_.get_style_context()->remove_class("disconnected"); label_.get_style_context()->remove_class("disconnected");
} }
label_.set_text(fmt::format(format, label_.set_markup(fmt::format(format,
fmt::arg("essid", essid_), fmt::arg("essid", essid_),
fmt::arg("signaldBm", signal_strength_dbm_), fmt::arg("signaldBm", signal_strength_dbm_),
fmt::arg("signalStrength", signal_strength_), fmt::arg("signalStrength", signal_strength_),

View File

@ -1,57 +1,53 @@
#include "modules/sni/snh.hpp" #include "modules/sni/host.hpp"
#include <iostream> #include <iostream>
using namespace waybar::modules::SNI; using namespace waybar::modules::SNI;
Host::Host(Glib::Dispatcher* dp, const Json::Value &config) Host::Host(const std::size_t id, const Json::Value &config,
: dp_(dp), config_(config) const std::function<void(std::unique_ptr<Item>&)>& on_add,
const std::function<void(std::unique_ptr<Item>&)>& on_remove)
: bus_name_("org.kde.StatusNotifierHost-" + std::to_string(getpid()) + "-" + std::to_string(id)),
object_path_("/StatusNotifierHost/" + std::to_string(id)),
bus_name_id_(Gio::DBus::own_name(Gio::DBus::BusType::BUS_TYPE_SESSION, bus_name_,
sigc::mem_fun(*this, &Host::busAcquired))),
config_(config), on_add_(on_add), on_remove_(on_remove)
{ {
GBusNameOwnerFlags flags = static_cast<GBusNameOwnerFlags>(
G_BUS_NAME_OWNER_FLAGS_NONE);
bus_name_ = "org.kde.StatusNotifierHost-" + std::to_string(getpid());
object_path_ = "/StatusNotifierHost";
bus_name_id_ = g_bus_own_name(G_BUS_TYPE_SESSION,
bus_name_.c_str(), flags,
&Host::busAcquired, nullptr, nullptr, this, nullptr);
} }
void Host::busAcquired(GDBusConnection* connection, Host::~Host()
const gchar* name, gpointer data)
{ {
auto host = static_cast<SNI::Host *>(data); Gio::DBus::unwatch_name(bus_name_id_);
host->watcher_id_ = g_bus_watch_name(
G_BUS_TYPE_SESSION,
"org.kde.StatusNotifierWatcher",
G_BUS_NAME_WATCHER_FLAGS_NONE,
&Host::nameAppeared, &Host::nameVanished, data, nullptr);
} }
void Host::nameAppeared(GDBusConnection* connection, void Host::busAcquired(const Glib::RefPtr<Gio::DBus::Connection>& conn, Glib::ustring name)
const gchar* name, const gchar* name_owner, gpointer data)
{ {
auto host = static_cast<SNI::Host *>(data); watcher_id_ = Gio::DBus::watch_name(conn, "org.kde.StatusNotifierWatcher",
if (host->cancellable_ != nullptr) { sigc::mem_fun(*this, &Host::nameAppeared), sigc::mem_fun(*this, &Host::nameVanished));
}
void Host::nameAppeared(const Glib::RefPtr<Gio::DBus::Connection>& conn, const Glib::ustring name,
const Glib::ustring& name_owner)
{
if (cancellable_ != nullptr) {
// TODO // TODO
return; return;
} }
host->cancellable_ = g_cancellable_new(); cancellable_ = g_cancellable_new();
sn_watcher_proxy_new( sn_watcher_proxy_new(
connection, conn->gobj(),
G_DBUS_PROXY_FLAGS_NONE, G_DBUS_PROXY_FLAGS_NONE,
"org.kde.StatusNotifierWatcher", "org.kde.StatusNotifierWatcher",
"/StatusNotifierWatcher", "/StatusNotifierWatcher",
host->cancellable_, &Host::proxyReady, data); cancellable_, &Host::proxyReady, this);
} }
void Host::nameVanished(GDBusConnection* connection, void Host::nameVanished(const Glib::RefPtr<Gio::DBus::Connection>& conn, const Glib::ustring name)
const gchar* name, gpointer data)
{ {
auto host = static_cast<SNI::Host *>(data); g_cancellable_cancel(cancellable_);
g_cancellable_cancel(host->cancellable_); g_clear_object(&cancellable_);
g_clear_object(&host->cancellable_); g_clear_object(&watcher_);
g_clear_object(&host->watcher_); items_.clear();
host->items.clear();
} }
void Host::proxyReady(GObject* src, GAsyncResult* res, void Host::proxyReady(GObject* src, GAsyncResult* res,
@ -105,8 +101,7 @@ void Host::registerHost(GObject* src, GAsyncResult* res,
g_strfreev(items); g_strfreev(items);
} }
void Host::itemRegistered( void Host::itemRegistered(SnWatcher* watcher, const gchar* service, gpointer data)
SnWatcher* watcher, const gchar* service, gpointer data)
{ {
auto host = static_cast<SNI::Host *>(data); auto host = static_cast<SNI::Host *>(data);
host->addRegisteredItem(service); host->addRegisteredItem(service);
@ -117,35 +112,28 @@ void Host::itemUnregistered(
{ {
auto host = static_cast<SNI::Host *>(data); auto host = static_cast<SNI::Host *>(data);
auto [bus_name, object_path] = host->getBusNameAndObjectPath(service); auto [bus_name, object_path] = host->getBusNameAndObjectPath(service);
for (auto it = host->items.begin(); it != host->items.end(); ++it) { for (auto it = host->items_.begin(); it != host->items_.end(); ++it) {
if (it->bus_name == bus_name && it->object_path == object_path) { if ((*it)->bus_name == bus_name && (*it)->object_path == object_path) {
host->items.erase(it); host->on_remove_(*it);
host->items_.erase(it);
break; break;
} }
} }
host->dp_->emit();
} }
std::tuple<std::string, std::string> Host::getBusNameAndObjectPath( std::tuple<std::string, std::string> Host::getBusNameAndObjectPath(
const gchar* service) const std::string service)
{ {
std::string bus_name; auto it = service.find("/");
std::string object_path; if (it != std::string::npos) {
gchar* tmp = g_strstr_len(service, -1, "/"); return {service.substr(0, it), service.substr(it)};
if (tmp != nullptr) {
gchar** str = g_strsplit(service, "/", 2);
bus_name = str[0];
object_path = tmp;
g_strfreev(str);
} else {
bus_name = service;
object_path = "/StatusNotifierItem";
} }
return { bus_name, object_path }; return {service, "/StatusNotifierItem"};
} }
void Host::addRegisteredItem(const gchar* service) void Host::addRegisteredItem(std::string service)
{ {
auto [bus_name, object_path] = getBusNameAndObjectPath(service); auto [bus_name, object_path] = getBusNameAndObjectPath(service);
items.emplace_back(bus_name, object_path, dp_, config_); items_.emplace_back(new Item(bus_name, object_path, config_));
on_add_(items_.back());
} }

View File

@ -1,18 +1,14 @@
#include "modules/sni/sni.hpp" #include "modules/sni/item.hpp"
#include <iostream> #include <iostream>
#include <libdbusmenu-gtk/dbusmenu-gtk.h>
waybar::modules::SNI::Item::Item(std::string bn, std::string op, waybar::modules::SNI::Item::Item(std::string bn, std::string op, const Json::Value& config)
Glib::Dispatcher *dp, Json::Value config) : bus_name(bn), object_path(op), icon_size(16), effective_icon_size(0)
: bus_name(bn), object_path(op), event_box(), icon_size(16),
effective_icon_size(0), image(Gtk::manage(new Gtk::Image())),
dp_(dp), config_(config)
{ {
if (config_["icon-size"].isUInt()) { if (config["icon-size"].isUInt()) {
icon_size = config_["icon-size"].asUInt(); icon_size = config["icon-size"].asUInt();
} }
event_box.add(*image); event_box.add(image);
event_box.add_events(Gdk::BUTTON_PRESS_MASK); event_box.add_events(Gdk::BUTTON_PRESS_MASK);
event_box.signal_button_press_event().connect( event_box.signal_button_press_event().connect(
sigc::mem_fun(*this, &Item::handleClick)); sigc::mem_fun(*this, &Item::handleClick));
@ -40,11 +36,10 @@ void waybar::modules::SNI::Item::proxyReady(GObject *obj, GAsyncResult *res,
auto conn = g_dbus_proxy_get_connection(G_DBUS_PROXY(proxy)); auto conn = g_dbus_proxy_get_connection(G_DBUS_PROXY(proxy));
g_dbus_connection_call(conn, item->bus_name.c_str(), g_dbus_connection_call(conn, item->bus_name.c_str(),
item->object_path.c_str(), item->object_path.c_str(), "org.freedesktop.DBus.Properties", "GetAll",
"org.freedesktop.DBus.Properties", "GetAll", g_variant_new("(s)", "org.kde.StatusNotifierItem"),
g_variant_new("(s)", "org.kde.StatusNotifierItem"), G_VARIANT_TYPE("(a{sv})"), G_DBUS_CALL_FLAGS_NONE, -1, item->cancellable_,
G_VARIANT_TYPE("(a{sv})"), G_DBUS_CALL_FLAGS_NONE, -1, &Item::getAll, data);
item->cancellable_, &Item::getAll, data);
} }
void waybar::modules::SNI::Item::getAll(GObject *obj, GAsyncResult *res, void waybar::modules::SNI::Item::getAll(GObject *obj, GAsyncResult *res,
@ -107,18 +102,16 @@ void waybar::modules::SNI::Item::getAll(GObject *obj, GAsyncResult *res,
g_variant_unref(properties); g_variant_unref(properties);
if (item->id.empty() || item->category.empty() || item->status.empty()) { if (item->id.empty() || item->category.empty() || item->status.empty()) {
std::cerr << "Invalid Status Notifier Item: " + item->bus_name + "," + std::cerr << "Invalid Status Notifier Item: " + item->bus_name + "," +
item->object_path item->object_path << std::endl;
<< std::endl;
return; return;
} }
if (!item->icon_theme_path.empty()) { if (!item->icon_theme_path.empty()) {
GtkIconTheme *icon_theme = gtk_icon_theme_get_default(); GtkIconTheme *icon_theme = gtk_icon_theme_get_default();
gtk_icon_theme_append_search_path(icon_theme, gtk_icon_theme_append_search_path(icon_theme,
item->icon_theme_path.c_str()); item->icon_theme_path.c_str());
} }
item->updateImage(); item->updateImage();
item->updateMenu(); // item->event_box.set_tooltip_text(item->title);
item->dp_->emit();
// TODO: handle change // TODO: handle change
} }
@ -170,23 +163,10 @@ waybar::modules::SNI::Item::extractPixBuf(GVariant *variant) {
return Glib::RefPtr<Gdk::Pixbuf>{}; return Glib::RefPtr<Gdk::Pixbuf>{};
} }
void waybar::modules::SNI::Item::updateMenu()
{
event_box.set_tooltip_text(title);
if (gtk_menu == nullptr && !menu.empty()) {
auto dbmenu = dbusmenu_gtkmenu_new(bus_name.data(), menu.data());
if (dbmenu != nullptr) {
g_object_ref_sink(dbmenu);
gtk_menu = Glib::wrap(GTK_MENU(dbmenu), false);
gtk_menu->attach_to_widget(event_box);
}
}
}
void waybar::modules::SNI::Item::updateImage() void waybar::modules::SNI::Item::updateImage()
{ {
image->set_from_icon_name("image-missing", Gtk::ICON_SIZE_MENU); image.set_from_icon_name("image-missing", Gtk::ICON_SIZE_MENU);
image->set_pixel_size(icon_size); image.set_pixel_size(icon_size);
if (!icon_name.empty()) { if (!icon_name.empty()) {
try { try {
// Try to find icons specified by path and filename // Try to find icons specified by path and filename
@ -201,10 +181,10 @@ void waybar::modules::SNI::Item::updateImage()
// the tray // the tray
pixbuf = pixbuf->scale_simple(icon_size, icon_size, pixbuf = pixbuf->scale_simple(icon_size, icon_size,
Gdk::InterpType::INTERP_BILINEAR); Gdk::InterpType::INTERP_BILINEAR);
image->set(pixbuf); image.set(pixbuf);
} }
} else { } else {
image->set(getIconByName(icon_name, icon_size)); image.set(getIconByName(icon_name, icon_size));
} }
} catch (Glib::Error &e) { } catch (Glib::Error &e) {
std::cerr << "Exception: " << e.what() << std::endl; std::cerr << "Exception: " << e.what() << std::endl;
@ -213,7 +193,7 @@ void waybar::modules::SNI::Item::updateImage()
// An icon extracted may be the wrong size for the tray // An icon extracted may be the wrong size for the tray
icon_pixmap = icon_pixmap->scale_simple(icon_size, icon_size, icon_pixmap = icon_pixmap->scale_simple(icon_size, icon_size,
Gdk::InterpType::INTERP_BILINEAR); Gdk::InterpType::INTERP_BILINEAR);
image->set(icon_pixmap); image.set(icon_pixmap);
} }
} }
@ -237,42 +217,49 @@ waybar::modules::SNI::Item::getIconByName(std::string name, int request_size) {
tmp_size = request_size; tmp_size = request_size;
} }
return icon_theme->load_icon(name.c_str(), tmp_size, return icon_theme->load_icon(name.c_str(), tmp_size,
Gtk::IconLookupFlags::ICON_LOOKUP_FORCE_SIZE); Gtk::IconLookupFlags::ICON_LOOKUP_FORCE_SIZE);
} }
void waybar::modules::SNI::Item::handleActivate(GObject *src, GAsyncResult *res, void waybar::modules::SNI::Item::onMenuDestroyed(Item *self)
gpointer data) { {
auto item = static_cast<SNI::Item *>(data); self->gtk_menu = nullptr;
sn_item_call_activate_finish(item->proxy_, res, nullptr); self->dbus_menu = nullptr;
} }
void waybar::modules::SNI::Item::handleSecondaryActivate(GObject *src, bool waybar::modules::SNI::Item::makeMenu(GdkEventButton *const &ev)
GAsyncResult *res, {
gpointer data) { if (gtk_menu == nullptr) {
auto item = static_cast<SNI::Item *>(data); if (!menu.empty()) {
sn_item_call_secondary_activate_finish(item->proxy_, res, nullptr); dbus_menu = dbusmenu_gtkmenu_new(bus_name.data(), menu.data());
if (dbus_menu != nullptr) {
g_object_ref_sink(G_OBJECT(dbus_menu));
g_object_weak_ref(G_OBJECT(dbus_menu), (GWeakNotify)onMenuDestroyed, this);
gtk_menu = Glib::wrap(GTK_MENU(dbus_menu));
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 waybar::modules::SNI::Item::handleClick(GdkEventButton *const &ev) { bool waybar::modules::SNI::Item::handleClick(GdkEventButton *const &ev) {
if (ev->type == GDK_BUTTON_PRESS) { if ((ev->button == 1 && item_is_menu) || ev->button == 3) {
if (gtk_menu && gtk_menu->get_children().size() > 0) { if (!makeMenu(ev)) {
#if GTK_CHECK_VERSION(3, 22, 0) return sn_item_call_context_menu_sync(proxy_, ev->x, ev->y, nullptr, nullptr);
gtk_menu->popup_at_widget(reinterpret_cast<Gtk::Widget*>(&event_box),
Gdk::GRAVITY_NORTH_WEST, Gdk::GRAVITY_NORTH_WEST,
reinterpret_cast<GdkEvent*>(ev));
#else
gtk_menu->popup(ev->button, ev->time);
#endif
gtk_menu->set_state_flags(Gtk::STATE_FLAG_ACTIVE, false);
} else {
sn_item_call_activate(
proxy_, ev->x, ev->y, nullptr, &Item::handleActivate, this);
} }
} else if (ev->type == GDK_2BUTTON_PRESS) { } else if (ev->button == 1) {
sn_item_call_secondary_activate( return sn_item_call_activate_sync(proxy_, ev->x, ev->y, nullptr, nullptr);
proxy_, ev->x, ev->y, nullptr, &Item::handleSecondaryActivate, this); } else if (ev->button == 2) {
} else { return sn_item_call_secondary_activate_sync(proxy_, ev->x, ev->y,
return false; nullptr, nullptr);
} }
return true; return false;
} }

View File

@ -2,21 +2,31 @@
#include <iostream> #include <iostream>
waybar::modules::SNI::Tray::Tray(const Json::Value &config) waybar::modules::SNI::Tray::Tray(Bar& bar, const Json::Value &config)
: config_(config), watcher_(), host_(&dp, config) : config_(config), watcher_(), host_(bar.nb_tray_hosts, config,
std::bind(&Tray::onAdd, this, std::placeholders::_1),
std::bind(&Tray::onRemove, this, std::placeholders::_1))
{ {
std::cout << "Tray is in beta, so there may be bugs or even be unusable." << std::endl; std::cout << "Tray is in beta, so there may be bugs or even be unusable." << std::endl;
if (config_["spacing"].isUInt()) { if (config_["spacing"].isUInt()) {
box_.set_spacing(config_["spacing"].asUInt()); box_.set_spacing(config_["spacing"].asUInt());
} }
bar.nb_tray_hosts += 1;
}
void waybar::modules::SNI::Tray::onAdd(std::unique_ptr<Item>& item)
{
box_.pack_start(item->event_box);
dp.emit();
}
void waybar::modules::SNI::Tray::onRemove(std::unique_ptr<Item>& item)
{
box_.remove(item->event_box);
dp.emit();
} }
auto waybar::modules::SNI::Tray::update() -> void { auto waybar::modules::SNI::Tray::update() -> void {
auto childrens = box_.get_children();
childrens.erase(childrens.begin(), childrens.end());
for (auto &item : host_.items) {
box_.pack_start(item.event_box);
}
if (box_.get_children().size() > 0) { if (box_.get_children().size() > 0) {
box_.set_name("tray"); box_.set_name("tray");
box_.show_all(); box_.show_all();

View File

@ -1,41 +1,32 @@
#include "modules/sni/snw.hpp" #include "modules/sni/watcher.hpp"
#include <iostream> #include <iostream>
using namespace waybar::modules::SNI; using namespace waybar::modules::SNI;
Watcher::Watcher() Watcher::Watcher()
{ : bus_name_id_(Gio::DBus::own_name(Gio::DBus::BusType::BUS_TYPE_SESSION,
GBusNameOwnerFlags flags = static_cast<GBusNameOwnerFlags>( "org.kde.StatusNotifierWatcher", sigc::mem_fun(*this, &Watcher::busAcquired),
G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT Gio::DBus::SlotNameAcquired(), Gio::DBus::SlotNameLost(),
| G_BUS_NAME_OWNER_FLAGS_REPLACE); Gio::DBus::BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | Gio::DBus::BUS_NAME_OWNER_FLAGS_REPLACE)),
bus_name_id_ = g_bus_own_name(G_BUS_TYPE_SESSION, watcher_(sn_watcher_skeleton_new())
"org.kde.StatusNotifierWatcher", flags,
&Watcher::busAcquired, nullptr, nullptr, this, nullptr);
watcher_ = sn_watcher_skeleton_new();
sn_watcher_set_protocol_version(watcher_, 1);
}
Watcher::~Watcher()
{ {
} }
void Watcher::busAcquired(GDBusConnection* connection, const gchar* name, void Watcher::busAcquired(const Glib::RefPtr<Gio::DBus::Connection>& conn, Glib::ustring name)
gpointer data)
{ {
GError* error = nullptr; GError* error = nullptr;
auto host = static_cast<SNI::Watcher*>(data); g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(watcher_),
g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(host->watcher_), conn->gobj(), "/StatusNotifierWatcher", &error);
connection, "/StatusNotifierWatcher", &error);
if (error != nullptr) { if (error != nullptr) {
std::cerr << error->message << std::endl; std::cerr << error->message << std::endl;
g_error_free(error); g_error_free(error);
return; return;
} }
g_signal_connect_swapped(host->watcher_, "handle-register-item", g_signal_connect_swapped(watcher_, "handle-register-item",
G_CALLBACK(&Watcher::handleRegisterItem), data); G_CALLBACK(&Watcher::handleRegisterItem), this);
g_signal_connect_swapped(host->watcher_, "handle-register-host", g_signal_connect_swapped(watcher_, "handle-register-host",
G_CALLBACK(&Watcher::handleRegisterHost), data); G_CALLBACK(&Watcher::handleRegisterHost), this);
} }
gboolean Watcher::handleRegisterHost(Watcher* obj, gboolean Watcher::handleRegisterHost(Watcher* obj,

View File

@ -36,7 +36,7 @@ auto waybar::modules::sway::Mode::update() -> void
label_.hide(); label_.hide();
} else { } else {
label_.set_name("mode"); label_.set_name("mode");
label_.set_text(fmt::format(format_, mode_)); label_.set_markup(fmt::format(format_, mode_));
label_.set_tooltip_text(mode_); label_.set_tooltip_text(mode_);
label_.show(); label_.show();
} }

View File

@ -4,6 +4,10 @@ waybar::modules::sway::Window::Window(Bar &bar, const Json::Value& config)
: ALabel(config, "{}"), bar_(bar), windowId_(-1) : ALabel(config, "{}"), bar_(bar), windowId_(-1)
{ {
label_.set_name("window"); label_.set_name("window");
if (label_.get_max_width_chars() == -1) {
label_.set_hexpand(true);
label_.set_ellipsize(Pango::EllipsizeMode::ELLIPSIZE_END);
}
ipc_.connect(); ipc_.connect();
ipc_.subscribe("[\"window\",\"workspace\"]"); ipc_.subscribe("[\"window\",\"workspace\"]");
getFocusedWindow(); getFocusedWindow();
@ -39,7 +43,7 @@ void waybar::modules::sway::Window::worker()
auto waybar::modules::sway::Window::update() -> void auto waybar::modules::sway::Window::update() -> void
{ {
label_.set_text(fmt::format(format_, window_)); label_.set_markup(fmt::format(format_, window_));
label_.set_tooltip_text(window_); label_.set_tooltip_text(window_);
} }