mirror of
https://github.com/labwc/labwc.git
synced 2026-03-09 05:33:53 -04:00
Support smooth scroll and horizontal scroll
note that this changes Scroll mousebinds from taking a "button" attribute to taking a "direction" attribute
This commit is contained in:
parent
6164ba73ff
commit
2b753a98b8
7 changed files with 119 additions and 20 deletions
|
|
@ -187,7 +187,7 @@ The rest of this man page describes configuration options.
|
||||||
*<mouse><doubleClickTime>*
|
*<mouse><doubleClickTime>*
|
||||||
Set double click time in milliseconds. Default is 500.
|
Set double click time in milliseconds. Default is 500.
|
||||||
|
|
||||||
*<mouse><context name=""><mousebind button=""><action>*
|
*<mouse><context name=""><mousebind button="" direction=""><action>*
|
||||||
Multiple *<mousebind>* can exist within one *<context>*; and multiple
|
Multiple *<mousebind>* can exist within one *<context>*; and multiple
|
||||||
*<action>* can exist within one *<mousebind>*
|
*<action>* can exist within one *<mousebind>*
|
||||||
|
|
||||||
|
|
@ -219,8 +219,12 @@ The rest of this man page describes configuration options.
|
||||||
- Left
|
- Left
|
||||||
- Middle
|
- Middle
|
||||||
- Right
|
- Right
|
||||||
- Up (scroll up)
|
|
||||||
- Down (scroll down)
|
Supported scroll directions are:
|
||||||
|
- Up
|
||||||
|
- Down
|
||||||
|
- Left
|
||||||
|
- Right
|
||||||
|
|
||||||
Supported mouse actions include:
|
Supported mouse actions include:
|
||||||
- Press: Pressing the specified button down in the context.
|
- Press: Pressing the specified button down in the context.
|
||||||
|
|
@ -229,6 +233,7 @@ The rest of this man page describes configuration options.
|
||||||
- DoubleClick: Two presses within the doubleClickTime.
|
- DoubleClick: Two presses within the doubleClickTime.
|
||||||
- Drag: Pressing the button within the context, then moving the cursor
|
- Drag: Pressing the button within the context, then moving the cursor
|
||||||
- Scroll: Scrolling up or down in the context.
|
- Scroll: Scrolling up or down in the context.
|
||||||
|
Scroll actions must have a *direction* specified instead of *button*.
|
||||||
|
|
||||||
*<mouse><default />*
|
*<mouse><default />*
|
||||||
Load default mousebinds. This is an addition to the openbox
|
Load default mousebinds. This is an addition to the openbox
|
||||||
|
|
|
||||||
|
|
@ -301,10 +301,10 @@
|
||||||
<mousebind button="Middle" action="Press">
|
<mousebind button="Middle" action="Press">
|
||||||
<action name="ShowMenu"><menu>root-menu</menu></action>
|
<action name="ShowMenu"><menu>root-menu</menu></action>
|
||||||
</mousebind>
|
</mousebind>
|
||||||
<mousebind button="Up" action="Scroll">
|
<mousebind direction="Up" action="Scroll">
|
||||||
<action name="GoToDesktop" to="left"/>
|
<action name="GoToDesktop" to="left"/>
|
||||||
</mousebind>
|
</mousebind>
|
||||||
<mousebind button="Down" action="Scroll">
|
<mousebind direction="Down" action="Scroll">
|
||||||
<action name="GoToDesktop" to="right"/>
|
<action name="GoToDesktop" to="right"/>
|
||||||
</mousebind>
|
</mousebind>
|
||||||
</context>
|
</context>
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,23 @@ enum mouse_event {
|
||||||
MOUSE_ACTION_SCROLL,
|
MOUSE_ACTION_SCROLL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum direction {
|
||||||
|
LAB_DIRECTION_INVALID = 0,
|
||||||
|
LAB_DIRECTION_LEFT,
|
||||||
|
LAB_DIRECTION_RIGHT,
|
||||||
|
LAB_DIRECTION_UP,
|
||||||
|
LAB_DIRECTION_DOWN,
|
||||||
|
};
|
||||||
|
|
||||||
struct mousebind {
|
struct mousebind {
|
||||||
enum ssd_part_type context;
|
enum ssd_part_type context;
|
||||||
|
|
||||||
/* ex: BTN_LEFT, BTN_RIGHT from linux/input_event_codes.h */
|
/* ex: BTN_LEFT, BTN_RIGHT from linux/input_event_codes.h */
|
||||||
uint32_t button;
|
uint32_t button;
|
||||||
|
|
||||||
|
/* scroll direction; considered instead of button for scroll events */
|
||||||
|
enum direction direction;
|
||||||
|
|
||||||
/* ex: WLR_MODIFIER_SHIFT | WLR_MODIFIER_LOGO */
|
/* ex: WLR_MODIFIER_SHIFT | WLR_MODIFIER_LOGO */
|
||||||
uint32_t modifiers;
|
uint32_t modifiers;
|
||||||
|
|
||||||
|
|
@ -35,6 +46,7 @@ struct mousebind {
|
||||||
|
|
||||||
enum mouse_event mousebind_event_from_str(const char *str);
|
enum mouse_event mousebind_event_from_str(const char *str);
|
||||||
uint32_t mousebind_button_from_str(const char *str, uint32_t *modifiers);
|
uint32_t mousebind_button_from_str(const char *str, uint32_t *modifiers);
|
||||||
|
enum direction mousebind_direction_from_str(const char *str, uint32_t *modifiers);
|
||||||
struct mousebind *mousebind_create(const char *context);
|
struct mousebind *mousebind_create(const char *context);
|
||||||
|
|
||||||
#endif /* __LABWC_MOUSEBIND_H */
|
#endif /* __LABWC_MOUSEBIND_H */
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,9 @@ struct seat {
|
||||||
enum lab_cursors server_cursor;
|
enum lab_cursors server_cursor;
|
||||||
struct wlr_cursor *cursor;
|
struct wlr_cursor *cursor;
|
||||||
struct wlr_xcursor_manager *xcursor_manager;
|
struct wlr_xcursor_manager *xcursor_manager;
|
||||||
|
struct {
|
||||||
|
double x, y;
|
||||||
|
} smooth_scroll_offset;
|
||||||
|
|
||||||
struct wlr_pointer_constraint_v1 *current_constraint;
|
struct wlr_pointer_constraint_v1 *current_constraint;
|
||||||
struct wlr_idle *wlr_idle;
|
struct wlr_idle *wlr_idle;
|
||||||
|
|
|
||||||
|
|
@ -34,16 +34,44 @@ mousebind_button_from_str(const char *str, uint32_t *modifiers)
|
||||||
return BTN_RIGHT;
|
return BTN_RIGHT;
|
||||||
} else if (!strcasecmp(str, "Middle")) {
|
} else if (!strcasecmp(str, "Middle")) {
|
||||||
return BTN_MIDDLE;
|
return BTN_MIDDLE;
|
||||||
} else if (!strcasecmp(str, "Up")) {
|
|
||||||
return BTN_GEAR_UP;
|
|
||||||
} else if (!strcasecmp(str, "Down")) {
|
|
||||||
return BTN_GEAR_DOWN;
|
|
||||||
}
|
}
|
||||||
invalid:
|
invalid:
|
||||||
wlr_log(WLR_ERROR, "unknown button (%s)", str);
|
wlr_log(WLR_ERROR, "unknown button (%s)", str);
|
||||||
return UINT32_MAX;
|
return UINT32_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum direction
|
||||||
|
mousebind_direction_from_str(const char *str, uint32_t *modifiers)
|
||||||
|
{
|
||||||
|
assert(str);
|
||||||
|
|
||||||
|
if (modifiers) {
|
||||||
|
*modifiers = 0;
|
||||||
|
while (strlen(str) >= 2 && str[1] == '-') {
|
||||||
|
char modname[2] = {str[0], 0};
|
||||||
|
uint32_t parsed_modifier = parse_modifier(modname);
|
||||||
|
if (!parsed_modifier) {
|
||||||
|
goto invalid;
|
||||||
|
}
|
||||||
|
*modifiers |= parsed_modifier;
|
||||||
|
str += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcasecmp(str, "Left")) {
|
||||||
|
return LAB_DIRECTION_LEFT;
|
||||||
|
} else if (!strcasecmp(str, "Right")) {
|
||||||
|
return LAB_DIRECTION_RIGHT;
|
||||||
|
} else if (!strcasecmp(str, "Up")) {
|
||||||
|
return LAB_DIRECTION_UP;
|
||||||
|
} else if (!strcasecmp(str, "Down")) {
|
||||||
|
return LAB_DIRECTION_DOWN;
|
||||||
|
}
|
||||||
|
invalid:
|
||||||
|
wlr_log(WLR_ERROR, "unknown direction (%s)", str);
|
||||||
|
return LAB_DIRECTION_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
enum mouse_event
|
enum mouse_event
|
||||||
mousebind_event_from_str(const char *str)
|
mousebind_event_from_str(const char *str)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -131,6 +131,9 @@ fill_mousebind(char *nodename, char *content)
|
||||||
} else if (!strcmp(nodename, "button")) {
|
} else if (!strcmp(nodename, "button")) {
|
||||||
current_mousebind->button = mousebind_button_from_str(content,
|
current_mousebind->button = mousebind_button_from_str(content,
|
||||||
¤t_mousebind->modifiers);
|
¤t_mousebind->modifiers);
|
||||||
|
} else if (!strcmp(nodename, "direction")) {
|
||||||
|
current_mousebind->direction = mousebind_direction_from_str(content,
|
||||||
|
¤t_mousebind->modifiers);
|
||||||
} else if (!strcmp(nodename, "action")) {
|
} else if (!strcmp(nodename, "action")) {
|
||||||
/* <mousebind button="" action="EVENT"> */
|
/* <mousebind button="" action="EVENT"> */
|
||||||
current_mousebind->mouse_event =
|
current_mousebind->mouse_event =
|
||||||
|
|
@ -621,9 +624,14 @@ load_default_mouse_bindings(void)
|
||||||
|| strcmp(current->event, mouse_combos[i - 1].event)) {
|
|| strcmp(current->event, mouse_combos[i - 1].event)) {
|
||||||
/* Create new mousebind */
|
/* Create new mousebind */
|
||||||
m = mousebind_create(current->context);
|
m = mousebind_create(current->context);
|
||||||
m->button = mousebind_button_from_str(current->button,
|
|
||||||
&m->modifiers);
|
|
||||||
m->mouse_event = mousebind_event_from_str(current->event);
|
m->mouse_event = mousebind_event_from_str(current->event);
|
||||||
|
if (m->mouse_event == MOUSE_ACTION_SCROLL) {
|
||||||
|
m->direction = mousebind_direction_from_str(current->button,
|
||||||
|
&m->modifiers);
|
||||||
|
} else {
|
||||||
|
m->button = mousebind_button_from_str(current->button,
|
||||||
|
&m->modifiers);
|
||||||
|
}
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -649,6 +657,7 @@ merge_mouse_bindings(void)
|
||||||
}
|
}
|
||||||
if (existing->context == current->context
|
if (existing->context == current->context
|
||||||
&& existing->button == current->button
|
&& existing->button == current->button
|
||||||
|
&& existing->direction == current->direction
|
||||||
&& existing->mouse_event == current->mouse_event) {
|
&& existing->mouse_event == current->mouse_event) {
|
||||||
wl_list_remove(&existing->link);
|
wl_list_remove(&existing->link);
|
||||||
action_list_free(&existing->actions);
|
action_list_free(&existing->actions);
|
||||||
|
|
|
||||||
60
src/cursor.c
60
src/cursor.c
|
|
@ -889,6 +889,38 @@ cursor_button(struct wl_listener *listener, void *data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
compare_delta(const struct wlr_pointer_axis_event *event, double *accum)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Smooth scroll deltas are in surface space, so treating each unit as a
|
||||||
|
* scroll event would result in too-fast scrolling.
|
||||||
|
*
|
||||||
|
* This fudge factor (inherited from various historic projects, incl. Weston)
|
||||||
|
* produces events at a more reasonable rate.
|
||||||
|
*
|
||||||
|
* For historic context, see:
|
||||||
|
* https://lists.freedesktop.org/archives/wayland-devel/2019-April/040377.html
|
||||||
|
*/
|
||||||
|
const double SCROLL_THRESHOLD = 10.0;
|
||||||
|
|
||||||
|
if (event->delta == 0.0) {
|
||||||
|
/* Delta 0 marks the end of a scroll */
|
||||||
|
*accum = 0.0;
|
||||||
|
} else {
|
||||||
|
/* Accumulate smooth scrolling until we hit threshold */
|
||||||
|
*accum += event->delta;
|
||||||
|
}
|
||||||
|
if (event->delta_discrete < 0 || *accum < -SCROLL_THRESHOLD) {
|
||||||
|
*accum = fmod(*accum, SCROLL_THRESHOLD);
|
||||||
|
return -1;
|
||||||
|
} else if (event->delta_discrete > 0 || *accum > SCROLL_THRESHOLD) {
|
||||||
|
*accum = fmod(*accum, SCROLL_THRESHOLD);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
handle_cursor_axis(struct server *server, struct cursor_context *ctx,
|
handle_cursor_axis(struct server *server, struct cursor_context *ctx,
|
||||||
struct wlr_pointer_axis_event *event)
|
struct wlr_pointer_axis_event *event)
|
||||||
|
|
@ -899,22 +931,32 @@ handle_cursor_axis(struct server *server, struct cursor_context *ctx,
|
||||||
uint32_t modifiers = wlr_keyboard_get_modifiers(
|
uint32_t modifiers = wlr_keyboard_get_modifiers(
|
||||||
&server->seat.keyboard_group->keyboard);
|
&server->seat.keyboard_group->keyboard);
|
||||||
|
|
||||||
uint32_t button = 0;
|
enum direction direction = LAB_DIRECTION_INVALID;
|
||||||
if (event->delta_discrete < 0) {
|
if (event->orientation == WLR_AXIS_ORIENTATION_HORIZONTAL) {
|
||||||
button = BTN_GEAR_UP;
|
int rel = compare_delta(event, &server->seat.smooth_scroll_offset.x);
|
||||||
} else if (event->delta_discrete > 0) {
|
if (rel < 0) {
|
||||||
button = BTN_GEAR_DOWN;
|
direction = LAB_DIRECTION_LEFT;
|
||||||
|
} else if (rel > 0) {
|
||||||
|
direction = LAB_DIRECTION_RIGHT;
|
||||||
|
}
|
||||||
|
} else if (event->orientation == WLR_AXIS_ORIENTATION_VERTICAL) {
|
||||||
|
int rel = compare_delta(event, &server->seat.smooth_scroll_offset.y);
|
||||||
|
if (rel < 0) {
|
||||||
|
direction = LAB_DIRECTION_UP;
|
||||||
|
} else if (rel > 0) {
|
||||||
|
direction = LAB_DIRECTION_DOWN;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
wlr_log(WLR_DEBUG, "Failed to handle cursor axis event");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!button || event->source != WLR_AXIS_SOURCE_WHEEL
|
if (direction == LAB_DIRECTION_INVALID) {
|
||||||
|| event->orientation != WLR_AXIS_ORIENTATION_VERTICAL) {
|
|
||||||
wlr_log(WLR_DEBUG, "Failed to handle cursor axis event");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_list_for_each(mousebind, &rc.mousebinds, link) {
|
wl_list_for_each(mousebind, &rc.mousebinds, link) {
|
||||||
if (ssd_part_contains(mousebind->context, ctx->type)
|
if (ssd_part_contains(mousebind->context, ctx->type)
|
||||||
&& mousebind->button == button
|
&& mousebind->direction == direction
|
||||||
&& modifiers == mousebind->modifiers
|
&& modifiers == mousebind->modifiers
|
||||||
&& mousebind->mouse_event == MOUSE_ACTION_SCROLL) {
|
&& mousebind->mouse_event == MOUSE_ACTION_SCROLL) {
|
||||||
handled = true;
|
handled = true;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue