diff --git a/include/wx/gtk/private/event.h b/include/wx/gtk/private/event.h index 9811422df3..c91332eed8 100644 --- a/include/wx/gtk/private/event.h +++ b/include/wx/gtk/private/event.h @@ -88,6 +88,12 @@ template void InitMouseEvent(wxWindowGTK *win, event.SetTimestamp( gdk_event->time ); } +// Update the window currently known to be under the mouse pointer. +// +// Returns true if it was updated, false if this window was already known to +// contain the mouse pointer. +bool SetWindowUnderMouse(wxWindowGTK* win); + } // namespace wxGTKImpl #endif // _GTK_PRIVATE_EVENT_H_ diff --git a/src/gtk/srchctrl.cpp b/src/gtk/srchctrl.cpp index 988df1abb0..1088fcd293 100644 --- a/src/gtk/srchctrl.cpp +++ b/src/gtk/srchctrl.cpp @@ -20,6 +20,7 @@ #include "wx/utils.h" #include "wx/gtk/private.h" +#include "wx/gtk/private/event.h" #include "wx/gtk/private/gtk3-compat.h" @@ -93,6 +94,28 @@ wx_gtk_icon_press(GtkEntry* WXUNUSED(entry), } } +static gboolean +wx_gtk_entry_event(GtkEntry* WXUNUSED(entry), + GdkEvent* event, + wxSearchCtrl* ctrl) +{ + if ( event->type == GDK_MOTION_NOTIFY ) + { + // GtkEntry "event" signal handler ignores motion events happening over + // inactive icons, but we want to notify the window about the mouse + // entering it when they happen. + if ( wxGTKImpl::SetWindowUnderMouse(ctrl) ) + { + wxMouseEvent mouseEvent(wxEVT_ENTER_WINDOW); + wxGTKImpl::InitMouseEvent(ctrl, mouseEvent, (GdkEventMotion*)event); + + ctrl->GTKProcessEvent(mouseEvent); + } + } + + return FALSE; +} + } // ============================================================================ @@ -209,6 +232,8 @@ void wxSearchCtrl::GTKCreateSearchEntryWidget() } g_signal_connect(m_entry, "icon-press", G_CALLBACK(wx_gtk_icon_press), this); + + g_signal_connect(m_entry, "event", G_CALLBACK(wx_gtk_entry_event), this); } GtkEditable *wxSearchCtrl::GetEditable() const diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index f18b904697..b05eda48eb 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -234,6 +234,23 @@ static wxWindowGTK *gs_deferredFocusOut = nullptr; GdkEvent *g_lastMouseEvent = nullptr; int g_lastButtonNumber = 0; +static wxWindowGTK* g_windowUnderMouse = nullptr; + +namespace wxGTKImpl +{ + +bool SetWindowUnderMouse(wxWindowGTK* win) +{ + if ( g_windowUnderMouse == win ) + return false; + + g_windowUnderMouse = win; + + return true; +} + +} // namespace wxGTKImpl + #ifdef wxHAS_XKB namespace { @@ -2251,6 +2268,26 @@ gtk_window_enter_callback( GtkWidget* widget, return FALSE; } + if ( g_windowUnderMouse == win ) + { + // This can happen if the enter event was generated from another + // callback, as is the case for wxSearchCtrl, for example. + wxLogTrace(TRACE_MOUSE, "Reentering window %s", wxDumpWindow(win)); + return FALSE; + } + + if ( g_windowUnderMouse ) + { + // We must not have got the leave event for the previous window, so + // generate it now -- better late than never. + wxMouseEvent event( wxEVT_LEAVE_WINDOW ); + InitMouseEvent(g_windowUnderMouse, event, gdk_event); + + (void)g_windowUnderMouse->GTKProcessEvent(event); + } + + g_windowUnderMouse = win; + wxMouseEvent event( wxEVT_ENTER_WINDOW ); InitMouseEvent(win, event, gdk_event); @@ -2285,6 +2322,9 @@ gtk_window_leave_callback( GtkWidget* widget, return FALSE; } + if ( win == g_windowUnderMouse ) + g_windowUnderMouse = nullptr; + wxMouseEvent event( wxEVT_LEAVE_WINDOW ); InitMouseEvent(win, event, gdk_event); @@ -2914,6 +2954,9 @@ wxWindowGTK::~wxWindowGTK() if ( g_captureWindow == this ) g_captureWindow = nullptr; + if ( g_windowUnderMouse == this ) + g_windowUnderMouse = nullptr; + if (m_wxwindow) { GTKDisconnect(m_wxwindow);