feat: Window click handlers
New parameters for defining fallback click handlers that will be triggered for the whole window unless a module action is matched. Parameters added to all [bar/foo] sections: - `click-left = ...` - `click-middle= ...` - `click-right= ...` - `scroll-up= ...` - `scroll-down= ...` Ref #226
This commit is contained in:
parent
3854515521
commit
ec39859093
@ -63,6 +63,25 @@ tray-padding = 2
|
|||||||
|
|
||||||
;override-redirect = true
|
;override-redirect = true
|
||||||
|
|
||||||
|
; Cycle bspwm desktops when scrolling on the bar (unless caught by module)
|
||||||
|
;
|
||||||
|
; NOTE: You should probably disable scrolling for
|
||||||
|
; the bspwm module by setting `enable-scroll = false`
|
||||||
|
; in the module section
|
||||||
|
;
|
||||||
|
;scroll-up = bspc desktop -f prev.local
|
||||||
|
;scroll-down = bspc desktop -f next.local
|
||||||
|
|
||||||
|
; Cycle i3 workspaces when scrolling on the bar (unless caught by module)
|
||||||
|
;
|
||||||
|
; NOTE: You should probably disable scrolling for
|
||||||
|
; the i3 module by setting `enable-scroll = false`
|
||||||
|
; in the module section
|
||||||
|
;
|
||||||
|
;scroll-up = i3-msg workspace prev_on_output
|
||||||
|
;scroll-down = i3-msg workspace next_on_output
|
||||||
|
|
||||||
|
|
||||||
[module/xwindow]
|
[module/xwindow]
|
||||||
type = internal/xwindow
|
type = internal/xwindow
|
||||||
label = %title:0:30:...%
|
label = %title:0:30:...%
|
||||||
|
@ -73,6 +73,22 @@ struct line_settings {
|
|||||||
uint16_t size{0U};
|
uint16_t size{0U};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct action {
|
||||||
|
mousebtn button{mousebtn::NONE};
|
||||||
|
string command;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct action_block : public action {
|
||||||
|
alignment align{alignment::NONE};
|
||||||
|
double start_x{0.0};
|
||||||
|
double end_x{0.0};
|
||||||
|
bool active{true};
|
||||||
|
|
||||||
|
uint16_t width() const {
|
||||||
|
return static_cast<uint16_t>(end_x - start_x + 0.5);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct bar_settings {
|
struct bar_settings {
|
||||||
monitor_t monitor;
|
monitor_t monitor;
|
||||||
edge origin{edge::TOP};
|
edge origin{edge::TOP};
|
||||||
@ -103,6 +119,8 @@ struct bar_settings {
|
|||||||
|
|
||||||
bool override_redirect{false};
|
bool override_redirect{false};
|
||||||
|
|
||||||
|
vector<action> actions;
|
||||||
|
|
||||||
const xcb_rectangle_t inner_area(bool abspos = false) const {
|
const xcb_rectangle_t inner_area(bool abspos = false) const {
|
||||||
xcb_rectangle_t rect{0, 0, size.w, size.h};
|
xcb_rectangle_t rect{0, 0, size.w, size.h};
|
||||||
|
|
||||||
@ -121,19 +139,6 @@ struct bar_settings {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct action_block {
|
|
||||||
alignment align{alignment::NONE};
|
|
||||||
double start_x{0.0};
|
|
||||||
double end_x{0.0};
|
|
||||||
mousebtn button{mousebtn::NONE};
|
|
||||||
string command;
|
|
||||||
bool active{true};
|
|
||||||
|
|
||||||
uint16_t width() const {
|
|
||||||
return static_cast<uint16_t>(end_x - start_x + 0.5);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct event_timer {
|
struct event_timer {
|
||||||
xcb_timestamp_t event{0L};
|
xcb_timestamp_t event{0L};
|
||||||
xcb_timestamp_t offset{1L};
|
xcb_timestamp_t offset{1L};
|
||||||
|
@ -53,10 +53,10 @@ namespace modules {
|
|||||||
static constexpr const char* TAG_LABEL_STATE{"<label-state>"};
|
static constexpr const char* TAG_LABEL_STATE{"<label-state>"};
|
||||||
static constexpr const char* TAG_LABEL_MODE{"<label-mode>"};
|
static constexpr const char* TAG_LABEL_MODE{"<label-mode>"};
|
||||||
|
|
||||||
static constexpr const char* EVENT_PREFIX{"i3"};
|
static constexpr const char* EVENT_PREFIX{"i3wm"};
|
||||||
static constexpr const char* EVENT_CLICK{"i3-wsfocus-"};
|
static constexpr const char* EVENT_CLICK{"i3wm-wsfocus-"};
|
||||||
static constexpr const char* EVENT_SCROLL_UP{"i3-wsnext"};
|
static constexpr const char* EVENT_SCROLL_UP{"i3wm-wsnext"};
|
||||||
static constexpr const char* EVENT_SCROLL_DOWN{"i3-wsprev"};
|
static constexpr const char* EVENT_SCROLL_DOWN{"i3wm-wsprev"};
|
||||||
|
|
||||||
map<state, label_t> m_statelabels;
|
map<state, label_t> m_statelabels;
|
||||||
vector<unique_ptr<workspace>> m_workspaces;
|
vector<unique_ptr<workspace>> m_workspaces;
|
||||||
|
@ -94,6 +94,29 @@ void bar::bootstrap(bool nodraw) {
|
|||||||
m_opts.strut.bottom = m_conf.get<int>("global/wm", "margin-bottom", 0);
|
m_opts.strut.bottom = m_conf.get<int>("global/wm", "margin-bottom", 0);
|
||||||
|
|
||||||
m_buttonpress.offset = xutils::event_timer_ms(m_conf, xcb_button_press_event_t{});
|
m_buttonpress.offset = xutils::event_timer_ms(m_conf, xcb_button_press_event_t{});
|
||||||
|
|
||||||
|
// Get fallback click handlers
|
||||||
|
auto click_left = m_conf.get<string>(bs, "click-left", "");
|
||||||
|
auto click_middle = m_conf.get<string>(bs, "click-middle", "");
|
||||||
|
auto click_right = m_conf.get<string>(bs, "click-right", "");
|
||||||
|
auto scroll_up = m_conf.get<string>(bs, "scroll-up", "");
|
||||||
|
auto scroll_down = m_conf.get<string>(bs, "scroll-down", "");
|
||||||
|
|
||||||
|
if (!click_left.empty()) {
|
||||||
|
m_opts.actions.emplace_back(action{mousebtn::LEFT, move(click_left)});
|
||||||
|
}
|
||||||
|
if (!click_middle.empty()) {
|
||||||
|
m_opts.actions.emplace_back(action{mousebtn::MIDDLE, move(click_middle)});
|
||||||
|
}
|
||||||
|
if (!click_right.empty()) {
|
||||||
|
m_opts.actions.emplace_back(action{mousebtn::RIGHT, move(click_right)});
|
||||||
|
}
|
||||||
|
if (!scroll_up.empty()) {
|
||||||
|
m_opts.actions.emplace_back(action{mousebtn::SCROLL_UP, move(scroll_up)});
|
||||||
|
}
|
||||||
|
if (!scroll_down.empty()) {
|
||||||
|
m_opts.actions.emplace_back(action{mousebtn::SCROLL_DOWN, move(scroll_down)});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_log.trace("bar: Load color values");
|
m_log.trace("bar: Load color values");
|
||||||
@ -638,7 +661,6 @@ void bar::handle(const evt::button_press& evt) {
|
|||||||
m_log.trace_x("bar: Ignoring action: end_x(%i) < event_x(%i)", action.end_x, event_x);
|
m_log.trace_x("bar: Ignoring action: end_x(%i) < event_x(%i)", action.end_x, event_x);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_log.trace("Found matching input area");
|
m_log.trace("Found matching input area");
|
||||||
m_log.trace_x("action.command = %s", action.command);
|
m_log.trace_x("action.command = %s", action.command);
|
||||||
m_log.trace_x("action.button = %i", static_cast<int>(action.button));
|
m_log.trace_x("action.button = %i", static_cast<int>(action.button));
|
||||||
@ -647,13 +669,23 @@ void bar::handle(const evt::button_press& evt) {
|
|||||||
|
|
||||||
if (g_signals::bar::action_click) {
|
if (g_signals::bar::action_click) {
|
||||||
g_signals::bar::action_click(action.command);
|
g_signals::bar::action_click(action.command);
|
||||||
} else {
|
|
||||||
m_log.warn("No signal handler's connected to 'action_click'");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto&& action : m_opts.actions) {
|
||||||
|
if (action.button == button && !action.command.empty()) {
|
||||||
|
m_log.trace("Triggering fallback click handler: %s", action.command);
|
||||||
|
|
||||||
|
if (g_signals::bar::action_click) {
|
||||||
|
g_signals::bar::action_click(action.command);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_log.warn("No matching input area found");
|
m_log.warn("No matching input area found");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,22 +206,18 @@ namespace modules {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool i3_module::handle_event(string cmd) {
|
bool i3_module::handle_event(string cmd) {
|
||||||
if (cmd.compare(0, 2, EVENT_PREFIX) != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
i3_util::connection_t ipc;
|
|
||||||
|
|
||||||
if (cmd.compare(0, strlen(EVENT_CLICK), EVENT_CLICK) == 0) {
|
if (cmd.compare(0, strlen(EVENT_CLICK), EVENT_CLICK) == 0) {
|
||||||
m_log.info("%s: Sending workspace focus command to ipc handler", name());
|
m_log.info("%s: Sending workspace focus command to ipc handler", name());
|
||||||
ipc.send_command("workspace number " + cmd.substr(strlen(EVENT_CLICK)));
|
i3_util::connection_t{}.send_command("workspace number " + cmd.substr(strlen(EVENT_CLICK)));
|
||||||
} else if (cmd.compare(0, strlen(EVENT_SCROLL_DOWN), EVENT_SCROLL_DOWN) == 0) {
|
} else if (cmd.compare(0, strlen(EVENT_SCROLL_DOWN), EVENT_SCROLL_DOWN) == 0) {
|
||||||
m_log.info("%s: Sending workspace prev command to ipc handler", name());
|
m_log.info("%s: Sending workspace prev command to ipc handler", name());
|
||||||
ipc.send_command("workspace next_on_output");
|
i3_util::connection_t{}.send_command("workspace next_on_output");
|
||||||
} else if (cmd.compare(0, strlen(EVENT_SCROLL_UP), EVENT_SCROLL_UP) == 0) {
|
} else if (cmd.compare(0, strlen(EVENT_SCROLL_UP), EVENT_SCROLL_UP) == 0) {
|
||||||
m_log.info("%s: Sending workspace next command to ipc handler", name());
|
m_log.info("%s: Sending workspace next command to ipc handler", name());
|
||||||
ipc.send_command("workspace prev_on_output");
|
i3_util::connection_t{}.send_command("workspace prev_on_output");
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
} catch (const exception& err) {
|
} catch (const exception& err) {
|
||||||
m_log.err("%s: %s", name(), err.what());
|
m_log.err("%s: %s", name(), err.what());
|
||||||
|
Loading…
Reference in New Issue
Block a user