|
2 | 2 | #include "scroller.h" |
3 | 3 | #include "toplevel.h" |
4 | 4 | #include "tree.h" |
| 5 | +#include <math.h> |
5 | 6 | #include <stdlib.h> |
6 | 7 | #include <string.h> |
7 | 8 | #include <wlr/types/wlr_xdg_shell.h> |
@@ -458,6 +459,105 @@ void scroller_apply_active_focus(desktop_t *d, struct output_t *m) { |
458 | 459 | } |
459 | 460 | } |
460 | 461 |
|
| 462 | + |
| 463 | +#define VIEW_GESTURE_WORKING_AREA_MOVEMENT 300. |
| 464 | + |
| 465 | +void scroller_view_offset_gesture_begin(desktop_t *d, bool is_touchpad) { |
| 466 | + scroller_state_t *s = d ? d->scroller_state : NULL; |
| 467 | + if (!s || s->column_count == 0) |
| 468 | + return; |
| 469 | + s->view_offset = 0.0; |
| 470 | + (void)is_touchpad; |
| 471 | +} |
| 472 | + |
| 473 | +void scroller_view_offset_gesture_update(desktop_t *d, double delta_x) { |
| 474 | + scroller_state_t *s = d ? d->scroller_state : NULL; |
| 475 | + if (!s || s->column_count == 0) |
| 476 | + return; |
| 477 | + |
| 478 | + double gap = (double)compute_window_gap(d); |
| 479 | + if (gap < 0) |
| 480 | + gap = 0.0; |
| 481 | + |
| 482 | + double area_w = (double)s->working_area.width; |
| 483 | + double norm_factor = area_w / VIEW_GESTURE_WORKING_AREA_MOVEMENT; |
| 484 | + if (norm_factor < 5.0) |
| 485 | + norm_factor = 5.0; |
| 486 | + |
| 487 | + double delta = delta_x * norm_factor; |
| 488 | + |
| 489 | + double *col_xs = malloc((size_t)(s->column_count + 1) * sizeof(*col_xs)); |
| 490 | + if (!col_xs) |
| 491 | + return; |
| 492 | + |
| 493 | + double wx = 0.0; |
| 494 | + for (int i = 0; i < s->column_count; i++) { |
| 495 | + col_xs[i] = wx; |
| 496 | + wx += s->columns[i].resolved_width + gap; |
| 497 | + } |
| 498 | + col_xs[s->column_count] = wx; |
| 499 | + |
| 500 | + double active_col_x = col_xs[s->active_column_idx]; |
| 501 | + double total_width = col_xs[s->column_count]; |
| 502 | + double min_offset = -active_col_x; |
| 503 | + double max_offset = total_width - active_col_x - area_w; |
| 504 | + |
| 505 | + s->view_offset += delta; |
| 506 | + if (s->view_offset < min_offset) |
| 507 | + s->view_offset = min_offset; |
| 508 | + if (s->view_offset > max_offset) |
| 509 | + s->view_offset = max_offset; |
| 510 | + |
| 511 | + free(col_xs); |
| 512 | +} |
| 513 | + |
| 514 | +bool scroller_view_offset_gesture_end(desktop_t *d) { |
| 515 | + scroller_state_t *s = d ? d->scroller_state : NULL; |
| 516 | + if (!s || s->column_count == 0) |
| 517 | + return false; |
| 518 | + |
| 519 | + double gap = (double)compute_window_gap(d); |
| 520 | + if (gap < 0) |
| 521 | + gap = 0.0; |
| 522 | + |
| 523 | + /* compute column x positions */ |
| 524 | + double *col_xs = malloc((size_t)(s->column_count + 1) * sizeof(*col_xs)); |
| 525 | + if (!col_xs) |
| 526 | + return false; |
| 527 | + |
| 528 | + double wx = 0.0; |
| 529 | + for (int i = 0; i < s->column_count; i++) { |
| 530 | + col_xs[i] = wx; |
| 531 | + wx += s->columns[i].resolved_width + gap; |
| 532 | + } |
| 533 | + col_xs[s->column_count] = wx; |
| 534 | + |
| 535 | + double active_col_x = col_xs[s->active_column_idx]; |
| 536 | + double view_pos = active_col_x + s->view_offset; |
| 537 | + |
| 538 | + int nearest = s->active_column_idx; |
| 539 | + double nearest_dist = fabs(view_pos - active_col_x); |
| 540 | + for (int i = 0; i < s->column_count; i++) { |
| 541 | + double dist = fabs(view_pos - col_xs[i]); |
| 542 | + if (dist < nearest_dist) { |
| 543 | + nearest_dist = dist; |
| 544 | + nearest = i; |
| 545 | + } |
| 546 | + } |
| 547 | + |
| 548 | + free(col_xs); |
| 549 | + |
| 550 | + if (nearest != s->active_column_idx) { |
| 551 | + s->active_column_idx = nearest; |
| 552 | + s->view_offset = 0.0; |
| 553 | + s->activate_prev_column_on_removal = false; |
| 554 | + return true; |
| 555 | + } |
| 556 | + |
| 557 | + s->view_offset = 0.0; |
| 558 | + return true; |
| 559 | +} |
| 560 | + |
461 | 561 | bool scroller_focus_next(desktop_t *d) { |
462 | 562 | scroller_state_t *s = d->scroller_state; |
463 | 563 | if (!s || s->column_count == 0) |
|
0 commit comments