Created
February 5, 2022 20:36
-
-
Save technic/c14b01da6642fe7ad4b5e705e793db1e to your computer and use it in GitHub Desktop.
AppInfo hacks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <filesystem> | |
#include <fstream> | |
#include <giomm/desktopappinfo.h> | |
#include <glibmm/keyfile.h> | |
#include <fmt/core.h> | |
#include <spdlog/spdlog.h> | |
#include "util/string.hpp" | |
#include "util/format.hpp" | |
/** Utilities for | |
* | |
*/ | |
namespace waybar::AppInfoProvider { | |
using AppInfo = Glib::RefPtr<Gio::DesktopAppInfo>; | |
// snap logic taken from | |
// https://gitlab.gnome.org/GNOME/mutter/-/blob/main/src/core/window.c#L867-L915 | |
// BAMF_DESKTOP_FILE_HINT logic taken from | |
// https://invent.kde.org/plasma/plasma-workspace/-/blob/master/libnotificationmanager/utils.cpp#L82-99 | |
// flatpak logic taken from | |
// https://gitlab.com/carbonOS/gde/gde-panel/-/blob/master/panel/appsys.vala#L59-L76 | |
// https://invent.kde.org/plasma/plasma-workspace/-/blob/master/libnotificationmanager/utils.cpp#L69-80 | |
/** | |
* @brief Find desktop file for process running in snap container | |
* | |
* Tries to read profile name from the security attributes of the process and find a .dekstop file with the matching name | |
* @param pid process id | |
* @return info from the matched desktop file, null when not found | |
*/ | |
AppInfo get_app_info_from_snap(uint32_t pid) { | |
using namespace std::literals; | |
// Example of the content for firefox snap on ubuntu 21.10: | |
// snap.firefox.firefox (enforce) | |
// We want to lookup: | |
// firefox_firefox.desktop | |
std::ifstream f{fmt::format("/proc/{}/attr/current", pid)}; | |
std::string data; | |
if(!std::getline(f, data)) { | |
return {}; | |
}; | |
constexpr auto SNAP_PREFIX = "snap."sv; | |
if (!starts_with(data, SNAP_PREFIX)) { | |
return {}; | |
} | |
data = data.substr(SNAP_PREFIX.size(), data.find(' ') - SNAP_PREFIX.size()); | |
std::replace(data.begin(), data.end(), '.', '_'); | |
return Gio::DesktopAppInfo::create(data + ".desktop"); | |
} | |
/** | |
* @brief Find desktop file for process based on BAMF_DESKTOP_FILE_HINT environment variable | |
* @param pid process id | |
* @return info from matched desktop file, null when not found | |
*/ | |
AppInfo get_app_info_from_bamf_env(uint32_t pid) { | |
using namespace std::literals; | |
constexpr auto ENV_PREFIX = "BAMF_DESKTOP_FILE_HINT="sv; | |
std::ifstream f{fmt::format("/proc/{}/environ", pid)}; | |
std::string data; | |
while (std::getline(f, data, '\0')) { | |
if (starts_with(data, ENV_PREFIX)) { | |
data = data.substr(ENV_PREFIX.size()); | |
return Gio::DesktopAppInfo::create_from_filename(data); | |
} | |
} | |
return {}; | |
} | |
/** | |
* @brief Find desktop file for process by looking for .flatpak-info file in the process's root | |
* @param pid process id | |
* @return info from matched desktop file, null when not found | |
*/ | |
AppInfo get_app_info_from_flatpak(uint32_t pid) { | |
namespace fs = std::filesystem; | |
fs::path flatpakInfo{fmt::format("/proc/{}/root/.flatpak-info", pid)}; | |
try { | |
if (!fs::is_regular_file(flatpakInfo)) { | |
return {}; | |
} | |
} catch (const std::exception&e) { | |
spdlog::error("fs error: {}", e.what()); | |
} | |
Glib::KeyFile keyFile; | |
try { | |
keyFile.load_from_file(flatpakInfo); | |
auto appName = keyFile.get_string("Application", "name"); | |
return Gio::DesktopAppInfo::create(appName + ".desktop"); | |
} catch (const Glib::Error& e) { | |
spdlog::error("Keyfile load failed {}", e.what()); | |
return {}; | |
} | |
} | |
}; // namespace waybar::AppInfoProvider |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment