fix(xrandr): Less strict monitor matching
Be less strict when matching randr outputs against specified name. This is a workaround to fix the output naming issue when switching between graphic drivers. On my system the output names include a dash when using the nvidia drivers but the intel driver does not. nvidia: HDMI-1 eDP-1 xf86-video-intel: HDMI1 eDP1 When strict mode is disabled the matching won't care about the connection state. The user can re-enable exact matching and connection state testing by setting the config parameter `monitor-strict = true`
This commit is contained in:
parent
2314b57bce
commit
4d7f6c14e6
4 changed files with 35 additions and 24 deletions
|
@ -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<randr_output>;
|
||||
|
||||
namespace randr_util {
|
||||
monitor_t make_monitor(xcb_randr_output_t randr, string name, int w, int h, int x, int y);
|
||||
vector<monitor_t> get_monitors(connection& conn, xcb_window_t root);
|
||||
vector<monitor_t> 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);
|
||||
|
|
|
@ -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<bool>(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<string>(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
|
||||
|
|
|
@ -10,10 +10,11 @@ namespace modules {
|
|||
*/
|
||||
void xbacklight_module::setup() {
|
||||
auto output = m_conf.get<string>(name(), "output", m_bar.monitor->name);
|
||||
auto strict = m_conf.get<bool>(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());
|
||||
}
|
||||
|
|
|
@ -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<monitor_t> get_monitors(connection& conn, xcb_window_t root) {
|
||||
vector<monitor_t> get_monitors(connection& conn, xcb_window_t root, bool connected_only) {
|
||||
vector<monitor_t> 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<uint32_t*>(xcb_randr_get_output_property_data(reply.get().get()));
|
||||
|
|
Loading…
Reference in a new issue