forked from 12to11/12to11
Fix dispatch of leave events with built-in move
* 12to11-test.xml (test_manager) <error>: New error `resize_rejected'. <resize_edge>: New enum. (test_surface) <move_resize, resize_finished>: New events and requests. * compositor.h: Update prototypes. * seat.c (CancelResizeOperation): Fix dangling pointer. (FakePointerEdge): (HandlePointerEdge): Always use builtin resize on test seats. (XLMoveToplevel): Return status code. * test.c (struct _TestSurface): New field `resize_callbacks'. (HandleResizeDone): New function. (DestroyBacking): Free resize callbacks. (GetResizeDimensions, MoveResize): New functions. (test_surface_impl, GetTestSurface): Attach new role hooks etc. * tests/seat_test.c (enum test_expect_event_kind): New event kind. (struct test_recorded_button_event): Add serial field. Set it. (struct test_recorded_resize_finished_event): New struct. (enum test_kind): New test. (test_names): Name that test. (LAST_TEST): Set it to the new test. (run_resize_test, test_single_step): Implement the new test. (expect_button_event): Return the serial of the button event. (expect_surface_enter, handle_test_surface_resize_finished) (test_surface_listener, handle_pointer_button) (handle_keyboard_enter): Adjust for changes to event handling.
This commit is contained in:
parent
3213ef6493
commit
bd3d0a96e0
5 changed files with 281 additions and 16 deletions
|
@ -55,6 +55,26 @@
|
|||
summary="the specified label is invalid"/>
|
||||
<entry name="invalid_user_time" value="12"
|
||||
summary="the specified user time lies in the past"/>
|
||||
<entry name="resize_rejected" value="13"
|
||||
summary="the resize was rejected"/>
|
||||
</enum>
|
||||
|
||||
|
||||
<enum name="resize_edge">
|
||||
<description summary="edge values for resizing">
|
||||
These values are used to indicate which edge of a surface
|
||||
is being dragged in a resize or move operation.
|
||||
</description>
|
||||
<entry name="none" value="0"/>
|
||||
<entry name="top" value="1"/>
|
||||
<entry name="bottom" value="2"/>
|
||||
<entry name="left" value="4"/>
|
||||
<entry name="top_left" value="5"/>
|
||||
<entry name="bottom_left" value="6"/>
|
||||
<entry name="right" value="8"/>
|
||||
<entry name="top_right" value="9"/>
|
||||
<entry name="bottom_right" value="10"/>
|
||||
<entry name="move" value="11"/>
|
||||
</enum>
|
||||
|
||||
<request name="get_test_surface">
|
||||
|
@ -155,12 +175,25 @@
|
|||
</request>
|
||||
|
||||
<request name="set_always_garbage">
|
||||
<description summary="set_always_garbage">
|
||||
<description summary="set always garbage">
|
||||
Force the subcompositor to be garbaged, and all contents
|
||||
redrawn from scratch upon any damage.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="move_resize">
|
||||
<description summary="begin move or resize">
|
||||
Begin a move or resize event with the specified resize edge
|
||||
and event serial on the given seat. Send a resize_rejected
|
||||
event if the edge is invalid or the serial is out of date, or
|
||||
the specified role no longer has a surface.
|
||||
</description>
|
||||
<arg name="edge" type="uint" summary="the resize edge"/>
|
||||
<arg name="serial" type="uint" summary="the resize serial"/>
|
||||
<arg name="seat" type="object" interface="wl_seat"
|
||||
summary="the resize seat"/>
|
||||
</request>
|
||||
|
||||
<event name="mapped">
|
||||
<description summary="role initialized">
|
||||
The map event is sent once the window is mapped and its
|
||||
|
@ -208,6 +241,13 @@
|
|||
</description>
|
||||
<arg name="presentation_hint" type="uint"/>
|
||||
</event>
|
||||
|
||||
<event name="resize_finished">
|
||||
<description summary="resize finished">
|
||||
The resize_finished event is sent immediately after a resize
|
||||
completes.
|
||||
</description>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="test_scale_lock" version="1">
|
||||
|
|
|
@ -1632,7 +1632,7 @@ extern void XLDispatchGEForSeats (XEvent *, Surface *,
|
|||
extern void XLSelectStandardEvents (Window);
|
||||
extern void XLInitSeats (void);
|
||||
extern Bool XLResizeToplevel (Seat *, Surface *, uint32_t, uint32_t);
|
||||
extern void XLMoveToplevel (Seat *, Surface *, uint32_t);
|
||||
extern Bool XLMoveToplevel (Seat *, Surface *, uint32_t);
|
||||
extern Bool XLSeatExplicitlyGrabSurface (Seat *, Surface *, uint32_t);
|
||||
|
||||
extern void *XLSeatRunAfterResize (Seat *, void (*) (void *, void *),
|
||||
|
|
31
seat.c
31
seat.c
|
@ -2051,6 +2051,7 @@ CancelResizeOperation (Seat *seat, Time time, Subcompositor *subcompositor,
|
|||
/* Stop the resize operation. */
|
||||
XLSurfaceCancelUnmapCallback (seat->resize_surface_callback);
|
||||
seat->resize_surface = NULL;
|
||||
seat->resize_surface_callback = NULL;
|
||||
|
||||
/* Run resize completion callbacks. */
|
||||
RunResizeDoneCallbacks (seat);
|
||||
|
@ -5098,21 +5099,30 @@ FakePointerEdge (Seat *seat, Surface *target, uint32_t serial,
|
|||
XISetMask (mask.mask, XI_ButtonPress);
|
||||
XISetMask (mask.mask, XI_ButtonRelease);
|
||||
|
||||
/* Grab the pointer, and don't let go until the button is
|
||||
released. */
|
||||
state = XIGrabDevice (compositor.display, seat->master_pointer,
|
||||
window, seat->its_press_time, cursor,
|
||||
XIGrabModeAsync, XIGrabModeAsync, False, &mask);
|
||||
if (!(seat->flags & IsTestSeat))
|
||||
{
|
||||
/* Grab the pointer, and don't let go until the button is
|
||||
released. */
|
||||
state = XIGrabDevice (compositor.display, seat->master_pointer,
|
||||
window, seat->its_press_time, cursor,
|
||||
XIGrabModeAsync, XIGrabModeAsync, False, &mask);
|
||||
|
||||
if (state != Success)
|
||||
return False;
|
||||
if (state != Success)
|
||||
return False;
|
||||
}
|
||||
|
||||
/* On the other hand, cancel focus locking and leave the surface,
|
||||
since we will not be reporting motion events until the resize
|
||||
operation completes. */
|
||||
|
||||
if (seat->grab_held)
|
||||
CancelGrabEarly (seat);
|
||||
{
|
||||
CancelGrabEarly (seat);
|
||||
|
||||
/* CancelGrabEarly may not have left the focus surface if the
|
||||
pointer remains on it. Force a leave event to be sent. */
|
||||
EnteredSurface (seat, NULL, seat->its_press_time, 0, 0, False);
|
||||
}
|
||||
|
||||
/* Set the surface as the surface undergoing resize. */
|
||||
seat->resize_surface = target;
|
||||
|
@ -5139,6 +5149,7 @@ HandlePointerEdge (Seat *seat, Surface *target, uint32_t serial,
|
|||
return False;
|
||||
|
||||
if (!XLWmSupportsHint (_NET_WM_MOVERESIZE)
|
||||
|| (seat->flags & IsTestSeat)
|
||||
|| getenv ("USE_BUILTIN_RESIZE"))
|
||||
return FakePointerEdge (seat, target, serial, edge);
|
||||
|
||||
|
@ -5417,10 +5428,10 @@ XLResizeToplevel (Seat *seat, Surface *surface, uint32_t serial,
|
|||
return StartResizeTracking (seat, surface, serial, edge);
|
||||
}
|
||||
|
||||
void
|
||||
Bool
|
||||
XLMoveToplevel (Seat *seat, Surface *surface, uint32_t serial)
|
||||
{
|
||||
StartResizeTracking (seat, surface, serial, MoveEdge);
|
||||
return StartResizeTracking (seat, surface, serial, MoveEdge);
|
||||
}
|
||||
|
||||
void *
|
||||
|
|
69
test.c
69
test.c
|
@ -47,6 +47,9 @@ struct _TestSurface
|
|||
/* The associated buffer release helper. */
|
||||
BufferReleaseHelper *release_helper;
|
||||
|
||||
/* List of live resize callbacks. */
|
||||
XLList *resize_callbacks;
|
||||
|
||||
/* The associated window. */
|
||||
Window window;
|
||||
|
||||
|
@ -71,6 +74,19 @@ static struct wl_global *test_manager_global;
|
|||
/* Hash table of all surfaces. */
|
||||
static XLAssocTable *surfaces;
|
||||
|
||||
static void
|
||||
HandleResizeDone (void *key, void *data)
|
||||
{
|
||||
TestSurface *test;
|
||||
|
||||
test = data;
|
||||
test->resize_callbacks
|
||||
= XLListRemove (test->resize_callbacks, key);
|
||||
|
||||
if (test->role.resource)
|
||||
test_surface_send_resize_finished (test->role.resource);
|
||||
}
|
||||
|
||||
static void
|
||||
DestroyBacking (TestSurface *test)
|
||||
{
|
||||
|
@ -90,6 +106,10 @@ DestroyBacking (TestSurface *test)
|
|||
/* Free the subcompositor. */
|
||||
SubcompositorFree (test->subcompositor);
|
||||
|
||||
/* Free all resize callbacks. */
|
||||
XLListFree (test->resize_callbacks,
|
||||
XLSeatCancelResizeCallback);
|
||||
|
||||
/* And since there are no C level references to the role anymore, it
|
||||
can be freed. */
|
||||
XLFree (test);
|
||||
|
@ -369,6 +389,18 @@ Activate (Surface *surface, Role *role, int deviceid,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
GetResizeDimensions (Surface *surface, Role *role, int *width,
|
||||
int *height)
|
||||
{
|
||||
TestSurface *test;
|
||||
|
||||
test = TestSurfaceFromRole (role);
|
||||
|
||||
*width = SubcompositorWidth (test->subcompositor);
|
||||
*height = SubcompositorHeight (test->subcompositor);
|
||||
}
|
||||
|
||||
static void
|
||||
SetAlwaysGarbage (struct wl_client *client, struct wl_resource *resource)
|
||||
{
|
||||
|
@ -380,10 +412,46 @@ SetAlwaysGarbage (struct wl_client *client, struct wl_resource *resource)
|
|||
SubcompositorSetAlwaysGarbaged (test->subcompositor);
|
||||
}
|
||||
|
||||
static void
|
||||
MoveResize (struct wl_client *client, struct wl_resource *resource,
|
||||
uint32_t edge, uint32_t serial,
|
||||
struct wl_resource *seat_resource)
|
||||
{
|
||||
TestSurface *test;
|
||||
Seat *seat;
|
||||
void *key;
|
||||
|
||||
test = wl_resource_get_user_data (resource);
|
||||
seat = wl_resource_get_user_data (seat_resource);
|
||||
|
||||
if (!test->role.surface)
|
||||
{
|
||||
wl_resource_post_error (resource, TEST_MANAGER_ERROR_RESIZE_REJECTED,
|
||||
"trying to resize test surface without surface");
|
||||
return;
|
||||
}
|
||||
|
||||
if (edge == TEST_MANAGER_RESIZE_EDGE_MOVE)
|
||||
{
|
||||
if (!XLMoveToplevel (seat, test->role.surface, serial))
|
||||
wl_resource_post_error (resource, TEST_MANAGER_ERROR_RESIZE_REJECTED,
|
||||
"move rejected for unspecified reason");
|
||||
}
|
||||
else if (!XLResizeToplevel (seat, test->role.surface, serial, edge))
|
||||
wl_resource_post_error (resource, TEST_MANAGER_ERROR_RESIZE_REJECTED,
|
||||
"resize rejected for unspecified reason");
|
||||
|
||||
/* Now attach a resize complete callback. */
|
||||
key = XLSeatRunAfterResize (seat, HandleResizeDone, test);
|
||||
test->resize_callbacks = XLListPrepend (test->resize_callbacks,
|
||||
key);
|
||||
}
|
||||
|
||||
static const struct test_surface_interface test_surface_impl =
|
||||
{
|
||||
.destroy = Destroy,
|
||||
.set_always_garbage = SetAlwaysGarbage,
|
||||
.move_resize = MoveResize,
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -535,6 +603,7 @@ GetTestSurface (struct wl_client *client, struct wl_resource *resource,
|
|||
test->role.funcs.subsurface_update = SubsurfaceUpdate;
|
||||
test->role.funcs.get_window = GetWindow;
|
||||
test->role.funcs.activate = Activate;
|
||||
test->role.funcs.get_resize_dimensions = GetResizeDimensions;
|
||||
|
||||
/* Add the resource implementation. */
|
||||
wl_resource_set_implementation (test->role.resource, &test_surface_impl,
|
||||
|
|
|
@ -33,6 +33,7 @@ enum test_expect_event_kind
|
|||
KEYBOARD_ENTER_EVENT,
|
||||
KEYBOARD_KEY_EVENT,
|
||||
KEYBOARD_MODIFIERS_EVENT,
|
||||
SURFACE_RESIZE_FINISHED_EVENT,
|
||||
};
|
||||
|
||||
struct test_recorded_event
|
||||
|
@ -84,6 +85,9 @@ struct test_recorded_button_event
|
|||
|
||||
/* The button and state. */
|
||||
uint32_t button, state;
|
||||
|
||||
/* The serial. */
|
||||
uint32_t serial;
|
||||
};
|
||||
|
||||
struct test_recorded_axis_value120_event
|
||||
|
@ -137,6 +141,12 @@ struct test_recorded_keyboard_modifiers_event
|
|||
uint32_t group;
|
||||
};
|
||||
|
||||
struct test_recorded_resize_finished_event
|
||||
{
|
||||
/* The event header. */
|
||||
struct test_recorded_event header;
|
||||
};
|
||||
|
||||
struct test_subsurface
|
||||
{
|
||||
/* The subsurface itself. */
|
||||
|
@ -154,6 +164,7 @@ enum test_kind
|
|||
TEST_GRAB_KIND,
|
||||
TEST_VALUATOR_KIND,
|
||||
TEST_KEY_KIND,
|
||||
TEST_RESIZE_KIND,
|
||||
};
|
||||
|
||||
static const char *test_names[] =
|
||||
|
@ -164,9 +175,10 @@ static const char *test_names[] =
|
|||
"test_grab",
|
||||
"test_valuator",
|
||||
"test_key",
|
||||
"test_resize",
|
||||
};
|
||||
|
||||
#define LAST_TEST TEST_KEY_KIND
|
||||
#define LAST_TEST TEST_RESIZE_KIND
|
||||
#define TEST_SOURCE_DEVICE 4500000
|
||||
|
||||
/* The display. */
|
||||
|
@ -206,13 +218,14 @@ static void expect_frame_event (void);
|
|||
static void expect_enter_event (struct wl_surface *, double, double);
|
||||
static void expect_motion_event (double, double);
|
||||
static void expect_leave_event (void);
|
||||
static void expect_button_event (int, int);
|
||||
static uint32_t expect_button_event (int, int);
|
||||
static void expect_axis_value120_event (uint32_t, int32_t);
|
||||
static void expect_keyboard_enter_event (struct wl_surface *, uint32_t *,
|
||||
size_t);
|
||||
static void expect_keyboard_key_event (uint32_t, uint32_t);
|
||||
static void expect_keyboard_modifiers_event (uint32_t, uint32_t,
|
||||
uint32_t, uint32_t);
|
||||
static void expect_resize_finished_event (void);
|
||||
static void expect_no_events (void);
|
||||
|
||||
|
||||
|
@ -749,6 +762,62 @@ run_key_test (void)
|
|||
expect_keyboard_enter_event (wayland_surface, NULL, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
run_resize_test (struct test_XIButtonState *button_state)
|
||||
{
|
||||
uint32_t serial;
|
||||
|
||||
test_seat_controller_dispatch_XI_ButtonPress (display->seat->controller,
|
||||
test_get_time (),
|
||||
TEST_SOURCE_DEVICE,
|
||||
1,
|
||||
test_get_root (),
|
||||
test_surface_window,
|
||||
None,
|
||||
wl_fixed_from_double (2.0),
|
||||
wl_fixed_from_double (2.0),
|
||||
wl_fixed_from_double (2.0),
|
||||
wl_fixed_from_double (2.0),
|
||||
0,
|
||||
button_state,
|
||||
NULL, NULL, NULL);
|
||||
test_XIButtonState_add_button (button_state, 1);
|
||||
record_events ();
|
||||
|
||||
/* Obtain the serial. */
|
||||
expect_frame_event ();
|
||||
serial = expect_button_event (BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED);
|
||||
expect_no_events ();
|
||||
|
||||
/* Now, start resize. */
|
||||
test_surface_move_resize (test_surface, TEST_MANAGER_RESIZE_EDGE_MOVE,
|
||||
serial, display->seat->seat);
|
||||
|
||||
/* And dispatch the button release. */
|
||||
test_seat_controller_dispatch_XI_ButtonRelease (display->seat->controller,
|
||||
test_get_time (),
|
||||
TEST_SOURCE_DEVICE,
|
||||
1,
|
||||
test_get_root (),
|
||||
test_surface_window,
|
||||
None,
|
||||
wl_fixed_from_double (2.0),
|
||||
wl_fixed_from_double (2.0),
|
||||
wl_fixed_from_double (2.0),
|
||||
wl_fixed_from_double (2.0),
|
||||
0,
|
||||
button_state,
|
||||
NULL, NULL, NULL);
|
||||
test_XIButtonState_remove_button (button_state, 1);
|
||||
|
||||
record_events ();
|
||||
expect_frame_event ();
|
||||
expect_enter_event (wayland_surface, 2.0, 2.0);
|
||||
expect_resize_finished_event ();
|
||||
expect_frame_event ();
|
||||
expect_leave_event ();
|
||||
}
|
||||
|
||||
static void
|
||||
test_single_step (enum test_kind kind)
|
||||
{
|
||||
|
@ -1007,6 +1076,24 @@ test_single_step (enum test_kind kind)
|
|||
key (SERIAL, TIME, 59, WL_KEYBOARD_KEY_STATE_RELEASED) */
|
||||
|
||||
run_key_test ();
|
||||
kind = TEST_RESIZE_KIND;
|
||||
goto again;
|
||||
|
||||
case TEST_RESIZE_KIND:
|
||||
/* Test simple resize (or rather movement). Dispatch a
|
||||
ButtonPress event, obtain the serial of said event, start
|
||||
resize, and dispatch a ButtonRelease event. Verify that the
|
||||
following events are sent to the pointer and surface.
|
||||
|
||||
button (SERIAL, TIME, BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED)
|
||||
frame ()
|
||||
leave ()
|
||||
resize_finished ()
|
||||
frame ();
|
||||
enter (SERIAL, SURFACE, 2.0, 2.0)
|
||||
frame (); */
|
||||
|
||||
run_resize_test (button_state);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1118,11 +1205,12 @@ expect_leave_event (void)
|
|||
report_test_failure ("a leave event was expected, but not received");
|
||||
}
|
||||
|
||||
static void
|
||||
static uint32_t
|
||||
expect_button_event (int button, int state)
|
||||
{
|
||||
struct test_recorded_event *event;
|
||||
struct test_recorded_button_event *button_event;
|
||||
uint32_t serial;
|
||||
|
||||
event = record_tail;
|
||||
|
||||
|
@ -1136,7 +1224,12 @@ expect_button_event (int button, int state)
|
|||
button_event = (struct test_recorded_button_event *) event;
|
||||
|
||||
if (button_event->button == button && button_event->state == state)
|
||||
free (event);
|
||||
{
|
||||
serial = button_event->serial;
|
||||
free (event);
|
||||
|
||||
return serial;
|
||||
}
|
||||
else
|
||||
report_test_failure ("expected button event received "
|
||||
"with incorrect parameters");
|
||||
|
@ -1283,6 +1376,25 @@ expect_no_events (void)
|
|||
"yet some arrived");
|
||||
}
|
||||
|
||||
static void
|
||||
expect_resize_finished_event (void)
|
||||
{
|
||||
struct test_recorded_event *event;
|
||||
|
||||
event = record_tail;
|
||||
|
||||
if (!event)
|
||||
return;
|
||||
|
||||
record_tail = record_tail->last;
|
||||
|
||||
if (event->kind == SURFACE_RESIZE_FINISHED_EVENT)
|
||||
free (event);
|
||||
else
|
||||
report_test_failure ("expected resize_finished_event, but it was"
|
||||
" not received");
|
||||
}
|
||||
|
||||
static void
|
||||
expect_surface_enter (double x, double y)
|
||||
{
|
||||
|
@ -1331,11 +1443,42 @@ handle_test_surface_committed (void *data, struct test_surface *surface,
|
|||
|
||||
}
|
||||
|
||||
static void
|
||||
handle_test_surface_resize_finished (void *data, struct test_surface *surface)
|
||||
{
|
||||
struct test_recorded_resize_finished_event *event;
|
||||
|
||||
if (!recording_events)
|
||||
{
|
||||
test_log ("ignored resize finish event");
|
||||
return;
|
||||
}
|
||||
|
||||
event = malloc (sizeof *event);
|
||||
|
||||
if (!event)
|
||||
report_test_failure ("failed to record event");
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
|
||||
#endif
|
||||
|
||||
event->header.kind = SURFACE_RESIZE_FINISHED_EVENT;
|
||||
event->header.last = record_tail;
|
||||
record_tail = &event->header;
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
}
|
||||
|
||||
static const struct test_surface_listener test_surface_listener =
|
||||
{
|
||||
handle_test_surface_mapped,
|
||||
NULL,
|
||||
handle_test_surface_committed,
|
||||
handle_test_surface_resize_finished,
|
||||
};
|
||||
|
||||
|
||||
|
@ -1475,6 +1618,7 @@ handle_pointer_button (void *data, struct wl_pointer *wl_pointer,
|
|||
|
||||
event->button = button;
|
||||
event->state = state;
|
||||
event->serial = serial;
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
|
@ -1634,6 +1778,7 @@ handle_keyboard_enter (void *data, struct wl_keyboard *keyboard,
|
|||
|
||||
memcpy (event->keys, keys->data, keys->size);
|
||||
event->num_keys = keys->size / sizeof (uint32_t);
|
||||
event->surface = surface;
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
|
|
Loading…
Add table
Reference in a new issue