mirror of
https://gitlab.freedesktop.org/xorg/xserver.git
synced 2026-01-04 05:10:13 +01:00
Merge branch 'xwayland-cursor-scale' into 'master'
Draft: xwayland: Track and apply output scales for tablet cursors Closes #1824 See merge request xorg/xserver!2033
This commit is contained in:
commit
1247821301
6 changed files with 185 additions and 43 deletions
|
|
@ -181,6 +181,26 @@ xwl_cursor_clear_frame_cb(struct xwl_cursor *xwl_cursor)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_seat_set_pointer_surface(struct xwl_seat *xwl_seat)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_seat->xwl_screen;
|
||||
struct xwl_cursor *xwl_cursor = &xwl_seat->cursor;
|
||||
int xhot, yhot;
|
||||
|
||||
if (!xwl_seat->x_cursor)
|
||||
return;
|
||||
|
||||
xhot = xwl_seat->x_cursor->bits->xhot / xwl_screen->global_surface_scale;
|
||||
yhot = xwl_seat->x_cursor->bits->yhot / xwl_screen->global_surface_scale;
|
||||
|
||||
wl_pointer_set_cursor(xwl_seat->wl_pointer,
|
||||
xwl_seat->pointer_enter_serial,
|
||||
xwl_cursor->surface,
|
||||
xhot,
|
||||
yhot);
|
||||
}
|
||||
|
||||
void
|
||||
xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
|
||||
{
|
||||
|
|
@ -188,7 +208,6 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
|
|||
struct xwl_screen *xwl_screen = xwl_seat->xwl_screen;
|
||||
PixmapPtr pixmap;
|
||||
CursorPtr cursor;
|
||||
int xhot, yhot;
|
||||
|
||||
if (!xwl_seat->wl_pointer)
|
||||
return;
|
||||
|
|
@ -215,18 +234,31 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
|
|||
|
||||
xwl_cursor_copy_bits_to_pixmap(cursor, pixmap);
|
||||
|
||||
xhot = xwl_seat->x_cursor->bits->xhot / xwl_screen->global_surface_scale;
|
||||
yhot = xwl_seat->x_cursor->bits->yhot / xwl_screen->global_surface_scale;
|
||||
|
||||
wl_pointer_set_cursor(xwl_seat->wl_pointer,
|
||||
xwl_seat->pointer_enter_serial,
|
||||
xwl_cursor->surface,
|
||||
xhot,
|
||||
yhot);
|
||||
xwl_seat_set_pointer_surface(xwl_seat);
|
||||
|
||||
xwl_cursor_attach_pixmap(xwl_seat, xwl_cursor, pixmap);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_tablet_tool_set_pointer_surface(struct xwl_tablet_tool *xwl_tablet_tool)
|
||||
{
|
||||
struct xwl_cursor *xwl_cursor = &xwl_tablet_tool->cursor;
|
||||
struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
|
||||
int xhot, yhot;
|
||||
|
||||
if (!xwl_seat->x_cursor)
|
||||
return;
|
||||
|
||||
xhot = xwl_seat->x_cursor->bits->xhot / xwl_cursor->surface_scale;
|
||||
yhot = xwl_seat->x_cursor->bits->yhot / xwl_cursor->surface_scale;
|
||||
|
||||
zwp_tablet_tool_v2_set_cursor(xwl_tablet_tool->tool,
|
||||
xwl_tablet_tool->proximity_in_serial,
|
||||
xwl_cursor->surface,
|
||||
xhot,
|
||||
yhot);
|
||||
}
|
||||
|
||||
void
|
||||
xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *xwl_tablet_tool)
|
||||
{
|
||||
|
|
@ -235,7 +267,6 @@ xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *xwl_tablet_tool)
|
|||
struct xwl_cursor *xwl_cursor = &xwl_tablet_tool->cursor;
|
||||
PixmapPtr pixmap;
|
||||
CursorPtr cursor;
|
||||
int xhot, yhot;
|
||||
|
||||
if (!xwl_seat->x_cursor) {
|
||||
zwp_tablet_tool_v2_set_cursor(xwl_tablet_tool->tool,
|
||||
|
|
@ -260,25 +291,11 @@ xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *xwl_tablet_tool)
|
|||
|
||||
xwl_cursor_copy_bits_to_pixmap(cursor, pixmap);
|
||||
|
||||
xhot = xwl_seat->x_cursor->bits->xhot / xwl_screen->global_surface_scale;
|
||||
yhot = xwl_seat->x_cursor->bits->yhot / xwl_screen->global_surface_scale;
|
||||
|
||||
zwp_tablet_tool_v2_set_cursor(xwl_tablet_tool->tool,
|
||||
xwl_tablet_tool->proximity_in_serial,
|
||||
xwl_cursor->surface,
|
||||
xhot,
|
||||
yhot);
|
||||
xwl_tablet_tool_set_pointer_surface(xwl_tablet_tool);
|
||||
|
||||
xwl_cursor_attach_pixmap(xwl_seat, xwl_cursor, pixmap);
|
||||
}
|
||||
|
||||
void
|
||||
xwl_cursor_release(struct xwl_cursor *xwl_cursor)
|
||||
{
|
||||
wl_surface_destroy(xwl_cursor->surface);
|
||||
xwl_cursor_clear_frame_cb(xwl_cursor);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_seat_update_all_cursors(struct xwl_seat *xwl_seat)
|
||||
{
|
||||
|
|
@ -295,6 +312,25 @@ xwl_seat_update_all_cursors(struct xwl_seat *xwl_seat)
|
|||
xwl_seat->pending_x_cursor = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_cursor_free_outputs(struct xwl_cursor *xwl_cursor)
|
||||
{
|
||||
struct xwl_surface_output *surface_output, *tmp;
|
||||
|
||||
xorg_list_for_each_entry_safe(surface_output, tmp, &xwl_cursor->xwl_output_list, link) {
|
||||
xorg_list_del(&surface_output->link);
|
||||
free(surface_output);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xwl_cursor_release(struct xwl_cursor *xwl_cursor)
|
||||
{
|
||||
wl_surface_destroy(xwl_cursor->surface);
|
||||
xwl_cursor_clear_frame_cb(xwl_cursor);
|
||||
xwl_cursor_free_outputs(xwl_cursor);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_seat_update_cursor_visibility(struct xwl_seat *xwl_seat)
|
||||
{
|
||||
|
|
@ -438,3 +474,94 @@ xwl_screen_init_cursor(struct xwl_screen *xwl_screen)
|
|||
&xwl_pointer_sprite_funcs,
|
||||
&xwl_pointer_screen_funcs, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_cursor_enter_output(struct xwl_cursor *xwl_cursor, struct xwl_output *xwl_output)
|
||||
{
|
||||
struct xwl_surface_output *surface_output;
|
||||
|
||||
surface_output = XNFcallocarray(1, sizeof(struct xwl_surface_output));
|
||||
surface_output->xwl_output = xwl_output;
|
||||
xorg_list_add(&surface_output->link, &xwl_cursor->xwl_output_list);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_cursor_leave_output(struct xwl_cursor *xwl_cursor, struct xwl_output *xwl_output)
|
||||
{
|
||||
struct xwl_surface_output *surface_output, *tmp;
|
||||
|
||||
xorg_list_for_each_entry_safe(surface_output, tmp, &xwl_cursor->xwl_output_list, link) {
|
||||
if (surface_output->xwl_output == xwl_output) {
|
||||
xorg_list_del(&surface_output->link);
|
||||
free(surface_output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
xwl_cursor_get_max_output_scale(struct xwl_cursor *xwl_cursor)
|
||||
{
|
||||
struct xwl_surface_output *surface_output;
|
||||
struct xwl_output *xwl_output;
|
||||
int scale = 1;
|
||||
|
||||
xorg_list_for_each_entry(surface_output, &xwl_cursor->xwl_output_list, link) {
|
||||
xwl_output = surface_output->xwl_output;
|
||||
if (xwl_output->scale > scale)
|
||||
scale = xwl_output->scale;
|
||||
}
|
||||
|
||||
return scale;
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_cursor_update_surface_scale(struct xwl_cursor *xwl_cursor)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_cursor->xwl_screen;
|
||||
struct xwl_tablet_tool *xwl_tablet_tool;
|
||||
struct xwl_seat *xwl_seat;
|
||||
|
||||
xwl_cursor->surface_scale = xwl_cursor_get_max_output_scale(xwl_cursor);
|
||||
|
||||
xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) {
|
||||
if (&xwl_seat->cursor == xwl_cursor)
|
||||
xwl_seat_set_pointer_surface(xwl_seat);
|
||||
|
||||
xorg_list_for_each_entry(xwl_tablet_tool, &xwl_seat->tablet_tools, link) {
|
||||
if (xwl_tablet_tool->proximity_in_serial == 0)
|
||||
continue;
|
||||
if (&xwl_tablet_tool->cursor == xwl_cursor)
|
||||
xwl_tablet_tool_set_pointer_surface(xwl_tablet_tool);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xwl_cursor_surface_enter(void *data,
|
||||
struct wl_surface *wl_surface,
|
||||
struct wl_output *wl_output)
|
||||
{
|
||||
struct xwl_cursor *xwl_cursor = data;
|
||||
struct xwl_screen *xwl_screen = xwl_cursor->xwl_screen;
|
||||
struct xwl_output *xwl_output = xwl_output_from_wl_output(xwl_screen, wl_output);
|
||||
|
||||
if (xwl_output) {
|
||||
xwl_cursor_enter_output(xwl_cursor, xwl_output);
|
||||
xwl_cursor_update_surface_scale(xwl_cursor);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xwl_cursor_surface_leave(void *data,
|
||||
struct wl_surface *wl_surface,
|
||||
struct wl_output *wl_output)
|
||||
{
|
||||
struct xwl_cursor *xwl_cursor = data;
|
||||
struct xwl_screen *xwl_screen = xwl_cursor->xwl_screen;
|
||||
struct xwl_output *xwl_output = xwl_output_from_wl_output(xwl_screen, wl_output);
|
||||
|
||||
if (xwl_output) {
|
||||
xwl_cursor_leave_output(xwl_cursor, xwl_output);
|
||||
xwl_cursor_update_surface_scale(xwl_cursor);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,5 +36,8 @@ void xwl_cursor_release(struct xwl_cursor *xwl_cursor);
|
|||
void xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *tool);
|
||||
void xwl_seat_set_cursor(struct xwl_seat *xwl_seat);
|
||||
Bool xwl_screen_init_cursor(struct xwl_screen *xwl_screen);
|
||||
|
||||
void xwl_cursor_surface_enter(void *data,
|
||||
struct wl_surface *wl_surface, struct wl_output *wl_output);
|
||||
void xwl_cursor_surface_leave(void *data,
|
||||
struct wl_surface *wl_surface, struct wl_output *wl_output);
|
||||
#endif /* XWAYLAND_CURSOR_H */
|
||||
|
|
|
|||
|
|
@ -1938,14 +1938,23 @@ static const struct wl_seat_listener seat_listener = {
|
|||
seat_handle_name
|
||||
};
|
||||
|
||||
static const struct wl_surface_listener surface_listener = {
|
||||
xwl_cursor_surface_enter,
|
||||
xwl_cursor_surface_leave
|
||||
};
|
||||
|
||||
static void
|
||||
xwl_cursor_init(struct xwl_cursor *xwl_cursor, struct xwl_screen *xwl_screen,
|
||||
void (* update_proc)(struct xwl_cursor *))
|
||||
{
|
||||
xwl_cursor->xwl_screen = xwl_screen;
|
||||
xwl_cursor->surface = wl_compositor_create_surface(xwl_screen->compositor);
|
||||
xwl_cursor->update_proc = update_proc;
|
||||
xwl_cursor->frame_cb = NULL;
|
||||
xwl_cursor->needs_update = FALSE;
|
||||
xwl_cursor->surface_scale = 1;
|
||||
xorg_list_init(&xwl_cursor->xwl_output_list);
|
||||
wl_surface_add_listener(xwl_cursor->surface, &surface_listener, xwl_cursor);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -47,10 +47,13 @@ struct xwl_pointer_warp_emulator {
|
|||
};
|
||||
|
||||
struct xwl_cursor {
|
||||
struct xwl_screen *xwl_screen;
|
||||
void (* update_proc) (struct xwl_cursor *);
|
||||
struct wl_surface *surface;
|
||||
struct wl_callback *frame_cb;
|
||||
struct xorg_list xwl_output_list;
|
||||
Bool needs_update;
|
||||
int surface_scale;
|
||||
};
|
||||
|
||||
struct xwl_seat {
|
||||
|
|
|
|||
|
|
@ -1087,22 +1087,22 @@ xwl_window_update_surface_scale(struct xwl_window *xwl_window)
|
|||
static void
|
||||
xwl_window_enter_output(struct xwl_window *xwl_window, struct xwl_output *xwl_output)
|
||||
{
|
||||
struct xwl_window_output *window_output;
|
||||
struct xwl_surface_output *surface_output;
|
||||
|
||||
window_output = XNFcallocarray(1, sizeof(struct xwl_window_output));
|
||||
window_output->xwl_output = xwl_output;
|
||||
xorg_list_add(&window_output->link, &xwl_window->xwl_output_list);
|
||||
surface_output = XNFcallocarray(1, sizeof(struct xwl_surface_output));
|
||||
surface_output->xwl_output = xwl_output;
|
||||
xorg_list_add(&surface_output->link, &xwl_window->xwl_output_list);
|
||||
}
|
||||
|
||||
void
|
||||
xwl_window_leave_output(struct xwl_window *xwl_window, struct xwl_output *xwl_output)
|
||||
{
|
||||
struct xwl_window_output *window_output, *tmp;
|
||||
struct xwl_surface_output *surface_output, *tmp;
|
||||
|
||||
xorg_list_for_each_entry_safe(window_output, tmp, &xwl_window->xwl_output_list, link) {
|
||||
if (window_output->xwl_output == xwl_output) {
|
||||
xorg_list_del(&window_output->link);
|
||||
free(window_output);
|
||||
xorg_list_for_each_entry_safe(surface_output, tmp, &xwl_window->xwl_output_list, link) {
|
||||
if (surface_output->xwl_output == xwl_output) {
|
||||
xorg_list_del(&surface_output->link);
|
||||
free(surface_output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1110,23 +1110,23 @@ xwl_window_leave_output(struct xwl_window *xwl_window, struct xwl_output *xwl_ou
|
|||
static void
|
||||
xwl_window_free_outputs(struct xwl_window *xwl_window)
|
||||
{
|
||||
struct xwl_window_output *window_output, *tmp;
|
||||
struct xwl_surface_output *surface_output, *tmp;
|
||||
|
||||
xorg_list_for_each_entry_safe(window_output, tmp, &xwl_window->xwl_output_list, link) {
|
||||
xorg_list_del(&window_output->link);
|
||||
free(window_output);
|
||||
xorg_list_for_each_entry_safe(surface_output, tmp, &xwl_window->xwl_output_list, link) {
|
||||
xorg_list_del(&surface_output->link);
|
||||
free(surface_output);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
xwl_window_get_max_output_scale(struct xwl_window *xwl_window)
|
||||
{
|
||||
struct xwl_window_output *window_output;
|
||||
struct xwl_surface_output *surface_output;
|
||||
struct xwl_output *xwl_output;
|
||||
int scale = 1;
|
||||
|
||||
xorg_list_for_each_entry(window_output, &xwl_window->xwl_output_list, link) {
|
||||
xwl_output = window_output->xwl_output;
|
||||
xorg_list_for_each_entry(surface_output, &xwl_window->xwl_output_list, link) {
|
||||
xwl_output = surface_output->xwl_output;
|
||||
if (xwl_output->scale > scale)
|
||||
scale = xwl_output->scale;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ struct xwl_wl_surface {
|
|||
struct xorg_list link;
|
||||
};
|
||||
|
||||
struct xwl_window_output {
|
||||
struct xwl_surface_output {
|
||||
struct xorg_list link;
|
||||
struct xwl_output *xwl_output;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue