compositor: Make pointers visible when an output is unplugged
Previously, if a pointer was inside an output that was unplugged, it could potentialy end up outside any valid output forever. With this patch, the pointer is moved to the "closest" output to the pointer.
This commit is contained in:
committed by
Kristian Høgsberg
parent
e1e2352dcc
commit
54e90c7e1e
@@ -3105,6 +3105,19 @@ weston_compositor_remove_output(struct weston_compositor *compositor,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
weston_compositor_verify_pointers(struct weston_compositor *ec)
|
||||||
|
{
|
||||||
|
struct weston_seat *seat;
|
||||||
|
|
||||||
|
wl_list_for_each(seat, &ec->seat_list, link) {
|
||||||
|
if (!seat->pointer)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
weston_pointer_verify(seat->pointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
WL_EXPORT void
|
WL_EXPORT void
|
||||||
weston_output_destroy(struct weston_output *output)
|
weston_output_destroy(struct weston_output *output)
|
||||||
{
|
{
|
||||||
@@ -3113,6 +3126,8 @@ weston_output_destroy(struct weston_output *output)
|
|||||||
weston_compositor_remove_output(output->compositor, output);
|
weston_compositor_remove_output(output->compositor, output);
|
||||||
wl_list_remove(&output->link);
|
wl_list_remove(&output->link);
|
||||||
|
|
||||||
|
weston_compositor_verify_pointers(output->compositor);
|
||||||
|
|
||||||
wl_signal_emit(&output->destroy_signal, output);
|
wl_signal_emit(&output->destroy_signal, output);
|
||||||
|
|
||||||
free(output->name);
|
free(output->name);
|
||||||
|
|||||||
@@ -375,6 +375,8 @@ weston_pointer_move(struct weston_pointer *pointer,
|
|||||||
void
|
void
|
||||||
weston_pointer_set_default_grab(struct weston_pointer *pointer,
|
weston_pointer_set_default_grab(struct weston_pointer *pointer,
|
||||||
const struct weston_pointer_grab_interface *interface);
|
const struct weston_pointer_grab_interface *interface);
|
||||||
|
void
|
||||||
|
weston_pointer_verify(struct weston_pointer *pointer);
|
||||||
|
|
||||||
struct weston_keyboard *
|
struct weston_keyboard *
|
||||||
weston_keyboard_create(void);
|
weston_keyboard_create(void);
|
||||||
|
|||||||
+64
-12
@@ -29,6 +29,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#include "../shared/os-compatibility.h"
|
#include "../shared/os-compatibility.h"
|
||||||
#include "compositor.h"
|
#include "compositor.h"
|
||||||
@@ -791,6 +792,28 @@ weston_touch_cancel_grab(struct weston_touch *touch)
|
|||||||
touch->grab->interface->cancel(touch->grab);
|
touch->grab->interface->cancel(touch->grab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
weston_pointer_clamp_for_output(struct weston_pointer *pointer,
|
||||||
|
struct weston_output *output,
|
||||||
|
wl_fixed_t *fx, wl_fixed_t *fy)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
x = wl_fixed_to_int(*fx);
|
||||||
|
y = wl_fixed_to_int(*fy);
|
||||||
|
|
||||||
|
if (x < output->x)
|
||||||
|
*fx = wl_fixed_from_int(output->x);
|
||||||
|
else if (x >= output->x + output->width)
|
||||||
|
*fx = wl_fixed_from_int(output->x +
|
||||||
|
output->width - 1);
|
||||||
|
if (y < output->y)
|
||||||
|
*fy = wl_fixed_from_int(output->y);
|
||||||
|
else if (y >= output->y + output->height)
|
||||||
|
*fy = wl_fixed_from_int(output->y +
|
||||||
|
output->height - 1);
|
||||||
|
}
|
||||||
|
|
||||||
WL_EXPORT void
|
WL_EXPORT void
|
||||||
weston_pointer_clamp(struct weston_pointer *pointer, wl_fixed_t *fx, wl_fixed_t *fy)
|
weston_pointer_clamp(struct weston_pointer *pointer, wl_fixed_t *fx, wl_fixed_t *fy)
|
||||||
{
|
{
|
||||||
@@ -817,18 +840,8 @@ weston_pointer_clamp(struct weston_pointer *pointer, wl_fixed_t *fx, wl_fixed_t
|
|||||||
if (!prev)
|
if (!prev)
|
||||||
prev = pointer->seat->output;
|
prev = pointer->seat->output;
|
||||||
|
|
||||||
if (prev && !valid) {
|
if (prev && !valid)
|
||||||
if (x < prev->x)
|
weston_pointer_clamp_for_output(pointer, prev, fx, fy);
|
||||||
*fx = wl_fixed_from_int(prev->x);
|
|
||||||
else if (x >= prev->x + prev->width)
|
|
||||||
*fx = wl_fixed_from_int(prev->x +
|
|
||||||
prev->width - 1);
|
|
||||||
if (y < prev->y)
|
|
||||||
*fy = wl_fixed_from_int(prev->y);
|
|
||||||
else if (y >= prev->y + prev->height)
|
|
||||||
*fy = wl_fixed_from_int(prev->y +
|
|
||||||
prev->height - 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Takes absolute values */
|
/* Takes absolute values */
|
||||||
@@ -856,6 +869,45 @@ weston_pointer_move(struct weston_pointer *pointer, wl_fixed_t x, wl_fixed_t y)
|
|||||||
wl_signal_emit(&pointer->motion_signal, pointer);
|
wl_signal_emit(&pointer->motion_signal, pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Verify if the pointer is in a valid position and move it if it isn't.
|
||||||
|
*/
|
||||||
|
WL_EXPORT void
|
||||||
|
weston_pointer_verify(struct weston_pointer *pointer)
|
||||||
|
{
|
||||||
|
struct weston_compositor *ec = pointer->seat->compositor;
|
||||||
|
struct weston_output *output, *closest = NULL;
|
||||||
|
int x, y, distance, min = INT_MAX;
|
||||||
|
wl_fixed_t fx, fy;
|
||||||
|
|
||||||
|
x = wl_fixed_to_int(pointer->x);
|
||||||
|
y = wl_fixed_to_int(pointer->y);
|
||||||
|
|
||||||
|
wl_list_for_each(output, &ec->output_list, link) {
|
||||||
|
if (pixman_region32_contains_point(&output->region,
|
||||||
|
x, y, NULL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Aproximante the distance from the pointer to the center of
|
||||||
|
* the output. */
|
||||||
|
distance = abs(output->x + output->width / 2 - x) +
|
||||||
|
abs(output->y + output->height / 2 - y);
|
||||||
|
if (distance < min) {
|
||||||
|
min = distance;
|
||||||
|
closest = output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nothing to do if there's no output left. */
|
||||||
|
if (!closest)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fx = pointer->x;
|
||||||
|
fy = pointer->y;
|
||||||
|
|
||||||
|
weston_pointer_clamp_for_output(pointer, closest, &fx, &fy);
|
||||||
|
weston_pointer_move(pointer, fx, fy);
|
||||||
|
}
|
||||||
|
|
||||||
WL_EXPORT void
|
WL_EXPORT void
|
||||||
notify_motion(struct weston_seat *seat,
|
notify_motion(struct weston_seat *seat,
|
||||||
uint32_t time, wl_fixed_t dx, wl_fixed_t dy)
|
uint32_t time, wl_fixed_t dx, wl_fixed_t dy)
|
||||||
|
|||||||
Reference in New Issue
Block a user