Finish
parent
61783aafaa
commit
38afa345dd
|
@ -9,6 +9,7 @@
|
|||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
|
@ -66,7 +67,8 @@ class Task
|
|||
bool button_visible_;
|
||||
bool ignored_;
|
||||
|
||||
bool with_icon_;
|
||||
bool with_icon_ = false;
|
||||
bool with_name_ = false;
|
||||
std::string format_before_;
|
||||
std::string format_after_;
|
||||
|
||||
|
@ -80,7 +82,8 @@ class Task
|
|||
private:
|
||||
std::string repr() const;
|
||||
std::string state_string(bool = false) const;
|
||||
void set_desktop_app_info(const std::string &app_id);
|
||||
void set_app_info_from_app_id_list(const std::string& app_id_list);
|
||||
bool image_load_icon(Gtk::Image& image, const Glib::RefPtr<Gtk::IconTheme>& icon_theme, Glib::RefPtr<Gio::DesktopAppInfo> app_info, int size);
|
||||
|
||||
public:
|
||||
/* Getter functions */
|
||||
|
@ -139,6 +142,7 @@ class Taskbar : public waybar::AModule
|
|||
|
||||
std::vector<Glib::RefPtr<Gtk::IconTheme>> icon_themes_;
|
||||
std::unordered_set<std::string> ignore_list_;
|
||||
std::map<std::string, std::string> app_ids_replace_map_;
|
||||
|
||||
struct zwlr_foreign_toplevel_manager_v1 *manager_;
|
||||
struct wl_seat *seat_;
|
||||
|
@ -161,8 +165,9 @@ class Taskbar : public waybar::AModule
|
|||
bool show_output(struct wl_output *) const;
|
||||
bool all_outputs() const;
|
||||
|
||||
std::vector<Glib::RefPtr<Gtk::IconTheme>> icon_themes() const;
|
||||
const std::vector<Glib::RefPtr<Gtk::IconTheme>>& icon_themes() const;
|
||||
const std::unordered_set<std::string>& ignore_list() const;
|
||||
const std::map<std::string, std::string>& app_ids_replace_map() const;
|
||||
};
|
||||
|
||||
} /* namespace waybar::modules::wlr */
|
||||
|
|
|
@ -72,10 +72,16 @@ Addressed by *wlr/taskbar*
|
|||
typeof: array ++
|
||||
List of app_id to be invisible.
|
||||
|
||||
*app_ids-mapping*: ++
|
||||
typeof: object ++
|
||||
Directory of app_id to be replaced with
|
||||
|
||||
# FORMAT REPLACEMENTS
|
||||
|
||||
*{icon}*: The icon of the application.
|
||||
|
||||
*{title}*: The application name as in desktop file if appropriate desktop fils found, otherwise same as {app_id}
|
||||
|
||||
*{title}*: The title of the application.
|
||||
|
||||
*{app_id}*: The app_id (== application name) of the application.
|
||||
|
@ -105,7 +111,10 @@ Addressed by *wlr/taskbar*
|
|||
"on-click-middle": "close",
|
||||
"ignore-list": [
|
||||
"Alacritty"
|
||||
]
|
||||
],
|
||||
"app_ids-mapping": {
|
||||
"firefoxdeveloperedition": "firefox-developer-edition"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -11,7 +11,9 @@
|
|||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <gdkmm/monitor.h>
|
||||
|
||||
#include <gtkmm/icontheme.h>
|
||||
|
@ -86,7 +88,7 @@ static Glib::RefPtr<Gdk::Pixbuf> load_icon_from_file(std::string icon_path, int
|
|||
}
|
||||
}
|
||||
|
||||
static Glib::RefPtr<GDesktopAppInfo> get_app_info_by_name(const std::string& app_id)
|
||||
static Glib::RefPtr<Gio::DesktopAppInfo> get_app_info_by_name(const std::string& app_id)
|
||||
{
|
||||
static std::vector<std::string> prefixes = search_prefix();
|
||||
|
||||
|
@ -118,12 +120,11 @@ static Glib::RefPtr<GDesktopAppInfo> get_app_info_by_name(const std::string& app
|
|||
return {};
|
||||
}
|
||||
|
||||
void Task::set_desktop_app_info(const std::string &app_id)
|
||||
Glib::RefPtr<Gio::DesktopAppInfo> get_desktop_app_info(const std::string &app_id)
|
||||
{
|
||||
auto app_info = get_app_info_by_name(app_id);
|
||||
if (app_info) {
|
||||
app_info_ = app_info;
|
||||
return;
|
||||
return app_info;
|
||||
}
|
||||
|
||||
std::string desktop_file = "";
|
||||
|
@ -133,7 +134,6 @@ void Task::set_desktop_app_info(const std::string &app_id)
|
|||
for (size_t i=0; desktop_list[0][i]; i++) {
|
||||
if (desktop_file == "") {
|
||||
desktop_file = desktop_list[0][i];
|
||||
// TODO: debug. Possible error
|
||||
} else {
|
||||
auto tmp_info = Gio::DesktopAppInfo::create(desktop_list[0][i]);
|
||||
auto startup_class = tmp_info->get_startup_wm_class();
|
||||
|
@ -148,12 +148,45 @@ void Task::set_desktop_app_info(const std::string &app_id)
|
|||
}
|
||||
g_free(desktop_list);
|
||||
|
||||
app_info = get_app_info_by_name(desktop_file);
|
||||
app_info_ = app_info;
|
||||
return get_app_info_by_name(desktop_file);
|
||||
}
|
||||
|
||||
/* Method 2 - use the app_id and check whether there is an icon with this name in the icon theme */
|
||||
static std::string get_from_icon_theme(const Glib::RefPtr<Gtk::IconTheme>& icon_theme,
|
||||
void Task::set_app_info_from_app_id_list(const std::string& app_id_list) {
|
||||
std::string app_id;
|
||||
std::istringstream stream(app_id_list);
|
||||
|
||||
/* Wayfire sends a list of app-id's in space separated format, other compositors
|
||||
* send a single app-id, but in any case this works fine */
|
||||
while (stream >> app_id)
|
||||
{
|
||||
app_info_ = get_desktop_app_info(app_id);
|
||||
if (app_info_) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lower_app_id = app_id;
|
||||
std::transform(lower_app_id.begin(), lower_app_id.end(), lower_app_id.begin(),
|
||||
[](char c){ return std::tolower(c); });
|
||||
app_info_ = get_desktop_app_info(lower_app_id);
|
||||
if (app_info_) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t start = 0, end = app_id.size();
|
||||
start = app_id.rfind(".", end);
|
||||
std::string app_name = app_id.substr(start+1, app_id.size());
|
||||
app_info_ = get_desktop_app_info(app_name);
|
||||
if (app_info_) {
|
||||
return;
|
||||
}
|
||||
|
||||
start = app_id.find("-");
|
||||
app_name = app_id.substr(0, start);
|
||||
app_info_ = get_desktop_app_info(app_name);
|
||||
}
|
||||
}
|
||||
|
||||
static std::string get_icon_name_from_icon_theme(const Glib::RefPtr<Gtk::IconTheme>& icon_theme,
|
||||
const std::string &app_id)
|
||||
{
|
||||
if (icon_theme->lookup_icon(app_id, 24))
|
||||
|
@ -162,62 +195,37 @@ static std::string get_from_icon_theme(const Glib::RefPtr<Gtk::IconTheme>& icon_
|
|||
return "";
|
||||
}
|
||||
|
||||
static bool image_load_icon(Gtk::Image& image, const Glib::RefPtr<Gtk::IconTheme>& icon_theme,
|
||||
const std::string &app_id_list, int size)
|
||||
bool Task::image_load_icon(Gtk::Image& image, const Glib::RefPtr<Gtk::IconTheme>& icon_theme, Glib::RefPtr<Gio::DesktopAppInfo> app_info, int size)
|
||||
{
|
||||
std::string app_id;
|
||||
std::istringstream stream(app_id_list);
|
||||
bool found = false;
|
||||
|
||||
/* Wayfire sends a list of app-id's in space separated format, other compositors
|
||||
* send a single app-id, but in any case this works fine */
|
||||
while (stream >> app_id)
|
||||
{
|
||||
size_t start = 0, end = app_id.size();
|
||||
start = app_id.rfind(".", end);
|
||||
std::string app_name = app_id.substr(start+1, app_id.size());
|
||||
|
||||
auto lower_app_id = app_id;
|
||||
std::transform(lower_app_id.begin(), lower_app_id.end(), lower_app_id.begin(),
|
||||
[](char c){ return std::tolower(c); });
|
||||
|
||||
std::string icon_name = get_from_icon_theme(icon_theme, app_id);
|
||||
|
||||
if (icon_name.empty())
|
||||
icon_name = get_from_icon_theme(icon_theme, lower_app_id);
|
||||
if (icon_name.empty())
|
||||
icon_name = get_from_icon_theme(icon_theme, app_name);
|
||||
if (icon_name.empty())
|
||||
icon_name = get_from_desktop_app_info(app_id);
|
||||
if (icon_name.empty())
|
||||
icon_name = get_from_desktop_app_info(lower_app_id);
|
||||
if (icon_name.empty())
|
||||
icon_name = get_from_desktop_app_info(app_name);
|
||||
if (icon_name.empty())
|
||||
icon_name = get_from_desktop_app_info_search(app_id);
|
||||
|
||||
if (icon_name.empty())
|
||||
icon_name = "unknown";
|
||||
std::string ret_icon_name = "unknown";
|
||||
if (app_info) {
|
||||
std::string icon_name = get_icon_name_from_icon_theme(icon_theme, app_info->get_startup_wm_class());
|
||||
if (!icon_name.empty()) {
|
||||
ret_icon_name = icon_name;
|
||||
} else {
|
||||
if (app_info->get_icon()) {
|
||||
ret_icon_name = app_info->get_icon()->to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Glib::RefPtr<Gdk::Pixbuf> pixbuf;
|
||||
|
||||
try {
|
||||
pixbuf = icon_theme->load_icon(icon_name, size, Gtk::ICON_LOOKUP_FORCE_SIZE);
|
||||
pixbuf = icon_theme->load_icon(ret_icon_name, size, Gtk::ICON_LOOKUP_FORCE_SIZE);
|
||||
} catch(...) {
|
||||
if (Glib::file_test(icon_name, Glib::FILE_TEST_EXISTS))
|
||||
pixbuf = load_icon_from_file(icon_name, size);
|
||||
if (Glib::file_test(ret_icon_name, Glib::FILE_TEST_EXISTS))
|
||||
pixbuf = load_icon_from_file(ret_icon_name, size);
|
||||
else
|
||||
pixbuf = {};
|
||||
}
|
||||
|
||||
if (pixbuf) {
|
||||
image.set(pixbuf);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return found;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Task class implementation */
|
||||
|
@ -298,13 +306,15 @@ Task::Task(const waybar::Bar &bar, const Json::Value &config, Taskbar *tbar,
|
|||
content_.show();
|
||||
button_.add(content_);
|
||||
|
||||
with_icon_ = false;
|
||||
format_before_.clear();
|
||||
format_after_.clear();
|
||||
|
||||
if (config_["format"].isString()) {
|
||||
/* The user defined a format string, use it */
|
||||
auto format = config_["format"].asString();
|
||||
if (format.find("{name}") != std::string::npos) {
|
||||
with_name_ = true;
|
||||
}
|
||||
|
||||
auto icon_pos = format.find("{icon}");
|
||||
if (icon_pos == 0) {
|
||||
|
@ -406,13 +416,28 @@ void Task::handle_app_id(const char *app_id)
|
|||
}
|
||||
}
|
||||
|
||||
if (!with_icon_)
|
||||
auto ids_replace_map = tbar_->app_ids_replace_map();
|
||||
if (ids_replace_map.count(app_id_)) {
|
||||
auto replaced_id = ids_replace_map[app_id_];
|
||||
spdlog::debug(fmt::format("Task ({}) [{}] app_id was replaced with {}", id_, app_id_, replaced_id));
|
||||
app_id_ = replaced_id;
|
||||
}
|
||||
|
||||
if (!with_icon_ && !with_name_) {
|
||||
return;
|
||||
}
|
||||
|
||||
set_app_info_from_app_id_list(app_id_);
|
||||
name_ = app_info_ ? app_info_->get_display_name() : app_id;
|
||||
|
||||
if (!with_icon_) {
|
||||
return;
|
||||
}
|
||||
|
||||
int icon_size = config_["icon-size"].isInt() ? config_["icon-size"].asInt() : 16;
|
||||
bool found = false;
|
||||
for (auto& icon_theme : tbar_->icon_themes()) {
|
||||
if (image_load_icon(icon_, icon_theme, app_id_, icon_size)) {
|
||||
if (image_load_icon(icon_, icon_theme, app_info_, icon_size)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
@ -735,6 +760,15 @@ Taskbar::Taskbar(const std::string &id, const waybar::Bar &bar, const Json::Valu
|
|||
}
|
||||
}
|
||||
|
||||
// Load app_id remappings
|
||||
if (config_["app_ids-mapping"].isObject()) {
|
||||
const Json::Value& mapping = config_["app_ids-mapping"];
|
||||
const std::vector<std::string> app_ids = config_["app_ids-mapping"].getMemberNames();
|
||||
for (auto& app_id : app_ids) {
|
||||
app_ids_replace_map_.emplace(app_id, mapping[app_id].asString());
|
||||
}
|
||||
}
|
||||
|
||||
icon_themes_.push_back(Gtk::IconTheme::get_default());
|
||||
}
|
||||
|
||||
|
@ -866,10 +900,10 @@ bool Taskbar::all_outputs() const
|
|||
return config_["all-outputs"].isBool() && config_["all-outputs"].asBool();
|
||||
}
|
||||
|
||||
std::vector<Glib::RefPtr<Gtk::IconTheme>> Taskbar::icon_themes() const
|
||||
{
|
||||
return icon_themes_;
|
||||
}
|
||||
const std::vector<Glib::RefPtr<Gtk::IconTheme>>& Taskbar::icon_themes() const { return icon_themes_; }
|
||||
|
||||
const std::unordered_set<std::string>& Taskbar::ignore_list() const { return ignore_list_; }
|
||||
|
||||
const std::map<std::string, std::string>& Taskbar::app_ids_replace_map() const { return app_ids_replace_map_; }
|
||||
|
||||
} /* namespace waybar::modules::wlr */
|
||||
|
|
Loading…
Reference in New Issue