mirror of
https://github.com/polybar/polybar.git
synced 2025-02-17 15:55:20 -05:00
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 {
|
struct randr_output {
|
||||||
xcb_randr_output_t randr_output;
|
|
||||||
string name;
|
string name;
|
||||||
int w = 0;
|
int w = 0;
|
||||||
int h = 0;
|
int h = 0;
|
||||||
int x = 0;
|
int x = 0;
|
||||||
int y = 0;
|
int y = 0;
|
||||||
|
xcb_randr_output_t output;
|
||||||
backlight_values backlight;
|
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>;
|
using monitor_t = shared_ptr<randr_output>;
|
||||||
|
|
||||||
namespace randr_util {
|
namespace randr_util {
|
||||||
monitor_t make_monitor(xcb_randr_output_t randr, string name, int w, int h, int x, int y);
|
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_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);
|
||||||
|
|
|
@ -532,19 +532,22 @@ void bar::configure_geom() { // {{{
|
||||||
void bar::create_monitor() { // {{{
|
void bar::create_monitor() { // {{{
|
||||||
m_log.trace("bar: Create monitor from matching X RandR output");
|
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()) {
|
if (monitors.empty()) {
|
||||||
throw application_error("No monitors found");
|
throw application_error("No monitors found");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto name = m_conf.get<string>(m_conf.bar_section(), "monitor", "");
|
auto name = m_conf.get<string>(m_conf.bar_section(), "monitor", "");
|
||||||
|
|
||||||
if (name.empty()) {
|
if (name.empty()) {
|
||||||
name = monitors[0]->name;
|
name = monitors[0]->name;
|
||||||
m_log.warn("No monitor specified, using \"%s\"", name);
|
m_log.warn("No monitor specified, using \"%s\"", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto&& monitor : monitors) {
|
for (auto&& monitor : monitors) {
|
||||||
if (name == monitor->name) {
|
if (monitor->match(name, strict)) {
|
||||||
m_opts.monitor = move(monitor);
|
m_opts.monitor = move(monitor);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -841,18 +844,14 @@ void bar::handle(const evt::expose& evt) { // {{{
|
||||||
/**
|
/**
|
||||||
* Event handler for XCB_PROPERTY_NOTIFY events
|
* Event handler for XCB_PROPERTY_NOTIFY events
|
||||||
*
|
*
|
||||||
* Used to emit events whenever the bar window's
|
* - Emit events whenever the bar window's
|
||||||
* visibility gets changes. This allows us to toggle the
|
* visibility gets changed. This allows us to toggle the
|
||||||
* state of the tray container even though the tray
|
* 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.
|
* - Track the root pixmap atom to update the
|
||||||
*
|
* pseudo-transparent background when it changes
|
||||||
* 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
|
|
||||||
*/
|
*/
|
||||||
void bar::handle(const evt::property_notify& evt) { // {{{
|
void bar::handle(const evt::property_notify& evt) { // {{{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
|
@ -10,10 +10,11 @@ namespace modules {
|
||||||
*/
|
*/
|
||||||
void xbacklight_module::setup() {
|
void xbacklight_module::setup() {
|
||||||
auto output = m_conf.get<string>(name(), "output", m_bar.monitor->name);
|
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
|
// 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())) {
|
for (auto&& mon : randr_util::get_monitors(m_connection, m_connection.root(), strict)) {
|
||||||
if (mon->name == output) {
|
if (mon->match(output, strict)) {
|
||||||
m_output.swap(mon);
|
m_output.swap(mon);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -70,7 +71,7 @@ namespace modules {
|
||||||
return;
|
return;
|
||||||
else if (evt->u.op.window != m_proxy)
|
else if (evt->u.op.window != m_proxy)
|
||||||
return;
|
return;
|
||||||
else if (evt->u.op.output != m_output->randr_output)
|
else if (evt->u.op.output != m_output->output)
|
||||||
return;
|
return;
|
||||||
else if (evt->u.op.atom != m_output->backlight.atom)
|
else if (evt->u.op.atom != m_output->backlight.atom)
|
||||||
return;
|
return;
|
||||||
|
@ -164,7 +165,7 @@ namespace modules {
|
||||||
const int values[1]{new_value};
|
const int values[1]{new_value};
|
||||||
|
|
||||||
m_connection.change_output_property_checked(
|
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) {
|
} catch (const exception& err) {
|
||||||
m_log.err("%s: %s", name(), err.what());
|
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 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{}};
|
monitor_t mon{new monitor_t::element_type{}};
|
||||||
mon->randr_output = randr;
|
mon->output = randr;
|
||||||
mon->name = name;
|
mon->name = name;
|
||||||
mon->x = x;
|
mon->x = x;
|
||||||
mon->y = y;
|
mon->y = y;
|
||||||
|
@ -20,14 +20,14 @@ namespace randr_util {
|
||||||
/**
|
/**
|
||||||
* Create a list of all available randr outputs
|
* 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;
|
vector<monitor_t> monitors;
|
||||||
auto outputs = conn.get_screen_resources(root).outputs();
|
auto outputs = conn.get_screen_resources(root).outputs();
|
||||||
|
|
||||||
for (auto it = outputs.begin(); it != outputs.end(); it++) {
|
for (auto it = outputs.begin(); it != outputs.end(); it++) {
|
||||||
try {
|
try {
|
||||||
auto info = conn.get_output_info(*it);
|
auto info = conn.get_output_info(*it);
|
||||||
if (info->connection != XCB_RANDR_CONNECTION_CONNECTED)
|
if (connected_only && info->connection != XCB_RANDR_CONNECTION_CONNECTED)
|
||||||
continue;
|
continue;
|
||||||
auto crtc = conn.get_crtc_info(info->crtc);
|
auto crtc = conn.get_crtc_info(info->crtc);
|
||||||
string name{info.name().begin(), info.name().end()};
|
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) {
|
void get_backlight_range(connection& conn, const monitor_t& mon, backlight_values& dst) {
|
||||||
auto atom = Backlight;
|
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.min = 0;
|
||||||
dst.max = 0;
|
dst.max = 0;
|
||||||
|
|
||||||
if (!reply->range || reply->length != 2) {
|
if (!reply->range || reply->length != 2) {
|
||||||
atom = BACKLIGHT;
|
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) {
|
if (!reply->range || reply->length != 2) {
|
||||||
|
@ -84,7 +84,7 @@ namespace randr_util {
|
||||||
return;
|
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)
|
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()));
|
dst.val = *reinterpret_cast<uint32_t*>(xcb_randr_get_output_property_data(reply.get().get()));
|
||||||
|
|
Loading…
Add table
Reference in a new issue