app: use gdk_seat_grab() instead of deprecated gdk_device_grab().

Additionally to fixing a deprecation, I also ensure that we don't limit
pointer source to what the system considers the "Core Pointer" on
Wayland.

It is another bug similar to #8016 and possibly what !924 was trying to
fix, even though it turned out this was not the same problem which I
initially reported. In this other variant, when you were hitting Space,
it would originate from the "Core Keyboard" which was associated to a
"Core Pointer". On a laptop, this Core Pointer could be the trackpoint
for instance (in my case) so you could pan with Space + trackpoint move.
Yet say you add a graphics tablet, which is a separate pointer: you
could not pan with Space + stylus move!

Now you can, because when we are pan-spacing, events from all pointer
sources are accepted. Only when the panning comes from a pointer source
(middle click) do we listen only events from this same pointer device.
This commit is contained in:
Jehan 2024-10-27 22:40:50 +01:00
parent 3a8825cf06
commit 0b4d104c15
3 changed files with 35 additions and 22 deletions

View File

@ -31,6 +31,7 @@
#include "gimpdisplayshell-grab.h"
#if 0
static GdkDevice *
get_associated_pointer (GdkDevice *device)
{
@ -58,45 +59,56 @@ get_associated_pointer (GdkDevice *device)
return device;
}
#endif
gboolean
gimp_display_shell_pointer_grab (GimpDisplayShell *shell,
const GdkEvent *event,
GdkEventMask event_mask)
{
GdkDisplay *display;
GdkSeat *seat;
GdkDevice *device;
GdkDevice *source_device;
GdkGrabStatus status;
g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
g_return_val_if_fail (shell->grab_pointer == NULL, FALSE);
g_return_val_if_fail (shell->grab_seat == NULL, FALSE);
source_device = gimp_devices_get_from_event (shell->display->gimp,
event, &device);
display = gdk_device_get_display (device);
seat = gdk_display_get_default_seat (display);
if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
{
device = get_associated_pointer (device);
/* When the source grab event was a keyboard, we want to accept
* pointer events from any pointing device. This is especially
* true on Wayland where each pointing device can be really
* independant whereas on X11, they all appear as "Virtual core
* pointer".
*/
device = NULL;
source_device = NULL;
}
status = gdk_device_grab (device,
status = gdk_seat_grab (seat,
gtk_widget_get_window (shell->canvas),
GDK_OWNERSHIP_APPLICATION,
FALSE, event_mask, NULL,
gdk_event_get_time (event));
GDK_SEAT_CAPABILITY_ALL_POINTING,
FALSE, NULL,
event, NULL, NULL);
if (status == GDK_GRAB_SUCCESS)
{
shell->grab_seat = seat;
shell->grab_pointer = device;
shell->grab_pointer_source = source_device;
shell->grab_pointer_time = gdk_event_get_time (event);
return TRUE;
}
g_printerr ("%s: gdk_device_grab(%s) failed with status %d\n",
g_printerr ("%s: gdk_seat_grab(%s) failed with status %d\n",
G_STRFUNC, gdk_device_get_name (device), status);
return FALSE;
@ -108,11 +120,11 @@ gimp_display_shell_pointer_ungrab (GimpDisplayShell *shell,
{
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
g_return_if_fail (event != NULL);
g_return_if_fail (shell->grab_pointer != NULL);
g_return_if_fail (shell->grab_seat != NULL);
gdk_device_ungrab (shell->grab_pointer, shell->grab_pointer_time);
gdk_seat_ungrab (shell->grab_seat);
shell->grab_seat = NULL;
shell->grab_pointer = NULL;
shell->grab_pointer_source = NULL;
shell->grab_pointer_time = 0;
}

View File

@ -410,7 +410,7 @@ gimp_display_shell_canvas_tool_events (GtkWidget *canvas,
return TRUE;
/* ignore enter notify while we have a grab */
if (shell->grab_pointer)
if (shell->grab_seat)
return TRUE;
gimp_display_shell_proximity_in (shell);
@ -431,7 +431,7 @@ gimp_display_shell_canvas_tool_events (GtkWidget *canvas,
return TRUE;
/* ignore leave notify while we have a grab */
if (shell->grab_pointer)
if (shell->grab_seat)
return TRUE;
gimp_display_shell_proximity_out (shell);
@ -471,7 +471,7 @@ gimp_display_shell_canvas_tool_events (GtkWidget *canvas,
g_warning ("%s: FOCUS_IN but canvas has no focus", G_STRFUNC);
/* ignore focus changes while we have a grab */
if (shell->grab_pointer)
if (shell->grab_seat)
return TRUE;
/* press modifier keys when the canvas gets the focus */
@ -484,7 +484,7 @@ gimp_display_shell_canvas_tool_events (GtkWidget *canvas,
g_warning ("%s: FOCUS_OUT but canvas has focus", G_STRFUNC);
/* ignore focus changes while we have a grab */
if (shell->grab_pointer)
if (shell->grab_seat)
return TRUE;
/* release modifier keys when the canvas loses the focus */
@ -502,7 +502,7 @@ gimp_display_shell_canvas_tool_events (GtkWidget *canvas,
/* ignore new mouse events */
if (gimp->busy ||
shell->mod_action != GIMP_MODIFIER_ACTION_NONE ||
shell->grab_pointer ||
shell->grab_seat ||
shell->button1_release_pending)
return TRUE;
@ -703,7 +703,7 @@ gimp_display_shell_canvas_tool_events (GtkWidget *canvas,
* a button press we intentionally ignored because we had
* a grab on another device at the time of the press
*/
if (! shell->grab_pointer || shell->mod_action != GIMP_MODIFIER_ACTION_NONE)
if (! shell->grab_seat || shell->mod_action != GIMP_MODIFIER_ACTION_NONE)
return TRUE;
if (active_tool &&
@ -1215,7 +1215,7 @@ gimp_display_shell_canvas_tool_events (GtkWidget *canvas,
/* We need to ungrab the pointer in order to catch
* button release events.
*/
if (shell->grab_pointer)
if (shell->grab_seat)
gimp_display_shell_pointer_ungrab (shell, event);
}
else
@ -1630,7 +1630,8 @@ gimp_display_shell_check_device (GimpDisplayShell *shell,
event->type != GDK_KEY_RELEASE &&
event->type != GDK_FOCUS_CHANGE)
{
if ((shell->grab_pointer && (shell->grab_pointer != grab_device)) ||
if (shell->grab_seat &&
(shell->grab_pointer && shell->grab_pointer != grab_device) &&
(shell->grab_pointer_source && (shell->grab_pointer_source != device)))
{
GIMP_LOG (TOOL_EVENTS,
@ -1813,7 +1814,7 @@ gimp_display_shell_stop_scrolling (GimpDisplayShell *shell,
/* We may have ungrabbed the pointer when space was released while
* mouse was down, to be able to catch a GDK_BUTTON_RELEASE event.
*/
if (shell->grab_pointer)
if (shell->grab_seat)
gimp_display_shell_pointer_ungrab (shell, event);
}

View File

@ -193,9 +193,9 @@ struct _GimpDisplayShell
gboolean size_allocate_center_image;
/* the state of gimp_display_shell_tool_events() */
GdkSeat *grab_seat;
GdkDevice *grab_pointer;
GdkDevice *grab_pointer_source;
guint32 grab_pointer_time;
/* the state of gimp_display_shell_zoom_gesture_*() */
gdouble last_zoom_scale;