Merge pull request #1554 from ErikReider/gamemode-module
Gamemode Module
This commit is contained in:
commit
03bbc9df64
|
@ -42,6 +42,9 @@
|
||||||
#ifdef HAVE_LIBEVDEV
|
#ifdef HAVE_LIBEVDEV
|
||||||
#include "modules/keyboard_state.hpp"
|
#include "modules/keyboard_state.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_GAMEMODE
|
||||||
|
#include "modules/gamemode.hpp"
|
||||||
|
#endif
|
||||||
#ifdef HAVE_UPOWER
|
#ifdef HAVE_UPOWER
|
||||||
#include "modules/upower/upower.hpp"
|
#include "modules/upower/upower.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "ALabel.hpp"
|
||||||
|
#include "giomm/dbusconnection.h"
|
||||||
|
#include "giomm/dbusproxy.h"
|
||||||
|
#include "glibconfig.h"
|
||||||
|
#include "gtkmm/box.h"
|
||||||
|
#include "gtkmm/image.h"
|
||||||
|
#include "gtkmm/label.h"
|
||||||
|
#include "gtkmm/overlay.h"
|
||||||
|
|
||||||
|
namespace waybar::modules {
|
||||||
|
|
||||||
|
class Gamemode : public AModule {
|
||||||
|
public:
|
||||||
|
Gamemode(const std::string &, const Json::Value &);
|
||||||
|
~Gamemode();
|
||||||
|
auto update() -> void;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::string DEFAULT_ICON_NAME = "input-gaming-symbolic";
|
||||||
|
const std::string DEFAULT_FORMAT = "{glyph}";
|
||||||
|
const std::string DEFAULT_FORMAT_ALT = "{glyph} {count}";
|
||||||
|
const std::string DEFAULT_TOOLTIP_FORMAT = "Games running: {count}";
|
||||||
|
const std::string DEFAULT_GLYPH = "";
|
||||||
|
|
||||||
|
void appear(const Glib::RefPtr<Gio::DBus::Connection> &connection, const Glib::ustring &name,
|
||||||
|
const Glib::ustring &name_owner);
|
||||||
|
void disappear(const Glib::RefPtr<Gio::DBus::Connection> &connection, const Glib::ustring &name);
|
||||||
|
void prepareForSleep_cb(const Glib::RefPtr<Gio::DBus::Connection> &connection,
|
||||||
|
const Glib::ustring &sender_name, const Glib::ustring &object_path,
|
||||||
|
const Glib::ustring &interface_name, const Glib::ustring &signal_name,
|
||||||
|
const Glib::VariantContainerBase ¶meters);
|
||||||
|
void notify_cb(const Glib::ustring &sender_name, const Glib::ustring &signal_name,
|
||||||
|
const Glib::VariantContainerBase &arguments);
|
||||||
|
|
||||||
|
void getData();
|
||||||
|
bool handleToggle(GdkEventButton *const &);
|
||||||
|
|
||||||
|
// Config
|
||||||
|
std::string format = DEFAULT_FORMAT;
|
||||||
|
std::string format_alt = DEFAULT_FORMAT_ALT;
|
||||||
|
std::string tooltip_format = DEFAULT_TOOLTIP_FORMAT;
|
||||||
|
std::string glyph = DEFAULT_GLYPH;
|
||||||
|
bool tooltip = true;
|
||||||
|
bool hideNotRunning = true;
|
||||||
|
bool useIcon = true;
|
||||||
|
uint iconSize = 20;
|
||||||
|
uint iconSpacing = 4;
|
||||||
|
std::string iconName = DEFAULT_ICON_NAME;
|
||||||
|
|
||||||
|
Gtk::Box box_;
|
||||||
|
Gtk::Image icon_;
|
||||||
|
Gtk::Label label_;
|
||||||
|
|
||||||
|
const std::string dbus_name = "com.feralinteractive.GameMode";
|
||||||
|
const std::string dbus_obj_path = "/com/feralinteractive/GameMode";
|
||||||
|
const std::string dbus_interface = "org.freedesktop.DBus.Properties";
|
||||||
|
const std::string dbus_get_interface = "com.feralinteractive.GameMode";
|
||||||
|
|
||||||
|
uint gameCount = 0;
|
||||||
|
|
||||||
|
std::string lastStatus;
|
||||||
|
bool showAltText = false;
|
||||||
|
|
||||||
|
guint login1_id;
|
||||||
|
Glib::RefPtr<Gio::DBus::Proxy> gamemode_proxy;
|
||||||
|
Glib::RefPtr<Gio::DBus::Connection> system_connection;
|
||||||
|
bool gamemodeRunning;
|
||||||
|
guint gamemodeWatcher_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar::modules
|
|
@ -0,0 +1,95 @@
|
||||||
|
waybar-gamemode(5)
|
||||||
|
|
||||||
|
# NAME
|
||||||
|
|
||||||
|
waybar - gamemode module
|
||||||
|
|
||||||
|
# DESCRIPTION
|
||||||
|
|
||||||
|
The *gamemode* module displays if any game or application is running with ++
|
||||||
|
Feral Gamemode optimizations.
|
||||||
|
|
||||||
|
# CONFIGURATION
|
||||||
|
|
||||||
|
*format*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: {glyph} ++
|
||||||
|
The text format.
|
||||||
|
|
||||||
|
*format-alt*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: {glyph} {count} ++
|
||||||
|
The text format when toggled.
|
||||||
|
|
||||||
|
*tooltip*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
defualt: true ++
|
||||||
|
Option to disable tooltip on hover.
|
||||||
|
|
||||||
|
*tooltip-format*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: Games running: {glyph} ++
|
||||||
|
The text format of the tooltip.
|
||||||
|
|
||||||
|
*hide-not-running*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: true ++
|
||||||
|
Defines if the module should be hidden if no games are running.
|
||||||
|
|
||||||
|
*use-icon*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: true ++
|
||||||
|
Defines if the module should display a GTK icon instead of the specified *glyph*
|
||||||
|
|
||||||
|
*glyph*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: ++
|
||||||
|
The string icon to display. Only visible if *use-icon* is set to false.
|
||||||
|
|
||||||
|
*icon-name*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: input-gaming-symbolic ++
|
||||||
|
The GTK icon to display. Only visible if *use-icon* is set to true.
|
||||||
|
|
||||||
|
*icon-size*: ++
|
||||||
|
typeof: unsigned integer ++
|
||||||
|
default: 20 ++
|
||||||
|
Defines the size of the icons.
|
||||||
|
|
||||||
|
*icon-spacing*: ++
|
||||||
|
typeof: unsigned integer ++
|
||||||
|
default: 4 ++
|
||||||
|
Defines the spacing between the icon and the text.
|
||||||
|
|
||||||
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
|
*{glyph}*: The string icon glyph to use instead.
|
||||||
|
|
||||||
|
*{count}*: The amount of games running with gamemode optimizations.
|
||||||
|
|
||||||
|
# TOOLTIP FORMAT REPLACEMENTS
|
||||||
|
|
||||||
|
*{count}*: The amount of games running with gamemode optimizations.
|
||||||
|
|
||||||
|
# EXAMPLES
|
||||||
|
|
||||||
|
```
|
||||||
|
"gamemode": {
|
||||||
|
"format": "{glyph}",
|
||||||
|
"format-alt": "{glyph} {count}",
|
||||||
|
"glyph": "",
|
||||||
|
"hide-not-running": true,
|
||||||
|
"use-icon": true,
|
||||||
|
"icon-name": "input-gaming-symbolic",
|
||||||
|
"icon-spacing": 4,
|
||||||
|
"icon-size": 20,
|
||||||
|
"tooltip": true,
|
||||||
|
"tooltip-format": "Games running: {count}"
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
# STYLE
|
||||||
|
|
||||||
|
- *#gamemode*
|
||||||
|
- *#gamemode.running*
|
|
@ -204,6 +204,11 @@ if libnl.found() and libnlgen.found()
|
||||||
src_files += 'src/modules/network.cpp'
|
src_files += 'src/modules/network.cpp'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if (giounix.found() and not get_option('logind').disabled())
|
||||||
|
add_project_arguments('-DHAVE_GAMEMODE', language: 'cpp')
|
||||||
|
src_files += 'src/modules/gamemode.cpp'
|
||||||
|
endif
|
||||||
|
|
||||||
if (upower_glib.found() and giounix.found() and not get_option('logind').disabled())
|
if (upower_glib.found() and giounix.found() and not get_option('logind').disabled())
|
||||||
add_project_arguments('-DHAVE_UPOWER', language: 'cpp')
|
add_project_arguments('-DHAVE_UPOWER', language: 'cpp')
|
||||||
src_files += 'src/modules/upower/upower.cpp'
|
src_files += 'src/modules/upower/upower.cpp'
|
||||||
|
|
|
@ -12,6 +12,11 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const {
|
||||||
return new waybar::modules::Battery(id, config_[name]);
|
return new waybar::modules::Battery(id, config_[name]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_GAMEMODE
|
||||||
|
if (ref == "gamemode") {
|
||||||
|
return new waybar::modules::Gamemode(id, config_[name]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#ifdef HAVE_UPOWER
|
#ifdef HAVE_UPOWER
|
||||||
if (ref == "upower") {
|
if (ref == "upower") {
|
||||||
return new waybar::modules::upower::UPower(id, config_[name]);
|
return new waybar::modules::upower::UPower(id, config_[name]);
|
||||||
|
|
|
@ -0,0 +1,237 @@
|
||||||
|
#include "modules/gamemode.hpp"
|
||||||
|
|
||||||
|
#include <fmt/core.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "AModule.hpp"
|
||||||
|
#include "giomm/dbusconnection.h"
|
||||||
|
#include "giomm/dbusinterface.h"
|
||||||
|
#include "giomm/dbusproxy.h"
|
||||||
|
#include "giomm/dbuswatchname.h"
|
||||||
|
#include "glibmm/error.h"
|
||||||
|
#include "glibmm/ustring.h"
|
||||||
|
#include "glibmm/variant.h"
|
||||||
|
#include "glibmm/varianttype.h"
|
||||||
|
#include "gtkmm/icontheme.h"
|
||||||
|
#include "gtkmm/label.h"
|
||||||
|
#include "gtkmm/tooltip.h"
|
||||||
|
|
||||||
|
namespace waybar::modules {
|
||||||
|
Gamemode::Gamemode(const std::string& id, const Json::Value& config)
|
||||||
|
: AModule(config, "gamemode", id), box_(Gtk::ORIENTATION_HORIZONTAL, 0), icon_(), label_() {
|
||||||
|
box_.pack_start(icon_);
|
||||||
|
box_.pack_start(label_);
|
||||||
|
box_.set_name(name_);
|
||||||
|
event_box_.add(box_);
|
||||||
|
|
||||||
|
// Tooltip
|
||||||
|
if (config_["tooltip"].isBool()) {
|
||||||
|
tooltip = config_["tooltip"].asBool();
|
||||||
|
}
|
||||||
|
box_.set_has_tooltip(tooltip);
|
||||||
|
|
||||||
|
// Tooltip Format
|
||||||
|
if (config_["tooltip-format"].isString()) {
|
||||||
|
tooltip_format = config_["tooltip-format"].asString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide when game count is 0
|
||||||
|
if (config_["hide-not-running"].isBool()) {
|
||||||
|
hideNotRunning = config_["hide-not-running"].asBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Icon Name
|
||||||
|
if (config_["icon-name"].isString()) {
|
||||||
|
iconName = config_["icon-name"].asString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Icon Spacing
|
||||||
|
if (config_["icon-spacing"].isUInt()) {
|
||||||
|
iconSpacing = config_["icon-spacing"].asUInt();
|
||||||
|
}
|
||||||
|
box_.set_spacing(iconSpacing);
|
||||||
|
|
||||||
|
// Wether to use icon or not
|
||||||
|
if (config_["use-icon"].isBool()) {
|
||||||
|
useIcon = config_["use-icon"].asBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Icon Size
|
||||||
|
if (config_["icon-size"].isUInt()) {
|
||||||
|
iconSize = config_["icon-size"].asUInt();
|
||||||
|
}
|
||||||
|
icon_.set_pixel_size(iconSize);
|
||||||
|
|
||||||
|
// Format
|
||||||
|
if (config_["format"].isString()) {
|
||||||
|
format = config_["format"].asString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format Alt
|
||||||
|
if (config_["format-alt"].isString()) {
|
||||||
|
format_alt = config_["format-alt"].asString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Glyph
|
||||||
|
if (config_["glyph"].isString()) {
|
||||||
|
glyph = config_["glyph"].asString();
|
||||||
|
}
|
||||||
|
|
||||||
|
gamemodeWatcher_id = Gio::DBus::watch_name(
|
||||||
|
Gio::DBus::BUS_TYPE_SESSION, dbus_name, sigc::mem_fun(*this, &Gamemode::appear),
|
||||||
|
sigc::mem_fun(*this, &Gamemode::disappear),
|
||||||
|
Gio::DBus::BusNameWatcherFlags::BUS_NAME_WATCHER_FLAGS_AUTO_START);
|
||||||
|
|
||||||
|
// Connect to gamemode
|
||||||
|
gamemode_proxy = Gio::DBus::Proxy::create_for_bus_sync(Gio::DBus::BusType::BUS_TYPE_SESSION,
|
||||||
|
dbus_name, dbus_obj_path, dbus_interface);
|
||||||
|
if (!gamemode_proxy) {
|
||||||
|
throw std::runtime_error("Unable to connect to gamemode DBus!...");
|
||||||
|
} else {
|
||||||
|
gamemode_proxy->signal_signal().connect(sigc::mem_fun(*this, &Gamemode::notify_cb));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect to Login1 PrepareForSleep signal
|
||||||
|
system_connection = Gio::DBus::Connection::get_sync(Gio::DBus::BusType::BUS_TYPE_SYSTEM);
|
||||||
|
if (!system_connection) {
|
||||||
|
throw std::runtime_error("Unable to connect to the SYSTEM Bus!...");
|
||||||
|
} else {
|
||||||
|
login1_id = system_connection->signal_subscribe(
|
||||||
|
sigc::mem_fun(*this, &Gamemode::prepareForSleep_cb), "org.freedesktop.login1",
|
||||||
|
"org.freedesktop.login1.Manager", "PrepareForSleep", "/org/freedesktop/login1");
|
||||||
|
}
|
||||||
|
|
||||||
|
event_box_.signal_button_press_event().connect(sigc::mem_fun(*this, &Gamemode::handleToggle));
|
||||||
|
}
|
||||||
|
|
||||||
|
Gamemode::~Gamemode() {
|
||||||
|
if (gamemode_proxy) gamemode_proxy->unreference();
|
||||||
|
if (gamemodeWatcher_id > 0) {
|
||||||
|
Gio::DBus::unwatch_name(gamemodeWatcher_id);
|
||||||
|
gamemodeWatcher_id = 0;
|
||||||
|
}
|
||||||
|
if (login1_id > 0) {
|
||||||
|
system_connection->signal_unsubscribe(login1_id);
|
||||||
|
login1_id = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the DBus ClientCount
|
||||||
|
void Gamemode::getData() {
|
||||||
|
if (gamemodeRunning && gamemode_proxy) {
|
||||||
|
try {
|
||||||
|
// Get game count
|
||||||
|
auto parameters = Glib::VariantContainerBase(
|
||||||
|
g_variant_new("(ss)", dbus_get_interface.c_str(), "ClientCount"));
|
||||||
|
Glib::VariantContainerBase data = gamemode_proxy->call_sync("Get", parameters);
|
||||||
|
if (data && data.is_of_type(Glib::VariantType("(v)"))) {
|
||||||
|
Glib::VariantBase variant;
|
||||||
|
g_variant_get(data.gobj_copy(), "(v)", &variant);
|
||||||
|
if (variant && variant.is_of_type(Glib::VARIANT_TYPE_INT32)) {
|
||||||
|
g_variant_get(variant.gobj_copy(), "i", &gameCount);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Glib::Error& e) {
|
||||||
|
spdlog::error("Gamemode Error {}", e.what().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gameCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Whenever the DBus ClientCount changes
|
||||||
|
void Gamemode::notify_cb(const Glib::ustring& sender_name, const Glib::ustring& signal_name,
|
||||||
|
const Glib::VariantContainerBase& arguments) {
|
||||||
|
if (signal_name == "PropertiesChanged") {
|
||||||
|
getData();
|
||||||
|
dp.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gamemode::prepareForSleep_cb(const Glib::RefPtr<Gio::DBus::Connection>& connection,
|
||||||
|
const Glib::ustring& sender_name,
|
||||||
|
const Glib::ustring& object_path,
|
||||||
|
const Glib::ustring& interface_name,
|
||||||
|
const Glib::ustring& signal_name,
|
||||||
|
const Glib::VariantContainerBase& parameters) {
|
||||||
|
if (parameters.is_of_type(Glib::VariantType("(b)"))) {
|
||||||
|
gboolean sleeping;
|
||||||
|
g_variant_get(parameters.gobj_copy(), "(b)", &sleeping);
|
||||||
|
if (!sleeping) {
|
||||||
|
getData();
|
||||||
|
dp.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// When the gamemode name appears
|
||||||
|
void Gamemode::appear(const Glib::RefPtr<Gio::DBus::Connection>& connection,
|
||||||
|
const Glib::ustring& name, const Glib::ustring& name_owner) {
|
||||||
|
gamemodeRunning = true;
|
||||||
|
event_box_.set_visible(true);
|
||||||
|
getData();
|
||||||
|
dp.emit();
|
||||||
|
}
|
||||||
|
// When the gamemode name disappears
|
||||||
|
void Gamemode::disappear(const Glib::RefPtr<Gio::DBus::Connection>& connection,
|
||||||
|
const Glib::ustring& name) {
|
||||||
|
gamemodeRunning = false;
|
||||||
|
event_box_.set_visible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Gamemode::handleToggle(GdkEventButton* const& event) {
|
||||||
|
showAltText = !showAltText;
|
||||||
|
dp.emit();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Gamemode::update() -> void {
|
||||||
|
// Don't update widget if the Gamemode service isn't running
|
||||||
|
if (!gamemodeRunning || (gameCount <= 0 && hideNotRunning)) {
|
||||||
|
event_box_.set_visible(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show the module
|
||||||
|
if (!event_box_.get_visible()) event_box_.set_visible(true);
|
||||||
|
|
||||||
|
// CSS status class
|
||||||
|
const std::string status = gamemodeRunning && gameCount > 0 ? "running" : "";
|
||||||
|
// Remove last status if it exists
|
||||||
|
if (!lastStatus.empty() && box_.get_style_context()->has_class(lastStatus)) {
|
||||||
|
box_.get_style_context()->remove_class(lastStatus);
|
||||||
|
}
|
||||||
|
// Add the new status class to the Box
|
||||||
|
if (!status.empty() && !box_.get_style_context()->has_class(status)) {
|
||||||
|
box_.get_style_context()->add_class(status);
|
||||||
|
}
|
||||||
|
lastStatus = status;
|
||||||
|
|
||||||
|
// Tooltip
|
||||||
|
if (tooltip) {
|
||||||
|
std::string text = fmt::format(tooltip_format, fmt::arg("count", gameCount));
|
||||||
|
box_.set_tooltip_text(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Label format
|
||||||
|
std::string str =
|
||||||
|
fmt::format(showAltText ? format_alt : format, fmt::arg("glyph", useIcon ? "" : glyph),
|
||||||
|
fmt::arg("count", gameCount > 0 ? std::to_string(gameCount) : ""));
|
||||||
|
label_.set_markup(str);
|
||||||
|
|
||||||
|
if (useIcon) {
|
||||||
|
if (!Gtk::IconTheme::get_default()->has_icon(iconName)) {
|
||||||
|
iconName = DEFAULT_ICON_NAME;
|
||||||
|
}
|
||||||
|
icon_.set_from_icon_name(iconName, Gtk::ICON_SIZE_INVALID);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call parent update
|
||||||
|
AModule::update();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace waybar::modules
|
Loading…
Reference in New Issue