Merge branch 'uisim-xtest'
Make wxUIActionSimulator work with GTK+3, including when using DPI scaling.
This commit is contained in:
137
configure
vendored
137
configure
vendored
@@ -945,6 +945,8 @@ WEBKIT_LIBS
|
||||
WEBKIT_CFLAGS
|
||||
COND_PYTHON
|
||||
PYTHON
|
||||
XTST_LIBS
|
||||
XTST_CFLAGS
|
||||
LIBNOTIFY_LIBS
|
||||
LIBNOTIFY_CFLAGS
|
||||
GNOMEVFS_LIBS
|
||||
@@ -1094,6 +1096,7 @@ with_gtkprint
|
||||
with_gnomevfs
|
||||
with_libnotify
|
||||
with_opengl
|
||||
with_xtest
|
||||
with_dmalloc
|
||||
with_sdl
|
||||
with_regex
|
||||
@@ -1402,6 +1405,8 @@ GNOMEVFS_CFLAGS
|
||||
GNOMEVFS_LIBS
|
||||
LIBNOTIFY_CFLAGS
|
||||
LIBNOTIFY_LIBS
|
||||
XTST_CFLAGS
|
||||
XTST_LIBS
|
||||
WEBKIT_CFLAGS
|
||||
WEBKIT_LIBS
|
||||
CAIRO_CFLAGS
|
||||
@@ -2324,6 +2329,7 @@ Optional Packages:
|
||||
--with-gnomevfs use GNOME VFS for associating MIME types
|
||||
--with-libnotify use libnotify for notifications
|
||||
--with-opengl use OpenGL (or Mesa)
|
||||
--with-xtest use XTest extension
|
||||
--with-dmalloc use dmalloc library (http://dmalloc.com/)
|
||||
--with-sdl use SDL for audio on Unix
|
||||
--with-regex enable support for wxRegEx class
|
||||
@@ -2401,6 +2407,8 @@ Some influential environment variables:
|
||||
C compiler flags for LIBNOTIFY, overriding pkg-config
|
||||
LIBNOTIFY_LIBS
|
||||
linker flags for LIBNOTIFY, overriding pkg-config
|
||||
XTST_CFLAGS C compiler flags for XTST, overriding pkg-config
|
||||
XTST_LIBS linker flags for XTST, overriding pkg-config
|
||||
WEBKIT_CFLAGS
|
||||
C compiler flags for WEBKIT, overriding pkg-config
|
||||
WEBKIT_LIBS linker flags for WEBKIT, overriding pkg-config
|
||||
@@ -4833,6 +4841,35 @@ fi
|
||||
eval "$wx_cv_use_opengl"
|
||||
|
||||
|
||||
withstring=
|
||||
defaultval=$wxUSE_ALL_FEATURES
|
||||
if test -z "$defaultval"; then
|
||||
if test x"$withstring" = xwithout; then
|
||||
defaultval=yes
|
||||
else
|
||||
defaultval=no
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check whether --with-xtest was given.
|
||||
if test "${with_xtest+set}" = set; then :
|
||||
withval=$with_xtest;
|
||||
if test "$withval" = yes; then
|
||||
wx_cv_use_xtest='wxUSE_XTEST=yes'
|
||||
else
|
||||
wx_cv_use_xtest='wxUSE_XTEST=no'
|
||||
fi
|
||||
|
||||
else
|
||||
|
||||
wx_cv_use_xtest='wxUSE_XTEST=${'DEFAULT_wxUSE_XTEST":-$defaultval}"
|
||||
|
||||
fi
|
||||
|
||||
|
||||
eval "$wx_cv_use_xtest"
|
||||
|
||||
|
||||
fi
|
||||
|
||||
|
||||
@@ -33665,11 +33702,111 @@ if test "$wxUSE_MOUSEWHEEL" = "yes" ; then
|
||||
|
||||
fi
|
||||
|
||||
if test "$wxUSE_UIACTIONSIMULATOR" = "yes" ; then
|
||||
if test "$wxUSE_GTK" = 1 -o "$wxUSE_MOTIF" = 1 -o "$wxUSE_X11" = 1; then
|
||||
if test "$wxUSE_XTEST" = "yes" ; then
|
||||
|
||||
pkg_failed=no
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for XTST" >&5
|
||||
$as_echo_n "checking for XTST... " >&6; }
|
||||
|
||||
if test -n "$PKG_CONFIG"; then
|
||||
if test -n "$XTST_CFLAGS"; then
|
||||
pkg_cv_XTST_CFLAGS="$XTST_CFLAGS"
|
||||
else
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"xtst\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "xtst") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_XTST_CFLAGS=`$PKG_CONFIG --cflags "xtst" 2>/dev/null`
|
||||
else
|
||||
pkg_failed=yes
|
||||
fi
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi
|
||||
if test -n "$PKG_CONFIG"; then
|
||||
if test -n "$XTST_LIBS"; then
|
||||
pkg_cv_XTST_LIBS="$XTST_LIBS"
|
||||
else
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"xtst\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "xtst") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_XTST_LIBS=`$PKG_CONFIG --libs "xtst" 2>/dev/null`
|
||||
else
|
||||
pkg_failed=yes
|
||||
fi
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi
|
||||
|
||||
|
||||
|
||||
if test $pkg_failed = yes; then
|
||||
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||
_pkg_short_errors_supported=yes
|
||||
else
|
||||
_pkg_short_errors_supported=no
|
||||
fi
|
||||
if test $_pkg_short_errors_supported = yes; then
|
||||
XTST_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "xtst"`
|
||||
else
|
||||
XTST_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "xtst"`
|
||||
fi
|
||||
# Put the nasty error message in config.log where it belongs
|
||||
echo "$XTST_PKG_ERRORS" >&5
|
||||
|
||||
|
||||
if test "$WXGTK3" = 1; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: XTest not found, disabling wxUIActionSimulator" >&5
|
||||
$as_echo "$as_me: WARNING: XTest not found, disabling wxUIActionSimulator" >&2;}
|
||||
wxUSE_UIACTIONSIMULATOR=no
|
||||
fi
|
||||
wxUSE_XTEST="no"
|
||||
|
||||
|
||||
elif test $pkg_failed = untried; then
|
||||
|
||||
if test "$WXGTK3" = 1; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: XTest not found, disabling wxUIActionSimulator" >&5
|
||||
$as_echo "$as_me: WARNING: XTest not found, disabling wxUIActionSimulator" >&2;}
|
||||
wxUSE_UIACTIONSIMULATOR=no
|
||||
fi
|
||||
wxUSE_XTEST="no"
|
||||
|
||||
|
||||
else
|
||||
XTST_CFLAGS=$pkg_cv_XTST_CFLAGS
|
||||
XTST_LIBS=$pkg_cv_XTST_LIBS
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
|
||||
GUI_TK_LIBRARY="$GUI_TK_LIBRARY $XTST_LIBS"
|
||||
CFLAGS="$XTST_CFLAGS $CFLAGS"
|
||||
CXXFLAGS="$XTST_CFLAGS $CXXFLAGS"
|
||||
$as_echo "#define wxUSE_XTEST 1" >>confdefs.h
|
||||
|
||||
|
||||
fi
|
||||
elif test "$WXGTK3" = 1; then
|
||||
wxUSE_UIACTIONSIMULATOR=no
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$wxUSE_UIACTIONSIMULATOR" = "yes" ; then
|
||||
$as_echo "#define wxUSE_UIACTIONSIMULATOR 1" >>confdefs.h
|
||||
|
||||
SAMPLES_SUBDIRS="$SAMPLES_SUBDIRS uiaction"
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$wxUSE_DC_TRANSFORM_MATRIX" = "yes" ; then
|
||||
$as_echo "#define wxUSE_DC_TRANSFORM_MATRIX 1" >>confdefs.h
|
||||
|
31
configure.in
31
configure.in
@@ -542,6 +542,7 @@ WX_ARG_WITHOUT(gtkprint, [ --without-gtkprint don't use GTK printing sup
|
||||
WX_ARG_WITH(gnomevfs, [ --with-gnomevfs use GNOME VFS for associating MIME types], wxUSE_LIBGNOMEVFS)
|
||||
WX_ARG_WITH(libnotify, [ --with-libnotify use libnotify for notifications], wxUSE_LIBNOTIFY)
|
||||
WX_ARG_WITH(opengl, [ --with-opengl use OpenGL (or Mesa)], wxUSE_OPENGL)
|
||||
WX_ARG_WITH(xtest, [ --with-xtest use XTest extension], wxUSE_XTEST)
|
||||
|
||||
fi
|
||||
dnl for GUI only
|
||||
@@ -6388,10 +6389,40 @@ if test "$wxUSE_MOUSEWHEEL" = "yes" ; then
|
||||
AC_DEFINE(wxUSE_MOUSEWHEEL)
|
||||
fi
|
||||
|
||||
if test "$wxUSE_UIACTIONSIMULATOR" = "yes" ; then
|
||||
if test "$wxUSE_GTK" = 1 -o "$wxUSE_MOTIF" = 1 -o "$wxUSE_X11" = 1; then
|
||||
if test "$wxUSE_XTEST" = "yes" ; then
|
||||
PKG_CHECK_MODULES(XTST, xtst,
|
||||
[
|
||||
GUI_TK_LIBRARY="$GUI_TK_LIBRARY $XTST_LIBS"
|
||||
CFLAGS="$XTST_CFLAGS $CFLAGS"
|
||||
CXXFLAGS="$XTST_CFLAGS $CXXFLAGS"
|
||||
AC_DEFINE(wxUSE_XTEST)
|
||||
],
|
||||
[
|
||||
if test "$WXGTK3" = 1; then
|
||||
dnl This class can't work without XTest with GTK+ 3
|
||||
dnl which uses XInput2 and so ignores XSendEvent().
|
||||
AC_MSG_WARN([XTest not found, disabling wxUIActionSimulator])
|
||||
wxUSE_UIACTIONSIMULATOR=no
|
||||
fi
|
||||
dnl The other ports can use XSendEvent(), so don't warn
|
||||
wxUSE_XTEST="no"
|
||||
]
|
||||
)
|
||||
elif test "$WXGTK3" = 1; then
|
||||
dnl As per above, wxUIActionSimulator can't be used in this case,
|
||||
dnl but there is no need to warn, presumably the user knows what
|
||||
dnl he's doing if --without-xtest was explicitly specified.
|
||||
wxUSE_UIACTIONSIMULATOR=no
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$wxUSE_UIACTIONSIMULATOR" = "yes" ; then
|
||||
AC_DEFINE(wxUSE_UIACTIONSIMULATOR)
|
||||
SAMPLES_SUBDIRS="$SAMPLES_SUBDIRS uiaction"
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$wxUSE_DC_TRANSFORM_MATRIX" = "yes" ; then
|
||||
AC_DEFINE(wxUSE_DC_TRANSFORM_MATRIX)
|
||||
|
@@ -88,6 +88,7 @@ All (GUI):
|
||||
|
||||
wxGTK:
|
||||
|
||||
- Make wxUIActionSimulator work with GTK+ 3 (Scott Talbert).
|
||||
- Implement setting link colours in wxHyperlinkCtrl for GTK+3 (Hanmac).
|
||||
- Support background colour in wxDataViewCtrl attributes.
|
||||
- Improve wxSpinCtrl best size calculation.
|
||||
|
@@ -267,6 +267,7 @@ library:
|
||||
@itemdef{wxUSE_LIBSDL, Use SDL for wxSound implementation.}
|
||||
@itemdef{wxUSE_PLUGINS, See also wxUSE_LIBSDL.}
|
||||
@itemdef{wxUSE_UNIX, Enabled on Unix Platform.}
|
||||
@itemdef(wxUSE_XTEST, Use XTest extension.}
|
||||
@endDefList
|
||||
|
||||
|
||||
|
44
include/wx/private/uiaction.h
Normal file
44
include/wx/private/uiaction.h
Normal file
@@ -0,0 +1,44 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: wx/private/uiaction.h
|
||||
// Purpose: wxUIActionSimulatorImpl declaration
|
||||
// Author: Vadim Zeitlin
|
||||
// Created: 2016-05-21
|
||||
// Copyright: (c) 2016 Vadim Zeitlin <vadim@wxwidgets.org>
|
||||
// Licence: wxWindows licence
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _WX_PRIVATE_UIACTION_H_
|
||||
#define _WX_PRIVATE_UIACTION_H_
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Platform-specific implementation of wxUIActionSimulator
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class wxUIActionSimulatorImpl
|
||||
{
|
||||
public:
|
||||
wxUIActionSimulatorImpl() { }
|
||||
virtual ~wxUIActionSimulatorImpl() { }
|
||||
|
||||
// Low level mouse methods which must be implemented in the derived class.
|
||||
virtual bool MouseMove(long x, long y) = 0;
|
||||
virtual bool MouseDown(int button = wxMOUSE_BTN_LEFT) = 0;
|
||||
virtual bool MouseUp(int button = wxMOUSE_BTN_LEFT) = 0;
|
||||
|
||||
// Higher level mouse methods which have default implementation in the base
|
||||
// class but can be overridden if necessary.
|
||||
virtual bool MouseClick(int button = wxMOUSE_BTN_LEFT);
|
||||
virtual bool MouseDblClick(int button = wxMOUSE_BTN_LEFT);
|
||||
virtual bool MouseDragDrop(long x1, long y1, long x2, long y2,
|
||||
int button = wxMOUSE_BTN_LEFT);
|
||||
|
||||
// The low-level port-specific function which really generates the key
|
||||
// presses. It should generate exactly one key event with the given
|
||||
// parameters.
|
||||
virtual bool DoKey(int keycode, int modifiers, bool isDown) = 0;
|
||||
|
||||
private:
|
||||
wxDECLARE_NO_COPY_CLASS(wxUIActionSimulatorImpl);
|
||||
};
|
||||
|
||||
#endif // _WX_PRIVATE_UIACTION_H_
|
@@ -2,11 +2,10 @@
|
||||
// Name: wx/uiaction.h
|
||||
// Purpose: wxUIActionSimulator interface
|
||||
// Author: Kevin Ollivier, Steven Lamerton, Vadim Zeitlin
|
||||
// Modified by:
|
||||
// Created: 2010-03-06
|
||||
// Copyright: (c) Kevin Ollivier
|
||||
// Copyright: (c) 2010 Kevin Ollivier
|
||||
// (c) 2010 Steven Lamerton
|
||||
// (c) 2010 Vadim Zeitlin
|
||||
// (c) 2010-2016 Vadim Zeitlin
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -22,11 +21,8 @@
|
||||
class WXDLLIMPEXP_CORE wxUIActionSimulator
|
||||
{
|
||||
public:
|
||||
wxUIActionSimulator() { }
|
||||
|
||||
|
||||
// Default dtor, copy ctor and assignment operator are ok (even though the
|
||||
// last two don't make much sense for this class).
|
||||
wxUIActionSimulator();
|
||||
~wxUIActionSimulator();
|
||||
|
||||
|
||||
// Mouse simulation
|
||||
@@ -82,10 +78,12 @@ private:
|
||||
void SimulateModifiers(int modifier, bool isDown);
|
||||
|
||||
|
||||
// The low-level port-specific function which really generates the key
|
||||
// presses. It should generate exactly one key event with the given
|
||||
// parameters.
|
||||
bool DoKey(int keycode, int modifiers, bool isDown);
|
||||
|
||||
// This pointer is allocated in the ctor and points to the
|
||||
// platform-specific implementation.
|
||||
class wxUIActionSimulatorImpl* const m_impl;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(wxUIActionSimulator);
|
||||
};
|
||||
|
||||
#endif // wxUSE_UIACTIONSIMULATOR
|
||||
|
@@ -41,3 +41,11 @@
|
||||
# endif
|
||||
# endif
|
||||
#endif /* wxUSE_GSTREAMER */
|
||||
|
||||
#ifndef wxUSE_XTEST
|
||||
# ifdef wxABORT_ON_CONFIG_ERROR
|
||||
# error "wxUSE_XTEST must be defined, please read comment near the top of this file."
|
||||
# else
|
||||
# define wxUSE_XTEST 0
|
||||
# endif
|
||||
#endif /* !defined(wxUSE_XTEST) */
|
||||
|
@@ -67,6 +67,13 @@ public:
|
||||
wxX11Display() { m_dpy = XOpenDisplay(NULL); }
|
||||
~wxX11Display() { if ( m_dpy ) XCloseDisplay(m_dpy); }
|
||||
|
||||
// Pseudo move ctor: steals the open display from the other object.
|
||||
explicit wxX11Display(wxX11Display& display)
|
||||
{
|
||||
m_dpy = display.m_dpy;
|
||||
display.m_dpy = NULL;
|
||||
}
|
||||
|
||||
operator Display *() const { return m_dpy; }
|
||||
|
||||
// Using DefaultRootWindow() with an object of wxX11Display class doesn't
|
||||
|
@@ -2,9 +2,9 @@
|
||||
// Name: uiaction.cpp
|
||||
// Purpose: wxUIActionSimulator sample
|
||||
// Author: Kevin Ollivier
|
||||
// Modified by:
|
||||
// Created: 04/01/98
|
||||
// Copyright: (c) Kevin Ollivier, Steven Lamerton
|
||||
// Copyright: (c) 2010 Kevin Ollivier, Steven Lamerton
|
||||
// (c) 2016 Vadim Zeitlin
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
#include "wx/uiaction.h"
|
||||
#endif
|
||||
|
||||
#include "wx/stopwatch.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// resources
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -76,6 +78,7 @@ public:
|
||||
MyFrame(const wxString& title);
|
||||
|
||||
void OnButtonPressed(wxCommandEvent& event);
|
||||
void OnNew(wxCommandEvent& event);
|
||||
void OnRunSimulation(wxCommandEvent& event);
|
||||
void OnSimulateText(wxCommandEvent& event);
|
||||
void OnExit(wxCommandEvent& WXUNUSED(event)) { Close(); }
|
||||
@@ -89,6 +92,7 @@ private:
|
||||
|
||||
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
|
||||
EVT_BUTTON(wxID_ANY, MyFrame::OnButtonPressed)
|
||||
EVT_MENU(wxID_NEW, MyFrame::OnNew)
|
||||
EVT_MENU(RunSimulation, MyFrame::OnRunSimulation)
|
||||
EVT_MENU(SimulateText, MyFrame::OnSimulateText)
|
||||
EVT_MENU(wxID_EXIT, MyFrame::OnExit)
|
||||
@@ -139,9 +143,9 @@ MyFrame::MyFrame(const wxString& title)
|
||||
wxMenu *fileMenu = new wxMenu;
|
||||
|
||||
fileMenu->Append(wxID_NEW, "&New File...", "Open a new file");
|
||||
fileMenu->Append(RunSimulation, "&Run Simulation",
|
||||
fileMenu->Append(RunSimulation, "&Run Simulation\tCtrl-R",
|
||||
"Run predefined UI action simulation");
|
||||
fileMenu->Append(SimulateText, "Simulate &text input...",
|
||||
fileMenu->Append(SimulateText, "Simulate &text input...\tCtrl-T",
|
||||
"Enter text to simulate");
|
||||
fileMenu->AppendSeparator();
|
||||
|
||||
@@ -170,8 +174,25 @@ MyFrame::MyFrame(const wxString& title)
|
||||
|
||||
// event handlers
|
||||
|
||||
void MyFrame::OnNew(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
m_text->AppendText("\"New\" menu item was selected\n");
|
||||
}
|
||||
|
||||
void MyFrame::OnRunSimulation(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
m_text->SetValue("=== Starting the simulation "
|
||||
"(release any pressed keys) ===\n");
|
||||
|
||||
// This sleep is needed to give the time for the currently pressed modifier
|
||||
// keys, if any, to be released. Notice that Control modifier could well be
|
||||
// pressed if this command was activated from the menu using accelerator
|
||||
// and keeping it pressed would totally derail the test below, e.g. "A" key
|
||||
// press would actually become "Ctrl+A" selecting the entire text and so on.
|
||||
wxMilliSleep(500);
|
||||
|
||||
wxStopWatch sw;
|
||||
|
||||
wxUIActionSimulator sim;
|
||||
|
||||
// Add some extra distance to take account of window decorations
|
||||
@@ -193,6 +214,15 @@ void MyFrame::OnRunSimulation(wxCommandEvent& WXUNUSED(event))
|
||||
sim.Text("1 234.57e-8");
|
||||
sim.Char(WXK_RETURN);
|
||||
|
||||
// Process the resulting text events
|
||||
wxYield();
|
||||
|
||||
// Emulate opening a menu from keyboard.
|
||||
sim.Char('F', wxMOD_ALT);
|
||||
sim.Char('N');
|
||||
wxYield();
|
||||
|
||||
m_text->AppendText(wxString::Format("\n=== Done in %ldms ===\n", sw.Time()));
|
||||
}
|
||||
|
||||
void MyFrame::OnSimulateText(wxCommandEvent& WXUNUSED(event))
|
||||
|
10
setup.h.in
10
setup.h.in
@@ -639,6 +639,16 @@
|
||||
|
||||
#define wxUSE_GSTREAMER_PLAYER 0
|
||||
|
||||
/*
|
||||
Use XTest extension to implement wxUIActionSimulator?
|
||||
|
||||
Default is 1, it is set to 0 if the necessary headers/libraries are not
|
||||
found by configure.
|
||||
|
||||
Recommended setting: 1, wxUIActionSimulator won't work in wxGTK3 without it.
|
||||
*/
|
||||
#define wxUSE_XTEST 0
|
||||
|
||||
/* --- start MSW options --- */
|
||||
|
||||
|
||||
|
@@ -2,11 +2,10 @@
|
||||
// Name: src/common/uiactioncmn.cpp
|
||||
// Purpose: wxUIActionSimulator common implementation
|
||||
// Author: Kevin Ollivier, Steven Lamerton, Vadim Zeitlin
|
||||
// Modified by:
|
||||
// Created: 2010-03-06
|
||||
// Copyright: (c) Kevin Ollivier
|
||||
// Copyright: (c) 2010 Kevin Ollivier
|
||||
// (c) 2010 Steven Lamerton
|
||||
// (c) 2010 Vadim Zeitlin
|
||||
// (c) 2010-2016 Vadim Zeitlin
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -24,8 +23,48 @@
|
||||
#include "wx/listbox.h"
|
||||
#endif // wxNO_RTTI
|
||||
|
||||
#include "wx/private/uiaction.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Methods forwarded to wxUIActionSimulatorImpl
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool wxUIActionSimulator::MouseMove(long x, long y)
|
||||
{
|
||||
return m_impl->MouseMove(x, y);
|
||||
}
|
||||
|
||||
bool wxUIActionSimulator::MouseDown(int button)
|
||||
{
|
||||
return m_impl->MouseDown(button);
|
||||
}
|
||||
|
||||
bool wxUIActionSimulator::MouseUp(int button)
|
||||
{
|
||||
return m_impl->MouseUp(button);
|
||||
}
|
||||
|
||||
bool wxUIActionSimulator::MouseClick(int button)
|
||||
{
|
||||
return m_impl->MouseClick(button);
|
||||
}
|
||||
|
||||
bool wxUIActionSimulator::MouseDblClick(int button)
|
||||
{
|
||||
return m_impl->MouseDblClick(button);
|
||||
}
|
||||
|
||||
bool wxUIActionSimulator::MouseDragDrop(long x1, long y1, long x2, long y2,
|
||||
int button)
|
||||
{
|
||||
return m_impl->MouseDragDrop(x1, y1, x2, y2, button);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Methods implemented in wxUIActionSimulatorImpl itself
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool wxUIActionSimulatorImpl::MouseClick(int button)
|
||||
{
|
||||
MouseDown(button);
|
||||
MouseUp(button);
|
||||
@@ -33,9 +72,7 @@ bool wxUIActionSimulator::MouseClick(int button)
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef __WXOSX__
|
||||
|
||||
bool wxUIActionSimulator::MouseDblClick(int button)
|
||||
bool wxUIActionSimulatorImpl::MouseDblClick(int button)
|
||||
{
|
||||
MouseDown(button);
|
||||
MouseUp(button);
|
||||
@@ -45,7 +82,7 @@ bool wxUIActionSimulator::MouseDblClick(int button)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxUIActionSimulator::MouseDragDrop(long x1, long y1, long x2, long y2,
|
||||
bool wxUIActionSimulatorImpl::MouseDragDrop(long x1, long y1, long x2, long y2,
|
||||
int button)
|
||||
{
|
||||
MouseMove(x1, y1);
|
||||
@@ -56,8 +93,6 @@ bool wxUIActionSimulator::MouseDragDrop(long x1, long y1, long x2, long y2,
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool
|
||||
wxUIActionSimulator::Key(int keycode, int modifiers, bool isDown)
|
||||
{
|
||||
@@ -69,7 +104,7 @@ wxUIActionSimulator::Key(int keycode, int modifiers, bool isDown)
|
||||
if ( isDown )
|
||||
SimulateModifiers(modifiers, true);
|
||||
|
||||
bool rc = DoKey(keycode, modifiers, isDown);
|
||||
bool rc = m_impl->DoKey(keycode, modifiers, isDown);
|
||||
|
||||
if ( !isDown )
|
||||
SimulateModifiers(modifiers, false);
|
||||
@@ -80,11 +115,11 @@ wxUIActionSimulator::Key(int keycode, int modifiers, bool isDown)
|
||||
void wxUIActionSimulator::SimulateModifiers(int modifiers, bool isDown)
|
||||
{
|
||||
if ( modifiers & wxMOD_SHIFT )
|
||||
DoKey(WXK_SHIFT, modifiers, isDown);
|
||||
m_impl->DoKey(WXK_SHIFT, modifiers, isDown);
|
||||
if ( modifiers & wxMOD_ALT )
|
||||
DoKey(WXK_ALT, modifiers, isDown);
|
||||
m_impl->DoKey(WXK_ALT, modifiers, isDown);
|
||||
if ( modifiers & wxMOD_CONTROL )
|
||||
DoKey(WXK_CONTROL, modifiers, isDown);
|
||||
m_impl->DoKey(WXK_CONTROL, modifiers, isDown);
|
||||
}
|
||||
|
||||
bool wxUIActionSimulator::Char(int keycode, int modifiers)
|
||||
|
@@ -19,6 +19,8 @@
|
||||
#endif
|
||||
|
||||
#include "wx/uiaction.h"
|
||||
#include "wx/private/uiaction.h"
|
||||
|
||||
#include "wx/msw/wrapwin.h"
|
||||
|
||||
#include "wx/msw/private/keyboard.h"
|
||||
@@ -28,6 +30,31 @@
|
||||
namespace
|
||||
{
|
||||
|
||||
class wxUIActionSimulatorMSWImpl : public wxUIActionSimulatorImpl
|
||||
{
|
||||
public:
|
||||
// Returns a pointer to the global simulator object: as it's stateless, we
|
||||
// can reuse the same one without having to allocate it on the heap all the
|
||||
// time.
|
||||
static wxUIActionSimulatorMSWImpl* Get()
|
||||
{
|
||||
static wxUIActionSimulatorMSWImpl s_impl;
|
||||
return &s_impl;
|
||||
}
|
||||
|
||||
virtual bool MouseMove(long x, long y) wxOVERRIDE;
|
||||
virtual bool MouseDown(int button = wxMOUSE_BTN_LEFT) wxOVERRIDE;
|
||||
virtual bool MouseUp(int button = wxMOUSE_BTN_LEFT) wxOVERRIDE;
|
||||
|
||||
virtual bool DoKey(int keycode, int modifiers, bool isDown) wxOVERRIDE;
|
||||
|
||||
private:
|
||||
// This class has no public ctors, use Get() instead.
|
||||
wxUIActionSimulatorMSWImpl() { }
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(wxUIActionSimulatorMSWImpl);
|
||||
};
|
||||
|
||||
DWORD EventTypeForMouseButton(int button, bool isDown)
|
||||
{
|
||||
switch (button)
|
||||
@@ -49,7 +76,7 @@ DWORD EventTypeForMouseButton(int button, bool isDown)
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
bool wxUIActionSimulator::MouseDown(int button)
|
||||
bool wxUIActionSimulatorMSWImpl::MouseDown(int button)
|
||||
{
|
||||
POINT p;
|
||||
wxGetCursorPosMSW(&p);
|
||||
@@ -57,7 +84,7 @@ bool wxUIActionSimulator::MouseDown(int button)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxUIActionSimulator::MouseMove(long x, long y)
|
||||
bool wxUIActionSimulatorMSWImpl::MouseMove(long x, long y)
|
||||
{
|
||||
// Because MOUSEEVENTF_ABSOLUTE takes measurements scaled between 0 & 65535
|
||||
// we need to scale our input too
|
||||
@@ -73,7 +100,7 @@ bool wxUIActionSimulator::MouseMove(long x, long y)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxUIActionSimulator::MouseUp(int button)
|
||||
bool wxUIActionSimulatorMSWImpl::MouseUp(int button)
|
||||
{
|
||||
POINT p;
|
||||
wxGetCursorPosMSW(&p);
|
||||
@@ -82,7 +109,7 @@ bool wxUIActionSimulator::MouseUp(int button)
|
||||
}
|
||||
|
||||
bool
|
||||
wxUIActionSimulator::DoKey(int keycode, int WXUNUSED(modifiers), bool isDown)
|
||||
wxUIActionSimulatorMSWImpl::DoKey(int keycode, int WXUNUSED(modifiers), bool isDown)
|
||||
{
|
||||
bool isExtended;
|
||||
DWORD vkkeycode = wxMSWKeyboard::WXToVK(keycode, &isExtended);
|
||||
@@ -98,4 +125,15 @@ wxUIActionSimulator::DoKey(int keycode, int WXUNUSED(modifiers), bool isDown)
|
||||
return true;
|
||||
}
|
||||
|
||||
wxUIActionSimulator::wxUIActionSimulator()
|
||||
: m_impl(wxUIActionSimulatorMSWImpl::Get())
|
||||
{
|
||||
}
|
||||
|
||||
wxUIActionSimulator::~wxUIActionSimulator()
|
||||
{
|
||||
// We can use a static wxUIActionSimulatorMSWImpl object because it's
|
||||
// stateless, so no need to delete it.
|
||||
}
|
||||
|
||||
#endif // wxUSE_UIACTIONSIMULATOR
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/osx/uiaction_osx.cpp
|
||||
// Purpose: wxUIActionSimulator implementation
|
||||
// Purpose: wxUIActionSimulatorOSXImpl implementation
|
||||
// Author: Kevin Ollivier, Steven Lamerton, Vadim Zeitlin
|
||||
// Modified by:
|
||||
// Created: 2010-03-06
|
||||
@@ -19,6 +19,7 @@
|
||||
#if wxUSE_UIACTIONSIMULATOR
|
||||
|
||||
#include "wx/uiaction.h"
|
||||
#include "wx/private/uiaction.h"
|
||||
|
||||
#include "wx/log.h"
|
||||
|
||||
@@ -111,9 +112,38 @@ CGPoint GetMousePosition()
|
||||
return pos;
|
||||
}
|
||||
|
||||
class wxUIActionSimulatorOSXImpl : public wxUIActionSimulatorImpl
|
||||
{
|
||||
public:
|
||||
// Returns a pointer to the global simulator object: as it's stateless, we
|
||||
// can reuse the same one without having to allocate it on the heap all the
|
||||
// time.
|
||||
static wxUIActionSimulatorOSXImpl* Get()
|
||||
{
|
||||
static wxUIActionSimulatorOSXImpl s_impl;
|
||||
return &s_impl;
|
||||
}
|
||||
|
||||
virtual bool MouseMove(long x, long y) wxOVERRIDE;
|
||||
virtual bool MouseDown(int button = wxMOUSE_BTN_LEFT) wxOVERRIDE;
|
||||
virtual bool MouseUp(int button = wxMOUSE_BTN_LEFT) wxOVERRIDE;
|
||||
|
||||
virtual bool MouseDblClick(int button = wxMOUSE_BTN_LEFT) wxOVERRIDE;
|
||||
virtual bool MouseDragDrop(long x1, long y1, long x2, long y2,
|
||||
int button = wxMOUSE_BTN_LEFT) wxOVERRIDE;
|
||||
|
||||
virtual bool DoKey(int keycode, int modifiers, bool isDown) wxOVERRIDE;
|
||||
|
||||
private:
|
||||
// This class has no public ctors, use Get() instead.
|
||||
wxUIActionSimulatorOSXImpl() { }
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(wxUIActionSimulatorOSXImpl);
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
bool wxUIActionSimulator::MouseDown(int button)
|
||||
bool wxUIActionSimulatorOSXImpl::MouseDown(int button)
|
||||
{
|
||||
CGEventType type = CGEventTypeForMouseButton(button, true);
|
||||
wxCFRef<CGEventRef> event(
|
||||
@@ -131,7 +161,7 @@ bool wxUIActionSimulator::MouseDown(int button)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxUIActionSimulator::MouseMove(long x, long y)
|
||||
bool wxUIActionSimulatorOSXImpl::MouseMove(long x, long y)
|
||||
{
|
||||
CGPoint pos;
|
||||
pos.x = x;
|
||||
@@ -154,7 +184,7 @@ bool wxUIActionSimulator::MouseMove(long x, long y)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxUIActionSimulator::MouseUp(int button)
|
||||
bool wxUIActionSimulatorOSXImpl::MouseUp(int button)
|
||||
{
|
||||
CGEventType type = CGEventTypeForMouseButton(button, false);
|
||||
wxCFRef<CGEventRef> event(
|
||||
@@ -172,7 +202,7 @@ bool wxUIActionSimulator::MouseUp(int button)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxUIActionSimulator::MouseDblClick(int button)
|
||||
bool wxUIActionSimulatorOSXImpl::MouseDblClick(int button)
|
||||
{
|
||||
CGEventType downtype = CGEventTypeForMouseButton(button, true);
|
||||
CGEventType uptype = CGEventTypeForMouseButton(button, false);
|
||||
@@ -201,7 +231,7 @@ bool wxUIActionSimulator::MouseDblClick(int button)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxUIActionSimulator::MouseDragDrop(long x1, long y1, long x2, long y2,
|
||||
bool wxUIActionSimulatorOSXImpl::MouseDragDrop(long x1, long y1, long x2, long y2,
|
||||
int button)
|
||||
{
|
||||
CGPoint pos1,pos2;
|
||||
@@ -241,7 +271,7 @@ bool wxUIActionSimulator::MouseDragDrop(long x1, long y1, long x2, long y2,
|
||||
}
|
||||
|
||||
bool
|
||||
wxUIActionSimulator::DoKey(int keycode, int WXUNUSED(modifiers), bool isDown)
|
||||
wxUIActionSimulatorOSXImpl::DoKey(int keycode, int WXUNUSED(modifiers), bool isDown)
|
||||
{
|
||||
CGKeyCode cgcode = wxCharCodeWXToOSX((wxKeyCode)keycode);
|
||||
|
||||
@@ -258,5 +288,15 @@ wxUIActionSimulator::DoKey(int keycode, int WXUNUSED(modifiers), bool isDown)
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // wxUSE_UIACTIONSIMULATOR
|
||||
wxUIActionSimulator::wxUIActionSimulator()
|
||||
: m_impl(wxUIActionSimulatorOSXImpl::Get())
|
||||
{
|
||||
}
|
||||
|
||||
wxUIActionSimulator::~wxUIActionSimulator()
|
||||
{
|
||||
// We can use a static wxUIActionSimulatorOSXImpl object because it's
|
||||
// stateless, so no need to delete it.
|
||||
}
|
||||
|
||||
#endif // wxUSE_UIACTIONSIMULATOR
|
||||
|
@@ -12,13 +12,15 @@
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "wx/uiaction.h"
|
||||
#include "wx/private/uiaction.h"
|
||||
|
||||
#include <QtTest/QtTestGui>
|
||||
#include <QApplication>
|
||||
#include <QWidget>
|
||||
|
||||
#include "wx/qt/defs.h"
|
||||
#include "wx/qt/private/utils.h"
|
||||
#include "wx/uiaction.h"
|
||||
#include "wx/qt/private/converter.h"
|
||||
|
||||
|
||||
@@ -37,6 +39,31 @@ inline QWindow* argForEvents(QWidget* w) { return w->windowHandle(); }
|
||||
inline QWidget* argForEvents(QWidget* w) { return w; }
|
||||
#endif
|
||||
|
||||
class wxUIActionSimulatorQtImpl : public wxUIActionSimulatorImpl
|
||||
{
|
||||
public:
|
||||
// Returns a pointer to the global simulator object: as it's stateless, we
|
||||
// can reuse the same one without having to allocate it on the heap all the
|
||||
// time.
|
||||
static wxUIActionSimulatorQtImpl* Get()
|
||||
{
|
||||
static wxUIActionSimulatorQtImpl s_impl;
|
||||
return &s_impl;
|
||||
}
|
||||
|
||||
virtual bool MouseMove(long x, long y) wxOVERRIDE;
|
||||
virtual bool MouseDown(int button = wxMOUSE_BTN_LEFT) wxOVERRIDE;
|
||||
virtual bool MouseUp(int button = wxMOUSE_BTN_LEFT) wxOVERRIDE;
|
||||
|
||||
virtual bool DoKey(int keycode, int modifiers, bool isDown) wxOVERRIDE;
|
||||
|
||||
private:
|
||||
// This class has no public ctors, use Get() instead.
|
||||
wxUIActionSimulatorQtImpl() { }
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(wxUIActionSimulatorQtImpl);
|
||||
};
|
||||
|
||||
static MouseButton ConvertMouseButton( int button )
|
||||
{
|
||||
MouseButton qtButton;
|
||||
@@ -95,24 +122,24 @@ static bool SimulateKeyboardKey( KeyAction keyAction, Key key )
|
||||
return widget != NULL;
|
||||
}
|
||||
|
||||
bool wxUIActionSimulator::MouseDown( int button )
|
||||
bool wxUIActionSimulatorQtImpl::MouseDown( int button )
|
||||
{
|
||||
return SimulateMouseButton( MousePress, ConvertMouseButton( button ));
|
||||
}
|
||||
|
||||
bool wxUIActionSimulator::MouseUp(int button)
|
||||
bool wxUIActionSimulatorQtImpl::MouseUp(int button)
|
||||
{
|
||||
return SimulateMouseButton( MouseRelease, ConvertMouseButton( button ));
|
||||
}
|
||||
|
||||
bool wxUIActionSimulator::MouseMove(long x, long y)
|
||||
bool wxUIActionSimulatorQtImpl::MouseMove(long x, long y)
|
||||
{
|
||||
QCursor::setPos( x, y );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxUIActionSimulator::DoKey(int keyCode, int modifiers, bool isDown)
|
||||
bool wxUIActionSimulatorQtImpl::DoKey(int keyCode, int modifiers, bool isDown)
|
||||
{
|
||||
Qt::KeyboardModifiers qtmodifiers;
|
||||
enum Key key;
|
||||
@@ -124,5 +151,16 @@ bool wxUIActionSimulator::DoKey(int keyCode, int modifiers, bool isDown)
|
||||
return SimulateKeyboardKey( keyAction, key );
|
||||
}
|
||||
|
||||
#endif // wxUSE_UIACTIONSIMULATOR
|
||||
|
||||
wxUIActionSimulator::wxUIActionSimulator()
|
||||
: m_impl(wxUIActionSimulatorQtImpl::Get())
|
||||
{
|
||||
}
|
||||
|
||||
wxUIActionSimulator::~wxUIActionSimulator()
|
||||
{
|
||||
// We can use a static wxUIActionSimulatorQtImpl object because it's
|
||||
// stateless, so no need to delete it.
|
||||
}
|
||||
|
||||
#endif // wxUSE_UIACTIONSIMULATOR
|
||||
|
@@ -2,11 +2,10 @@
|
||||
// Name: src/unix/uiactionx11.cpp
|
||||
// Purpose: wxUIActionSimulator implementation
|
||||
// Author: Kevin Ollivier, Steven Lamerton, Vadim Zeitlin
|
||||
// Modified by:
|
||||
// Created: 2010-03-06
|
||||
// Copyright: (c) Kevin Ollivier
|
||||
// Copyright: (c) 2010 Kevin Ollivier
|
||||
// (c) 2010 Steven Lamerton
|
||||
// (c) 2010 Vadim Zeitlin
|
||||
// (c) 2010-2016 Vadim Zeitlin
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -18,16 +17,72 @@
|
||||
#include "wx/event.h"
|
||||
#include "wx/evtloop.h"
|
||||
|
||||
#include "wx/private/uiaction.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#if wxUSE_XTEST
|
||||
#include <X11/extensions/XTest.h>
|
||||
#endif
|
||||
|
||||
#include "wx/unix/utilsx11.h"
|
||||
|
||||
#ifdef __WXGTK3__
|
||||
#include <gdk/gdk.h>
|
||||
#include <gtk/gtk.h>
|
||||
#endif
|
||||
|
||||
// Normally we fall back on "plain X" implementation if XTest is not available,
|
||||
// but it's useless to do it when using GTK+ 3 as it's not going to work with
|
||||
// it anyhow because GTK+ 3 needs XInput2 events and not the "classic" ones we
|
||||
// synthesize here, so don't even compile in this code for wxGTK3 port.
|
||||
#define wxUSE_PLAINX_IMPL (!defined(__WXGTK3__))
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
void SendButtonEvent(int button, bool isDown)
|
||||
// Base class for both available X11 implementations.
|
||||
class wxUIActionSimulatorX11Impl : public wxUIActionSimulatorImpl
|
||||
{
|
||||
public:
|
||||
// Return the most appopriate implementation to use: if XTest is available,
|
||||
// use it, otherwise use plain X11 calls.
|
||||
//
|
||||
// The returned pointer is owned by the caller.
|
||||
static wxUIActionSimulatorImpl* New();
|
||||
|
||||
virtual bool MouseMove(long x, long y) wxOVERRIDE;
|
||||
virtual bool MouseDown(int button = wxMOUSE_BTN_LEFT) wxOVERRIDE;
|
||||
virtual bool MouseUp(int button = wxMOUSE_BTN_LEFT) wxOVERRIDE;
|
||||
|
||||
virtual bool DoKey(int keycode, int modifiers, bool isDown) wxOVERRIDE;
|
||||
|
||||
protected:
|
||||
// This ctor takes ownership of the display.
|
||||
explicit wxUIActionSimulatorX11Impl(wxX11Display& display)
|
||||
: m_display(display)
|
||||
{
|
||||
}
|
||||
|
||||
wxX11Display m_display;
|
||||
|
||||
private:
|
||||
// Common implementation of Mouse{Down,Up}() which just forwards to
|
||||
// DoX11Button() after translating wx button to X button constant.
|
||||
bool SendButtonEvent(int button, bool isDown);
|
||||
|
||||
virtual bool DoX11Button(int xbutton, bool isDown) = 0;
|
||||
virtual bool DoX11MouseMove(long x, long y) = 0;
|
||||
virtual bool DoX11Key(KeyCode xkeycode, int modifiers, bool isDown) = 0;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(wxUIActionSimulatorX11Impl);
|
||||
};
|
||||
|
||||
bool wxUIActionSimulatorX11Impl::SendButtonEvent(int button, bool isDown)
|
||||
{
|
||||
if ( !m_display )
|
||||
return false;
|
||||
|
||||
int xbutton;
|
||||
switch (button)
|
||||
{
|
||||
@@ -42,12 +97,37 @@ void SendButtonEvent(int button, bool isDown)
|
||||
break;
|
||||
default:
|
||||
wxFAIL_MSG("Unsupported button passed in.");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
wxX11Display display;
|
||||
wxCHECK_RET(display, "No display available!");
|
||||
// Ensure that the event is received by the correct window by processing
|
||||
// all pending events, notably mouse moves.
|
||||
XSync(m_display, False /* don't discard */);
|
||||
|
||||
return DoX11Button(xbutton, isDown);
|
||||
}
|
||||
|
||||
#if wxUSE_PLAINX_IMPL
|
||||
|
||||
// Implementation using just plain X11 calls.
|
||||
class wxUIActionSimulatorPlainX11Impl : public wxUIActionSimulatorX11Impl
|
||||
{
|
||||
public:
|
||||
explicit wxUIActionSimulatorPlainX11Impl(wxX11Display& display)
|
||||
: wxUIActionSimulatorX11Impl(display)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
virtual bool DoX11Button(int xbutton, bool isDown) wxOVERRIDE;
|
||||
virtual bool DoX11MouseMove(long x, long y) wxOVERRIDE;
|
||||
virtual bool DoX11Key(KeyCode xkeycode, int modifiers, bool isDown) wxOVERRIDE;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(wxUIActionSimulatorPlainX11Impl);
|
||||
};
|
||||
|
||||
bool wxUIActionSimulatorPlainX11Impl::DoX11Button(int xbutton, bool isDown)
|
||||
{
|
||||
XEvent event;
|
||||
memset(&event, 0x00, sizeof(event));
|
||||
|
||||
@@ -55,7 +135,7 @@ void SendButtonEvent(int button, bool isDown)
|
||||
event.xbutton.button = xbutton;
|
||||
event.xbutton.same_screen = True;
|
||||
|
||||
XQueryPointer(display, display.DefaultRoot(),
|
||||
XQueryPointer(m_display, m_display.DefaultRoot(),
|
||||
&event.xbutton.root, &event.xbutton.window,
|
||||
&event.xbutton.x_root, &event.xbutton.y_root,
|
||||
&event.xbutton.x, &event.xbutton.y, &event.xbutton.state);
|
||||
@@ -64,54 +144,29 @@ void SendButtonEvent(int button, bool isDown)
|
||||
while (event.xbutton.subwindow)
|
||||
{
|
||||
event.xbutton.window = event.xbutton.subwindow;
|
||||
XQueryPointer(display, event.xbutton.window,
|
||||
XQueryPointer(m_display, event.xbutton.window,
|
||||
&event.xbutton.root, &event.xbutton.subwindow,
|
||||
&event.xbutton.x_root, &event.xbutton.y_root,
|
||||
&event.xbutton.x, &event.xbutton.y, &event.xbutton.state);
|
||||
}
|
||||
|
||||
XSendEvent(display, PointerWindow, True, 0xfff, &event);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
bool wxUIActionSimulator::MouseDown(int button)
|
||||
{
|
||||
SendButtonEvent(button, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxUIActionSimulator::MouseMove(long x, long y)
|
||||
{
|
||||
wxX11Display display;
|
||||
wxASSERT_MSG(display, "No display available!");
|
||||
|
||||
Window root = display.DefaultRoot();
|
||||
XWarpPointer(display, None, root, 0, 0, 0, 0, x, y);
|
||||
|
||||
// At least with wxGTK we must always process the pending events before the
|
||||
// mouse position change really takes effect, so just do it from here
|
||||
// instead of forcing the client code using this function to always use
|
||||
// wxYield() which is unnecessary under the other platforms.
|
||||
if ( wxEventLoopBase* const loop = wxEventLoop::GetActive() )
|
||||
{
|
||||
loop->YieldFor(wxEVT_CATEGORY_USER_INPUT);
|
||||
}
|
||||
XSendEvent(m_display, PointerWindow, True, 0xfff, &event);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxUIActionSimulator::MouseUp(int button)
|
||||
bool wxUIActionSimulatorPlainX11Impl::DoX11MouseMove(long x, long y)
|
||||
{
|
||||
SendButtonEvent(button, false);
|
||||
Window root = m_display.DefaultRoot();
|
||||
XWarpPointer(m_display, None, root, 0, 0, 0, 0, x, y);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxUIActionSimulator::DoKey(int keycode, int modifiers, bool isDown)
|
||||
bool
|
||||
wxUIActionSimulatorPlainX11Impl::DoX11Key(KeyCode xkeycode,
|
||||
int modifiers,
|
||||
bool isDown)
|
||||
{
|
||||
wxX11Display display;
|
||||
wxCHECK_MSG(display, false, "No display available!");
|
||||
|
||||
int mask, type;
|
||||
|
||||
if ( isDown )
|
||||
@@ -125,14 +180,9 @@ bool wxUIActionSimulator::DoKey(int keycode, int modifiers, bool isDown)
|
||||
mask = KeyReleaseMask;
|
||||
}
|
||||
|
||||
WXKeySym xkeysym = wxCharCodeWXToX(keycode);
|
||||
KeyCode xkeycode = XKeysymToKeycode(display, xkeysym);
|
||||
if ( xkeycode == NoSymbol )
|
||||
return false;
|
||||
|
||||
Window focus;
|
||||
int revert;
|
||||
XGetInputFocus(display, &focus, &revert);
|
||||
XGetInputFocus(m_display, &focus, &revert);
|
||||
if (focus == None)
|
||||
return false;
|
||||
|
||||
@@ -147,7 +197,7 @@ bool wxUIActionSimulator::DoKey(int keycode, int modifiers, bool isDown)
|
||||
mod |= ControlMask;
|
||||
|
||||
XKeyEvent event;
|
||||
event.display = display;
|
||||
event.display = m_display;
|
||||
event.window = focus;
|
||||
event.root = DefaultRootWindow(event.display);
|
||||
event.subwindow = None;
|
||||
@@ -166,4 +216,141 @@ bool wxUIActionSimulator::DoKey(int keycode, int modifiers, bool isDown)
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // wxUSE_PLAINX_IMPL
|
||||
|
||||
#if wxUSE_XTEST
|
||||
|
||||
// Implementation using XTest extension.
|
||||
class wxUIActionSimulatorXTestImpl : public wxUIActionSimulatorX11Impl
|
||||
{
|
||||
public:
|
||||
explicit wxUIActionSimulatorXTestImpl(wxX11Display& display)
|
||||
: wxUIActionSimulatorX11Impl(display)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
virtual bool DoX11Button(int xbutton, bool isDown) wxOVERRIDE;
|
||||
virtual bool DoX11MouseMove(long x, long y) wxOVERRIDE;
|
||||
virtual bool DoX11Key(KeyCode xkeycode, int modifiers, bool isDown) wxOVERRIDE;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(wxUIActionSimulatorXTestImpl);
|
||||
};
|
||||
|
||||
bool wxUIActionSimulatorXTestImpl::DoX11Button(int xbutton, bool isDown)
|
||||
{
|
||||
return XTestFakeButtonEvent(m_display, xbutton, isDown, 0) != 0;
|
||||
}
|
||||
|
||||
bool wxUIActionSimulatorXTestImpl::DoX11MouseMove(long x, long y)
|
||||
{
|
||||
#ifdef __WXGTK3__
|
||||
// We need to take into account the scaling factor as the input coordinates
|
||||
// are in GTK logical "application pixels", while we need the physical
|
||||
// "device pixels" for the X call below, so scale them if we have the
|
||||
// required support at both compile- and run-time.
|
||||
#if GTK_CHECK_VERSION(3,10,0)
|
||||
if ( gtk_check_version(3, 10, 0) == NULL )
|
||||
{
|
||||
if ( GdkScreen* const screen = gdk_screen_get_default() )
|
||||
{
|
||||
// For multi-monitor support we would need to determine to which
|
||||
// monitor the point (x, y) belongs, for now just use the scale
|
||||
// factor of the main one.
|
||||
gint const scale = gdk_screen_get_monitor_scale_factor(screen, 0);
|
||||
x *= scale;
|
||||
y *= scale;
|
||||
}
|
||||
}
|
||||
#endif // GTK+ 3.10+
|
||||
#endif // __WXGTK3__
|
||||
|
||||
return XTestFakeMotionEvent(m_display, -1, x, y, 0) != 0;
|
||||
}
|
||||
|
||||
bool
|
||||
wxUIActionSimulatorXTestImpl::DoX11Key(KeyCode xkeycode,
|
||||
int WXUNUSED(modifiers),
|
||||
bool isDown)
|
||||
{
|
||||
return XTestFakeKeyEvent(m_display, xkeycode, isDown, 0) != 0;
|
||||
}
|
||||
|
||||
#endif // wxUSE_XTEST
|
||||
|
||||
wxUIActionSimulatorImpl* wxUIActionSimulatorX11Impl::New()
|
||||
{
|
||||
wxX11Display display;
|
||||
|
||||
#if wxUSE_XTEST
|
||||
// If we can fall back on plain X implementation, check if XTest extension
|
||||
// is available and if it isn't, use the other one. OTOH if we don't have
|
||||
// the other one anyhow, then testing for XTest availability is useless.
|
||||
#if wxUSE_PLAINX_IMPL
|
||||
int dummy;
|
||||
if ( XTestQueryExtension(display, &dummy, &dummy, &dummy, &dummy) )
|
||||
#endif // wxUSE_PLAINX_IMPL
|
||||
return new wxUIActionSimulatorXTestImpl(display);
|
||||
#endif // wxUSE_XTEST
|
||||
|
||||
#if wxUSE_PLAINX_IMPL
|
||||
return new wxUIActionSimulatorPlainX11Impl(display);
|
||||
#endif // wxUSE_PLAINX_IMPL
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
bool wxUIActionSimulatorX11Impl::MouseDown(int button)
|
||||
{
|
||||
return SendButtonEvent(button, true);
|
||||
}
|
||||
|
||||
bool wxUIActionSimulatorX11Impl::MouseMove(long x, long y)
|
||||
{
|
||||
if ( !m_display )
|
||||
return false;
|
||||
|
||||
if ( !DoX11MouseMove(x, y) )
|
||||
return false;
|
||||
|
||||
// At least with wxGTK we must always process the pending events before the
|
||||
// mouse position change really takes effect, so just do it from here
|
||||
// instead of forcing the client code using this function to always use
|
||||
// wxYield() which is unnecessary under the other platforms.
|
||||
if ( wxEventLoopBase* const loop = wxEventLoop::GetActive() )
|
||||
{
|
||||
loop->YieldFor(wxEVT_CATEGORY_USER_INPUT);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxUIActionSimulatorX11Impl::MouseUp(int button)
|
||||
{
|
||||
return SendButtonEvent(button, false);
|
||||
}
|
||||
|
||||
bool wxUIActionSimulatorX11Impl::DoKey(int keycode, int modifiers, bool isDown)
|
||||
{
|
||||
if ( !m_display )
|
||||
return false;
|
||||
|
||||
WXKeySym xkeysym = wxCharCodeWXToX(keycode);
|
||||
KeyCode xkeycode = XKeysymToKeycode(m_display, xkeysym);
|
||||
if ( xkeycode == NoSymbol )
|
||||
return false;
|
||||
|
||||
return DoX11Key(xkeycode, modifiers, isDown);
|
||||
}
|
||||
|
||||
wxUIActionSimulator::wxUIActionSimulator()
|
||||
: m_impl(wxUIActionSimulatorX11Impl::New())
|
||||
{
|
||||
}
|
||||
|
||||
wxUIActionSimulator::~wxUIActionSimulator()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
#endif // wxUSE_UIACTIONSIMULATOR
|
||||
|
Reference in New Issue
Block a user