mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-07-06 00:06:43 -04:00
better feedback with no animations and multi-gesture handling
This commit is contained in:
parent
596e0a9ed3
commit
868feb48b7
6 changed files with 122 additions and 55 deletions
|
|
@ -120,6 +120,7 @@ swipe_min_threshold=1
|
||||||
gesturebind=none,horizontal,4,tagscrub
|
gesturebind=none,horizontal,4,tagscrub
|
||||||
gesture_swipe_distance=500
|
gesture_swipe_distance=500
|
||||||
gesture_commit_ratio=0.5
|
gesture_commit_ratio=0.5
|
||||||
|
gesture_axis_lock=16
|
||||||
|
|
||||||
# mouse
|
# mouse
|
||||||
# need relogin to make it apply
|
# need relogin to make it apply
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,8 @@ The scrub follows your `trackpad_natural_scrolling` setting.
|
||||||
|
|
||||||
`gesture_commit_ratio` (0–1, default `0.5`) sets how far through that distance you must swipe to commit a `tagscrub`, e.g. `0.3` commits after 30%. A fast flick can commit a bit below this via momentum.
|
`gesture_commit_ratio` (0–1, default `0.5`) sets how far through that distance you must swipe to commit a `tagscrub`, e.g. `0.3` commits after 30%. A fast flick can commit a bit below this via momentum.
|
||||||
|
|
||||||
|
`gesture_axis_lock` (px, default `16`) is how far the swipe must travel before the scrub decides whether it's along its axis. Raise it if imprecise swipes get misread.
|
||||||
|
|
||||||
```ini
|
```ini
|
||||||
gesture_swipe_distance=500
|
gesture_swipe_distance=500
|
||||||
gesture_commit_ratio=0.5
|
gesture_commit_ratio=0.5
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,23 @@ static inline void tag_scrub_stage(Monitor *m, int dir) {
|
||||||
m->scrub_rubberband = false;
|
m->scrub_rubberband = false;
|
||||||
m->scrub_incoming_tag = (uint32_t)target;
|
m->scrub_incoming_tag = (uint32_t)target;
|
||||||
|
|
||||||
|
/* Mango lays out tags lazily: a tag you moved a window off of
|
||||||
|
* keeps stale window geometry until it's viewed. This is very annoying
|
||||||
|
* Here i try to predict the arrangement of the tag just so the tags don't
|
||||||
|
* appear miss-aligned in the scrub.
|
||||||
|
* */
|
||||||
|
{
|
||||||
|
uint32_t saved_curtag = m->pertag->curtag;
|
||||||
|
uint32_t saved_tagset = m->tagset[m->seltags];
|
||||||
|
m->pertag->curtag = (uint32_t)target;
|
||||||
|
m->tagset[m->seltags] = (1u << (target - 1));
|
||||||
|
pre_caculate_before_arrange(m, false, false, true);
|
||||||
|
m->pertag->ltidxs[target]->arrange(m);
|
||||||
|
m->pertag->curtag = saved_curtag;
|
||||||
|
m->tagset[m->seltags] = saved_tagset;
|
||||||
|
pre_caculate_before_arrange(m, false, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
Client *c;
|
Client *c;
|
||||||
uint32_t inbit = 1u << (target - 1);
|
uint32_t inbit = 1u << (target - 1);
|
||||||
wl_list_for_each(c, &clients, link) {
|
wl_list_for_each(c, &clients, link) {
|
||||||
|
|
@ -122,6 +139,23 @@ static inline void tag_scrub_apply(Monitor *m, double progress) {
|
||||||
|
|
||||||
static inline bool tag_scrub_active(Monitor *m) { return m && m->scrub_active; }
|
static inline bool tag_scrub_active(Monitor *m) { return m && m->scrub_active; }
|
||||||
|
|
||||||
|
static inline bool tag_scrub_engaged(Monitor *m) {
|
||||||
|
return m && m->scrub_active && m->scrub_axis_locked;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void tag_scrub_abort(Monitor *m) {
|
||||||
|
if (!m)
|
||||||
|
return;
|
||||||
|
m->scrub_active = false;
|
||||||
|
m->scrub_axis_locked = false;
|
||||||
|
m->scrub_dir = 0;
|
||||||
|
m->scrub_progress = 0.0;
|
||||||
|
m->scrub_accum = 0.0;
|
||||||
|
m->scrub_velocity = 0.0;
|
||||||
|
m->scrub_incoming_tag = 0;
|
||||||
|
m->scrub_rubberband = false;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool tag_scrub_arm(Monitor *m, const GestureBinding *g) {
|
static inline bool tag_scrub_arm(Monitor *m, const GestureBinding *g) {
|
||||||
if (!m || m->isoverview || m->pertag->curtag == 0)
|
if (!m || m->isoverview || m->pertag->curtag == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -136,6 +170,7 @@ static inline bool tag_scrub_arm(Monitor *m, const GestureBinding *g) {
|
||||||
m->scrub_velocity = 0.0;
|
m->scrub_velocity = 0.0;
|
||||||
m->scrub_last_delta = 0.0;
|
m->scrub_last_delta = 0.0;
|
||||||
m->scrub_last_time = 0;
|
m->scrub_last_time = 0;
|
||||||
|
m->scrub_axis_locked = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -143,6 +178,21 @@ static inline void tag_scrub_feed(Monitor *m, double dx, double dy,
|
||||||
uint32_t time_msec) {
|
uint32_t time_msec) {
|
||||||
if (!m->scrub_active)
|
if (!m->scrub_active)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!m->scrub_axis_locked) {
|
||||||
|
double along = (m->scrub_axis == HORIZONTAL) ? swipe_dx : swipe_dy;
|
||||||
|
double perp = (m->scrub_axis == HORIZONTAL) ? swipe_dy : swipe_dx;
|
||||||
|
double a = along < 0 ? -along : along;
|
||||||
|
double p = perp < 0 ? -perp : perp;
|
||||||
|
if (a + p < (double)config.gesture_axis_lock)
|
||||||
|
return;
|
||||||
|
if (p > a) {
|
||||||
|
m->scrub_active = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m->scrub_axis_locked = true;
|
||||||
|
}
|
||||||
|
|
||||||
double delta = (m->scrub_axis == HORIZONTAL) ? dx : dy;
|
double delta = (m->scrub_axis == HORIZONTAL) ? dx : dy;
|
||||||
if (config.trackpad_natural_scrolling)
|
if (config.trackpad_natural_scrolling)
|
||||||
delta = -delta;
|
delta = -delta;
|
||||||
|
|
@ -162,7 +212,13 @@ static inline void tag_scrub_feed(Monitor *m, double dx, double dy,
|
||||||
|
|
||||||
if (!config.animations) {
|
if (!config.animations) {
|
||||||
m->scrub_dir = (int8_t)dir;
|
m->scrub_dir = (int8_t)dir;
|
||||||
m->scrub_progress = mag_p;
|
uint32_t mask = tag_scrub_occupied_mask(m);
|
||||||
|
int target =
|
||||||
|
tag_scrub_neighbor((int)m->pertag->curtag, dir, LENGTH(tags), mask,
|
||||||
|
m->scrub_have_client, config.tag_carousel);
|
||||||
|
m->scrub_rubberband = (dir != 0 && target == 0);
|
||||||
|
m->scrub_incoming_tag = 0;
|
||||||
|
tag_scrub_apply(m, mag_p);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -178,35 +234,32 @@ static inline void tag_scrub_release(Monitor *m, bool cancelled) {
|
||||||
if (!m->scrub_active)
|
if (!m->scrub_active)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!config.animations) {
|
|
||||||
double oriented_v = m->scrub_velocity * (double)m->scrub_dir;
|
double oriented_v = m->scrub_velocity * (double)m->scrub_dir;
|
||||||
if (!cancelled && m->scrub_dir != 0 &&
|
|
||||||
gesture_scrub_should_commit(m->scrub_progress, oriented_v,
|
|
||||||
config.gesture_commit_ratio)) {
|
|
||||||
uint32_t mask = tag_scrub_occupied_mask(m);
|
|
||||||
int target = tag_scrub_neighbor(
|
|
||||||
(int)m->pertag->curtag, m->scrub_dir, LENGTH(tags), mask,
|
|
||||||
m->scrub_have_client, config.tag_carousel);
|
|
||||||
if (target != 0)
|
|
||||||
view_in_mon(&(Arg){.ui = 1u << (target - 1)}, false, m, true);
|
|
||||||
}
|
|
||||||
m->scrub_active = false;
|
|
||||||
m->scrub_dir = 0;
|
|
||||||
m->scrub_progress = 0.0;
|
|
||||||
m->scrub_accum = 0.0;
|
|
||||||
m->scrub_velocity = 0.0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
double oriented_v = m->scrub_velocity * (double)m->scrub_dir;
|
if (!config.animations) {
|
||||||
bool commit = !cancelled && !m->scrub_rubberband && m->scrub_incoming_tag &&
|
bool commit = !cancelled && m->scrub_dir != 0 && !m->scrub_rubberband &&
|
||||||
|
gesture_scrub_should_commit(m->scrub_progress, oriented_v,
|
||||||
|
config.gesture_commit_ratio);
|
||||||
|
int target = 0;
|
||||||
|
if (commit) {
|
||||||
|
uint32_t mask = tag_scrub_occupied_mask(m);
|
||||||
|
target = tag_scrub_neighbor(
|
||||||
|
(int)m->pertag->curtag, m->scrub_dir, LENGTH(tags), mask,
|
||||||
|
m->scrub_have_client, config.tag_carousel);
|
||||||
|
}
|
||||||
|
if (target != 0)
|
||||||
|
view_in_mon(&(Arg){.ui = 1u << (target - 1)}, false, m, true);
|
||||||
|
else
|
||||||
|
arrange(m, true, true);
|
||||||
|
} else {
|
||||||
|
bool commit = !cancelled && !m->scrub_rubberband &&
|
||||||
|
m->scrub_incoming_tag &&
|
||||||
gesture_scrub_should_commit(m->scrub_progress, oriented_v,
|
gesture_scrub_should_commit(m->scrub_progress, oriented_v,
|
||||||
config.gesture_commit_ratio);
|
config.gesture_commit_ratio);
|
||||||
|
|
||||||
if (commit) {
|
if (commit) {
|
||||||
Client *c;
|
|
||||||
uint32_t inbit = 1u << (m->scrub_incoming_tag - 1);
|
uint32_t inbit = 1u << (m->scrub_incoming_tag - 1);
|
||||||
uint32_t curbit = 1u << (m->pertag->curtag - 1);
|
uint32_t curbit = 1u << (m->pertag->curtag - 1);
|
||||||
|
Client *c;
|
||||||
wl_list_for_each(c, &clients, link) {
|
wl_list_for_each(c, &clients, link) {
|
||||||
if (c->mon == m && ISTILED(c) &&
|
if (c->mon == m && ISTILED(c) &&
|
||||||
((c->tags & inbit) || (c->tags & curbit)))
|
((c->tags & inbit) || (c->tags & curbit)))
|
||||||
|
|
@ -222,8 +275,8 @@ static inline void tag_scrub_release(Monitor *m, bool cancelled) {
|
||||||
wl_list_for_each(c, &clients, link) {
|
wl_list_for_each(c, &clients, link) {
|
||||||
if (c->mon != m || !ISTILED(c))
|
if (c->mon != m || !ISTILED(c))
|
||||||
continue;
|
continue;
|
||||||
bool is_incoming =
|
bool is_incoming = inbit && (c->tags & inbit) &&
|
||||||
inbit && (c->tags & inbit) && !(c->isglobal || c->isunglobal);
|
!(c->isglobal || c->isunglobal);
|
||||||
if (!is_incoming && !(c->tags & curbit))
|
if (!is_incoming && !(c->tags & curbit))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
@ -239,8 +292,10 @@ static inline void tag_scrub_release(Monitor *m, bool cancelled) {
|
||||||
}
|
}
|
||||||
request_fresh_all_monitors();
|
request_fresh_all_monitors();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m->scrub_active = false;
|
m->scrub_active = false;
|
||||||
|
m->scrub_axis_locked = false;
|
||||||
m->scrub_dir = 0;
|
m->scrub_dir = 0;
|
||||||
m->scrub_progress = 0.0;
|
m->scrub_progress = 0.0;
|
||||||
m->scrub_accum = 0.0;
|
m->scrub_accum = 0.0;
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@ static inline int tag_scrub_neighbor(int curtag, int dir, int ntags,
|
||||||
bool wrap) {
|
bool wrap) {
|
||||||
if (curtag < 1 || curtag > ntags || (dir != 1 && dir != -1))
|
if (curtag < 1 || curtag > ntags || (dir != 1 && dir != -1))
|
||||||
return 0;
|
return 0;
|
||||||
|
bool only_current_occupied = (occupied_mask & ~(1u << (curtag - 1))) == 0;
|
||||||
|
bool skip_empty = have_client && !only_current_occupied;
|
||||||
int t = curtag;
|
int t = curtag;
|
||||||
for (int step = 0; step < ntags; step++) {
|
for (int step = 0; step < ntags; step++) {
|
||||||
t += dir;
|
t += dir;
|
||||||
|
|
@ -35,7 +37,7 @@ static inline int tag_scrub_neighbor(int curtag, int dir, int ntags,
|
||||||
}
|
}
|
||||||
if (t == curtag)
|
if (t == curtag)
|
||||||
return 0;
|
return 0;
|
||||||
if (!have_client)
|
if (!skip_empty)
|
||||||
return t;
|
return t;
|
||||||
if (occupied_mask & (1u << (t - 1)))
|
if (occupied_mask & (1u << (t - 1)))
|
||||||
return t;
|
return t;
|
||||||
|
|
|
||||||
|
|
@ -238,6 +238,7 @@ typedef struct {
|
||||||
uint32_t swipe_min_threshold;
|
uint32_t swipe_min_threshold;
|
||||||
float gesture_commit_ratio;
|
float gesture_commit_ratio;
|
||||||
int32_t gesture_swipe_distance;
|
int32_t gesture_swipe_distance;
|
||||||
|
int32_t gesture_axis_lock;
|
||||||
float focused_opacity;
|
float focused_opacity;
|
||||||
float unfocused_opacity;
|
float unfocused_opacity;
|
||||||
float *scroller_proportion_preset;
|
float *scroller_proportion_preset;
|
||||||
|
|
@ -1538,6 +1539,8 @@ bool parse_option(Config *config, char *key, char *value) {
|
||||||
config->gesture_commit_ratio = atof(value);
|
config->gesture_commit_ratio = atof(value);
|
||||||
} else if (strcmp(key, "gesture_swipe_distance") == 0) {
|
} else if (strcmp(key, "gesture_swipe_distance") == 0) {
|
||||||
config->gesture_swipe_distance = atoi(value);
|
config->gesture_swipe_distance = atoi(value);
|
||||||
|
} else if (strcmp(key, "gesture_axis_lock") == 0) {
|
||||||
|
config->gesture_axis_lock = atoi(value);
|
||||||
} else if (strcmp(key, "focused_opacity") == 0) {
|
} else if (strcmp(key, "focused_opacity") == 0) {
|
||||||
config->focused_opacity = atof(value);
|
config->focused_opacity = atof(value);
|
||||||
} else if (strcmp(key, "unfocused_opacity") == 0) {
|
} else if (strcmp(key, "unfocused_opacity") == 0) {
|
||||||
|
|
@ -3569,6 +3572,7 @@ void override_config(void) {
|
||||||
CLAMP_FLOAT(config.gesture_commit_ratio, 0.0f, 1.0f);
|
CLAMP_FLOAT(config.gesture_commit_ratio, 0.0f, 1.0f);
|
||||||
config.gesture_swipe_distance =
|
config.gesture_swipe_distance =
|
||||||
CLAMP_INT(config.gesture_swipe_distance, 50, 4000);
|
CLAMP_INT(config.gesture_swipe_distance, 50, 4000);
|
||||||
|
config.gesture_axis_lock = CLAMP_INT(config.gesture_axis_lock, 0, 1000);
|
||||||
config.mouse_natural_scrolling =
|
config.mouse_natural_scrolling =
|
||||||
CLAMP_INT(config.mouse_natural_scrolling, 0, 1);
|
CLAMP_INT(config.mouse_natural_scrolling, 0, 1);
|
||||||
config.mouse_accel_profile = CLAMP_INT(config.mouse_accel_profile, 0, 2);
|
config.mouse_accel_profile = CLAMP_INT(config.mouse_accel_profile, 0, 2);
|
||||||
|
|
@ -3726,6 +3730,7 @@ void set_value_default() {
|
||||||
config.swipe_min_threshold = 1;
|
config.swipe_min_threshold = 1;
|
||||||
config.gesture_commit_ratio = 0.5f;
|
config.gesture_commit_ratio = 0.5f;
|
||||||
config.gesture_swipe_distance = 500;
|
config.gesture_swipe_distance = 500;
|
||||||
|
config.gesture_axis_lock = 16;
|
||||||
|
|
||||||
config.idleinhibit_ignore_visible = 0;
|
config.idleinhibit_ignore_visible = 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -591,6 +591,7 @@ struct Monitor {
|
||||||
double scrub_last_delta;
|
double scrub_last_delta;
|
||||||
uint32_t scrub_last_time;
|
uint32_t scrub_last_time;
|
||||||
double scrub_velocity;
|
double scrub_velocity;
|
||||||
|
bool scrub_axis_locked;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
@ -2212,9 +2213,10 @@ void swipe_update(struct wl_listener *listener, void *data) {
|
||||||
void swipe_end(struct wl_listener *listener, void *data) {
|
void swipe_end(struct wl_listener *listener, void *data) {
|
||||||
struct wlr_pointer_swipe_end_event *event = data;
|
struct wlr_pointer_swipe_end_event *event = data;
|
||||||
|
|
||||||
if (tag_scrub_active(selmon)) {
|
if (tag_scrub_engaged(selmon)) {
|
||||||
tag_scrub_release(selmon, event->cancelled);
|
tag_scrub_release(selmon, event->cancelled);
|
||||||
} else {
|
} else {
|
||||||
|
tag_scrub_abort(selmon);
|
||||||
ongesture(event);
|
ongesture(event);
|
||||||
}
|
}
|
||||||
swipe_dx = 0;
|
swipe_dx = 0;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue