randr: Add separate key for exact monitor matching
This adds `monitor-exact = true` in the bar section This also properly does best-match instead of first-match if multiple matches exists. For example if there are two monitors HDMI2 and HDMI-2 and we try to match HDMI-2 with monitor-exact = false, until now HDMI2 would be matched. Now exact matches are always preferred. Fixes #1532
This commit is contained in:
parent
ea5fc22c7d
commit
e793082008
@ -123,6 +123,7 @@ struct bar_settings {
|
|||||||
|
|
||||||
xcb_window_t window{XCB_NONE};
|
xcb_window_t window{XCB_NONE};
|
||||||
monitor_t monitor{};
|
monitor_t monitor{};
|
||||||
|
bool monitor_exact{true};
|
||||||
edge origin{edge::TOP};
|
edge origin{edge::TOP};
|
||||||
struct size size {
|
struct size size {
|
||||||
1U, 1U
|
1U, 1U
|
||||||
|
@ -37,7 +37,7 @@ struct randr_output {
|
|||||||
xcb_randr_output_t output;
|
xcb_randr_output_t output;
|
||||||
backlight_values backlight;
|
backlight_values backlight;
|
||||||
|
|
||||||
bool match(const string& o, bool strict = false) const;
|
bool match(const string& o, bool exact = true) const;
|
||||||
bool match(const position& p) const;
|
bool match(const position& p) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -50,6 +50,7 @@ namespace randr_util {
|
|||||||
|
|
||||||
monitor_t make_monitor(xcb_randr_output_t randr, string name, unsigned short int w, unsigned short int h, short int x, short int y);
|
monitor_t make_monitor(xcb_randr_output_t randr, string name, unsigned short int w, unsigned short int h, short int x, short int y);
|
||||||
vector<monitor_t> get_monitors(connection& conn, xcb_window_t root, bool connected_only = false, bool realloc = false);
|
vector<monitor_t> get_monitors(connection& conn, xcb_window_t root, bool connected_only = false, bool realloc = false);
|
||||||
|
monitor_t match_monitor(vector<monitor_t> monitors, const string& name, bool exact_match);
|
||||||
|
|
||||||
void get_backlight_range(connection& conn, const monitor_t& mon, backlight_values& dst);
|
void get_backlight_range(connection& conn, const monitor_t& mon, backlight_values& dst);
|
||||||
void get_backlight_value(connection& conn, const monitor_t& mon, backlight_values& dst);
|
void get_backlight_value(connection& conn, const monitor_t& mon, backlight_values& dst);
|
||||||
|
@ -73,6 +73,7 @@ bar::bar(connection& conn, signal_emitter& emitter, const config& config, const
|
|||||||
auto monitor_name = m_conf.get(bs, "monitor", ""s);
|
auto monitor_name = m_conf.get(bs, "monitor", ""s);
|
||||||
auto monitor_name_fallback = m_conf.get(bs, "monitor-fallback", ""s);
|
auto monitor_name_fallback = m_conf.get(bs, "monitor-fallback", ""s);
|
||||||
auto monitor_strictmode = m_conf.get(bs, "monitor-strict", false);
|
auto monitor_strictmode = m_conf.get(bs, "monitor-strict", false);
|
||||||
|
m_opts.monitor_exact = m_conf.get(bs, "monitor-exact", m_opts.monitor_exact);
|
||||||
auto monitors = randr_util::get_monitors(m_connection, m_connection.screen()->root, monitor_strictmode);
|
auto monitors = randr_util::get_monitors(m_connection, m_connection.screen()->root, monitor_strictmode);
|
||||||
|
|
||||||
if (monitors.empty()) {
|
if (monitors.empty()) {
|
||||||
@ -92,26 +93,17 @@ bar::bar(connection& conn, signal_emitter& emitter, const config& config, const
|
|||||||
m_log.warn("No monitor specified, using \"%s\"", monitor_name);
|
m_log.warn("No monitor specified, using \"%s\"", monitor_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool name_found{false};
|
m_opts.monitor = randr_util::match_monitor(monitors, monitor_name, m_opts.monitor_exact);
|
||||||
bool fallback_found{monitor_name_fallback.empty()};
|
|
||||||
monitor_t fallback{};
|
monitor_t fallback{};
|
||||||
|
|
||||||
for (auto&& monitor : monitors) {
|
if(!monitor_name_fallback.empty()) {
|
||||||
if (!name_found && (name_found = monitor->match(monitor_name, monitor_strictmode))) {
|
fallback = randr_util::match_monitor(monitors, monitor_name_fallback, m_opts.monitor_exact);
|
||||||
m_opts.monitor = move(monitor);
|
|
||||||
} else if (!fallback_found && (fallback_found = monitor->match(monitor_name_fallback, monitor_strictmode))) {
|
|
||||||
fallback = move(monitor);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name_found && fallback_found) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_opts.monitor) {
|
if (!m_opts.monitor) {
|
||||||
if (fallback) {
|
if (fallback) {
|
||||||
m_opts.monitor = move(fallback);
|
m_opts.monitor = move(fallback);
|
||||||
m_log.warn("Monitor \"%s\" not found, reverting to fallback \"%s\"", monitor_name, monitor_name_fallback);
|
m_log.warn("Monitor \"%s\" not found, reverting to fallback \"%s\"", monitor_name, m_opts.monitor->name);
|
||||||
} else {
|
} else {
|
||||||
throw application_error("Monitor \"" + monitor_name + "\" not found or disconnected");
|
throw application_error("Monitor \"" + monitor_name + "\" not found or disconnected");
|
||||||
}
|
}
|
||||||
|
@ -21,13 +21,9 @@ namespace modules {
|
|||||||
auto output = m_conf.get(name(), "output", m_bar.monitor->name);
|
auto output = m_conf.get(name(), "output", m_bar.monitor->name);
|
||||||
auto strict = m_conf.get(name(), "monitor-strict", false);
|
auto strict = m_conf.get(name(), "monitor-strict", false);
|
||||||
|
|
||||||
// Grab a list of all outputs and try to find the one defined in the config
|
auto monitors = randr_util::get_monitors(m_connection, m_connection.root(), strict);
|
||||||
for (auto&& mon : randr_util::get_monitors(m_connection, m_connection.root(), strict)) {
|
|
||||||
if (mon->match(output, strict)) {
|
m_output = randr_util::match_monitor(monitors, output, bar.monitor_exact);
|
||||||
m_output.swap(mon);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we didn't get a match we stop the module
|
// If we didn't get a match we stop the module
|
||||||
if (!m_output) {
|
if (!m_output) {
|
||||||
@ -44,7 +40,7 @@ namespace modules {
|
|||||||
randr_util::get_backlight_value(m_connection, m_output, backlight);
|
randr_util::get_backlight_value(m_connection, m_output, backlight);
|
||||||
} catch (const exception& err) {
|
} catch (const exception& err) {
|
||||||
m_log.err("%s: Could not get data (err: %s)", name(), err.what());
|
m_log.err("%s: Could not get data (err: %s)", name(), err.what());
|
||||||
throw module_error("Not supported for \"" + output + "\"");
|
throw module_error("Not supported for \"" + m_output->name + "\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create window that will proxy all RandR notify events
|
// Create window that will proxy all RandR notify events
|
||||||
|
@ -12,15 +12,17 @@
|
|||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Workaround for the inconsistent naming
|
* Workaround for the inconsistent naming of outputs between intel and nvidia
|
||||||
* of outputs between my intel and nvidia
|
|
||||||
* drivers (xf86-video-intel drops the dash)
|
* drivers (xf86-video-intel drops the dash)
|
||||||
|
*
|
||||||
|
* If exact == false, dashes will be ignored while matching
|
||||||
*/
|
*/
|
||||||
bool randr_output::match(const string& o, bool strict) const {
|
bool randr_output::match(const string& o, bool exact) const {
|
||||||
if (strict && name != o) {
|
if (exact) {
|
||||||
return false;
|
return name == o;
|
||||||
|
} else {
|
||||||
|
return string_util::replace(name, "-", "") == string_util::replace(o, "-", "");
|
||||||
}
|
}
|
||||||
return name == o || name == string_util::replace(o, "-", "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -172,6 +174,34 @@ namespace randr_util {
|
|||||||
return monitors;
|
return monitors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches for a monitor with name in monitors
|
||||||
|
*
|
||||||
|
* Does best-fit matching (if exact_match == true, this is also first-fit)
|
||||||
|
*/
|
||||||
|
monitor_t match_monitor(vector<monitor_t> monitors, const string& name, bool exact_match) {
|
||||||
|
monitor_t result{};
|
||||||
|
for(auto&& monitor : monitors) {
|
||||||
|
// If we can do an exact match, we have found our result
|
||||||
|
if(monitor->match(name, true)) {
|
||||||
|
result = move(monitor);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Non-exact matches are moved into the result but we continue searching
|
||||||
|
* through the list, maybe we can find an exact match
|
||||||
|
* Note: If exact_match == true, we don't need to run this because it
|
||||||
|
* would be the exact same check as above
|
||||||
|
*/
|
||||||
|
if(!exact_match && monitor->match(name, false)) {
|
||||||
|
result = move(monitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get backlight value range for given output
|
* Get backlight value range for given output
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user