Make wxSetInputFocusToXWindow a member instead of free function
Also add a couple of workarounds for problems when using Xvfb. See https://github.com/wxWidgets/wxWidgets/pull/1845
This commit is contained in:
		
				
					committed by
					
						
						Vadim Zeitlin
					
				
			
			
				
	
			
			
			
						parent
						
							609f77ff55
						
					
				
				
					commit
					a3e264e8a3
				
			@@ -25,33 +25,16 @@
 | 
				
			|||||||
#include <X11/extensions/XTest.h>
 | 
					#include <X11/extensions/XTest.h>
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "wx/log.h"
 | 
				
			||||||
 | 
					#include "wx/window.h" // for wxGetActiveWindow
 | 
				
			||||||
#include "wx/unix/utilsx11.h"
 | 
					#include "wx/unix/utilsx11.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __WXGTK20__
 | 
					#ifdef __WXGTK20__
 | 
				
			||||||
#include "wx/window.h"
 | 
					 | 
				
			||||||
#include "wx/gtk/private/wrapgtk.h"
 | 
					#include "wx/gtk/private/wrapgtk.h"
 | 
				
			||||||
#include <gdk/gdkx.h>
 | 
					#include <gdk/gdkx.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GtkWidget* wxGetTopLevelGTK();
 | 
					GtkWidget* wxGetTopLevelGTK();
 | 
				
			||||||
GdkWindow* wxGetTopLevelGDK();
 | 
					GdkWindow* wxGetTopLevelGDK();
 | 
				
			||||||
 | 
					 | 
				
			||||||
// This helper function tries to set the input focus to the correct (top level)
 | 
					 | 
				
			||||||
// window, i.e.: the window to which keyboard events will be reported.
 | 
					 | 
				
			||||||
static inline void wxSetInputFocusToXWindow(wxX11Display& display)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    wxWindow* const win = wxGetActiveWindow();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    GdkWindow* gdkwin;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if ( win && win->IsTopLevel() )
 | 
					 | 
				
			||||||
        gdkwin = gtk_widget_get_window(win->GetHandle());
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        gdkwin = wxGetTopLevelGDK();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    XSetInputFocus(display, GDK_WINDOW_XID(gdkwin), RevertToPointerRoot, CurrentTime);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#else // !__WXGTK__
 | 
					 | 
				
			||||||
#define wxSetInputFocusToXWindow(display)
 | 
					 | 
				
			||||||
#endif // __WXGTK__
 | 
					#endif // __WXGTK__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Normally we fall back on "plain X" implementation if XTest is not available,
 | 
					// Normally we fall back on "plain X" implementation if XTest is not available,
 | 
				
			||||||
@@ -147,7 +130,53 @@ protected:
 | 
				
			|||||||
        wxYield();
 | 
					        wxYield();
 | 
				
			||||||
        wxMilliSleep(50);
 | 
					        wxMilliSleep(50);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        wxSetInputFocusToXWindow(m_display);
 | 
					        SetInputFocusToXWindow();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // This helper function tries to set the input focus to the active (top level)
 | 
				
			||||||
 | 
					    // window, i.e.: the window to which keyboard events will be reported.
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    // Normally we would expect the input focus to be correctly set by the WM.
 | 
				
			||||||
 | 
					    // But for some reasons, the input focus is set to PointerRoot under Xvfb,
 | 
				
			||||||
 | 
					    // which means: all keyboard events are forewarded to whatever is underneath
 | 
				
			||||||
 | 
					    // mouse pointer. and consequently, our fake events could be simply lost and
 | 
				
			||||||
 | 
					    // do not reach the subject window at all.
 | 
				
			||||||
 | 
					    void SetInputFocusToXWindow()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Window focus;
 | 
				
			||||||
 | 
					        int revert_to; // dummy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        XGetInputFocus(m_display, &focus, &revert_to);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ( focus != PointerRoot && focus != None )
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        wxWindow* win = wxGetActiveWindow();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #if defined(__WXGTK__)
 | 
				
			||||||
 | 
					        if ( win && !win->IsTopLevel() )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            win = wxGetTopLevelParent(win);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        GdkWindow* gdkwin;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ( win )
 | 
				
			||||||
 | 
					            gdkwin = gtk_widget_get_window(win->GetHandle());
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            gdkwin = wxGetTopLevelGDK();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        focus = GDK_WINDOW_XID(gdkwin);
 | 
				
			||||||
 | 
					    #elif defined(__WXX11__)
 | 
				
			||||||
 | 
					        if ( !win )
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        focus = (Window)(win->GetHandle());
 | 
				
			||||||
 | 
					    #endif // __WXGTK__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        wxLogTrace("focus", "SetInputFocusToXWindow on Window 0x%ul.", focus);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        XSetInputFocus(m_display, focus, RevertToPointerRoot, CurrentTime);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    wxX11Display m_display;
 | 
					    wxX11Display m_display;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -584,6 +584,10 @@ void MenuTestCase::Events()
 | 
				
			|||||||
    // Invoke the accelerator.
 | 
					    // Invoke the accelerator.
 | 
				
			||||||
    m_frame->Show();
 | 
					    m_frame->Show();
 | 
				
			||||||
    m_frame->SetFocus();
 | 
					    m_frame->SetFocus();
 | 
				
			||||||
 | 
					#ifdef __WXGTK__
 | 
				
			||||||
 | 
					    // Without this, test fails when run with other tests under Xvfb.
 | 
				
			||||||
 | 
					    m_frame->Raise();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
    wxYield();
 | 
					    wxYield();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    wxUIActionSimulator sim;
 | 
					    wxUIActionSimulator sim;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -211,6 +211,16 @@ void NumValidatorTestCase::Interactive()
 | 
				
			|||||||
        return;
 | 
					        return;
 | 
				
			||||||
#endif // __WXMSW__
 | 
					#endif // __WXMSW__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __WXGTK20__
 | 
				
			||||||
 | 
					    // Travis CI fails without this!
 | 
				
			||||||
 | 
					    if ( IsAutomaticTest() )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        wxFrame* frame = wxDynamicCast(wxTheApp->GetTopWindow(), wxFrame);
 | 
				
			||||||
 | 
					        frame->SetFocus();
 | 
				
			||||||
 | 
					        frame->Raise();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif // __WXGTK20__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Set a locale using comma as thousands separator character.
 | 
					    // Set a locale using comma as thousands separator character.
 | 
				
			||||||
    wxLocale loc(wxLANGUAGE_ENGLISH_UK, wxLOCALE_DONT_LOAD_DEFAULT);
 | 
					    wxLocale loc(wxLANGUAGE_ENGLISH_UK, wxLOCALE_DONT_LOAD_DEFAULT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user