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:
ali kettab
2020-05-15 22:25:40 +01:00
committed by Vadim Zeitlin
parent 609f77ff55
commit a3e264e8a3
3 changed files with 63 additions and 20 deletions

View File

@@ -25,33 +25,16 @@
#include <X11/extensions/XTest.h>
#endif
#include "wx/log.h"
#include "wx/window.h" // for wxGetActiveWindow
#include "wx/unix/utilsx11.h"
#ifdef __WXGTK20__
#include "wx/window.h"
#include "wx/gtk/private/wrapgtk.h"
#include <gdk/gdkx.h>
GtkWidget* wxGetTopLevelGTK();
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__
// Normally we fall back on "plain X" implementation if XTest is not available,
@@ -147,7 +130,53 @@ protected:
wxYield();
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;

View File

@@ -584,6 +584,10 @@ void MenuTestCase::Events()
// Invoke the accelerator.
m_frame->Show();
m_frame->SetFocus();
#ifdef __WXGTK__
// Without this, test fails when run with other tests under Xvfb.
m_frame->Raise();
#endif
wxYield();
wxUIActionSimulator sim;

View File

@@ -211,6 +211,16 @@ void NumValidatorTestCase::Interactive()
return;
#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.
wxLocale loc(wxLANGUAGE_ENGLISH_UK, wxLOCALE_DONT_LOAD_DEFAULT);