diff options
Diffstat (limited to 'gdk')
-rw-r--r-- | gdk/win32/gdkevents-win32.c | 91 |
1 files changed, 85 insertions, 6 deletions
diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c index 8d97a5c65..d574b9eb7 100644 --- a/gdk/win32/gdkevents-win32.c +++ b/gdk/win32/gdkevents-win32.c @@ -31,6 +31,12 @@ * otherwise would make it possible to reliably generate * GDK_LEAVE_NOTIFY events, which would help get rid of those pesky * tooltips sometimes popping up in the wrong place. + * + * Update: a combination of TrackMouseEvent, GetCursorPos and + * GetWindowPos can and is actually used to get rid of those + * pesky tooltips. It should be possible to use this for the + * whole ENTER/LEAVE NOTIFY handling but some platforms may + * not have TrackMouseEvent at all (?) --hb */ #include "config.h" @@ -151,6 +157,46 @@ assign_object (gpointer lhsp, } } +static void +track_mouse_event (DWORD dwFlags, HWND hwnd) +{ + typedef BOOL (WINAPI *PFN_TrackMouseEvent) (LPTRACKMOUSEEVENT); + static PFN_TrackMouseEvent p_TrackMouseEvent = NULL; + static int once = 0; + + if (!once) + { + HMODULE user32; + HINSTANCE commctrl32; + + user32 = GetModuleHandle ("user32.dll"); + if ((p_TrackMouseEvent = (PFN_TrackMouseEvent)GetProcAddress (user32, "TrackMouseEvent")) == NULL) + { + if ((commctrl32 = LoadLibrary ("commctrl32.dll")) != NULL) + p_TrackMouseEvent = (PFN_TrackMouseEvent) + GetProcAddress (commctrl32, "_TrackMouseEvent"); + } + if (p_TrackMouseEvent != NULL) + GDK_NOTE (EVENTS, g_print ("Using TrackMouseEvent to detect leave events\n")); + + once = 1; + } + + if (p_TrackMouseEvent) + { + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(TRACKMOUSEEVENT); + tme.dwFlags = dwFlags; + tme.hwndTrack = hwnd; + tme.dwHoverTime = HOVER_DEFAULT; /* not used */ + + if (!p_TrackMouseEvent (&tme)) + WIN32_API_FAILED ("TrackMouseEvent"); + else + GDK_NOTE (EVENTS, g_print("TrackMouseEvent (%p, %s)\n", hwnd, dwFlags == TME_CANCEL ? "cancel" : "leave")); + } +} + gulong _gdk_win32_get_next_tick (gulong suggested_tick) { @@ -1196,6 +1242,11 @@ synthesize_leave_event (GdkWindow *window, else synthesize_enter_or_leave_event (window, msg, GDK_LEAVE_NOTIFY, mode, detail, current_x, current_y); + /* This would only make sense if the WM_MOUSEMOVE messages would come + * before the respective WM_MOUSELEAVE message, which apparently they + * do not. + track_mouse_event (TME_CANCEL, msg->hwnd); + */ } static void @@ -1221,6 +1272,8 @@ synthesize_enter_event (GdkWindow *window, ScreenToClient (GDK_WINDOW_HWND (window), &pt); } synthesize_enter_or_leave_event (window, msg, GDK_ENTER_NOTIFY, mode, detail, pt.x, pt.y); + + track_mouse_event (TME_LEAVE, msg->hwnd); } static void @@ -2435,6 +2488,12 @@ gdk_event_translate (GdkDisplay *display, doesnt_want_button_motion)) break; + if (GDK_WINDOW_DESTROYED (window)) + break; + + if (window != orig_window) + translate_mouse_coords (orig_window, window, msg); + /* If we haven't moved, don't create any event. * Windows sends WM_MOUSEMOVE messages after button presses * even if the mouse doesn't move. This disturbs gtk. @@ -2444,15 +2503,9 @@ gdk_event_translate (GdkDisplay *display, GET_Y_LPARAM (msg->lParam) == current_y) break; - if (GDK_WINDOW_DESTROYED (window)) - break; - event = gdk_event_new (GDK_MOTION_NOTIFY); event->motion.window = window; event->motion.time = _gdk_win32_get_next_tick (msg->time); - if (window != orig_window) - translate_mouse_coords (orig_window, window, msg); - event->motion.x = current_x = (gint16) GET_X_LPARAM (msg->lParam); event->motion.y = current_y = (gint16) GET_Y_LPARAM (msg->lParam); _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset); @@ -2485,6 +2538,32 @@ gdk_event_translate (GdkDisplay *display, break; + case WM_MOUSELEAVE: + { + HWND wndnow; + POINT pt; + + if (!GetCursorPos (&pt)) + WIN32_API_FAILED ("GetCursorPos"); + wndnow = WindowFromPoint (pt); + + if (!gdk_win32_handle_table_lookup ((GdkNativeWindow) wndnow)) + { + /* we are only interested if we don't know the new window */ + GDK_NOTE (EVENTS, g_print ("WM_MOUSELEAVE: %p %d (%d,%d)\n", + msg->hwnd, HIWORD (msg->wParam), pt.x, pt.y)); + synthesize_enter_or_leave_event (current_window, msg, + GDK_LEAVE_NOTIFY, GDK_CROSSING_NORMAL, GDK_NOTIFY_UNKNOWN, + current_x, current_y); + } + else + { + GDK_NOTE (EVENTS, g_print ("WM_MOUSELEAVE: %p %d (%d,%d) ignored\n", + msg->hwnd, HIWORD (msg->wParam), pt.x, pt.y)); + } + } + return_val = TRUE; + break; case WM_MOUSEWHEEL: GDK_NOTE (EVENTS, g_print ("WM_MOUSEWHEEL: %p %d\n", msg->hwnd, HIWORD (msg->wParam))); |