[gimp/gtk3-port: 197/386] app: make input devices, grabs and therefore generally tools work again



commit 315fad9de1bc30eff5845d901b02c757555527d1
Author: Michael Natterer <mitch gimp org>
Date:   Sun Feb 27 16:38:51 2011 +0100

    app: make input devices, grabs and therefore generally tools work again
    
    - add new "device from event" apparatus that works on GTK+ 3.x
    - fix the active device selection mechanism
    - use the new device grabbing functions
    - make sure we don't process events while we have a grab on
      another device
    - compensate for some really obscure (and likely broken) behavior
      of XI2, it feels like we are the first real users...

 app/display/gimpdisplayshell-grab.c        |  172 ++++++++++++++++++++-------
 app/display/gimpdisplayshell-tool-events.c |  127 ++++++++++++++-------
 app/display/gimpdisplayshell.h             |   10 +-
 app/widgets/gimpdevices.c                  |  116 ++++++++++++++++---
 app/widgets/gimpdevices.h                  |   34 +++---
 5 files changed, 337 insertions(+), 122 deletions(-)
---
diff --git a/app/display/gimpdisplayshell-grab.c b/app/display/gimpdisplayshell-grab.c
index d9dec38..2126a78 100644
--- a/app/display/gimpdisplayshell-grab.c
+++ b/app/display/gimpdisplayshell-grab.c
@@ -24,41 +24,110 @@
 
 #include "display-types.h"
 
+#include "widgets/gimpdevices.h"
+
+#include "gimpdisplay.h"
 #include "gimpdisplayshell.h"
 #include "gimpdisplayshell-grab.h"
 
 
+static GdkDevice *
+get_associated_pointer (GdkDevice *device)
+{
+  switch (gdk_device_get_device_type (device))
+    {
+    case GDK_DEVICE_TYPE_SLAVE:
+      device = gdk_device_get_associated_device (device);
+      break;
+
+    case GDK_DEVICE_TYPE_FLOATING:
+      {
+        GdkDisplay       *display = gdk_device_get_display (device);
+        GdkDeviceManager *manager = gdk_display_get_device_manager (display);
+
+        return gdk_device_manager_get_client_pointer (manager);
+      }
+      break;
+
+    default:
+      break;
+    }
+
+  if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
+    device = gdk_device_get_associated_device (device);
+
+  return device;
+}
+
+static GdkDevice *
+get_associated_keyboard (GdkDevice *device)
+{
+  switch (gdk_device_get_device_type (device))
+    {
+    case GDK_DEVICE_TYPE_SLAVE:
+      device = gdk_device_get_associated_device (device);
+      break;
+
+    case GDK_DEVICE_TYPE_FLOATING:
+      {
+        GdkDisplay       *display = gdk_device_get_display (device);
+        GdkDeviceManager *manager = gdk_display_get_device_manager (display);
+
+        device = gdk_device_manager_get_client_pointer (manager);
+      }
+      break;
+
+    default:
+      break;
+    }
+
+  if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
+    device = gdk_device_get_associated_device (device);
+
+  return device;
+}
+
 gboolean
 gimp_display_shell_pointer_grab (GimpDisplayShell *shell,
                                  const GdkEvent   *event,
                                  GdkEventMask      event_mask)
 {
+  GdkDevice     *device;
+  GdkDevice     *source_device;
+  GdkGrabStatus  status;
+
   g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), FALSE);
-  g_return_val_if_fail (shell->pointer_grabbed == FALSE, FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
+  g_return_val_if_fail (shell->grab_pointer == NULL, FALSE);
+
+  source_device = gimp_devices_get_from_event (shell->display->gimp,
+                                               event, &device);
 
-  if (event)
+  if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
     {
-      GdkGrabStatus status;
+      device        = get_associated_pointer (device);
+      source_device = NULL;
+    }
 
-      status = gdk_pointer_grab (gtk_widget_get_window (shell->canvas),
-                                 FALSE, event_mask, NULL, NULL,
-                                 gdk_event_get_time (event));
+  status = gdk_device_grab (device,
+                            gtk_widget_get_window (shell->canvas),
+                            GDK_OWNERSHIP_APPLICATION,
+                            FALSE, event_mask, NULL,
+                            gdk_event_get_time (event));
 
-      if (status != GDK_GRAB_SUCCESS)
-        {
-          g_printerr ("%s: gdk_pointer_grab failed with status %d\n",
-                      G_STRFUNC, status);
-          return FALSE;
-        }
+  if (status == GDK_GRAB_SUCCESS)
+    {
+      shell->grab_pointer        = device;
+      shell->grab_pointer_source = source_device;
+      shell->grab_pointer_time   = gdk_event_get_time (event);
 
-      shell->pointer_grab_time = gdk_event_get_time (event);
+      return TRUE;
     }
 
-  gtk_grab_add (shell->canvas);
+  g_printerr ("%s: gdk_device_grab(%s) failed with status %d\n",
+              G_STRFUNC, gdk_device_get_name (device), status);
 
-  shell->pointer_grabbed = TRUE;
-
-  return TRUE;
+  return FALSE;
 }
 
 void
@@ -66,46 +135,59 @@ gimp_display_shell_pointer_ungrab (GimpDisplayShell *shell,
                                    const GdkEvent   *event)
 {
   g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
-  g_return_if_fail (shell->pointer_grabbed == TRUE);
-
-  gtk_grab_remove (shell->canvas);
+  g_return_if_fail (event != NULL);
+  g_return_if_fail (shell->grab_pointer != NULL);
 
-  if (event)
-    {
-      gdk_display_pointer_ungrab (gtk_widget_get_display (shell->canvas),
-                                  shell->pointer_grab_time);
+  gdk_device_ungrab (shell->grab_pointer, shell->grab_pointer_time);
 
-      shell->pointer_grab_time = 0;
-    }
-
-  shell->pointer_grabbed = FALSE;
+  shell->grab_pointer        = NULL;
+  shell->grab_pointer_source = NULL;
+  shell->grab_pointer_time   = 0;
 }
 
 gboolean
 gimp_display_shell_keyboard_grab (GimpDisplayShell *shell,
                                   const GdkEvent   *event)
 {
-  GdkGrabStatus status;
+  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->keyboard_grabbed == FALSE, FALSE);
+  g_return_val_if_fail (shell->grab_keyboard == NULL, FALSE);
 
-  status = gdk_keyboard_grab (gtk_widget_get_window (shell->canvas),
-                              FALSE,
-                              gdk_event_get_time (event));
+  source_device = gimp_devices_get_from_event (shell->display->gimp,
+                                               event, &device);
 
-  if (status != GDK_GRAB_SUCCESS)
+  if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
     {
-      g_printerr ("%s: gdk_keyboard_grab failed with status %d\n",
-                  G_STRFUNC, status);
-      return FALSE;
+      device        = get_associated_keyboard (device);
+      source_device = NULL;
+    }
+
+  status = gdk_device_grab (device,
+                            gtk_widget_get_window (shell->canvas),
+                            GDK_OWNERSHIP_APPLICATION,
+                            FALSE,
+                            GDK_KEY_PRESS_MASK   |
+                            GDK_KEY_RELEASE_MASK |
+                            GDK_FOCUS_CHANGE_MASK,
+                            NULL, gdk_event_get_time (event));
+
+  if (status == GDK_GRAB_SUCCESS)
+    {
+      shell->grab_keyboard        = device;
+      shell->grab_keyboard_source = source_device;
+      shell->grab_keyboard_time   = gdk_event_get_time (event);
+
+      return TRUE;
     }
 
-  shell->keyboard_grabbed   = TRUE;
-  shell->keyboard_grab_time = gdk_event_get_time (event);
+  g_printerr ("%s: gdk_device_grab(%s) failed with status %d\n",
+              G_STRFUNC, gdk_device_get_name (device), status);
 
-  return TRUE;
+  return FALSE;
 }
 
 void
@@ -114,11 +196,11 @@ gimp_display_shell_keyboard_ungrab (GimpDisplayShell *shell,
 {
   g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
   g_return_if_fail (event != NULL);
-  g_return_if_fail (shell->keyboard_grabbed == TRUE);
+  g_return_if_fail (shell->grab_keyboard != NULL);
 
-  gdk_display_keyboard_ungrab (gtk_widget_get_display (shell->canvas),
-                               shell->keyboard_grab_time);
+  gdk_device_ungrab (shell->grab_keyboard, shell->grab_keyboard_time);
 
-  shell->keyboard_grabbed   = FALSE;
-  shell->keyboard_grab_time = 0;
+  shell->grab_keyboard        = NULL;
+  shell->grab_keyboard_source = NULL;
+  shell->grab_keyboard_time   = 0;
 }
diff --git a/app/display/gimpdisplayshell-tool-events.c b/app/display/gimpdisplayshell-tool-events.c
index bd00e86..29f3e59 100644
--- a/app/display/gimpdisplayshell-tool-events.c
+++ b/app/display/gimpdisplayshell-tool-events.c
@@ -84,6 +84,9 @@ static GdkModifierType
 static void       gimp_display_shell_proximity_in                (GimpDisplayShell   *shell);
 static void       gimp_display_shell_proximity_out               (GimpDisplayShell   *shell);
 
+static gboolean   gimp_display_shell_check_device                (GimpDisplayShell   *shell,
+                                                                  GdkEvent           *event,
+                                                                  gboolean           *device_changed);
 static void       gimp_display_shell_check_device_cursor         (GimpDisplayShell   *shell);
 
 static void       gimp_display_shell_start_scrolling             (GimpDisplayShell   *shell,
@@ -421,10 +424,11 @@ gimp_display_shell_ruler_button_press (GtkWidget           *widget,
           gimp_display_shell_update_focus (shell, TRUE,
                                            NULL, event->state);
 
-          if (gimp_display_shell_pointer_grab (shell, NULL, 0))
+          if (gimp_display_shell_pointer_grab (shell, (GdkEvent *) event,
+                                               GDK_POINTER_MOTION_MASK |
+                                               GDK_BUTTON_RELEASE_MASK))
             {
-              if (gimp_display_shell_keyboard_grab (shell,
-                                                    (GdkEvent *) event))
+              if (gimp_display_shell_keyboard_grab (shell, (GdkEvent *) event))
                 {
                   if (event->state & gimp_get_toggle_behavior_mask ())
                     {
@@ -440,7 +444,7 @@ gimp_display_shell_ruler_button_press (GtkWidget           *widget,
                 }
               else
                 {
-                  gimp_display_shell_pointer_ungrab (shell, NULL);
+                  gimp_display_shell_pointer_ungrab (shell, (GdkEvent *) event);
                 }
             }
         }
@@ -524,25 +528,8 @@ gimp_display_shell_canvas_tool_events_internal (GtkWidget         *canvas,
   GIMP_LOG (TOOL_EVENTS, "event (display %p): %s",
             display, gimp_print_event (event));
 
-  /* See bug 771444 */
-  if (shell->pointer_grabbed &&
-      event->type == GDK_MOTION_NOTIFY)
-    {
-      GimpDeviceManager *manager = gimp_devices_get_manager (gimp);
-      GimpDeviceInfo    *info;
-
-      info = gimp_device_manager_get_current_device (manager);
-
-      if (info->device != event->motion.device)
-        return FALSE;
-    }
-
-  /*  Find out what device the event occurred upon  */
-  if (! gimp->busy && gimp_devices_check_change (gimp, event))
-    {
-      gimp_display_shell_check_device_cursor (shell);
-      device_changed = TRUE;
-    }
+  if (gimp_display_shell_check_device (shell, event, &device_changed))
+    return TRUE;
 
   gimp_display_shell_get_event_coords (shell, event,
                                        &display_coords,
@@ -570,7 +557,7 @@ gimp_display_shell_canvas_tool_events_internal (GtkWidget         *canvas,
           return TRUE;
 
         /*  ignore enter notify while we have a grab  */
-        if (shell->pointer_grabbed)
+        if (shell->grab_pointer)
           return TRUE;
 
         gimp_display_shell_proximity_in (shell);
@@ -591,7 +578,7 @@ gimp_display_shell_canvas_tool_events_internal (GtkWidget         *canvas,
           return TRUE;
 
         /*  ignore leave notify while we have a grab  */
-        if (shell->pointer_grabbed)
+        if (shell->grab_pointer)
           return TRUE;
 
         gimp_display_shell_proximity_out (shell);
@@ -631,7 +618,7 @@ gimp_display_shell_canvas_tool_events_internal (GtkWidget         *canvas,
               g_warning ("%s: FOCUS_IN but canvas has no focus", G_STRFUNC);
 
             /*  ignore focus changes while we have a grab  */
-            if (shell->pointer_grabbed)
+            if (shell->grab_pointer)
               return TRUE;
 
             /*   press modifier keys when the canvas gets the focus  */
@@ -644,7 +631,7 @@ gimp_display_shell_canvas_tool_events_internal (GtkWidget         *canvas,
               g_warning ("%s: FOCUS_OUT but canvas has focus", G_STRFUNC);
 
             /*  ignore focus changes while we have a grab  */
-            if (shell->pointer_grabbed)
+            if (shell->grab_pointer)
               return TRUE;
 
             /*  release modifier keys when the canvas loses the focus  */
@@ -660,8 +647,7 @@ gimp_display_shell_canvas_tool_events_internal (GtkWidget         *canvas,
         GdkModifierType  button_state;
 
         /*  ignore new mouse events  */
-        if (gimp->busy || shell->scrolling ||
-            shell->pointer_grabbed         ||
+        if (gimp->busy || shell->scrolling || shell->grab_pointer ||
             shell->button1_release_pending)
           return TRUE;
 
@@ -725,13 +711,15 @@ gimp_display_shell_canvas_tool_events_internal (GtkWidget         *canvas,
           }
         else if (bevent->button == 1)
           {
-            if (! gimp_display_shell_pointer_grab (shell, NULL, 0))
+            if (! gimp_display_shell_pointer_grab (shell, event,
+                                                   GDK_POINTER_MOTION_MASK |
+                                                   GDK_BUTTON_RELEASE_MASK))
               return TRUE;
 
             if (! shell->space_release_pending)
               if (! gimp_display_shell_keyboard_grab (shell, event))
                 {
-                  gimp_display_shell_pointer_ungrab (shell, NULL);
+                  gimp_display_shell_pointer_ungrab (shell, event);
                   return TRUE;
                 }
 
@@ -760,7 +748,7 @@ gimp_display_shell_canvas_tool_events_internal (GtkWidget         *canvas,
           }
         else if (bevent->button == 2)
           {
-            gimp_display_shell_start_scrolling (shell, NULL, state,
+            gimp_display_shell_start_scrolling (shell, event, state,
                                                 bevent->x, bevent->y);
           }
 
@@ -844,7 +832,11 @@ gimp_display_shell_canvas_tool_events_internal (GtkWidget         *canvas,
 
         if (bevent->button == 1)
           {
-            if (! shell->pointer_grabbed || shell->scrolling)
+            /*  If we don't have a grab, this is a release paired with
+             *  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->scrolling)
               return TRUE;
 
             if (! shell->space_release_pending)
@@ -875,12 +867,12 @@ gimp_display_shell_canvas_tool_events_internal (GtkWidget         *canvas,
               gimp_display_shell_update_focus (shell, FALSE,
                                                &image_coords, 0);
 
-            gimp_display_shell_pointer_ungrab (shell, NULL);
+            gimp_display_shell_pointer_ungrab (shell, event);
           }
         else if (bevent->button == 2)
           {
             if (shell->scrolling)
-              gimp_display_shell_stop_scrolling (shell, NULL);
+              gimp_display_shell_stop_scrolling (shell, event);
           }
         else if (bevent->button == 3)
           {
@@ -891,7 +883,7 @@ gimp_display_shell_canvas_tool_events_internal (GtkWidget         *canvas,
             GdkEventButton *bevent = (GdkEventButton *) event;
             GimpController *mouse  = gimp_controllers_get_mouse (gimp);
 
-            if (!(shell->scrolling || shell->pointer_grabbed) &&
+            if (!(shell->scrolling || shell->grab_pointer) &&
                 mouse && gimp_controller_mouse_button (GIMP_CONTROLLER_MOUSE (mouse),
                                                        bevent))
               {
@@ -1363,7 +1355,7 @@ gimp_display_shell_canvas_tool_events_internal (GtkWidget         *canvas,
                     /* We need to ungrab the pointer in order to catch
                      * button release events.
                      */
-                    if (shell->pointer_grabbed)
+                    if (shell->grab_pointer)
                       gimp_display_shell_pointer_ungrab (shell, event);
                   }
                 else
@@ -1483,6 +1475,61 @@ gimp_display_shell_proximity_out (GimpDisplayShell *shell)
     }
 }
 
+static gboolean
+gimp_display_shell_check_device (GimpDisplayShell *shell,
+                                 GdkEvent         *event,
+                                 gboolean         *device_changed)
+{
+  Gimp      *gimp = gimp_display_get_gimp (shell->display);
+  GdkDevice *device;
+  GdkDevice *grab_device;
+
+  /*  Find out what device the event occurred upon  */
+  device = gimp_devices_get_from_event (gimp, event, &grab_device);
+
+  if (device)
+    {
+      /*  While we have a grab, ignore all events from all other devices
+       *  of the same type
+       */
+      if (event->type == GDK_KEY_PRESS   ||
+          event->type == GDK_KEY_RELEASE ||
+          event->type == GDK_FOCUS_CHANGE)
+        {
+          if ((shell->grab_keyboard && (shell->grab_keyboard != grab_device)) ||
+              (shell->grab_keyboard_source && (shell->grab_keyboard_source != device)))
+            {
+              GIMP_LOG (TOOL_EVENTS,
+                        "ignoring key event from '%s' while waiting for event from '%s'\n",
+                        gdk_device_get_name (device),
+                        gdk_device_get_name (shell->grab_keyboard_source));
+              return TRUE;
+            }
+        }
+      else
+        {
+          if ((shell->grab_pointer && (shell->grab_pointer != grab_device)) ||
+              (shell->grab_pointer_source && (shell->grab_pointer_source != device)))
+            {
+              GIMP_LOG (TOOL_EVENTS,
+                        "ignoring pointer event from '%s' while waiting for event from '%s'\n",
+                        gdk_device_get_name (device),
+                        gdk_device_get_name (shell->grab_pointer_source));
+              return TRUE;
+            }
+        }
+
+      if (! gimp->busy && gimp_devices_check_change (gimp, device))
+        {
+          gimp_display_shell_check_device_cursor (shell);
+
+          *device_changed = TRUE;
+        }
+    }
+
+  return FALSE;
+}
+
 static void
 gimp_display_shell_check_device_cursor (GimpDisplayShell *shell)
 {
@@ -1505,7 +1552,9 @@ gimp_display_shell_start_scrolling (GimpDisplayShell *shell,
 {
   g_return_if_fail (! shell->scrolling);
 
-  gimp_display_shell_pointer_grab (shell, event, GDK_POINTER_MOTION_MASK);
+  gimp_display_shell_pointer_grab (shell, event,
+                                   GDK_POINTER_MOTION_MASK |
+                                   GDK_BUTTON_RELEASE_MASK);
 
   shell->scrolling         = TRUE;
   shell->scroll_last_x     = x;
@@ -1543,7 +1592,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->pointer_grabbed)
+  if (shell->grab_pointer)
     gimp_display_shell_pointer_ungrab (shell, event);
 }
 
diff --git a/app/display/gimpdisplayshell.h b/app/display/gimpdisplayshell.h
index c9d9a00..813ce66 100644
--- a/app/display/gimpdisplayshell.h
+++ b/app/display/gimpdisplayshell.h
@@ -181,11 +181,13 @@ struct _GimpDisplayShell
   gboolean           size_allocate_from_configure_event;
 
   /*  the state of gimp_display_shell_tool_events()  */
-  gboolean           pointer_grabbed;
-  guint32            pointer_grab_time;
+  GdkDevice         *grab_pointer;
+  GdkDevice         *grab_pointer_source;
+  guint32            grab_pointer_time;
 
-  gboolean           keyboard_grabbed;
-  guint32            keyboard_grab_time;
+  GdkDevice         *grab_keyboard;
+  GdkDevice         *grab_keyboard_source;
+  guint32            grab_keyboard_time;
 
   /* Two states are possible when the shell is grabbed: it can be
    * grabbed with space (or space+button1 which is the same state),
diff --git a/app/widgets/gimpdevices.c b/app/widgets/gimpdevices.c
index 741f582..edeabcf 100644
--- a/app/widgets/gimpdevices.c
+++ b/app/widgets/gimpdevices.c
@@ -232,6 +232,89 @@ gimp_devices_get_manager (Gimp *gimp)
   return manager;
 }
 
+GdkDevice *
+gimp_devices_get_from_event (Gimp            *gimp,
+                             const GdkEvent  *event,
+                             GdkDevice      **grab_device)
+{
+  GdkDevice *device;
+
+  g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
+  g_return_val_if_fail (event != NULL, NULL);
+
+  device = gdk_event_get_source_device (event);
+
+  /*  initialize the default grab device to the event's device,
+   *  because that is always either a master or a floating device,
+   *  which is the types of devices we can make grabs on without
+   *  disturbing side effects.
+   */
+  if (grab_device)
+    *grab_device = gdk_event_get_device (event);
+
+  if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
+    {
+      switch (gdk_device_get_device_type (device))
+        {
+        case GDK_DEVICE_TYPE_MASTER:
+          /*  this happens on focus synthesized focus changed events,
+           *  and we can't do anything with the returned device, so
+           *  return NULL
+           */
+          return NULL;
+
+        case GDK_DEVICE_TYPE_SLAVE:
+          /*  it makes no sense for us to distinguigh between
+           *  different slave keyboards, so just always return
+           *  their respective master
+           */
+          return gdk_device_get_associated_device (device);
+
+        case GDK_DEVICE_TYPE_FLOATING:
+          /*  we have no way of explicitly enabling floating
+           *  keyboards, so we cannot get their events
+           */
+          g_return_val_if_reached (device);
+       }
+    }
+  else
+    {
+      switch (gdk_device_get_device_type (device))
+        {
+        case GDK_DEVICE_TYPE_MASTER:
+          /*  this can only happen for synthesized events which have
+           *  no actual source, so return NULL to indicate that we
+           *  cannot do anything with the event's device information
+           */
+          return NULL;
+
+        case GDK_DEVICE_TYPE_SLAVE:
+          /*  this is the tricky part: we do want to distingiugh slave
+           *  devices, but only if we actually enabled them ourselves
+           *  explicitely (like the pens of a tablet); however we
+           *  usually don't enable the different incarnations of the
+           *  mouse itself (like touchpad, trackpoint, usb mouse
+           *  etc.), so for these return their respective master so
+           *  its settings are used
+           */
+          if (gdk_device_get_mode (device) == GDK_MODE_DISABLED)
+            {
+              return gdk_device_get_associated_device (device);
+            }
+
+          return device;
+
+        case GDK_DEVICE_TYPE_FLOATING:
+          /*  we only get events for floating devices which have
+           *  enabled ourselves, so return the floating device
+           */
+          return device;
+        }
+    }
+
+  g_return_val_if_reached (device);
+}
+
 void
 gimp_devices_add_widget (Gimp      *gimp,
                          GtkWidget *widget)
@@ -253,44 +336,39 @@ gimp_devices_check_callback (GtkWidget *widget,
   g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
 
   if (! gimp->busy)
-    gimp_devices_check_change (gimp, event);
+    {
+      GdkDevice *device;
+
+      device = gimp_devices_get_from_event (gimp, event, NULL);
+
+      if (device)
+        gimp_devices_check_change (gimp, device);
+    }
 
   return FALSE;
 }
 
 gboolean
-gimp_devices_check_change (Gimp     *gimp,
-                           GdkEvent *event)
+gimp_devices_check_change (Gimp      *gimp,
+                           GdkDevice *device)
 {
   GimpDeviceManager *manager;
-  GdkDevice         *device;
   GimpDeviceInfo    *device_info;
 
   g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
-  g_return_val_if_fail (event != NULL, FALSE);
+  g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
 
   manager = gimp_devices_get_manager (gimp);
 
   g_return_val_if_fail (GIMP_IS_DEVICE_MANAGER (manager), FALSE);
 
-  device = gdk_event_get_source_device (event);
-
-  if (! device)
-    device = gimp_device_manager_get_current_device (manager)->device;
-
   device_info = gimp_device_info_get_by_device (device);
 
   if (! device_info)
-    {
-      device = gdk_event_get_device (event);
-
-      if (! device)
-        device = gimp_device_manager_get_current_device (manager)->device;
-
-      device_info = gimp_device_info_get_by_device (device);
-    }
+    device_info = gimp_device_manager_get_current_device (manager);
 
-  if (device_info && device_info != gimp_device_manager_get_current_device (manager))
+  if (device_info &&
+      device_info != gimp_device_manager_get_current_device (manager))
     {
       gimp_device_manager_set_current_device (manager, device_info);
       return TRUE;
diff --git a/app/widgets/gimpdevices.h b/app/widgets/gimpdevices.h
index a2cdbc8..9d5bce6 100644
--- a/app/widgets/gimpdevices.h
+++ b/app/widgets/gimpdevices.h
@@ -19,26 +19,30 @@
 #define __GIMP_DEVICES_H__
 
 
-void                gimp_devices_init           (Gimp      *gimp);
-void                gimp_devices_exit           (Gimp      *gimp);
+void                gimp_devices_init           (Gimp       *gimp);
+void                gimp_devices_exit           (Gimp       *gimp);
 
-void                gimp_devices_restore        (Gimp      *gimp);
-void                gimp_devices_save           (Gimp      *gimp,
-                                                 gboolean   always_save);
+void                gimp_devices_restore        (Gimp       *gimp);
+void                gimp_devices_save           (Gimp       *gimp,
+                                                 gboolean    always_save);
 
-gboolean            gimp_devices_clear          (Gimp      *gimp,
-                                                 GError   **error);
+gboolean            gimp_devices_clear          (Gimp       *gimp,
+                                                 GError    **error);
 
-GimpDeviceManager * gimp_devices_get_manager    (Gimp      *gimp);
+GimpDeviceManager * gimp_devices_get_manager    (Gimp       *gimp);
 
-void                gimp_devices_add_widget     (Gimp      *gimp,
-                                                 GtkWidget *widget);
+GdkDevice         * gimp_devices_get_from_event (Gimp            *gimp,
+                                                 const GdkEvent  *event,
+                                                 GdkDevice      **grab_device);
 
-gboolean            gimp_devices_check_callback (GtkWidget *widget,
-                                                 GdkEvent  *event,
-                                                 Gimp      *gimp);
-gboolean            gimp_devices_check_change   (Gimp      *gimp,
-                                                 GdkEvent  *event);
+void                gimp_devices_add_widget     (Gimp       *gimp,
+                                                 GtkWidget  *widget);
+
+gboolean            gimp_devices_check_callback (GtkWidget  *widget,
+                                                 GdkEvent   *event,
+                                                 Gimp       *gimp);
+gboolean            gimp_devices_check_change   (Gimp       *gimp,
+                                                 GdkDevice  *device);
 
 
 #endif /* __GIMP_DEVICES_H__ */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]