mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	intersect cursor and device regions
This commit is contained in:
		
							parent
							
								
									dc7e32552d
								
							
						
					
					
						commit
						ac503a47a7
					
				
					 3 changed files with 82 additions and 11 deletions
				
			
		| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
#ifndef _WLR_TYPES_GEOMETRY_H
 | 
					#ifndef _WLR_TYPES_GEOMETRY_H
 | 
				
			||||||
#define _WLR_TYPES_GEOMETRY_H
 | 
					#define _WLR_TYPES_GEOMETRY_H
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_geometry {
 | 
					struct wlr_geometry {
 | 
				
			||||||
	int x, y;
 | 
						int x, y;
 | 
				
			||||||
| 
						 | 
					@ -9,4 +10,9 @@ struct wlr_geometry {
 | 
				
			||||||
void wlr_geometry_closest_boundary(struct wlr_geometry *geo, double x, double y,
 | 
					void wlr_geometry_closest_boundary(struct wlr_geometry *geo, double x, double y,
 | 
				
			||||||
		int *dest_x, int *dest_y, double *distance);
 | 
							int *dest_x, int *dest_y, double *distance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool wlr_geometry_intersection(struct wlr_geometry *geo_a,
 | 
				
			||||||
 | 
							struct wlr_geometry *geo_b, struct wlr_geometry **dest);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool wlr_geometry_contains_point(struct wlr_geometry *geo, int x, int y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -147,19 +147,20 @@ void wlr_cursor_move(struct wlr_cursor *cur, struct wlr_input_device *dev,
 | 
				
			||||||
	double x = cur->x + delta_x;
 | 
						double x = cur->x + delta_x;
 | 
				
			||||||
	double y = cur->y + delta_y;
 | 
						double y = cur->y + delta_y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// cursor geometry constraints
 | 
						// geometry constraints
 | 
				
			||||||
	if (cur->state->mapped_geometry) {
 | 
						struct wlr_geometry *constraints = NULL;
 | 
				
			||||||
		int closest_x, closest_y;
 | 
						if (cur->state->mapped_geometry != NULL ||
 | 
				
			||||||
		wlr_geometry_closest_boundary(cur->state->mapped_geometry, x, y,
 | 
								c_device->mapped_geometry != NULL) {
 | 
				
			||||||
			&closest_x, &closest_y, NULL);
 | 
							constraints = calloc(1, sizeof(struct wlr_geometry));
 | 
				
			||||||
		x = closest_x;
 | 
					
 | 
				
			||||||
		y = closest_y;
 | 
							if (!wlr_geometry_intersection(cur->state->mapped_geometry,
 | 
				
			||||||
 | 
									c_device->mapped_geometry, &constraints)) {
 | 
				
			||||||
 | 
								// TODO handle no possible movement
 | 
				
			||||||
 | 
								goto out;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// device constraints
 | 
					 | 
				
			||||||
	if (c_device->mapped_geometry) {
 | 
					 | 
				
			||||||
		int closest_x, closest_y;
 | 
							int closest_x, closest_y;
 | 
				
			||||||
		wlr_geometry_closest_boundary(c_device->mapped_geometry, x, y,
 | 
							wlr_geometry_closest_boundary(constraints, x, y,
 | 
				
			||||||
			&closest_x, &closest_y, NULL);
 | 
								&closest_x, &closest_y, NULL);
 | 
				
			||||||
		x = closest_x;
 | 
							x = closest_x;
 | 
				
			||||||
		y = closest_y;
 | 
							y = closest_y;
 | 
				
			||||||
| 
						 | 
					@ -177,10 +178,20 @@ void wlr_cursor_move(struct wlr_cursor *cur, struct wlr_input_device *dev,
 | 
				
			||||||
		y = closest_y;
 | 
							y = closest_y;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (constraints && !wlr_geometry_contains_point(constraints, x, y)) {
 | 
				
			||||||
 | 
							// TODO handle no possible movement
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (wlr_cursor_warp(cur, dev, x, y)) {
 | 
						if (wlr_cursor_warp(cur, dev, x, y)) {
 | 
				
			||||||
		cur->x = x;
 | 
							cur->x = x;
 | 
				
			||||||
		cur->y = y;
 | 
							cur->y = y;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
						if (constraints) {
 | 
				
			||||||
 | 
							free(constraints);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_pointer_motion(struct wl_listener *listener, void *data) {
 | 
					static void handle_pointer_motion(struct wl_listener *listener, void *data) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,9 @@
 | 
				
			||||||
#include <limits.h>
 | 
					#include <limits.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <math.h>
 | 
					#include <math.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
#include <wlr/types/wlr_geometry.h>
 | 
					#include <wlr/types/wlr_geometry.h>
 | 
				
			||||||
 | 
					#include <wlr/util/log.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static double get_distance(double x1, double y1, double x2, double y2) {
 | 
					static double get_distance(double x1, double y1, double x2, double y2) {
 | 
				
			||||||
	double distance;
 | 
						double distance;
 | 
				
			||||||
| 
						 | 
					@ -34,3 +36,55 @@ void wlr_geometry_closest_boundary(struct wlr_geometry *geo, double x, double y,
 | 
				
			||||||
		*distance = get_distance(*dest_x, *dest_y, x, y);
 | 
							*distance = get_distance(*dest_x, *dest_y, x, y);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef max
 | 
				
			||||||
 | 
					#define max(a,b) ((a) > (b) ? (a) : (b))
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef min
 | 
				
			||||||
 | 
					#define min(a,b) ((a) < (b) ? (a) : (b))
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool wlr_geometry_empty(struct wlr_geometry *geo) {
 | 
				
			||||||
 | 
						return geo == NULL || geo->width < 0 || geo->height < 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool wlr_geometry_intersection(struct wlr_geometry *geo_a,
 | 
				
			||||||
 | 
							struct wlr_geometry *geo_b, struct wlr_geometry **geo_dest) {
 | 
				
			||||||
 | 
						struct wlr_geometry *dest = *geo_dest;
 | 
				
			||||||
 | 
						bool a_empty = wlr_geometry_empty(geo_a);
 | 
				
			||||||
 | 
						bool b_empty = wlr_geometry_empty(geo_b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (a_empty && b_empty) {
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						} else if (a_empty) {
 | 
				
			||||||
 | 
							dest->x = geo_b->x;
 | 
				
			||||||
 | 
							dest->y = geo_b->y;
 | 
				
			||||||
 | 
							dest->height = geo_b->height;
 | 
				
			||||||
 | 
							dest->width = geo_b->width;
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						} else if (b_empty) {
 | 
				
			||||||
 | 
							dest->x = geo_a->x;
 | 
				
			||||||
 | 
							dest->y = geo_a->y;
 | 
				
			||||||
 | 
							dest->height = geo_a->height;
 | 
				
			||||||
 | 
							dest->width = geo_a->width;
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int x1 = max(geo_a->x, geo_b->x);
 | 
				
			||||||
 | 
						int y1 = max(geo_a->y, geo_b->y);
 | 
				
			||||||
 | 
						int x2 = min(geo_a->x + geo_a->width, geo_b->x + geo_b->width);
 | 
				
			||||||
 | 
						int y2 = min(geo_a->y + geo_a->height, geo_b->y + geo_b->height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dest->x = x1;
 | 
				
			||||||
 | 
						dest->y = y1;
 | 
				
			||||||
 | 
						dest->width = x2 - x1;
 | 
				
			||||||
 | 
						dest->height = y2 - y1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return !wlr_geometry_empty(dest);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool wlr_geometry_contains_point(struct wlr_geometry *geo, int x, int y) {
 | 
				
			||||||
 | 
						return x >= geo->x && x <= geo->x + geo->width &&
 | 
				
			||||||
 | 
							y >= geo->y && y <= geo->y + geo->height;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue