]> Pileus Git - ~andy/gtk/commitdiff
win32: Fix synaptics trackpad issues
authorAlexander Larsson <alexl@redhat.com>
Tue, 1 Nov 2011 21:25:26 +0000 (22:25 +0100)
committerAlexander Larsson <alexl@redhat.com>
Thu, 10 Nov 2011 16:41:09 +0000 (17:41 +0100)
The synaptics trackpad driver has some weird behaviour on scroll.
It pops up a window over the mouse pointer (looking like a scrollbar).
This has two problems:
* We get extra enter/leave events for the trackpad window
* We get back the trackpad window when we look for the window
  under the mouse to deliver the mousewheel message.

So, we add some trackpad specific hacks to avoid this (sigh) based
on the trackpad window window class.

This fixes bug #542777 and was partially based on a patch there
from Peter Clifton.

gdk/win32/gdkevents-win32.c

index 4f5aa62c1b923057a6a9b86749a50dec0f34911e..b3932a1e6217d241dffc2eadf28468e198a8382b 100644 (file)
@@ -90,6 +90,8 @@
  * Private function declarations
  */
 
+#define SYNAPSIS_ICON_WINDOW_CLASS "SynTrackCursorWindowClass"
+
 static gboolean gdk_event_translate (MSG        *msg,
                                     gint       *ret_valp);
 static void     handle_wm_paint     (MSG        *msg,
@@ -122,6 +124,7 @@ static GSourceFuncs event_funcs = {
 GPollFD event_poll_fd;
 
 static GdkWindow *mouse_window = NULL;
+static GdkWindow *mouse_window_ignored_leave = NULL;
 static gint current_x, current_y;
 static gint current_root_x, current_root_y;
 static UINT client_message;
@@ -1898,6 +1901,7 @@ gdk_event_translate (MSG  *msg,
   BYTE key_state[256];
   HIMC himc;
   WINDOWPOS *windowpos;
+  gboolean ignore_leave;
 
   GdkEvent *event;
 
@@ -2357,6 +2361,7 @@ gdk_event_translate (MSG  *msg,
                                          msg->time,
                                          FALSE);
              assign_object (&mouse_window, new_window);
+             mouse_window_ignored_leave = NULL;
            }
        }
 
@@ -2410,9 +2415,19 @@ gdk_event_translate (MSG  *msg,
                                      msg->time,
                                      FALSE);
          assign_object (&mouse_window, new_window);
+         mouse_window_ignored_leave = NULL;
          if (new_window != NULL)
            track_mouse_event (TME_LEAVE, GDK_WINDOW_HWND (new_window));
        }
+      else if (new_window != NULL && 
+              new_window == mouse_window_ignored_leave)
+       {
+         /* If we ignored a leave event for this window and we're now getting
+            input again we need to re-arm the mouse tracking, as that was
+            cancelled by the mouseleave. */
+         mouse_window_ignored_leave = NULL;
+         track_mouse_event (TME_LEAVE, GDK_WINDOW_HWND (new_window));
+       }
 
       assign_object (&window, find_window_for_mouse_event (window, msg));
 
@@ -2456,24 +2471,38 @@ gdk_event_translate (MSG  *msg,
 
       new_window = NULL;
       hwnd = WindowFromPoint (msg->pt);
+      ignore_leave = FALSE;
       if (hwnd != NULL)
        {
+         char classname[64];
+
          POINT client_pt = msg->pt;
 
+         /* The synapitics trackpad drivers have this irritating
+            feature where it pops up a window right under the pointer
+            when you scroll. We ignore the leave and enter events for 
+            this window */
+         if (GetClassNameA (hwnd, classname, sizeof(classname)) &&
+             strcmp (classname, SYNAPSIS_ICON_WINDOW_CLASS) == 0)
+           ignore_leave = TRUE;
+
          ScreenToClient (hwnd, &client_pt);
          GetClientRect (hwnd, &rect);
          if (PtInRect (&rect, client_pt))
            new_window = gdk_win32_handle_table_lookup (hwnd);
        }
 
-      synthesize_crossing_events (_gdk_display,
-                                 mouse_window, new_window,
-                                 GDK_CROSSING_NORMAL,
-                                 &msg->pt,
-                                 0, /* TODO: Set right mask */
-                                 msg->time,
-                                 FALSE);
+      if (!ignore_leave)
+       synthesize_crossing_events (_gdk_display,
+                                   mouse_window, new_window,
+                                   GDK_CROSSING_NORMAL,
+                                   &msg->pt,
+                                   0, /* TODO: Set right mask */
+                                   msg->time,
+                                   FALSE);
       assign_object (&mouse_window, new_window);
+      mouse_window_ignored_leave = ignore_leave ? new_window : NULL;
+
 
       return_val = TRUE;
       break;
@@ -2491,6 +2520,30 @@ gdk_event_translate (MSG  *msg,
 
       if ((hwnd = WindowFromPoint (point)) == NULL)
        break;
+      
+      {
+       char classname[64];
+
+       /* The synapitics trackpad drivers have this irritating
+          feature where it pops up a window right under the pointer
+          when you scroll. We backtrack and to the toplevel and
+          find the innermost child instead. */
+       if (GetClassNameA (hwnd, classname, sizeof(classname)) &&
+           strcmp (classname, SYNAPSIS_ICON_WINDOW_CLASS) == 0)
+         {
+           HWND hwndc;
+
+           /* Find our toplevel window */
+           hwnd = GetAncestor (msg->hwnd, GA_ROOT);
+
+           /* Walk back up to the outermost child at the desired point */
+           do {
+             ScreenToClient (hwnd, &point);
+             hwndc = ChildWindowFromPoint (hwnd, point);
+             ClientToScreen (hwnd, &point);
+           } while (hwndc != hwnd && (hwnd = hwndc, 1));
+         }
+      }
 
       msg->hwnd = hwnd;
       if ((new_window = gdk_win32_handle_table_lookup (msg->hwnd)) == NULL)