From e7930820086374403077bdbc1b089e795f4283d9 Mon Sep 17 00:00:00 2001 From: patrick96 Date: Mon, 3 Dec 2018 01:21:20 +0100 Subject: [PATCH] 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 --- include/components/types.hpp | 1 + include/x11/extensions/randr.hpp | 3 ++- src/components/bar.cpp | 18 ++++---------- src/modules/xbacklight.cpp | 12 +++------ src/x11/extensions/randr.cpp | 42 +++++++++++++++++++++++++++----- 5 files changed, 48 insertions(+), 28 deletions(-) diff --git a/include/components/types.hpp b/include/components/types.hpp index 1a1299ed..b24e58d0 100644 --- a/include/components/types.hpp +++ b/include/components/types.hpp @@ -123,6 +123,7 @@ struct bar_settings { xcb_window_t window{XCB_NONE}; monitor_t monitor{}; + bool monitor_exact{true}; edge origin{edge::TOP}; struct size size { 1U, 1U diff --git a/include/x11/extensions/randr.hpp b/include/x11/extensions/randr.hpp index 8c9ea967..515a059e 100644 --- a/include/x11/extensions/randr.hpp +++ b/include/x11/extensions/randr.hpp @@ -37,7 +37,7 @@ struct randr_output { xcb_randr_output_t output; 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; }; @@ -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); vector get_monitors(connection& conn, xcb_window_t root, bool connected_only = false, bool realloc = false); + monitor_t match_monitor(vector monitors, const string& name, bool exact_match); 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); diff --git a/src/components/bar.cpp b/src/components/bar.cpp index d9bb3087..1bdb7640 100644 --- a/src/components/bar.cpp +++ b/src/components/bar.cpp @@ -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_fallback = m_conf.get(bs, "monitor-fallback", ""s); 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); 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); } - bool name_found{false}; - bool fallback_found{monitor_name_fallback.empty()}; + m_opts.monitor = randr_util::match_monitor(monitors, monitor_name, m_opts.monitor_exact); monitor_t fallback{}; - for (auto&& monitor : monitors) { - if (!name_found && (name_found = monitor->match(monitor_name, monitor_strictmode))) { - 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(!monitor_name_fallback.empty()) { + fallback = randr_util::match_monitor(monitors, monitor_name_fallback, m_opts.monitor_exact); } if (!m_opts.monitor) { if (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 { throw application_error("Monitor \"" + monitor_name + "\" not found or disconnected"); } diff --git a/src/modules/xbacklight.cpp b/src/modules/xbacklight.cpp index 5debbe45..0364dfc1 100644 --- a/src/modules/xbacklight.cpp +++ b/src/modules/xbacklight.cpp @@ -21,13 +21,9 @@ namespace modules { auto output = m_conf.get(name(), "output", m_bar.monitor->name); 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 - for (auto&& mon : randr_util::get_monitors(m_connection, m_connection.root(), strict)) { - if (mon->match(output, strict)) { - m_output.swap(mon); - break; - } - } + auto monitors = randr_util::get_monitors(m_connection, m_connection.root(), strict); + + m_output = randr_util::match_monitor(monitors, output, bar.monitor_exact); // If we didn't get a match we stop the module if (!m_output) { @@ -44,7 +40,7 @@ namespace modules { randr_util::get_backlight_value(m_connection, m_output, backlight); } catch (const exception& err) { 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 diff --git a/src/x11/extensions/randr.cpp b/src/x11/extensions/randr.cpp index dab74473..bd11806d 100644 --- a/src/x11/extensions/randr.cpp +++ b/src/x11/extensions/randr.cpp @@ -12,15 +12,17 @@ POLYBAR_NS /** - * Workaround for the inconsistent naming - * of outputs between my intel and nvidia + * Workaround for the inconsistent naming of outputs between intel and nvidia * 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 { - if (strict && name != o) { - return false; +bool randr_output::match(const string& o, bool exact) const { + if (exact) { + 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; } + /** + * 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 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 */