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]
|
||||
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]
|
||||
|
||||
; State
|
||||
|
@ -105,6 +105,18 @@ namespace modules {
|
||||
*/
|
||||
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
|
||||
*
|
||||
@ -182,6 +194,24 @@ namespace modules {
|
||||
*/
|
||||
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
|
||||
* command to dwm after parsing the command.
|
||||
@ -211,7 +241,22 @@ namespace modules {
|
||||
/**
|
||||
* 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
|
||||
|
@ -28,8 +28,7 @@ namespace modules {
|
||||
m_ipc = factory_util::unique<dwmipc::Connection>(socket_path);
|
||||
|
||||
// Load configuration
|
||||
m_formatter->add(
|
||||
DEFAULT_FORMAT, DEFAULT_FORMAT_TAGS, {TAG_LABEL_TAGS, TAG_LABEL_LAYOUT, TAG_LABEL_TITLE});
|
||||
m_formatter->add(DEFAULT_FORMAT, DEFAULT_FORMAT_TAGS, {TAG_LABEL_TAGS, TAG_LABEL_LAYOUT, TAG_LABEL_TITLE});
|
||||
|
||||
// Populate m_state_labels map with labels and their states
|
||||
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_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);
|
||||
|
||||
try {
|
||||
@ -153,17 +154,27 @@ namespace modules {
|
||||
if (tag == TAG_LABEL_TITLE) {
|
||||
builder->node(m_title_label);
|
||||
} else if (tag == TAG_LABEL_LAYOUT) {
|
||||
if (m_click) {
|
||||
if (m_layout_click) {
|
||||
// Toggle between secondary and default layout
|
||||
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)));
|
||||
// Set previous layout
|
||||
builder->cmd(mousebtn::RIGHT, build_cmd(EVENT_LAYOUT_RCLICK, "0"));
|
||||
}
|
||||
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();
|
||||
} else {
|
||||
builder->node(m_layout_label);
|
||||
}
|
||||
} else if (tag == TAG_LABEL_TAGS) {
|
||||
bool first = true;
|
||||
@ -175,7 +186,7 @@ namespace modules {
|
||||
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::RIGHT, build_cmd(EVENT_TAG_RCLICK, to_string(tag.bit_mask)));
|
||||
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) ||
|
||||
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 {
|
||||
@ -289,6 +301,30 @@ namespace modules {
|
||||
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() {
|
||||
for (auto& t : m_tags) {
|
||||
t.state = get_state(t.bit_mask);
|
||||
|
Loading…
Reference in New Issue
Block a user