mousebind: add support for more contexts and mouse events

This commit is contained in:
ARDiDo 2021-11-01 20:32:14 -04:00 committed by Johan Malm
parent 98085b4546
commit 6b948c7106
4 changed files with 89 additions and 30 deletions

View file

@ -7,6 +7,9 @@
enum mouse_event { enum mouse_event {
MOUSE_ACTION_NONE = 0, MOUSE_ACTION_NONE = 0,
MOUSE_ACTION_DOUBLECLICK, MOUSE_ACTION_DOUBLECLICK,
MOUSE_ACTION_CLICK,
MOUSE_ACTION_PRESS,
MOUSE_ACTION_RELEASE,
}; };
struct mousebind { struct mousebind {
@ -21,6 +24,7 @@ struct mousebind {
const char *command; const char *command;
struct wl_list link; /* rcxml::mousebinds */ struct wl_list link; /* rcxml::mousebinds */
bool pressed_in_context; /* used in click events */
}; };
enum mouse_event mousebind_event_from_str(const char *str); enum mouse_event mousebind_event_from_str(const char *str);

View file

@ -27,8 +27,14 @@ enum mouse_event
mousebind_event_from_str(const char *str) mousebind_event_from_str(const char *str)
{ {
assert(str); assert(str);
if (strcasecmp(str, "doubleclick") == 0) { if (!strcasecmp(str, "doubleclick")) {
return MOUSE_ACTION_DOUBLECLICK; return MOUSE_ACTION_DOUBLECLICK;
} else if (!strcasecmp(str, "click")) {
return MOUSE_ACTION_CLICK;
} else if (!strcasecmp(str, "press")) {
return MOUSE_ACTION_PRESS;
} else if (!strcasecmp(str, "release")) {
return MOUSE_ACTION_RELEASE;
} }
wlr_log(WLR_ERROR, "unknown mouse action (%s)", str); wlr_log(WLR_ERROR, "unknown mouse action (%s)", str);
return MOUSE_ACTION_NONE; return MOUSE_ACTION_NONE;
@ -39,6 +45,12 @@ context_from_str(const char *str)
{ {
if (!strcasecmp(str, "Titlebar")) { if (!strcasecmp(str, "Titlebar")) {
return LAB_SSD_PART_TITLEBAR; return LAB_SSD_PART_TITLEBAR;
} else if (!strcasecmp(str, "Close")) {
return LAB_SSD_BUTTON_CLOSE;
} else if (!strcasecmp(str, "Maximize")) {
return LAB_SSD_BUTTON_MAXIMIZE;
} else if (!strcasecmp(str, "Iconify")) {
return LAB_SSD_BUTTON_ICONIFY;
} }
wlr_log(WLR_ERROR, "unknown mouse context (%s)", str); wlr_log(WLR_ERROR, "unknown mouse context (%s)", str);
return LAB_SSD_NONE; return LAB_SSD_NONE;

View file

@ -466,6 +466,9 @@ static struct {
const char *context, *button, *event, *action, *command; const char *context, *button, *event, *action, *command;
} mouse_combos[] = { } mouse_combos[] = {
{ "TitleBar", "Left", "DoubleClick", "ToggleMaximize", NULL }, { "TitleBar", "Left", "DoubleClick", "ToggleMaximize", NULL },
{ "Close", "Left", "Click", "Close", NULL },
{ "Iconify", "Left", "Click", "Iconify", NULL},
{ "Maximize", "Left", "Click", "ToggleMaximize", NULL},
{ NULL, NULL, NULL, NULL, NULL }, { NULL, NULL, NULL, NULL, NULL },
}; };

View file

@ -420,6 +420,27 @@ handle_cursor_button_with_meta_key(struct view *view, uint32_t button,
interactive_begin(view, LAB_INPUT_STATE_RESIZE, edges); interactive_begin(view, LAB_INPUT_STATE_RESIZE, edges);
} }
static void
handle_release_mousebinding(struct server *server, uint32_t button, enum ssd_part_type view_area)
{
struct mousebind *mousebind;
wl_list_for_each_reverse(mousebind, &rc.mousebinds, link) {
if (mousebind->context == view_area
&& mousebind->button == button) {
if (mousebind->mouse_event
== MOUSE_ACTION_RELEASE) {
action(server, mousebind->action,
mousebind->command);
}
if (mousebind->pressed_in_context) {
mousebind->pressed_in_context = false;
action(server, mousebind->action,
mousebind->command);
}
}
}
}
static bool static bool
is_double_click(long double_click_speed) is_double_click(long double_click_speed)
{ {
@ -433,6 +454,37 @@ is_double_click(long double_click_speed)
return ms < double_click_speed && ms >= 0; return ms < double_click_speed && ms >= 0;
} }
static bool
handle_press_mousebinding(struct server *server, uint32_t button, enum ssd_part_type view_area)
{
struct mousebind *mousebind;
bool double_click = is_double_click(rc.doubleclick_time);
bool bound;
wl_list_for_each_reverse(mousebind, &rc.mousebinds, link) {
if (mousebind->context == view_area
&& mousebind->button == button) {
if (mousebind->mouse_event
== MOUSE_ACTION_PRESS) {
bound = true;
action(server, mousebind->action,
mousebind->command);
} else if (mousebind->mouse_event
== MOUSE_ACTION_CLICK) {
bound = true;
mousebind->pressed_in_context = true;
} else if (double_click
&& mousebind->mouse_event
== MOUSE_ACTION_DOUBLECLICK) {
bound = true;
action(server, mousebind->action,
mousebind->command);
}
}
}
return bound;
}
void void
cursor_button(struct wl_listener *listener, void *data) cursor_button(struct wl_listener *listener, void *data)
{ {
@ -471,10 +523,13 @@ cursor_button(struct wl_listener *listener, void *data)
if (server->input_mode == LAB_INPUT_STATE_MENU) { if (server->input_mode == LAB_INPUT_STATE_MENU) {
return; return;
} }
/* Exit interactive move/resize/menu mode. */
server->input_mode = LAB_INPUT_STATE_PASSTHROUGH;
damage_all_outputs(server); damage_all_outputs(server);
return; if (server->input_mode != LAB_INPUT_STATE_PASSTHROUGH) {
/* Exit interactive move/resize/menu mode. */
server->input_mode = LAB_INPUT_STATE_PASSTHROUGH;
return;
}
goto mousebindings;
} }
if (server->input_mode == LAB_INPUT_STATE_MENU) { if (server->input_mode == LAB_INPUT_STATE_MENU) {
@ -507,39 +562,24 @@ cursor_button(struct wl_listener *listener, void *data)
desktop_raise_view(view); desktop_raise_view(view);
damage_all_outputs(server); damage_all_outputs(server);
if (is_double_click(rc.doubleclick_time)
&& view_area == LAB_SSD_PART_TITLEBAR) {
struct mousebind *mousebind;
wl_list_for_each_reverse (mousebind, &rc.mousebinds, link) {
/* TODO: make this more generic */
if ((mousebind->context == LAB_SSD_PART_TITLEBAR) &&
(mousebind->mouse_event == MOUSE_ACTION_DOUBLECLICK) &&
(mousebind->button == event->button)) {
action(server, mousebind->action, mousebind->command);
}
}
return;
}
resize_edges = ssd_resize_edges(view_area); resize_edges = ssd_resize_edges(view_area);
if (resize_edges) { if (resize_edges) {
interactive_begin(view, LAB_INPUT_STATE_RESIZE, resize_edges); interactive_begin(view, LAB_INPUT_STATE_RESIZE, resize_edges);
return; return;
} }
switch (view_area) { mousebindings:
case LAB_SSD_BUTTON_CLOSE: if (event->state == WLR_BUTTON_RELEASED) {
view->impl->close(view); handle_release_mousebinding(server, event->button, view_area);
break; return;
case LAB_SSD_BUTTON_ICONIFY: } else if (event->state == WLR_BUTTON_PRESSED) {
view_minimize(view, true); if (handle_press_mousebinding(server, event->button, view_area)) {
break; return;
case LAB_SSD_PART_TITLEBAR: }
}
if (view_area == LAB_SSD_PART_TITLEBAR) {
interactive_begin(view, LAB_INPUT_STATE_MOVE, 0); interactive_begin(view, LAB_INPUT_STATE_MOVE, 0);
break;
case LAB_SSD_BUTTON_MAXIMIZE:
view_toggle_maximize(view);
break;
} }
} }