wip(xworkspaces): Monitor support
This commit is contained in:
parent
6fe411ea9e
commit
3413c4a463
@ -3,6 +3,7 @@
|
|||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
|
||||||
#include "components/config.hpp"
|
#include "components/config.hpp"
|
||||||
|
#include "components/types.hpp"
|
||||||
#include "modules/meta/static_module.hpp"
|
#include "modules/meta/static_module.hpp"
|
||||||
#include "x11/events.hpp"
|
#include "x11/events.hpp"
|
||||||
#include "x11/ewmh.hpp"
|
#include "x11/ewmh.hpp"
|
||||||
@ -22,10 +23,17 @@ namespace modules {
|
|||||||
OCCUPIED,
|
OCCUPIED,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct desktop {
|
enum class viewport_state {
|
||||||
explicit desktop(string&& name, desktop_state state) : name(name), state(state) {}
|
NONE,
|
||||||
|
FOCUSED,
|
||||||
|
UNFOCUSED,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct viewport {
|
||||||
|
position pos;
|
||||||
string name;
|
string name;
|
||||||
desktop_state state{desktop_state::NONE};
|
vector<pair<desktop_state, label_t>> desktops;
|
||||||
|
viewport_state state;
|
||||||
label_t label;
|
label_t label;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -37,6 +45,7 @@ namespace modules {
|
|||||||
xworkspaces_module(const bar_settings& bar, const logger& logger, const config& config, string name);
|
xworkspaces_module(const bar_settings& bar, const logger& logger, const config& config, string name);
|
||||||
|
|
||||||
void setup();
|
void setup();
|
||||||
|
void start();
|
||||||
void teardown();
|
void teardown();
|
||||||
void handle(const evt::property_notify& evt);
|
void handle(const evt::property_notify& evt);
|
||||||
void update();
|
void update();
|
||||||
@ -49,18 +58,22 @@ namespace modules {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr const char* DEFAULT_ICON{"icon-default"};
|
static constexpr const char* DEFAULT_ICON{"icon-default"};
|
||||||
static constexpr const char* DEFAULT_LABEL{"%icon% %name%"};
|
static constexpr const char* DEFAULT_LABEL_STATE{"%icon% %name%"};
|
||||||
|
static constexpr const char* DEFAULT_LABEL_MONITOR{"%name%"};
|
||||||
|
|
||||||
static constexpr const char* TAG_LABEL{"<label>"};
|
static constexpr const char* TAG_LABEL_MONITOR{"<label-monitor>"};
|
||||||
|
static constexpr const char* TAG_LABEL_STATE{"<label-state>"};
|
||||||
|
|
||||||
connection& m_connection;
|
connection& m_connection;
|
||||||
ewmh_connection_t m_ewmh;
|
ewmh_connection_t m_ewmh;
|
||||||
event_timer m_throttle{0, 0};
|
vector<monitor_t> m_monitors;
|
||||||
|
bool m_monitorsupport{true};
|
||||||
|
|
||||||
vector<unique_ptr<desktop>> m_desktops;
|
vector<unique_ptr<viewport>> m_viewports;
|
||||||
map<desktop_state, label_t> m_labels;
|
map<desktop_state, label_t> m_labels;
|
||||||
|
label_t m_monitorlabel;
|
||||||
iconset_t m_icons;
|
iconset_t m_icons;
|
||||||
|
bool m_pinworkspaces{false};
|
||||||
size_t m_index{0};
|
size_t m_index{0};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
|
struct position;
|
||||||
|
|
||||||
using ewmh_connection_t = memory_util::malloc_ptr_t<xcb_ewmh_connection_t>;
|
using ewmh_connection_t = memory_util::malloc_ptr_t<xcb_ewmh_connection_t>;
|
||||||
|
|
||||||
namespace ewmh_util {
|
namespace ewmh_util {
|
||||||
@ -21,6 +23,7 @@ namespace ewmh_util {
|
|||||||
string get_icon_name(xcb_ewmh_connection_t* conn, xcb_window_t win);
|
string get_icon_name(xcb_ewmh_connection_t* conn, xcb_window_t win);
|
||||||
string get_reply_string(xcb_ewmh_get_utf8_strings_reply_t* reply);
|
string get_reply_string(xcb_ewmh_get_utf8_strings_reply_t* reply);
|
||||||
|
|
||||||
|
vector<position> get_desktop_viewports(xcb_ewmh_connection_t* conn, int screen = 0);
|
||||||
vector<string> get_desktop_names(xcb_ewmh_connection_t* conn, int screen = 0);
|
vector<string> get_desktop_names(xcb_ewmh_connection_t* conn, int screen = 0);
|
||||||
uint32_t get_current_desktop(xcb_ewmh_connection_t* conn, int screen = 0);
|
uint32_t get_current_desktop(xcb_ewmh_connection_t* conn, int screen = 0);
|
||||||
xcb_window_t get_active_window(xcb_ewmh_connection_t* conn, int screen = 0);
|
xcb_window_t get_active_window(xcb_ewmh_connection_t* conn, int screen = 0);
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
class connection;
|
class connection;
|
||||||
|
struct position;
|
||||||
|
|
||||||
namespace evt {
|
namespace evt {
|
||||||
using randr_notify = xpp::randr::event::notify<connection&>;
|
using randr_notify = xpp::randr::event::notify<connection&>;
|
||||||
@ -37,6 +38,7 @@ struct randr_output {
|
|||||||
backlight_values backlight;
|
backlight_values backlight;
|
||||||
|
|
||||||
bool match(const string& o, bool strict = false) const;
|
bool match(const string& o, bool strict = false) const;
|
||||||
|
bool match(const position& p) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
using monitor_t = shared_ptr<randr_output>;
|
using monitor_t = shared_ptr<randr_output>;
|
||||||
|
@ -345,6 +345,7 @@ namespace modules {
|
|||||||
builder->node(ws.second);
|
builder->node(ws.second);
|
||||||
builder->cmd_close();
|
builder->cmd_close();
|
||||||
} else {
|
} else {
|
||||||
|
workspace_n++;
|
||||||
builder->node(ws.second);
|
builder->node(ws.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include "modules/xworkspaces.hpp"
|
#include <utility>
|
||||||
|
|
||||||
#include "drawtypes/iconset.hpp"
|
#include "drawtypes/iconset.hpp"
|
||||||
#include "drawtypes/label.hpp"
|
#include "drawtypes/label.hpp"
|
||||||
|
#include "modules/xworkspaces.hpp"
|
||||||
#include "x11/atoms.hpp"
|
#include "x11/atoms.hpp"
|
||||||
#include "x11/connection.hpp"
|
#include "x11/connection.hpp"
|
||||||
|
|
||||||
@ -25,7 +27,8 @@ namespace modules {
|
|||||||
* Bootstrap the module
|
* Bootstrap the module
|
||||||
*/
|
*/
|
||||||
void xworkspaces_module::setup() {
|
void xworkspaces_module::setup() {
|
||||||
connection& conn{configure_connection().create<decltype(conn)>()};
|
// Load config values
|
||||||
|
m_pinworkspaces = m_conf.get<bool>(name(), "pin-workspaces", m_pinworkspaces);
|
||||||
|
|
||||||
// Initialize ewmh atoms
|
// Initialize ewmh atoms
|
||||||
if ((m_ewmh = ewmh_util::initialize()) == nullptr) {
|
if ((m_ewmh = ewmh_util::initialize()) == nullptr) {
|
||||||
@ -33,22 +36,36 @@ namespace modules {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if the WM supports _NET_CURRENT_DESKTOP
|
// Check if the WM supports _NET_CURRENT_DESKTOP
|
||||||
if (!ewmh_util::supports(m_ewmh.get(), _NET_CURRENT_DESKTOP)) {
|
if (!ewmh_util::supports(m_ewmh.get(), m_ewmh->_NET_CURRENT_DESKTOP)) {
|
||||||
throw module_error("The WM does not list _NET_CURRENT_DESKTOP as a supported hint");
|
throw module_error("The WM does not support _NET_CURRENT_DESKTOP, aborting...");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add formats and elements
|
// Check if the WM supports _NET_DESKTOP_VIEWPORT
|
||||||
m_formatter->add(DEFAULT_FORMAT, TAG_LABEL, {TAG_LABEL});
|
if (!ewmh_util::supports(m_ewmh.get(), m_ewmh->_NET_DESKTOP_VIEWPORT) && m_pinworkspaces) {
|
||||||
|
throw module_error("The WM does not support _NET_DESKTOP_VIEWPORT (required when `pin-workspaces = true`)");
|
||||||
|
} else if (!m_pinworkspaces) {
|
||||||
|
m_monitorsupport = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_formatter->has(TAG_LABEL)) {
|
// Get list of monitors
|
||||||
|
m_monitors = randr_util::get_monitors(m_connection, m_connection.root(), false);
|
||||||
|
|
||||||
|
// Add formats and elements
|
||||||
|
m_formatter->add(DEFAULT_FORMAT, TAG_LABEL_STATE, {TAG_LABEL_STATE, TAG_LABEL_MONITOR});
|
||||||
|
|
||||||
|
if (m_formatter->has(TAG_LABEL_MONITOR)) {
|
||||||
|
m_monitorlabel = load_optional_label(m_conf, name(), "label-monitor", DEFAULT_LABEL_MONITOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_formatter->has(TAG_LABEL_STATE)) {
|
||||||
m_labels.insert(
|
m_labels.insert(
|
||||||
make_pair(desktop_state::ACTIVE, load_optional_label(m_conf, name(), "label-active", DEFAULT_LABEL)));
|
make_pair(desktop_state::ACTIVE, load_optional_label(m_conf, name(), "label-active", DEFAULT_LABEL_STATE)));
|
||||||
|
m_labels.insert(make_pair(
|
||||||
|
desktop_state::OCCUPIED, load_optional_label(m_conf, name(), "label-occupied", DEFAULT_LABEL_STATE)));
|
||||||
m_labels.insert(
|
m_labels.insert(
|
||||||
make_pair(desktop_state::OCCUPIED, load_optional_label(m_conf, name(), "label-occupied", DEFAULT_LABEL)));
|
make_pair(desktop_state::URGENT, load_optional_label(m_conf, name(), "label-urgent", DEFAULT_LABEL_STATE)));
|
||||||
m_labels.insert(
|
m_labels.insert(
|
||||||
make_pair(desktop_state::URGENT, load_optional_label(m_conf, name(), "label-urgent", DEFAULT_LABEL)));
|
make_pair(desktop_state::EMPTY, load_optional_label(m_conf, name(), "label-empty", DEFAULT_LABEL_STATE)));
|
||||||
m_labels.insert(
|
|
||||||
make_pair(desktop_state::EMPTY, load_optional_label(m_conf, name(), "label-empty", DEFAULT_LABEL)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_icons = make_shared<iconset>();
|
m_icons = make_shared<iconset>();
|
||||||
@ -62,85 +79,103 @@ namespace modules {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we get notified when root properties change
|
// Make sure we get notified when root properties change
|
||||||
window{conn, conn.root()}.ensure_event_mask(XCB_EVENT_MASK_PROPERTY_CHANGE);
|
window{m_connection, m_connection.root()}.ensure_event_mask(XCB_EVENT_MASK_PROPERTY_CHANGE);
|
||||||
|
|
||||||
// Connect with the event registry
|
|
||||||
conn.attach_sink(this, 1);
|
|
||||||
|
|
||||||
// Get desktops
|
|
||||||
rebuild_desktops();
|
|
||||||
set_current_desktop();
|
|
||||||
|
|
||||||
// Trigger the initial draw event
|
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void xworkspaces_module::start() {
|
||||||
|
// Connect with the event registry
|
||||||
|
m_connection.attach_sink(this, 3);
|
||||||
|
static_module::start();
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Disconnect from the event registry
|
* Disconnect from the event registry
|
||||||
*/
|
*/
|
||||||
void xworkspaces_module::teardown() {
|
void xworkspaces_module::teardown() {
|
||||||
connection& conn{configure_connection().create<decltype(conn)>()};
|
m_connection.detach_sink(this, 3);
|
||||||
conn.detach_sink(this, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for XCB_PROPERTY_NOTIFY events
|
* Handler for XCB_PROPERTY_NOTIFY events
|
||||||
*/
|
*/
|
||||||
void xworkspaces_module::handle(const evt::property_notify& evt) {
|
void xworkspaces_module::handle(const evt::property_notify& evt) {
|
||||||
if (evt->atom == m_ewmh->_NET_DESKTOP_NAMES && !m_throttle.throttle(evt->time)) {
|
if (evt->atom == m_ewmh->_NET_DESKTOP_NAMES) {
|
||||||
rebuild_desktops();
|
update();
|
||||||
} else if (evt->atom == m_ewmh->_NET_CURRENT_DESKTOP && !m_throttle.throttle(evt->time)) {
|
} else if (evt->atom == m_ewmh->_NET_CURRENT_DESKTOP) {
|
||||||
set_current_desktop();
|
update();
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
update();
|
|
||||||
|
|
||||||
// m_log.err("%lu %s", evt->time, m_connection.get_atom_name(evt->atom).name());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the currently active window and query its title
|
|
||||||
*/
|
|
||||||
void xworkspaces_module::update() {
|
|
||||||
size_t desktop_index{0};
|
|
||||||
|
|
||||||
for (const auto& desktop : m_desktops) {
|
|
||||||
switch (desktop->state) {
|
|
||||||
case desktop_state::ACTIVE:
|
|
||||||
desktop->label = m_labels[desktop_state::ACTIVE]->clone();
|
|
||||||
break;
|
|
||||||
case desktop_state::EMPTY:
|
|
||||||
desktop->label = m_labels[desktop_state::EMPTY]->clone();
|
|
||||||
break;
|
|
||||||
case desktop_state::URGENT:
|
|
||||||
desktop->label = m_labels[desktop_state::URGENT]->clone();
|
|
||||||
break;
|
|
||||||
case desktop_state::OCCUPIED:
|
|
||||||
desktop->label = m_labels[desktop_state::URGENT]->clone();
|
|
||||||
break;
|
|
||||||
case desktop_state::NONE:
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
desktop->label->reset_tokens();
|
|
||||||
desktop->label->replace_token("%name%", desktop->name);
|
|
||||||
desktop->label->replace_token("%icon%", m_icons->get(desktop->name, DEFAULT_ICON)->get());
|
|
||||||
desktop->label->replace_token("%index%", to_string(++desktop_index));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emit notification to trigger redraw
|
// Emit notification to trigger redraw
|
||||||
broadcast();
|
broadcast();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch and parse data
|
||||||
|
*/
|
||||||
|
void xworkspaces_module::update() {
|
||||||
|
auto current = ewmh_util::get_current_desktop(m_ewmh.get());
|
||||||
|
auto names = ewmh_util::get_desktop_names(m_ewmh.get());
|
||||||
|
vector<position> viewports;
|
||||||
|
size_t num{0};
|
||||||
|
position pos;
|
||||||
|
|
||||||
|
if (m_monitorsupport) {
|
||||||
|
viewports = ewmh_util::get_desktop_viewports(m_ewmh.get());
|
||||||
|
num = std::min(names.size(), viewports.size());
|
||||||
|
} else {
|
||||||
|
num = names.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_viewports.clear();
|
||||||
|
|
||||||
|
for (size_t n = 0; n < num; n++) {
|
||||||
|
if (m_pinworkspaces && !m_bar.monitor->match(viewports[n])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_monitorsupport && (n == 0 || pos.x != viewports[n].x || pos.y != viewports[n].y)) {
|
||||||
|
m_viewports.emplace_back(make_unique<viewport>());
|
||||||
|
|
||||||
|
for (auto&& monitor : m_monitors) {
|
||||||
|
if (monitor->match(viewports[n])) {
|
||||||
|
m_viewports.back()->name = monitor->name;
|
||||||
|
m_viewports.back()->pos.x = static_cast<int16_t>(monitor->x);
|
||||||
|
m_viewports.back()->pos.y = static_cast<int16_t>(monitor->y);
|
||||||
|
m_viewports.back()->state = viewport_state::FOCUSED;
|
||||||
|
m_viewports.back()->label = m_monitorlabel->clone();
|
||||||
|
m_viewports.back()->label->replace_token("%name%", monitor->name);
|
||||||
|
pos = m_viewports.back()->pos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!m_monitorsupport && n == 0) {
|
||||||
|
m_viewports.emplace_back(make_unique<viewport>());
|
||||||
|
m_viewports.back()->state = viewport_state::NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current == n) {
|
||||||
|
m_viewports.back()->desktops.emplace_back(make_pair(desktop_state::ACTIVE, m_labels[desktop_state::ACTIVE]->clone()));
|
||||||
|
} else {
|
||||||
|
m_viewports.back()->desktops.emplace_back(make_pair(desktop_state::EMPTY, m_labels[desktop_state::EMPTY]->clone()));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& desktop = m_viewports.back()->desktops.back();
|
||||||
|
desktop.second->reset_tokens();
|
||||||
|
desktop.second->replace_token("%name%", names[n]);
|
||||||
|
desktop.second->replace_token("%icon%", m_icons->get(names[n], DEFAULT_ICON)->get());
|
||||||
|
desktop.second->replace_token("%index%", to_string(n));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate module output
|
* Generate module output
|
||||||
*/
|
*/
|
||||||
string xworkspaces_module::get_output() {
|
string xworkspaces_module::get_output() {
|
||||||
string output;
|
string output;
|
||||||
for (m_index = 0; m_index < m_desktops.size(); m_index++) {
|
for (m_index = 0; m_index < m_viewports.size(); m_index++) {
|
||||||
if (m_index > 0) {
|
if (m_index > 0) {
|
||||||
m_builder->space(m_formatter->get(DEFAULT_FORMAT)->spacing);
|
m_builder->space(m_formatter->get(DEFAULT_FORMAT)->spacing);
|
||||||
}
|
}
|
||||||
@ -153,38 +188,21 @@ namespace modules {
|
|||||||
* Output content as defined in the config
|
* Output content as defined in the config
|
||||||
*/
|
*/
|
||||||
bool xworkspaces_module::build(builder* builder, const string& tag) const {
|
bool xworkspaces_module::build(builder* builder, const string& tag) const {
|
||||||
if (tag == TAG_LABEL && m_desktops[m_index]->state != desktop_state::NONE) {
|
if (tag == TAG_LABEL_MONITOR && m_viewports[m_index]->state != viewport_state::NONE) {
|
||||||
builder->node(m_desktops[m_index]->label);
|
builder->node(m_viewports[m_index]->label);
|
||||||
} else {
|
return true;
|
||||||
return false;
|
} else if (tag == TAG_LABEL_STATE) {
|
||||||
}
|
size_t num{0};
|
||||||
return true;
|
for (auto&& d : m_viewports[m_index]->desktops) {
|
||||||
}
|
if (d.second.get()) {
|
||||||
|
num++;
|
||||||
/**
|
builder->node(d.second);
|
||||||
* Rebuild the list of desktops
|
}
|
||||||
*/
|
}
|
||||||
void xworkspaces_module::rebuild_desktops() {
|
return num > 0;
|
||||||
m_desktops.clear();
|
|
||||||
|
|
||||||
for (auto&& name : ewmh_util::get_desktop_names(m_ewmh.get())) {
|
|
||||||
m_desktops.emplace_back(make_unique<desktop>(move(name), desktop_state::EMPTY));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flag the desktop that is currently active
|
|
||||||
*/
|
|
||||||
void xworkspaces_module::set_current_desktop() {
|
|
||||||
auto current = ewmh_util::get_current_desktop(m_ewmh.get());
|
|
||||||
|
|
||||||
for (auto&& desktop : m_desktops) {
|
|
||||||
desktop->state = desktop_state::EMPTY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_desktops.size() > current) {
|
return false;
|
||||||
m_desktops[current]->state = desktop_state::ACTIVE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include "components/types.hpp"
|
||||||
#include "x11/ewmh.hpp"
|
#include "x11/ewmh.hpp"
|
||||||
#include "x11/xutils.hpp"
|
#include "x11/xutils.hpp"
|
||||||
|
|
||||||
@ -81,6 +82,19 @@ namespace ewmh_util {
|
|||||||
return XCB_NONE;
|
return XCB_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vector<position> get_desktop_viewports(xcb_ewmh_connection_t* conn, int screen) {
|
||||||
|
xcb_ewmh_get_desktop_viewport_reply_t reply;
|
||||||
|
xcb_ewmh_get_desktop_viewport_reply(conn, xcb_ewmh_get_desktop_viewport(conn, screen), &reply, nullptr);
|
||||||
|
|
||||||
|
vector<position> viewports;
|
||||||
|
|
||||||
|
for (size_t n = 0; n < reply.desktop_viewport_len; n++) {
|
||||||
|
viewports.emplace_back(position{static_cast<int16_t>(reply.desktop_viewport[n].x), static_cast<int16_t>(reply.desktop_viewport[n].y)});
|
||||||
|
}
|
||||||
|
|
||||||
|
return viewports;
|
||||||
|
}
|
||||||
|
|
||||||
vector<string> get_desktop_names(xcb_ewmh_connection_t* conn, int screen) {
|
vector<string> get_desktop_names(xcb_ewmh_connection_t* conn, int screen) {
|
||||||
xcb_ewmh_get_utf8_strings_reply_t reply;
|
xcb_ewmh_get_utf8_strings_reply_t reply;
|
||||||
xcb_ewmh_get_desktop_names_reply(conn, xcb_ewmh_get_desktop_names(conn, screen), &reply, nullptr);
|
xcb_ewmh_get_desktop_names_reply(conn, xcb_ewmh_get_desktop_names(conn, screen), &reply, nullptr);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include "components/types.hpp"
|
||||||
#include "utils/string.hpp"
|
#include "utils/string.hpp"
|
||||||
#include "x11/atoms.hpp"
|
#include "x11/atoms.hpp"
|
||||||
#include "x11/connection.hpp"
|
#include "x11/connection.hpp"
|
||||||
@ -19,6 +20,13 @@ bool randr_output::match(const string& o, bool strict) const {
|
|||||||
return name == o || name == string_util::replace(o, "-", "");
|
return name == o || name == string_util::replace(o, "-", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Match position
|
||||||
|
*/
|
||||||
|
bool randr_output::match(const position& p) const {
|
||||||
|
return p.x == x && p.y == y;
|
||||||
|
}
|
||||||
|
|
||||||
namespace randr_util {
|
namespace randr_util {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user