dwm: Add click handlers to label-layout
secondary-layout-symbol is the symbol of the layout to switch to when the layout symbol is left-clicked. This symbol is used to look up the memory address of the layout to set. The default is the monocle layout. setlayoutsafe is the dwm command name for setting layouts. The argument is the layout memory address. Left-clicking switches to the layout represented by secondary-layout-symbol, and right-clicking switches to the previous layout (specified by an argument of 0). To keep track of the different layouts, the layouts are retrieved in the constructor if the layout label is included and stored in m_layouts. m_current_layout is updated with the address of the current layout. m_default_layout is updated in the constructor to the first layout in the array which is the default layout in dwm. m_secondary_layout is updated to the address of the layout identified by secondary-layout-symbol. The builder adds click handlers (if layout label is included) to the layout symbol as described above. Left-clicking toggles between the secondary layout and the default layout. Right-clicking toggles between the previous layout and the current layout. find_layout are a pair of functions for finding a layout by address or symbol from the m_layouts array.
This commit is contained in:
parent
ecc881b9b3
commit
bc16268d30
@ -172,6 +172,9 @@ format = <label-state> <label-layout> <label-title>
|
||||
|
||||
enable-click = false
|
||||
|
||||
; If enable-click = true, clicking the layout symbol will switch to this layout
|
||||
secondary-layout-symbol = [M]
|
||||
|
||||
; State
|
||||
; Available tokens:
|
||||
; %name%
|
||||
|
@ -93,6 +93,18 @@ namespace modules {
|
||||
*/
|
||||
static constexpr const char* EVENT_TAG_RCLICK{"toggleview"};
|
||||
|
||||
/**
|
||||
* Event name is same as the IPC command name to set the layout to the
|
||||
* secondary layout when the layout symbol is clicked
|
||||
*/
|
||||
static constexpr const char* EVENT_LAYOUT_LCLICK{"setlayoutsafe"};
|
||||
|
||||
/**
|
||||
* Event name is same as the IPC command name to set the layout to the
|
||||
* last layout.
|
||||
*/
|
||||
static constexpr const char* EVENT_LAYOUT_RCLICK{"setlayoutsafe"};
|
||||
|
||||
/**
|
||||
* Called by has_event on layout changes. This updates the layout label
|
||||
*
|
||||
@ -162,6 +174,16 @@ namespace modules {
|
||||
*/
|
||||
auto get_state(tag_mask_t bit_mask) const -> state_t;
|
||||
|
||||
/**
|
||||
* Get the address to the layout represented by the symbol.
|
||||
*/
|
||||
auto find_layout(const string& sym) const -> const dwmipc::Layout*;
|
||||
|
||||
/**
|
||||
* Get the address to the layout represented by the address.
|
||||
*/
|
||||
auto find_layout(uintptr_t addr) 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.
|
||||
@ -193,6 +215,28 @@ namespace modules {
|
||||
*/
|
||||
bool m_click{true};
|
||||
|
||||
/**
|
||||
* If the layout symbol is clicked on, it will set the layout represented by
|
||||
* this symbol. The default is monocle mode [M].
|
||||
*/
|
||||
string m_secondary_layout_symbol{"[M]"};
|
||||
|
||||
/**
|
||||
* Holds the address to the secondary layout specified by the secondary
|
||||
* layout symbol
|
||||
*/
|
||||
const dwmipc::Layout* m_secondary_layout = nullptr;
|
||||
|
||||
/**
|
||||
* Holds the address to the current layout
|
||||
*/
|
||||
const dwmipc::Layout* m_current_layout = nullptr;
|
||||
|
||||
/**
|
||||
* Holds the address to the default layout
|
||||
*/
|
||||
const dwmipc::Layout* m_default_layout = nullptr;
|
||||
|
||||
/**
|
||||
* Holds the address to the currently active monitor in the m_monitors array
|
||||
*/
|
||||
@ -233,6 +277,11 @@ namespace modules {
|
||||
*/
|
||||
shared_ptr<vector<dwmipc::Monitor>> m_monitors;
|
||||
|
||||
/**
|
||||
* Vector of layouts returned by m_ipc->get_layouts
|
||||
*/
|
||||
shared_ptr<vector<dwmipc::Layout>> m_layouts;
|
||||
|
||||
/**
|
||||
* Maps state_t enum values to their corresponding labels
|
||||
*/
|
||||
|
@ -56,6 +56,8 @@ namespace modules {
|
||||
|
||||
m_click = m_conf.get(name(), "enable-click", m_click);
|
||||
|
||||
m_secondary_layout_symbol = m_conf.get(name(), "secondary-layout-symbol", m_secondary_layout_symbol);
|
||||
|
||||
try {
|
||||
update_monitor_ref();
|
||||
|
||||
@ -68,11 +70,20 @@ namespace modules {
|
||||
m_tags.emplace_back(t.tag_name, t.bit_mask, state, move(label));
|
||||
}
|
||||
|
||||
// This event is only needed to update the layout label
|
||||
if (m_layout_label) {
|
||||
auto layouts = m_ipc->get_layouts();
|
||||
m_layouts = m_ipc->get_layouts();
|
||||
// First layout is treated as default by dwm
|
||||
m_default_layout = &m_layouts->at(0);
|
||||
m_current_layout = find_layout(m_bar_mon->layout.address.cur);
|
||||
m_secondary_layout = find_layout(m_secondary_layout_symbol);
|
||||
if (m_secondary_layout == nullptr) {
|
||||
throw module_error("Secondary layout symbol does not exist");
|
||||
}
|
||||
|
||||
// Initialize layout symbol
|
||||
m_layout_label->replace_token("%layout%", m_bar_mon->layout.symbol.cur);
|
||||
// This event is only needed to update the layout label
|
||||
m_ipc->on_layout_change = [this](const dwmipc::LayoutChangeEvent& ev) { on_layout_change(ev); };
|
||||
m_ipc->subscribe(dwmipc::Event::LAYOUT_CHANGE);
|
||||
}
|
||||
@ -137,10 +148,21 @@ namespace modules {
|
||||
}
|
||||
|
||||
auto dwm_module::build(builder* builder, const string& tag) const -> bool {
|
||||
if (tag == TAG_LABEL_LAYOUT) {
|
||||
builder->node(m_layout_label);
|
||||
} else if (tag == TAG_LABEL_TITLE) {
|
||||
if (tag == TAG_LABEL_TITLE) {
|
||||
builder->node(m_title_label);
|
||||
} else if (tag == TAG_LABEL_LAYOUT) {
|
||||
if (m_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"));
|
||||
builder->node(m_layout_label);
|
||||
builder->cmd_close();
|
||||
builder->cmd_close();
|
||||
} else {
|
||||
builder->node(m_layout_label);
|
||||
}
|
||||
} else if (tag == TAG_LABEL_STATE) {
|
||||
bool first = true;
|
||||
for (const auto& tag : m_tags) {
|
||||
@ -168,7 +190,6 @@ namespace modules {
|
||||
}
|
||||
|
||||
auto dwm_module::check_send_cmd(string cmd, const string& ev_name) -> bool {
|
||||
std::cerr << cmd << std::endl;
|
||||
// cmd = <EVENT_PREFIX><ev_name>-<arg>
|
||||
cmd.erase(0, strlen(EVENT_PREFIX));
|
||||
|
||||
@ -176,7 +197,7 @@ namespace modules {
|
||||
if (cmd.compare(0, ev_name.size(), ev_name) == 0) {
|
||||
// Erase '<ev_name>-'
|
||||
cmd.erase(0, ev_name.size() + 1);
|
||||
m_log.info("%s: Sending workspace %s command to ipc handler", ev_name, name());
|
||||
m_log.info("%s: Sending workspace %s command to ipc handler", name(), ev_name);
|
||||
|
||||
try {
|
||||
m_ipc->run_command(ev_name, stoul(cmd));
|
||||
@ -196,7 +217,8 @@ namespace modules {
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
auto dwm_module::get_state(tag_mask_t bit_mask) const -> state_t {
|
||||
@ -247,6 +269,24 @@ namespace modules {
|
||||
}
|
||||
}
|
||||
|
||||
auto dwm_module::find_layout(const string& sym) const -> const dwmipc::Layout* {
|
||||
for (const auto& lt : *m_layouts) {
|
||||
if (lt.symbol == sym) {
|
||||
return <
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto dwm_module::find_layout(const uintptr_t addr) const -> const dwmipc::Layout* {
|
||||
for (const auto& lt : *m_layouts) {
|
||||
if (lt.address == addr) {
|
||||
return <
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void dwm_module::update_tag_labels() {
|
||||
for (auto& t : m_tags) {
|
||||
t.state = get_state(t.bit_mask);
|
||||
@ -293,6 +333,7 @@ namespace modules {
|
||||
|
||||
void dwm_module::on_layout_change(const dwmipc::LayoutChangeEvent& ev) {
|
||||
if (ev.monitor_num == m_bar_mon->num) {
|
||||
m_current_layout = find_layout(ev.new_address);
|
||||
m_layout_label->reset_tokens();
|
||||
m_layout_label->replace_token("%layout%", ev.new_symbol);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user