diff --git a/include/x11/randr.hpp b/include/x11/randr.hpp index 349f30f7..d5610ed7 100644 --- a/include/x11/randr.hpp +++ b/include/x11/randr.hpp @@ -20,20 +20,31 @@ struct backlight_values { }; struct randr_output { - xcb_randr_output_t randr_output; string name; int w = 0; int h = 0; int x = 0; int y = 0; + xcb_randr_output_t output; backlight_values backlight; + + /** + * Workaround for the inconsistent naming + * of outputs between my intel and nvidia + * drivers (xf86-video-intel drops the dash) + */ + bool match(const string& o, bool strict = false) const { + if (strict && name != o) + return false; + return name == o || name == string_util::replace(o, "-", ""); + } }; using monitor_t = shared_ptr; namespace randr_util { monitor_t make_monitor(xcb_randr_output_t randr, string name, int w, int h, int x, int y); - vector get_monitors(connection& conn, xcb_window_t root); + vector get_monitors(connection& conn, xcb_window_t root, bool connected_only = false); 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 6ca8fb0d..6898e17e 100644 --- a/src/components/bar.cpp +++ b/src/components/bar.cpp @@ -532,19 +532,22 @@ void bar::configure_geom() { // {{{ void bar::create_monitor() { // {{{ m_log.trace("bar: Create monitor from matching X RandR output"); - auto monitors = randr_util::get_monitors(m_connection, m_screen->root); + auto strict = m_conf.get(m_conf.bar_section(), "monitor-strict", false); + auto monitors = randr_util::get_monitors(m_connection, m_screen->root, strict); + if (monitors.empty()) { throw application_error("No monitors found"); } auto name = m_conf.get(m_conf.bar_section(), "monitor", ""); + if (name.empty()) { name = monitors[0]->name; m_log.warn("No monitor specified, using \"%s\"", name); } for (auto&& monitor : monitors) { - if (name == monitor->name) { + if (monitor->match(name, strict)) { m_opts.monitor = move(monitor); break; } @@ -841,18 +844,14 @@ void bar::handle(const evt::expose& evt) { // {{{ /** * Event handler for XCB_PROPERTY_NOTIFY events * - * Used to emit events whenever the bar window's - * visibility gets changes. This allows us to toggle the + * - Emit events whenever the bar window's + * visibility gets changed. This allows us to toggle the * state of the tray container even though the tray - * window restacking failed. + * window restacking failed. Used as a fallback for + * tedious WM's, like i3. * - * This is used as a fallback for tedious WM's, like i3. - * - * Some might call it a dirty hack, others a crappy - * solution... I choose to call it a masterpiece! Plus - * it's not really any overhead worth talking about. - * - * Also tracks the root pixmap + * - Track the root pixmap atom to update the + * pseudo-transparent background when it changes */ void bar::handle(const evt::property_notify& evt) { // {{{ #ifdef DEBUG diff --git a/src/modules/xbacklight.cpp b/src/modules/xbacklight.cpp index 61eb7697..42bf2e23 100644 --- a/src/modules/xbacklight.cpp +++ b/src/modules/xbacklight.cpp @@ -10,10 +10,11 @@ namespace modules { */ void xbacklight_module::setup() { 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())) { - if (mon->name == output) { + for (auto&& mon : randr_util::get_monitors(m_connection, m_connection.root(), strict)) { + if (mon->match(output, strict)) { m_output.swap(mon); break; } @@ -70,7 +71,7 @@ namespace modules { return; else if (evt->u.op.window != m_proxy) return; - else if (evt->u.op.output != m_output->randr_output) + else if (evt->u.op.output != m_output->output) return; else if (evt->u.op.atom != m_output->backlight.atom) return; @@ -164,7 +165,7 @@ namespace modules { const int values[1]{new_value}; m_connection.change_output_property_checked( - m_output->randr_output, m_output->backlight.atom, XCB_ATOM_INTEGER, 32, XCB_PROP_MODE_REPLACE, 1, values); + m_output->output, m_output->backlight.atom, XCB_ATOM_INTEGER, 32, XCB_PROP_MODE_REPLACE, 1, values); } catch (const exception& err) { m_log.err("%s: %s", name(), err.what()); } diff --git a/src/x11/randr.cpp b/src/x11/randr.cpp index 08cb3d0c..f91e7a85 100644 --- a/src/x11/randr.cpp +++ b/src/x11/randr.cpp @@ -8,7 +8,7 @@ namespace randr_util { */ monitor_t make_monitor(xcb_randr_output_t randr, string name, int w, int h, int x, int y) { monitor_t mon{new monitor_t::element_type{}}; - mon->randr_output = randr; + mon->output = randr; mon->name = name; mon->x = x; mon->y = y; @@ -20,14 +20,14 @@ namespace randr_util { /** * Create a list of all available randr outputs */ - vector get_monitors(connection& conn, xcb_window_t root) { + vector get_monitors(connection& conn, xcb_window_t root, bool connected_only) { vector monitors; auto outputs = conn.get_screen_resources(root).outputs(); for (auto it = outputs.begin(); it != outputs.end(); it++) { try { auto info = conn.get_output_info(*it); - if (info->connection != XCB_RANDR_CONNECTION_CONNECTED) + if (connected_only && info->connection != XCB_RANDR_CONNECTION_CONNECTED) continue; auto crtc = conn.get_crtc_info(info->crtc); string name{info.name().begin(), info.name().end()}; @@ -54,14 +54,14 @@ namespace randr_util { */ void get_backlight_range(connection& conn, const monitor_t& mon, backlight_values& dst) { auto atom = Backlight; - auto reply = conn.query_output_property(mon->randr_output, atom); + auto reply = conn.query_output_property(mon->output, atom); dst.min = 0; dst.max = 0; if (!reply->range || reply->length != 2) { atom = BACKLIGHT; - reply = conn.query_output_property(mon->randr_output, atom); + reply = conn.query_output_property(mon->output, atom); } if (!reply->range || reply->length != 2) { @@ -84,7 +84,7 @@ namespace randr_util { return; } - auto reply = conn.get_output_property(mon->randr_output, dst.atom, XCB_ATOM_NONE, 0, 4, 0, 0); + auto reply = conn.get_output_property(mon->output, dst.atom, XCB_ATOM_NONE, 0, 4, 0, 0); if (reply->num_items == 1 && reply->format == 32 && reply->type == XCB_ATOM_INTEGER) dst.val = *reinterpret_cast(xcb_randr_get_output_property_data(reply.get().get()));