dwm: Add layout scroll; rename settings
Rename settings and allow more flexible configuration by allowing the user to enable click handlers for the tags and the layout label separately. Add a scroll handler for the layout label so the user can scroll through the available layouts. Enabling layout-scroll-wrap allows wrapping back to the beginning/end of the array of available layouts. next_layout and prev_layout take the address of a layout and returns the next/previous layout in the m_layouts array if possible, wrapping if specified, otherwise returns the same layout. This is used to for the layout scroll handlers to cycle through layouts.
This commit is contained in:
parent
33a8226827
commit
a22b2ffcc3
@ -168,11 +168,14 @@ label-urgent-padding = 2
|
|||||||
|
|
||||||
[module/dwm]
|
[module/dwm]
|
||||||
type = internal/dwm
|
type = internal/dwm
|
||||||
format = <label-tags> <label-layout>> <label-title>
|
format = <label-tags> <label-layout> <label-title>
|
||||||
|
|
||||||
enable-click = false
|
enable-tags-click = false
|
||||||
|
enable-layout-click = false
|
||||||
|
enable-layout-scroll = false
|
||||||
|
layout-scroll-wrap = false
|
||||||
|
|
||||||
; If enable-click = true, clicking the layout symbol will switch to this layout
|
; If enable-layout-click = true, clicking the layout symbol will switch to this layout
|
||||||
secondary-layout-symbol = [M]
|
secondary-layout-symbol = [M]
|
||||||
|
|
||||||
; State
|
; State
|
||||||
|
@ -105,6 +105,18 @@ namespace modules {
|
|||||||
*/
|
*/
|
||||||
static constexpr const char* EVENT_LAYOUT_RCLICK{"setlayoutsafe"};
|
static constexpr const char* EVENT_LAYOUT_RCLICK{"setlayoutsafe"};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event name is same as the IPC command name to set the layout to the
|
||||||
|
* previous layout in the array.
|
||||||
|
*/
|
||||||
|
static constexpr const char* EVENT_LAYOUT_SDOWN{"setlayoutsafe"};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event name is same as the IPC command name to set the layout to the
|
||||||
|
* next layout in the array.
|
||||||
|
*/
|
||||||
|
static constexpr const char* EVENT_LAYOUT_SUP{"setlayoutsafe"};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by has_event on layout changes. This updates the layout label
|
* Called by has_event on layout changes. This updates the layout label
|
||||||
*
|
*
|
||||||
@ -182,6 +194,24 @@ namespace modules {
|
|||||||
*/
|
*/
|
||||||
auto find_layout(uintptr_t addr) const -> const dwmipc::Layout*;
|
auto find_layout(uintptr_t addr) const -> const dwmipc::Layout*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the address of the next layout in m_layouts.
|
||||||
|
*
|
||||||
|
* @param layout Address of the current layout
|
||||||
|
* @param wrap True to wrap around the array, false to return the same
|
||||||
|
* layout if the next layout does not exist.
|
||||||
|
*/
|
||||||
|
auto next_layout(const dwmipc::Layout& layout, bool wrap) const -> const dwmipc::Layout*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the address of the previous layout in m_layouts.
|
||||||
|
*
|
||||||
|
* @param layout Address of the current layout
|
||||||
|
* @param wrap True to wrap around the array, false to return the same
|
||||||
|
* layout if the next layout does not exist.
|
||||||
|
*/
|
||||||
|
auto prev_layout(const dwmipc::Layout& layout, bool wrap) const -> const dwmipc::Layout*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the command matches the specified event name and if so, send a
|
* Check if the command matches the specified event name and if so, send a
|
||||||
* command to dwm after parsing the command.
|
* command to dwm after parsing the command.
|
||||||
@ -211,7 +241,22 @@ namespace modules {
|
|||||||
/**
|
/**
|
||||||
* If true, enables the click handlers for the tags
|
* If true, enables the click handlers for the tags
|
||||||
*/
|
*/
|
||||||
bool m_click{true};
|
bool m_tags_click{true};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If true, enables the click handlers for the layout label
|
||||||
|
*/
|
||||||
|
bool m_layout_click{true};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If true, scrolling the layout cycle through available layouts
|
||||||
|
*/
|
||||||
|
bool m_layout_scroll{true};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If true, scrolling the layout will wrap around to the beginning
|
||||||
|
*/
|
||||||
|
bool m_layout_wrap{true};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the layout symbol is clicked on, it will set the layout represented by
|
* If the layout symbol is clicked on, it will set the layout represented by
|
||||||
|
@ -28,8 +28,7 @@ namespace modules {
|
|||||||
m_ipc = factory_util::unique<dwmipc::Connection>(socket_path);
|
m_ipc = factory_util::unique<dwmipc::Connection>(socket_path);
|
||||||
|
|
||||||
// Load configuration
|
// Load configuration
|
||||||
m_formatter->add(
|
m_formatter->add(DEFAULT_FORMAT, DEFAULT_FORMAT_TAGS, {TAG_LABEL_TAGS, TAG_LABEL_LAYOUT, TAG_LABEL_TITLE});
|
||||||
DEFAULT_FORMAT, DEFAULT_FORMAT_TAGS, {TAG_LABEL_TAGS, TAG_LABEL_LAYOUT, TAG_LABEL_TITLE});
|
|
||||||
|
|
||||||
// Populate m_state_labels map with labels and their states
|
// Populate m_state_labels map with labels and their states
|
||||||
if (m_formatter->has(TAG_LABEL_TAGS)) {
|
if (m_formatter->has(TAG_LABEL_TAGS)) {
|
||||||
@ -55,8 +54,10 @@ namespace modules {
|
|||||||
m_title_label = load_optional_label(m_conf, name(), "label-title", "%title%");
|
m_title_label = load_optional_label(m_conf, name(), "label-title", "%title%");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_click = m_conf.get(name(), "enable-click", m_click);
|
m_tags_click = m_conf.get(name(), "enable-tags-click", m_tags_click);
|
||||||
|
m_layout_click = m_conf.get(name(), "enable-layout-click", m_layout_click);
|
||||||
|
m_layout_scroll = m_conf.get(name(), "enable-layout-scroll", m_layout_scroll);
|
||||||
|
m_layout_wrap = m_conf.get(name(), "layout-scroll-wrap", m_layout_wrap);
|
||||||
m_secondary_layout_symbol = m_conf.get(name(), "secondary-layout-symbol", m_secondary_layout_symbol);
|
m_secondary_layout_symbol = m_conf.get(name(), "secondary-layout-symbol", m_secondary_layout_symbol);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -153,17 +154,27 @@ namespace modules {
|
|||||||
if (tag == TAG_LABEL_TITLE) {
|
if (tag == TAG_LABEL_TITLE) {
|
||||||
builder->node(m_title_label);
|
builder->node(m_title_label);
|
||||||
} else if (tag == TAG_LABEL_LAYOUT) {
|
} else if (tag == TAG_LABEL_LAYOUT) {
|
||||||
if (m_click) {
|
if (m_layout_click) {
|
||||||
// Toggle between secondary and default layout
|
// Toggle between secondary and default layout
|
||||||
auto addr = (m_current_layout == m_default_layout ? m_secondary_layout : m_default_layout)->address;
|
auto addr = (m_current_layout == m_default_layout ? m_secondary_layout : m_default_layout)->address;
|
||||||
builder->cmd(mousebtn::LEFT, build_cmd(EVENT_LAYOUT_LCLICK, to_string(addr)));
|
builder->cmd(mousebtn::LEFT, build_cmd(EVENT_LAYOUT_LCLICK, to_string(addr)));
|
||||||
// Set previous layout
|
// Set previous layout
|
||||||
builder->cmd(mousebtn::RIGHT, build_cmd(EVENT_LAYOUT_RCLICK, "0"));
|
builder->cmd(mousebtn::RIGHT, build_cmd(EVENT_LAYOUT_RCLICK, "0"));
|
||||||
builder->node(m_layout_label);
|
}
|
||||||
|
if (m_layout_scroll) {
|
||||||
|
auto addr_next = next_layout(*m_current_layout, m_layout_wrap)->address;
|
||||||
|
auto addr_prev = prev_layout(*m_current_layout, m_layout_wrap)->address;
|
||||||
|
builder->cmd(mousebtn::SCROLL_DOWN, build_cmd(EVENT_LAYOUT_SDOWN, to_string(addr_prev)));
|
||||||
|
builder->cmd(mousebtn::SCROLL_UP, build_cmd(EVENT_LAYOUT_SUP, to_string(addr_next)));
|
||||||
|
}
|
||||||
|
builder->node(m_layout_label);
|
||||||
|
if (m_layout_click) {
|
||||||
|
builder->cmd_close();
|
||||||
|
builder->cmd_close();
|
||||||
|
}
|
||||||
|
if (m_layout_scroll) {
|
||||||
builder->cmd_close();
|
builder->cmd_close();
|
||||||
builder->cmd_close();
|
builder->cmd_close();
|
||||||
} else {
|
|
||||||
builder->node(m_layout_label);
|
|
||||||
}
|
}
|
||||||
} else if (tag == TAG_LABEL_TAGS) {
|
} else if (tag == TAG_LABEL_TAGS) {
|
||||||
bool first = true;
|
bool first = true;
|
||||||
@ -175,7 +186,7 @@ namespace modules {
|
|||||||
builder->node(m_seperator_label);
|
builder->node(m_seperator_label);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_click) {
|
if (m_tags_click) {
|
||||||
builder->cmd(mousebtn::LEFT, build_cmd(EVENT_TAG_LCLICK, to_string(tag.bit_mask)));
|
builder->cmd(mousebtn::LEFT, build_cmd(EVENT_TAG_LCLICK, to_string(tag.bit_mask)));
|
||||||
builder->cmd(mousebtn::RIGHT, build_cmd(EVENT_TAG_RCLICK, to_string(tag.bit_mask)));
|
builder->cmd(mousebtn::RIGHT, build_cmd(EVENT_TAG_RCLICK, to_string(tag.bit_mask)));
|
||||||
builder->node(tag.label);
|
builder->node(tag.label);
|
||||||
@ -220,7 +231,8 @@ namespace modules {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return check_send_cmd(cmd, EVENT_TAG_LCLICK) || check_send_cmd(cmd, EVENT_TAG_RCLICK) ||
|
return check_send_cmd(cmd, EVENT_TAG_LCLICK) || check_send_cmd(cmd, EVENT_TAG_RCLICK) ||
|
||||||
check_send_cmd(cmd, EVENT_LAYOUT_LCLICK) || check_send_cmd(cmd, EVENT_LAYOUT_RCLICK);
|
check_send_cmd(cmd, EVENT_LAYOUT_LCLICK) || check_send_cmd(cmd, EVENT_LAYOUT_RCLICK) ||
|
||||||
|
check_send_cmd(cmd, EVENT_LAYOUT_SDOWN) || check_send_cmd(cmd, EVENT_LAYOUT_SUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto dwm_module::get_state(tag_mask_t bit_mask) const -> state_t {
|
auto dwm_module::get_state(tag_mask_t bit_mask) const -> state_t {
|
||||||
@ -289,6 +301,30 @@ namespace modules {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto dwm_module::next_layout(const dwmipc::Layout& layout, bool wrap) const -> const dwmipc::Layout* {
|
||||||
|
const auto* next = &layout + 1;
|
||||||
|
const auto* first = m_layouts->begin().base();
|
||||||
|
if (next < m_layouts->end().base()) {
|
||||||
|
return next;
|
||||||
|
} else if (wrap) {
|
||||||
|
return first;
|
||||||
|
} else {
|
||||||
|
return &layout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto dwm_module::prev_layout(const dwmipc::Layout& layout, bool wrap) const -> const dwmipc::Layout* {
|
||||||
|
const auto* prev = &layout - 1;
|
||||||
|
const auto* last = m_layouts->end().base() - 1;
|
||||||
|
if (prev >= m_layouts->begin().base()) {
|
||||||
|
return prev;
|
||||||
|
} else if (wrap) {
|
||||||
|
return last;
|
||||||
|
} else {
|
||||||
|
return &layout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void dwm_module::update_tag_labels() {
|
void dwm_module::update_tag_labels() {
|
||||||
for (auto& t : m_tags) {
|
for (auto& t : m_tags) {
|
||||||
t.state = get_state(t.bit_mask);
|
t.state = get_state(t.bit_mask);
|
||||||
|
Loading…
Reference in New Issue
Block a user