mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2025-10-29 05:40:12 -04:00
Implement pointer-constraints protocol in wlroots and rootston
This commit is contained in:
parent
437f538772
commit
fa2e6e7d9d
23 changed files with 1134 additions and 20 deletions
|
|
@ -1,5 +1,8 @@
|
|||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <wlr/types/wlr_box.h>
|
||||
#include <wlr/util/region.h>
|
||||
|
||||
void wlr_region_scale(pixman_region32_t *dst, pixman_region32_t *src,
|
||||
|
|
@ -177,3 +180,71 @@ void wlr_region_rotated_bounds(pixman_region32_t *dst, pixman_region32_t *src,
|
|||
pixman_region32_init_rects(dst, dst_rects, nrects);
|
||||
free(dst_rects);
|
||||
}
|
||||
|
||||
static void region_confine(pixman_region32_t *region, double x1, double y1, double x2,
|
||||
double y2, double *x2_out, double *y2_out, pixman_box32_t box) {
|
||||
double x_clamped = fmax(fmin(x2, box.x2 - 1), box.x1);
|
||||
double y_clamped = fmax(fmin(y2, box.y2 - 1), box.y1);
|
||||
|
||||
// If the target coordinates are above box.{x,y}2 - 1, but less than
|
||||
// box.{x,y}2, then they are still within the box.
|
||||
if (floor(x_clamped) == floor(x2) && floor(y_clamped) == floor(y2)) {
|
||||
*x2_out = x2;
|
||||
*y2_out = y2;
|
||||
return;
|
||||
}
|
||||
|
||||
double dx = x2 - x1;
|
||||
double dy = y2 - y1;
|
||||
|
||||
// We use fabs to avoid negative zeroes and thus avoid a bug
|
||||
// with negative infinity.
|
||||
double delta = fmin(fabs(x_clamped - x1) / fabs(dx), fabs(y_clamped - y1) / fabs(dy));
|
||||
|
||||
// We clamp it again due to precision errors.
|
||||
double x = fmax(fmin(delta * dx + x1, box.x2 - 1), box.x1);
|
||||
double y = fmax(fmin(delta * dy + y1, box.y2 - 1), box.y1);
|
||||
|
||||
// Go one unit past the boundary to find an adjacent box.
|
||||
int x_ext = floor(x) + (dx == 0 ? 0 : dx > 0 ? 1 : -1);
|
||||
int y_ext = floor(y) + (dy == 0 ? 0 : dy > 0 ? 1 : -1);
|
||||
|
||||
if (pixman_region32_contains_point(region, x_ext, y_ext, &box)) {
|
||||
return region_confine(region, x1, y1, x2, y2, x2_out, y2_out, box);
|
||||
} else if (dx == 0 || dy == 0) {
|
||||
*x2_out = x;
|
||||
*y2_out = y;
|
||||
} else {
|
||||
bool bordering_x = x == box.x1 || x == box.x2 - 1;
|
||||
bool bordering_y = y == box.y1 || y == box.y2 - 1;
|
||||
|
||||
if ((bordering_x && bordering_y) || (!bordering_x && !bordering_y)) {
|
||||
double x2_potential, y2_potential;
|
||||
double tmp1, tmp2;
|
||||
region_confine(region, x, y, x, y2, &tmp1, &y2_potential, box);
|
||||
region_confine(region, x, y, x2, y, &x2_potential, &tmp2, box);
|
||||
if (fabs(x2_potential - x) > fabs(y2_potential - y)) {
|
||||
*x2_out = x2_potential;
|
||||
*y2_out = y;
|
||||
} else {
|
||||
*x2_out = x;
|
||||
*y2_out = y2_potential;
|
||||
}
|
||||
} else if (bordering_x) {
|
||||
return region_confine(region, x, y, x, y2, x2_out, y2_out, box);
|
||||
} else if (bordering_y) {
|
||||
return region_confine(region, x, y, x2, y, x2_out, y2_out, box);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool wlr_region_confine(pixman_region32_t *region, double x1, double y1, double x2,
|
||||
double y2, double *x2_out, double *y2_out) {
|
||||
pixman_box32_t box;
|
||||
if (pixman_region32_contains_point(region, x1, y1, &box)) {
|
||||
region_confine(region, x1, y1, x2, y2, x2_out, y2_out, box);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue