added output-dimensions option

pull/1358/head
Ryan Gibb 2021-12-22 14:53:41 +00:00
parent 0e3be30e01
commit 39983c16da
7 changed files with 88 additions and 18 deletions

View File

@ -21,6 +21,8 @@ struct waybar_output {
Glib::RefPtr<Gdk::Monitor> monitor; Glib::RefPtr<Gdk::Monitor> monitor;
std::string name; std::string name;
std::string identifier; std::string identifier;
int32_t width;
int32_t height;
std::unique_ptr<struct zxdg_output_v1, decltype(&zxdg_output_v1_destroy)> xdg_output = { std::unique_ptr<struct zxdg_output_v1, decltype(&zxdg_output_v1_destroy)> xdg_output = {
nullptr, &zxdg_output_v1_destroy}; nullptr, &zxdg_output_v1_destroy};

View File

@ -43,6 +43,7 @@ class Client {
static void handleGlobal(void *data, struct wl_registry *registry, uint32_t name, static void handleGlobal(void *data, struct wl_registry *registry, uint32_t name,
const char *interface, uint32_t version); const char *interface, uint32_t version);
static void handleGlobalRemove(void *data, struct wl_registry *registry, uint32_t name); static void handleGlobalRemove(void *data, struct wl_registry *registry, uint32_t name);
static void handleOutputLogicalSize(void *, struct zxdg_output_v1 *, int32_t, int32_t);
static void handleOutputDone(void *, struct zxdg_output_v1 *); static void handleOutputDone(void *, struct zxdg_output_v1 *);
static void handleOutputName(void *, struct zxdg_output_v1 *, const char *); static void handleOutputName(void *, struct zxdg_output_v1 *, const char *);
static void handleOutputDescription(void *, struct zxdg_output_v1 *, const char *); static void handleOutputDescription(void *, struct zxdg_output_v1 *, const char *);

View File

@ -25,7 +25,7 @@ class Config {
Json::Value &getConfig() { return config_; } Json::Value &getConfig() { return config_; }
std::vector<Json::Value> getOutputConfigs(const std::string &name, const std::string &identifier); std::vector<Json::Value> getOutputConfigs(const std::string &name, const std::string &identifier, int32_t width, int32_t height);
private: private:
void setupConfig(Json::Value &dst, const std::string &config_file, int depth); void setupConfig(Json::Value &dst, const std::string &config_file, int depth);

View File

@ -31,6 +31,10 @@ Also a minimal example configuration can be found on the at the bottom of this m
typeof: string|array ++ typeof: string|array ++
Specifies on which screen this bar will be displayed. Exclamation mark(*!*) can be used to exclude specific output. Specifies on which screen this bar will be displayed. Exclamation mark(*!*) can be used to exclude specific output.
*output-dimensions* ++
typeof: string|array ++
If *output* is not specified, allows selecting outputs by dimensions. Format "(width/height) (</>) (value)", e.g. "width > 1080". Multiple conditions can be chained.
*position* ++ *position* ++
typeof: string ++ typeof: string ++
default: top ++ default: top ++
@ -240,6 +244,24 @@ A module group is defined by specifying a module named "group/some-group-name".
} }
``` ```
## Select outputs by dimensions
```
{
"layer": "top",
"output-dimensions": "width > 1080",
...
}
```
```
{
"layer": "top",
"output-dimensions": ["width < 3840", "height < 2160"],
...
}
```
# SUPPORTED MODULES # SUPPORTED MODULES
- *waybar-backlight(5)* - *waybar-backlight(5)*

View File

@ -40,7 +40,7 @@ void waybar::Client::handleGlobalRemove(void * data, struct wl_registry * /*re
void waybar::Client::handleOutput(struct waybar_output &output) { void waybar::Client::handleOutput(struct waybar_output &output) {
static const struct zxdg_output_v1_listener xdgOutputListener = { static const struct zxdg_output_v1_listener xdgOutputListener = {
.logical_position = [](void *, struct zxdg_output_v1 *, int32_t, int32_t) {}, .logical_position = [](void *, struct zxdg_output_v1 *, int32_t, int32_t) {},
.logical_size = [](void *, struct zxdg_output_v1 *, int32_t, int32_t) {}, .logical_size = &handleOutputLogicalSize,
.done = &handleOutputDone, .done = &handleOutputDone,
.name = &handleOutputName, .name = &handleOutputName,
.description = &handleOutputDescription, .description = &handleOutputDescription,
@ -61,7 +61,19 @@ struct waybar::waybar_output &waybar::Client::getOutput(void *addr) {
} }
std::vector<Json::Value> waybar::Client::getOutputConfigs(struct waybar_output &output) { std::vector<Json::Value> waybar::Client::getOutputConfigs(struct waybar_output &output) {
return config.getOutputConfigs(output.name, output.identifier); return config.getOutputConfigs(output.name, output.identifier, output.width, output.height);
}
void waybar::Client::handleOutputLogicalSize(void *data, struct zxdg_output_v1 *object,
int32_t width, int32_t height) {
auto client = waybar::Client::inst();
try {
auto &output = client->getOutput(data);
output.width = width;
output.height = height;
} catch (const std::exception &e) {
std::cerr << e.what() << std::endl;
}
} }
void waybar::Client::handleOutputDone(void *data, struct zxdg_output_v1 * /*xdg_output*/) { void waybar::Client::handleOutputDone(void *data, struct zxdg_output_v1 * /*xdg_output*/) {

View File

@ -103,7 +103,7 @@ void Config::mergeConfig(Json::Value &a_config_, Json::Value &b_config_) {
} }
} }
bool isValidOutput(const Json::Value &config, const std::string &name, bool isValidOutput(const Json::Value &config, const std::string &name,
const std::string &identifier) { const std::string &identifier, int32_t width, int32_t height) {
if (config["output"].isArray()) { if (config["output"].isArray()) {
for (auto const &output_conf : config["output"]) { for (auto const &output_conf : config["output"]) {
if (output_conf.isString() && if (output_conf.isString() &&
@ -122,6 +122,38 @@ bool isValidOutput(const Json::Value &config, const std::string &name,
} }
} }
// if "output-dimensions" is a string, make it an array of size 1
Json::Value config_output_dimensions = config["output-dimensions"];
if (config_output_dimensions.isString()) {
Json::Value jsonArray(Json::arrayValue);
jsonArray.append(config_output_dimensions);
config_output_dimensions = jsonArray;
}
if (config_output_dimensions.isArray()) {
for (auto const &config_output_dimension : config_output_dimensions) {
if (!config_output_dimension.isString()) {
continue;
}
std::string str = config_output_dimension.asString();
int i = str.find(" ");
std::string dimension = str.substr(0, i);
str = str.substr(i + 1);
i = str.find(" ");
std::string comparator = str.substr(0, i);
int value = std::stoi(str.substr(i));
if (dimension == "height" && comparator == "<" && height >= value) {
return false;
} else if (dimension == "height" && comparator == ">" && height <= value) {
return false;
}else if (dimension == "width" && comparator == "<" && width >= value) {
return false;
}else if (dimension == "width" && comparator == ">" && width <= value) {
return false;
}
return true;
}
}
return true; return true;
} }
@ -136,15 +168,16 @@ void Config::load(const std::string &config) {
} }
std::vector<Json::Value> Config::getOutputConfigs(const std::string &name, std::vector<Json::Value> Config::getOutputConfigs(const std::string &name,
const std::string &identifier) { const std::string &identifier,
int32_t width, int32_t height) {
std::vector<Json::Value> configs; std::vector<Json::Value> configs;
if (config_.isArray()) { if (config_.isArray()) {
for (auto const &config : config_) { for (auto const &config : config_) {
if (config.isObject() && isValidOutput(config, name, identifier)) { if (config.isObject() && isValidOutput(config, name, identifier, width, height)) {
configs.push_back(config); configs.push_back(config);
} }
} }
} else if (isValidOutput(config_, name, identifier)) { } else if (isValidOutput(config_, name, identifier, width, height)) {
configs.push_back(config_); configs.push_back(config_);
} }
return configs; return configs;

View File

@ -13,11 +13,11 @@ TEST_CASE("Load simple config", "[config]") {
REQUIRE(data["height"].asInt() == 30); REQUIRE(data["height"].asInt() == 30);
} }
SECTION("select configs for configured output") { SECTION("select configs for configured output") {
auto configs = conf.getOutputConfigs("HDMI-0", "Fake HDMI output #0"); auto configs = conf.getOutputConfigs("HDMI-0", "Fake HDMI output #0", 0, 0);
REQUIRE(configs.size() == 1); REQUIRE(configs.size() == 1);
} }
SECTION("select configs for missing output") { SECTION("select configs for missing output") {
auto configs = conf.getOutputConfigs("HDMI-1", "Fake HDMI output #1"); auto configs = conf.getOutputConfigs("HDMI-1", "Fake HDMI output #1", 0, 0);
REQUIRE(configs.empty()); REQUIRE(configs.empty());
} }
} }
@ -27,7 +27,7 @@ TEST_CASE("Load config with multiple bars", "[config]") {
conf.load("test/config/multi.json"); conf.load("test/config/multi.json");
SECTION("select multiple configs #1") { SECTION("select multiple configs #1") {
auto data = conf.getOutputConfigs("DP-0", "Fake DisplayPort output #0"); auto data = conf.getOutputConfigs("DP-0", "Fake DisplayPort output #0", 0, 0);
REQUIRE(data.size() == 3); REQUIRE(data.size() == 3);
REQUIRE(data[0]["layer"].asString() == "bottom"); REQUIRE(data[0]["layer"].asString() == "bottom");
REQUIRE(data[0]["height"].asInt() == 20); REQUIRE(data[0]["height"].asInt() == 20);
@ -39,7 +39,7 @@ TEST_CASE("Load config with multiple bars", "[config]") {
REQUIRE(data[2]["height"].asInt() == 23); REQUIRE(data[2]["height"].asInt() == 23);
} }
SECTION("select multiple configs #2") { SECTION("select multiple configs #2") {
auto data = conf.getOutputConfigs("HDMI-0", "Fake HDMI output #0"); auto data = conf.getOutputConfigs("HDMI-0", "Fake HDMI output #0", 0, 0);
REQUIRE(data.size() == 2); REQUIRE(data.size() == 2);
REQUIRE(data[0]["layer"].asString() == "bottom"); REQUIRE(data[0]["layer"].asString() == "bottom");
REQUIRE(data[0]["height"].asInt() == 20); REQUIRE(data[0]["height"].asInt() == 20);
@ -48,7 +48,7 @@ TEST_CASE("Load config with multiple bars", "[config]") {
REQUIRE(data[1]["height"].asInt() == 23); REQUIRE(data[1]["height"].asInt() == 23);
} }
SECTION("select single config by output description") { SECTION("select single config by output description") {
auto data = conf.getOutputConfigs("HDMI-1", "Fake HDMI output #1"); auto data = conf.getOutputConfigs("HDMI-1", "Fake HDMI output #1", 0, 0);
REQUIRE(data.size() == 1); REQUIRE(data.size() == 1);
REQUIRE(data[0]["layer"].asString() == "overlay"); REQUIRE(data[0]["layer"].asString() == "overlay");
REQUIRE(data[0]["position"].asString() == "left"); REQUIRE(data[0]["position"].asString() == "left");
@ -71,11 +71,11 @@ TEST_CASE("Load simple config with include", "[config]") {
REQUIRE((data.isMember("nullOption") && data["nullOption"].isNull())); REQUIRE((data.isMember("nullOption") && data["nullOption"].isNull()));
} }
SECTION("select configs for configured output") { SECTION("select configs for configured output") {
auto configs = conf.getOutputConfigs("HDMI-0", "Fake HDMI output #0"); auto configs = conf.getOutputConfigs("HDMI-0", "Fake HDMI output #0", 0, 0);
REQUIRE(configs.size() == 1); REQUIRE(configs.size() == 1);
} }
SECTION("select configs for missing output") { SECTION("select configs for missing output") {
auto configs = conf.getOutputConfigs("HDMI-1", "Fake HDMI output #1"); auto configs = conf.getOutputConfigs("HDMI-1", "Fake HDMI output #1", 0, 0);
REQUIRE(configs.empty()); REQUIRE(configs.empty());
} }
} }
@ -85,25 +85,25 @@ TEST_CASE("Load multiple bar config with include", "[config]") {
conf.load("test/config/include-multi.json"); conf.load("test/config/include-multi.json");
SECTION("bar config with sole include") { SECTION("bar config with sole include") {
auto data = conf.getOutputConfigs("OUT-0", "Fake output #0"); auto data = conf.getOutputConfigs("OUT-0", "Fake output #0", 0, 0);
REQUIRE(data.size() == 1); REQUIRE(data.size() == 1);
REQUIRE(data[0]["height"].asInt() == 20); REQUIRE(data[0]["height"].asInt() == 20);
} }
SECTION("bar config with output and include") { SECTION("bar config with output and include") {
auto data = conf.getOutputConfigs("OUT-1", "Fake output #1"); auto data = conf.getOutputConfigs("OUT-1", "Fake output #1", 0, 0);
REQUIRE(data.size() == 1); REQUIRE(data.size() == 1);
REQUIRE(data[0]["height"].asInt() == 21); REQUIRE(data[0]["height"].asInt() == 21);
} }
SECTION("bar config with output override") { SECTION("bar config with output override") {
auto data = conf.getOutputConfigs("OUT-2", "Fake output #2"); auto data = conf.getOutputConfigs("OUT-2", "Fake output #2", 0, 0);
REQUIRE(data.size() == 1); REQUIRE(data.size() == 1);
REQUIRE(data[0]["height"].asInt() == 22); REQUIRE(data[0]["height"].asInt() == 22);
} }
SECTION("multiple levels of include") { SECTION("multiple levels of include") {
auto data = conf.getOutputConfigs("OUT-3", "Fake output #3"); auto data = conf.getOutputConfigs("OUT-3", "Fake output #3", 0, 0);
REQUIRE(data.size() == 1); REQUIRE(data.size() == 1);
REQUIRE(data[0]["height"].asInt() == 23); REQUIRE(data[0]["height"].asInt() == 23);
} }