From 571d991bb3232f0dcd3319dbdc9d35e5c80f4c71 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 22 Aug 2010 22:15:42 +0000 Subject: [PATCH] Merge wxUIActionSimulator fixes from SOC2010_GUI_TEST branch. Correct a lot of problems with the initial implementation, notably make the API consistent across all platforms, e.g. all keyboard-related methods now take just a wxKeyCode. Add some useful higher-level helpers such as Text() and MouseDragDrop(). Improve documentation. wxUIActionSimulator now works under MSW, GTK and OS X and is enabled by default. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@65385 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- configure | 1 - configure.in | 1 - docs/changes.txt | 1 + docs/doxygen/mainpages/samples.h | 12 ++ include/wx/motif/setup0.h | 4 +- include/wx/msw/setup0.h | 4 +- include/wx/msw/wince/setup.h | 4 +- include/wx/os2/setup0.h | 4 +- include/wx/osx/setup0.h | 4 +- include/wx/palmos/setup0.h | 4 +- include/wx/setup_inc.h | 4 +- include/wx/uiaction.h | 139 ++++++++++++-------- include/wx/univ/setup0.h | 4 +- include/wx/unix/utilsx11.h | 4 + include/wx/x11/privx.h | 3 - interface/wx/uiaction.h | 112 ++++++++-------- samples/uiaction/uiaction.cpp | 73 ++++++----- src/common/uiactioncmn.cpp | 53 ++++++-- src/msw/uiaction.cpp | 68 +++++++--- src/osx/uiaction_osx.cpp | 270 +++++++++++++++++++++++++++++---------- src/unix/uiactionx11.cpp | 119 ++++++++++------- src/unix/utilsx11.cpp | 6 +- 22 files changed, 578 insertions(+), 316 deletions(-) rewrite include/wx/uiaction.h (69%) diff --git a/configure b/configure index e6e851b..4dbc508 100755 --- a/configure +++ b/configure @@ -2980,7 +2980,6 @@ DEFAULT_wxUSE_LIBSDL=no DEFAULT_wxUSE_ACCESSIBILITY=no DEFAULT_wxUSE_IPV6=no DEFAULT_wxUSE_GSTREAMER8=no -DEFAULT_wxUSE_UIACTIONSIMULATOR=no DEFAULT_wxUSE_UNICODE_UTF8=auto DEFAULT_wxUSE_OPENGL=auto diff --git a/configure.in b/configure.in index ff376e9..0db87d3 100644 --- a/configure.in +++ b/configure.in @@ -387,7 +387,6 @@ dnl features disabled by default DEFAULT_wxUSE_ACCESSIBILITY=no DEFAULT_wxUSE_IPV6=no DEFAULT_wxUSE_GSTREAMER8=no -DEFAULT_wxUSE_UIACTIONSIMULATOR=no dnl automatic features DEFAULT_wxUSE_UNICODE_UTF8=auto diff --git a/docs/changes.txt b/docs/changes.txt index 7e831c5..2682b19 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -407,6 +407,7 @@ All (GUI): - Added wxRichMessageDialog (Rickard Westerlund, GSoC 2010 project). - Added wxCommandLinkButton (Rickard Westerlund, GSoC 2010 project). +- Added wxUIActionSimulator (Steven Lamerton, GSoC 2010 project). - wxAUI: support auto-orientable toolbars (wsu). - Added wxDataViewCtrl::Set/GetCurrentItem(). - wxHTML: render in RTL order inside RTL window (Richard Bullington-McGuire). diff --git a/docs/doxygen/mainpages/samples.h b/docs/doxygen/mainpages/samples.h index 88dd1fa..ae26850 100644 --- a/docs/doxygen/mainpages/samples.h +++ b/docs/doxygen/mainpages/samples.h @@ -131,6 +131,7 @@ TODO: Organize them in a more human-readable way. @li @sample{toolbar} @li @sample{treectrl} @li @sample{typetest} +@li @sample{uiaction} @li @sample{validate} @li @sample{vscroll} @li @sample{widgets} @@ -989,6 +990,17 @@ demonstrated here as well - try the corresponding menu entries. @sampledir{typetest} +@section page_samples_uiaction wxUIActionSimulator Sample + +@sampleabout{wxUIActionSimulator} + +This sample shows some features of wxUIActionSimulator class. When a simulation +is ran using its menu items, you can see that the button is pressed +programmatically and the characters generated by the program appear in the text +control. + +@sampledir{uiaction} + @section page_samples_validate Validator Sample @sampleabout{wxValidator} diff --git a/include/wx/motif/setup0.h b/include/wx/motif/setup0.h index 955c6d2..f5ac2e4 100644 --- a/include/wx/motif/setup0.h +++ b/include/wx/motif/setup0.h @@ -1246,9 +1246,7 @@ // Include mouse wheel support // Compile wxUIActionSimulator class? -// -// This is experimental code subject to change. It's not fully implemented yet. -#define wxUSE_UIACTIONSIMULATOR 0 +#define wxUSE_UIACTIONSIMULATOR 1 // ---------------------------------------------------------------------------- // wxDC classes for various output formats diff --git a/include/wx/msw/setup0.h b/include/wx/msw/setup0.h index 58314a3..4a2210c 100644 --- a/include/wx/msw/setup0.h +++ b/include/wx/msw/setup0.h @@ -1246,9 +1246,7 @@ // Include mouse wheel support // Compile wxUIActionSimulator class? -// -// This is experimental code subject to change. It's not fully implemented yet. -#define wxUSE_UIACTIONSIMULATOR 0 +#define wxUSE_UIACTIONSIMULATOR 1 // ---------------------------------------------------------------------------- // wxDC classes for various output formats diff --git a/include/wx/msw/wince/setup.h b/include/wx/msw/wince/setup.h index 0cb30ad..b8f731c 100644 --- a/include/wx/msw/wince/setup.h +++ b/include/wx/msw/wince/setup.h @@ -1246,9 +1246,7 @@ // Include mouse wheel support // Compile wxUIActionSimulator class? -// -// This is experimental code subject to change. It's not fully implemented yet. -#define wxUSE_UIACTIONSIMULATOR 0 +#define wxUSE_UIACTIONSIMULATOR 1 // ---------------------------------------------------------------------------- // wxDC classes for various output formats diff --git a/include/wx/os2/setup0.h b/include/wx/os2/setup0.h index 9b6bbe5..45ba6ad 100644 --- a/include/wx/os2/setup0.h +++ b/include/wx/os2/setup0.h @@ -1246,9 +1246,7 @@ // Include mouse wheel support // Compile wxUIActionSimulator class? -// -// This is experimental code subject to change. It's not fully implemented yet. -#define wxUSE_UIACTIONSIMULATOR 0 +#define wxUSE_UIACTIONSIMULATOR 1 // ---------------------------------------------------------------------------- // wxDC classes for various output formats diff --git a/include/wx/osx/setup0.h b/include/wx/osx/setup0.h index 1093b26..29ef9e4 100644 --- a/include/wx/osx/setup0.h +++ b/include/wx/osx/setup0.h @@ -1247,9 +1247,7 @@ // Include mouse wheel support // Compile wxUIActionSimulator class? -// -// This is experimental code subject to change. It's not fully implemented yet. -#define wxUSE_UIACTIONSIMULATOR 0 +#define wxUSE_UIACTIONSIMULATOR 1 // ---------------------------------------------------------------------------- // wxDC classes for various output formats diff --git a/include/wx/palmos/setup0.h b/include/wx/palmos/setup0.h index 3ddfa59..7c806a1 100644 --- a/include/wx/palmos/setup0.h +++ b/include/wx/palmos/setup0.h @@ -1246,9 +1246,7 @@ // Include mouse wheel support // Compile wxUIActionSimulator class? -// -// This is experimental code subject to change. It's not fully implemented yet. -#define wxUSE_UIACTIONSIMULATOR 0 +#define wxUSE_UIACTIONSIMULATOR 1 // ---------------------------------------------------------------------------- // wxDC classes for various output formats diff --git a/include/wx/setup_inc.h b/include/wx/setup_inc.h index 9f6cb8c..0db49ad 100644 --- a/include/wx/setup_inc.h +++ b/include/wx/setup_inc.h @@ -1242,9 +1242,7 @@ // Include mouse wheel support // Compile wxUIActionSimulator class? -// -// This is experimental code subject to change. It's not fully implemented yet. -#define wxUSE_UIACTIONSIMULATOR 0 +#define wxUSE_UIACTIONSIMULATOR 1 // ---------------------------------------------------------------------------- // wxDC classes for various output formats diff --git a/include/wx/uiaction.h b/include/wx/uiaction.h dissimilarity index 69% index a08aea7..e662b2c 100644 --- a/include/wx/uiaction.h +++ b/include/wx/uiaction.h @@ -1,56 +1,83 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: wx/uiaction.h -// Purpose: wxUIActionSimulator interface -// Author: Kevin Ollivier -// Modified by: -// Created: 2010-03-06 -// RCS-ID: $Id: menu.cpp 54129 2008-06-11 19:30:52Z SC $ -// Copyright: (c) Kevin Ollivier -// Licence: wxWindows licence -///////////////////////////////////////////////////////////////////////////// - -#ifndef _WX_UIACTIONSIMULATOR_H_ -#define _WX_UIACTIONSIMULATOR_H_ - -#include "wx/defs.h" - -#if wxUSE_UIACTIONSIMULATOR - -#include "wx/event.h" -#include "wx/dynarray.h" - -class WXDLLIMPEXP_CORE wxUIActionSimulator -{ -public: - wxUIActionSimulator(); - ~wxUIActionSimulator(); - - // Mouse related - bool MouseMove(long x, long y); - bool MouseDown(int button = wxMOUSE_BTN_LEFT); - bool MouseUp(int button = wxMOUSE_BTN_LEFT); - bool MouseClick(int button = wxMOUSE_BTN_LEFT); - bool MouseDblClick(int button = wxMOUSE_BTN_LEFT); - bool MouseDragDrop(long x1, long y1, long x2, long y2, int button = wxMOUSE_BTN_LEFT); - - // Keyboard related: - - bool KeyDown(int keycode, bool shiftDown=false, bool cmdDown=false, bool altDown=false) - { return Key(keycode, true, shiftDown, cmdDown, altDown); } - - bool KeyUp(int keycode, bool shiftDown=false, bool cmdDown=false, bool altDown=false) - { return Key(keycode, false, shiftDown, cmdDown, altDown); } - - bool Char(int keycode, bool shiftDown=false, bool cmdDown=false, bool altDown=false); - -protected: - // Implementation-wise, since key events take more code to set up on GTK and Mac, it makes - // sense to handle both key down and key up in one method. However, I wanted the API for pressing - // and releasing the mouse and keyboard to be consistent, and I don't really like using a bool - // for pressed state, so I'm leaving this as an implementation detail. - bool Key(int keycode, bool isDown=true, bool shiftDown=false, bool cmdDown=false, bool altDown=false); -}; - -#endif // wxUSE_UIACTIONSIMULATOR - -#endif // _WX_UIACTIONSIMULATOR_H_ +///////////////////////////////////////////////////////////////////////////// +// Name: wx/uiaction.h +// Purpose: wxUIActionSimulator interface +// Author: Kevin Ollivier, Steven Lamerton, Vadim Zeitlin +// Modified by: +// Created: 2010-03-06 +// RCS-ID: $Id: menu.cpp 54129 2008-06-11 19:30:52Z SC $ +// Copyright: (c) Kevin Ollivier +// (c) 2010 Steven Lamerton +// (c) 2010 Vadim Zeitlin +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_UIACTIONSIMULATOR_H_ +#define _WX_UIACTIONSIMULATOR_H_ + +#include "wx/defs.h" + +#if wxUSE_UIACTIONSIMULATOR + +#include "wx/mousestate.h" // for wxMOUSE_BTN_XXX constants + +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). + + + // Mouse simulation + // ---------------- + + // Low level methods + bool MouseMove(long x, long y); + bool MouseMove(const wxPoint& point) { return MouseMove(point.x, point.y); } + + bool MouseDown(int button = wxMOUSE_BTN_LEFT); + bool MouseUp(int button = wxMOUSE_BTN_LEFT); + + // Higher level interface, use it if possible instead + bool MouseClick(int button = wxMOUSE_BTN_LEFT); + bool MouseDblClick(int button = wxMOUSE_BTN_LEFT); + bool MouseDragDrop(long x1, long y1, long x2, long y2, + int button = wxMOUSE_BTN_LEFT); + + + // Keyboard simulation + // ------------------- + + // Low level methods for generating key presses and releases + bool KeyDown(int keycode, int modifiers = wxMOD_NONE) + { return Key(keycode, modifiers, true); } + + bool KeyUp(int keycode, int modifiers = wxMOD_NONE) + { return Key(keycode, modifiers, false); } + + // Higher level methods for generating both the key press and release for a + // single key or for all characters in the ASCII string "text" which can + // currently contain letters only (no digits, no punctuation). + bool Char(int keycode, int modifiers = wxMOD_NONE); + + bool Text(const char *text); + +private: + // This is the common part of Key{Down,Up}() methods: while we keep them + // separate at public API level for consistency with Mouse{Down,Up}(), at + // implementation level it makes more sense to have them in a single + // function. + // + // This is a simple wrapper verifying the input parameters validity around + // the platform-specific DoKey() method implemented in platform-specific + // files. + bool Key(int keycode, int modifiers, bool isDown); + + bool DoKey(int keycode, int modifiers, bool isDown); +}; + +#endif // wxUSE_UIACTIONSIMULATOR + +#endif // _WX_UIACTIONSIMULATOR_H_ diff --git a/include/wx/univ/setup0.h b/include/wx/univ/setup0.h index afea2b1..a6fc8f7 100644 --- a/include/wx/univ/setup0.h +++ b/include/wx/univ/setup0.h @@ -1245,9 +1245,7 @@ // Include mouse wheel support // Compile wxUIActionSimulator class? -// -// This is experimental code subject to change. It's not fully implemented yet. -#define wxUSE_UIACTIONSIMULATOR 0 +#define wxUSE_UIACTIONSIMULATOR 1 // ---------------------------------------------------------------------------- // wxDC classes for various output formats diff --git a/include/wx/unix/utilsx11.h b/include/wx/unix/utilsx11.h index 4fbca1a..11bb7b7 100644 --- a/include/wx/unix/utilsx11.h +++ b/include/wx/unix/utilsx11.h @@ -26,8 +26,12 @@ #if defined(__WXGTK__) typedef void WXDisplay; typedef void* WXWindow; +typedef unsigned long WXKeySym; #endif +int wxCharCodeXToWX(WXKeySym keySym); +WXKeySym wxCharCodeWXToX(int id); + class wxIconBundle; void wxSetIconsX11( WXDisplay* display, WXWindow window, diff --git a/include/wx/x11/privx.h b/include/wx/x11/privx.h index 4767a94..ef445f3 100644 --- a/include/wx/x11/privx.h +++ b/include/wx/x11/privx.h @@ -35,9 +35,6 @@ class WXDLLIMPEXP_FWD_CORE wxRegion; // key events related functions // ---------------------------------------------------------------------------- -extern int wxCharCodeXToWX(KeySym keySym); -extern KeySym wxCharCodeWXToX(int id); - WXPixel wxGetBestMatchingPixel(Display *display, XColor *desiredColor, Colormap cmap); Pixmap XCreateInsensitivePixmap( Display *display, Pixmap pixmap ); diff --git a/interface/wx/uiaction.h b/interface/wx/uiaction.h index c8a922c..b74ef64 100644 --- a/interface/wx/uiaction.h +++ b/interface/wx/uiaction.h @@ -12,31 +12,24 @@ wxUIActionSimulator is a class used to simulate user interface actions such as a mouse click or a key press. - @note that this class is currently experimental and disabled by default, - you must set @c wxUSE_UIACTIONSIMULATOR to 1 in your setup.h file or use - configure @c --enable-uiactionsim option to enable it. + Common usage for this class would be to provide playback and record (aka + macro recording) functionality for users, or to drive unit tests by + simulating user sessions. - Common usages for this class would be to provide playback and record (aka macro recording) - functionality for users, or to drive unit tests by simulating user sessions. + See the @ref page_samples_uiaction for an example of using this class. - See the uiaction sample for example usage of this class. - - NOTE: For keyboard operations, currently you must pass the keycode of the actual - key on the keyboard. To simulate, e.g. IME actions, you'd need to simulate the actual - keypresses needed to active the IME, then the keypresses needed to type and select - the desired character. + @since 2.9.2 @library{wxcore} */ class wxUIActionSimulator { - public: +public: /** - Constructor. + Default constructor. */ wxUIActionSimulator(); - ~wxUIActionSimulator(); /** Move the mouse to the specified coordinates. @@ -47,37 +40,49 @@ class wxUIActionSimulator @param y y coordinate to move to, in screen coordinates. */ - bool MouseMove(long x, long y); + bool MouseMove(long x, long y); + + /** + Move the mouse to the specified coordinates. + + @param point + Point to move to, in screen coordinates. + */ + bool MouseMove(const wxPoint& point); /** Press a mouse button. @param button - Button to press. Valid constants are wxMOUSE_BTN_LEFT, wxMOUSE_BTN_MIDDLE, and wxMOUSE_BTN_RIGHT. + Button to press. Valid constants are @c wxMOUSE_BTN_LEFT, + @c wxMOUSE_BTN_MIDDLE, and @c wxMOUSE_BTN_RIGHT. */ - bool MouseDown(int button = wxMOUSE_BTN_LEFT); + bool MouseDown(int button = wxMOUSE_BTN_LEFT); /** Release a mouse button. @param button - Button to press. See wxUIActionSimulator::MouseDown for a list of valid constants. + Button to press. See wxUIActionSimulator::MouseDown for a list of + valid constants. */ - bool MouseUp(int button = wxMOUSE_BTN_LEFT); + bool MouseUp(int button = wxMOUSE_BTN_LEFT); /** Click a mouse button. @param button - Button to press. See wxUIActionSimulator::MouseDown for a list of valid constants. + Button to press. See wxUIActionSimulator::MouseDown for a list of + valid constants. */ - bool MouseClick(int button = wxMOUSE_BTN_LEFT); + bool MouseClick(int button = wxMOUSE_BTN_LEFT); /** Double-click a mouse button. @param button - Button to press. See wxUIActionSimulator::MouseDown for a list of valid constants. + Button to press. See wxUIActionSimulator::MouseDown for a list of + valid constants. */ - bool MouseDblClick(int button = wxMOUSE_BTN_LEFT); + bool MouseDblClick(int button = wxMOUSE_BTN_LEFT); /** Perform a drag and drop operation. @@ -95,59 +100,60 @@ class wxUIActionSimulator y destination coordinate, in screen coordinates. @param button - Button to press. See wxUIActionSimulator::MouseDown for a list of valid constants. + Button to press. See wxUIActionSimulator::MouseDown for a list of + valid constants. */ - bool MouseDragDrop(long x1, long y1, long x2, long y2, int button = wxMOUSE_BTN_LEFT); + bool MouseDragDrop(long x1, long y1, long x2, long y2, + int button = wxMOUSE_BTN_LEFT); /** Press a key. - @param keycode - key to operate on, as an integer. - - @param shiftDown - true if the shift key should be pressed, false otherwise. + If you are using modifiers then it needs to be paired with an identical + KeyUp or the modifiers will not be released (MSW and OSX). - @param cmdDown - true if the cmd key should be pressed, false otherwise. + @param keycode + Key to operate on, as an integer. It is interpreted as a wxKeyCode. - @param altDown - true if the alt key should be pressed, false otherwise. + @param modifiers + A combination of ::wxKeyModifier flags to be pressed with the given + keycode. */ - bool KeyDown(int keycode, bool shiftDown=false, bool cmdDown=false, bool altDown=false); + bool KeyDown(int keycode, int modifiers = wxMOD_NONE); /** Release a key. @param keycode - key to operate on, as an integer. - - @param shiftDown - true if the shift key should be pressed, false otherwise. - - @param cmdDown - true if the cmd key should be pressed, false otherwise. + Key to operate on, as an integer. It is interpreted as a wxKeyCode. - @param altDown - true if the alt key should be pressed, false otherwise. + @param modifiers + A combination of ::wxKeyModifier flags to be pressed with the given + keycode. */ - bool KeyUp(int keycode, bool shiftDown=false, bool cmdDown=false, bool altDown=false); + bool KeyUp(int keycode, int modifiers = wxMOD_NONE); /** Press and release a key. @param keycode - key to operate on, as an integer. + Key to operate on, as an integer. It is interpreted as a wxKeyCode. - @param shiftDown - true if the shift key should be pressed, false otherwise. + @param modifiers + A combination of ::wxKeyModifier flags to be pressed with the given + keycode. + */ + bool Char(int keycode, int modifiers = wxMOD_NONE); + + /** + Emulate typing in the keys representing the given string. - @param cmdDown - true if the cmd key should be pressed, false otherwise. + Currently only the ASCII letters (i.e. characters @c a-z and @c A-Z) + are supported. - @param altDown - true if the alt key should be pressed, false otherwise. + @param text + The string to type. */ - bool Char(int keycode, bool shiftDown=false, bool cmdDown=false, bool altDown=false); + bool Text(const wxString& text); }; diff --git a/samples/uiaction/uiaction.cpp b/samples/uiaction/uiaction.cpp index 63a5bb6..3b6d078 100644 --- a/samples/uiaction/uiaction.cpp +++ b/samples/uiaction/uiaction.cpp @@ -5,7 +5,7 @@ // Modified by: // Created: 04/01/98 // RCS-ID: $Id$ -// Copyright: (c) Kevin Ollivier +// Copyright: (c) Kevin Ollivier, Steven Lamerton // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -16,10 +16,10 @@ // ---------------------------------------------------------------------------- // headers // ---------------------------------------------------------------------------- - + // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" - + #ifdef __BORLANDC__ #pragma hdrstop #endif @@ -52,8 +52,7 @@ enum { // menu items - TheButton = 100, - RunSimulation + RunSimulation = 1 }; // ---------------------------------------------------------------------------- @@ -76,22 +75,21 @@ public: // ctor(s) MyFrame(const wxString& title); - void OnButtonPressed(wxCommandEvent&); - void OnRunSimulation(wxCommandEvent&); - - bool ButtonPressed() const { return m_buttonPressed; } - bool MenuSelected() const { return m_menuSelected; } - + void OnButtonPressed(wxCommandEvent& event); + void OnRunSimulation(wxCommandEvent& event); + void OnExit(wxCommandEvent& WXUNUSED(event)) { Close(); } + private: - bool m_buttonPressed; - bool m_menuSelected; + wxButton* m_button; + wxTextCtrl* m_text; DECLARE_EVENT_TABLE() }; BEGIN_EVENT_TABLE(MyFrame, wxFrame) - EVT_BUTTON(TheButton, MyFrame::OnButtonPressed) + EVT_BUTTON(wxID_ANY, MyFrame::OnButtonPressed) EVT_MENU(RunSimulation, MyFrame::OnRunSimulation) + EVT_MENU(wxID_EXIT, MyFrame::OnExit) END_EVENT_TABLE() #endif // wxUSE_UIACTIONSIMULATOR @@ -114,7 +112,7 @@ bool MyApp::OnInit() #if wxUSE_UIACTIONSIMULATOR MyFrame *frame = new MyFrame("wxUIActionSimulator sample application"); frame->Show(true); - + return true; #else // !wxUSE_UIACTIONSIMULATOR wxLogError("wxUSE_UIACTIONSIMULATOR must be 1 for this sample"); @@ -134,9 +132,6 @@ MyFrame::MyFrame(const wxString& title) { SetIcon(wxICON(sample)); - m_buttonPressed = false; - m_menuSelected = false; - #if wxUSE_MENUS // create a menu bar wxMenu *fileMenu = new wxMenu; @@ -152,30 +147,48 @@ MyFrame::MyFrame(const wxString& title) SetMenuBar(menuBar); #endif // wxUSE_MENUS - wxButton* button = new wxButton(this, TheButton, "Button"); - button->SetName("TheButton"); + wxPanel *panel = new wxPanel(this); + + wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL); + panel->SetSizer(sizer); + + m_button = new wxButton(panel, wxID_ANY, "&Button"); + sizer->Add(m_button, wxSizerFlags().Centre().Border()); + + m_text = new wxTextCtrl(panel, wxID_ANY, "", + wxDefaultPosition, wxDefaultSize, + wxTE_MULTILINE); + sizer->Add(m_text, wxSizerFlags(1).Expand().Border()); } // event handlers -void MyFrame::OnRunSimulation(wxCommandEvent&) +void MyFrame::OnRunSimulation(wxCommandEvent& WXUNUSED(event)) { wxUIActionSimulator sim; - wxWindow* button = FindWindow(wxString("TheButton")); - wxPoint globalPoint = button->ClientToScreen(wxPoint(20, 10)); - sim.MouseMove(globalPoint.x, globalPoint.y); + + // Add some extra distance to take account of window decorations + sim.MouseMove(m_button->GetScreenPosition() + wxPoint(10, 10)); sim.MouseClick(wxMOUSE_BTN_LEFT); - + + // Process the resulting button event wxYield(); - - if (ButtonPressed()) - wxMessageBox("Button automagically pressed!"); + + m_text->SetFocus(); + sim.Char('A'); + sim.Char('A', wxMOD_SHIFT); + sim.Char(WXK_RETURN); + sim.Char('Z'); + sim.Char('Z', wxMOD_SHIFT); + sim.Char(WXK_RETURN); + sim.Text("aAbBcC"); + sim.Char(WXK_RETURN); } -void MyFrame::OnButtonPressed(wxCommandEvent&) +void MyFrame::OnButtonPressed(wxCommandEvent& WXUNUSED(event)) { - m_buttonPressed = true; + m_text->AppendText("Button pressed.\n"); } #endif // wxUSE_UIACTIONSIMULATOR diff --git a/src/common/uiactioncmn.cpp b/src/common/uiactioncmn.cpp index 20c4141..fce2871 100644 --- a/src/common/uiactioncmn.cpp +++ b/src/common/uiactioncmn.cpp @@ -1,11 +1,13 @@ ///////////////////////////////////////////////////////////////////////////// // Name: src/common/uiactioncmn.cpp // Purpose: wxUIActionSimulator common implementation -// Author: Kevin Ollivier +// Author: Kevin Ollivier, Steven Lamerton, Vadim Zeitlin // Modified by: // Created: 2010-03-06 // RCS-ID: $Id: menu.cpp 54129 2008-06-11 19:30:52Z SC $ // Copyright: (c) Kevin Ollivier +// (c) 2010 Steven Lamerton +// (c) 2010 Vadim Zeitlin // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -15,15 +17,6 @@ #include "wx/uiaction.h" -wxUIActionSimulator::wxUIActionSimulator() -{ -} - -wxUIActionSimulator::~wxUIActionSimulator() -{ -} - - bool wxUIActionSimulator::MouseClick(int button) { MouseDown(button); @@ -42,7 +35,9 @@ bool wxUIActionSimulator::MouseDblClick(int button) return true; } -bool wxUIActionSimulator::MouseDragDrop(long x1, long y1, long x2, long y2, int button) +bool +wxUIActionSimulator::MouseDragDrop(long x1, long y1, long x2, long y2, + int button) { MouseMove(x1, y1); MouseDown(button); @@ -52,10 +47,40 @@ bool wxUIActionSimulator::MouseDragDrop(long x1, long y1, long x2, long y2, int return true; } -bool wxUIActionSimulator::Char(int keycode, bool shiftDown, bool cmdDown, bool altDown) +bool +wxUIActionSimulator::Key(int keycode, int modifiers, bool isDown) +{ + wxASSERT_MSG( !(modifiers & wxMOD_CONTROL), + "wxMOD_CONTROL is not implemented, use wxMOD_CMD instead" ); + wxASSERT_MSG( (modifiers & wxMOD_ALTGR) != wxMOD_ALTGR, + "wxMOD_ALTGR is not implemented" ); + wxASSERT_MSG( !(modifiers & wxMOD_META ), + "wxMOD_META is not implemented" ); + wxASSERT_MSG( !(modifiers & wxMOD_WIN ), + "wxMOD_WIN is not implemented" ); + + return DoKey(keycode, modifiers, isDown); +} + +bool wxUIActionSimulator::Char(int keycode, int modifiers) +{ + Key(keycode, modifiers, true); + Key(keycode, modifiers, false); + + return true; +} + +bool wxUIActionSimulator::Text(const char *s) { - Key(keycode, false, shiftDown, cmdDown, altDown); - Key(keycode, true, shiftDown, cmdDown, altDown); + while ( *s != '\0' ) + { + const char ch = *s++; + + wxASSERT_MSG( ch, "Only letters are allowed" ); + + if ( !Char(ch, isupper(ch) ? wxMOD_SHIFT : 0) ) + return false; + } return true; } diff --git a/src/msw/uiaction.cpp b/src/msw/uiaction.cpp index d421b9a..e9128a6 100644 --- a/src/msw/uiaction.cpp +++ b/src/msw/uiaction.cpp @@ -1,11 +1,13 @@ ///////////////////////////////////////////////////////////////////////////// // Name: src/msw/uiaction.cpp // Purpose: wxUIActionSimulator implementation -// Author: Kevin Ollivier +// Author: Kevin Ollivier, Steven Lamerton, Vadim Zeitlin // Modified by: // Created: 2010-03-06 // RCS-ID: $Id: menu.cpp 54129 2008-06-11 19:30:52Z SC $ // Copyright: (c) Kevin Ollivier +// (c) 2010 Steven Lamerton +// (c) 2010 Vadim Zeitlin // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -17,32 +19,35 @@ #include "wx/msw/wrapwin.h" +namespace +{ + DWORD EventTypeForMouseButton(int button, bool isDown) { switch (button) { case wxMOUSE_BTN_LEFT: - if (isDown) - return MOUSEEVENTF_LEFTDOWN; - else - return MOUSEEVENTF_LEFTUP; + return isDown ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP; + case wxMOUSE_BTN_RIGHT: - if (isDown) - return MOUSEEVENTF_RIGHTDOWN; - else - return MOUSEEVENTF_RIGHTUP; + return isDown ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP; + case wxMOUSE_BTN_MIDDLE: - if (isDown) - return MOUSEEVENTF_MIDDLEDOWN; - else - return MOUSEEVENTF_MIDDLEUP; + return isDown ? MOUSEEVENTF_MIDDLEDOWN : MOUSEEVENTF_MIDDLEUP; default: wxFAIL_MSG("Unsupported button passed in."); - return -1; + return (DWORD)-1; } } +void DoSimulateKbdEvent(DWORD vk, bool isDown) +{ + keybd_event(vk, 0, isDown ? 0 : KEYEVENTF_KEYUP, 0); +} + +} // anonymous namespace + bool wxUIActionSimulator::MouseDown(int button) { POINT p; @@ -53,7 +58,13 @@ bool wxUIActionSimulator::MouseDown(int button) bool wxUIActionSimulator::MouseMove(long x, long y) { - mouse_event(MOUSEEVENTF_MOVE, x, y, 0, 0); + // Because MOUSEEVENTF_ABSOLUTE takes measurements scaled between 0 & 65535 + // we need to scale our input too + int displayx, displayy, scaledx, scaledy; + wxDisplaySize(&displayx, &displayy); + scaledx = ((float)x / displayx) * 65535; + scaledy = ((float)y / displayy) * 65535; + mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, scaledx, scaledy, 0, 0); return true; } @@ -65,12 +76,31 @@ bool wxUIActionSimulator::MouseUp(int button) return true; } -bool wxUIActionSimulator::Key(int keycode, bool isDown, bool shiftDown, bool cmdDown, bool altDown) +bool wxUIActionSimulator::DoKey(int keycode, int modifiers, bool isDown) { - DWORD flags = 0; + if (isDown) + { + if (modifiers & wxMOD_SHIFT) + DoSimulateKbdEvent(VK_SHIFT, true); + if (modifiers & wxMOD_ALT) + DoSimulateKbdEvent(VK_MENU, true); + if (modifiers & wxMOD_CMD) + DoSimulateKbdEvent(VK_CONTROL, true); + } + + DWORD vkkeycode = wxCharCodeWXToMSW(keycode); + keybd_event(vkkeycode, 0, isDown ? 0 : KEYEVENTF_KEYUP, 0); + if (!isDown) - flags = KEYEVENTF_KEYUP; - keybd_event(keycode, 0, flags, 0); + { + if (modifiers & wxMOD_SHIFT) + DoSimulateKbdEvent(VK_SHIFT, false); + if (modifiers & wxMOD_ALT) + DoSimulateKbdEvent(VK_MENU, false); + if (modifiers & wxMOD_CMD) + DoSimulateKbdEvent(VK_CONTROL, false); + } + return true; } diff --git a/src/osx/uiaction_osx.cpp b/src/osx/uiaction_osx.cpp index 603b303..a1667c6 100644 --- a/src/osx/uiaction_osx.cpp +++ b/src/osx/uiaction_osx.cpp @@ -1,11 +1,13 @@ ///////////////////////////////////////////////////////////////////////////// // Name: src/osx/uiaction_osx.cpp // Purpose: wxUIActionSimulator implementation -// Author: Kevin Ollivier +// Author: Kevin Ollivier, Steven Lamerton, Vadim Zeitlin // Modified by: // Created: 2010-03-06 // RCS-ID: $Id: menu.cpp 54129 2008-06-11 19:30:52Z SC $ // Copyright: (c) Kevin Ollivier +// (c) 2010 Steven Lamerton +// (c) 2010 Vadim Zeitlin // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -15,61 +17,189 @@ #include "wx/uiaction.h" -#include +#include "wx/log.h" + +#include "wx/osx/private.h" +#include "wx/osx/core/cfref.h" + +namespace +{ CGEventTapLocation tap = kCGSessionEventTap; CGEventType CGEventTypeForMouseButton(int button, bool isDown) { - switch (button) + switch ( button ) { case wxMOUSE_BTN_LEFT: - if (isDown) - return kCGEventLeftMouseDown; - else - return kCGEventLeftMouseUp; - case wxMOUSE_BTN_RIGHT: - if (isDown) - return kCGEventRightMouseDown; - else - return kCGEventRightMouseUp; + return isDown ? kCGEventLeftMouseDown : kCGEventLeftMouseUp; - // Apparently all other buttons use the constant OtherMouseDown + case wxMOUSE_BTN_RIGHT: + return isDown ? kCGEventRightMouseDown : kCGEventRightMouseUp; + // All the other buttons use the constant OtherMouseDown but we still + // want to check for invalid parameters so assert first default: - if (isDown) - return kCGEventOtherMouseDown; - else - return kCGEventOtherMouseUp; + wxFAIL_MSG("Unsupported button passed in."); + // fall back to the only known remaining case + + case wxMOUSE_BTN_MIDDLE: + return isDown ? kCGEventOtherMouseDown : kCGEventOtherMouseUp; } } -void SendCharCode(CGCharCode keycode, bool isDown) +CGPoint GetMousePosition() { - CGEventRef event = CGEventCreateKeyboardEvent(NULL, keycode, isDown); - if (event) + int x, y; + wxGetMousePosition(&x, &y); + + CGPoint pos; + pos.x = x; + pos.y = y; + + return pos; +} + +bool SendCharCode(CGKeyCode keycode, bool isDown) +{ + wxCFRef + event(CGEventCreateKeyboardEvent(NULL, keycode, isDown)); + if ( !event ) + return false; + + CGEventPost(kCGHIDEventTap, event); + return true; +} + +CGKeyCode wxCharCodeWXToOSX(wxKeyCode code) +{ + CGKeyCode keycode; + + switch (code) { - CGEventPost(kCGHIDEventTap, event); + case 'a': case 'A': keycode = kVK_ANSI_A; break; + case 'b': case 'B': keycode = kVK_ANSI_B; break; + case 'c': case 'C': keycode = kVK_ANSI_C; break; + case 'd': case 'D': keycode = kVK_ANSI_D; break; + case 'e': case 'E': keycode = kVK_ANSI_E; break; + case 'f': case 'F': keycode = kVK_ANSI_F; break; + case 'g': case 'G': keycode = kVK_ANSI_G; break; + case 'h': case 'H': keycode = kVK_ANSI_H; break; + case 'i': case 'I': keycode = kVK_ANSI_I; break; + case 'j': case 'J': keycode = kVK_ANSI_J; break; + case 'k': case 'K': keycode = kVK_ANSI_K; break; + case 'l': case 'L': keycode = kVK_ANSI_L; break; + case 'm': case 'M': keycode = kVK_ANSI_M; break; + case 'n': case 'N': keycode = kVK_ANSI_N; break; + case 'o': case 'O': keycode = kVK_ANSI_O; break; + case 'p': case 'P': keycode = kVK_ANSI_P; break; + case 'q': case 'Q': keycode = kVK_ANSI_Q; break; + case 'r': case 'R': keycode = kVK_ANSI_R; break; + case 's': case 'S': keycode = kVK_ANSI_S; break; + case 't': case 'T': keycode = kVK_ANSI_T; break; + case 'u': case 'U': keycode = kVK_ANSI_U; break; + case 'v': case 'V': keycode = kVK_ANSI_V; break; + case 'w': case 'W': keycode = kVK_ANSI_W; break; + case 'x': case 'X': keycode = kVK_ANSI_X; break; + case 'y': case 'Y': keycode = kVK_ANSI_Y; break; + case 'z': case 'Z': keycode = kVK_ANSI_Z; break; + + case '0': keycode = kVK_ANSI_0; break; + case '1': keycode = kVK_ANSI_1; break; + case '2': keycode = kVK_ANSI_2; break; + case '3': keycode = kVK_ANSI_3; break; + case '4': keycode = kVK_ANSI_4; break; + case '5': keycode = kVK_ANSI_5; break; + case '6': keycode = kVK_ANSI_6; break; + case '7': keycode = kVK_ANSI_7; break; + case '8': keycode = kVK_ANSI_8; break; + case '9': keycode = kVK_ANSI_9; break; + + case WXK_BACK: keycode = kVK_Delete; break; + case WXK_TAB: keycode = kVK_Tab; break; + case WXK_RETURN: keycode = kVK_Return; break; + case WXK_ESCAPE: keycode = kVK_Escape; break; + case WXK_SPACE: keycode = kVK_Space; break; + case WXK_DELETE: keycode = kVK_Delete; break; + + case WXK_SHIFT: keycode = kVK_Shift; break; + case WXK_ALT: keycode = kVK_Option; break; + case WXK_CONTROL: keycode = kVK_Control; break; + case WXK_COMMAND: keycode = kVK_Command; break; + + case WXK_CAPITAL: keycode = kVK_CapsLock; break; + case WXK_END: keycode = kVK_End; break; + case WXK_HOME: keycode = kVK_Home; break; + case WXK_LEFT: keycode = kVK_LeftArrow; break; + case WXK_UP: keycode = kVK_UpArrow; break; + case WXK_RIGHT: keycode = kVK_RightArrow; break; + case WXK_DOWN: keycode = kVK_DownArrow; break; + + case WXK_HELP: keycode = kVK_Help; break; + + + case WXK_NUMPAD0: keycode = kVK_ANSI_Keypad0; break; + case WXK_NUMPAD1: keycode = kVK_ANSI_Keypad1; break; + case WXK_NUMPAD2: keycode = kVK_ANSI_Keypad2; break; + case WXK_NUMPAD3: keycode = kVK_ANSI_Keypad3; break; + case WXK_NUMPAD4: keycode = kVK_ANSI_Keypad4; break; + case WXK_NUMPAD5: keycode = kVK_ANSI_Keypad5; break; + case WXK_NUMPAD6: keycode = kVK_ANSI_Keypad6; break; + case WXK_NUMPAD7: keycode = kVK_ANSI_Keypad7; break; + case WXK_NUMPAD8: keycode = kVK_ANSI_Keypad8; break; + case WXK_NUMPAD9: keycode = kVK_ANSI_Keypad9; break; + case WXK_F1: keycode = kVK_F1; break; + case WXK_F2: keycode = kVK_F2; break; + case WXK_F3: keycode = kVK_F3; break; + case WXK_F4: keycode = kVK_F4; break; + case WXK_F5: keycode = kVK_F5; break; + case WXK_F6: keycode = kVK_F6; break; + case WXK_F7: keycode = kVK_F7; break; + case WXK_F8: keycode = kVK_F8; break; + case WXK_F9: keycode = kVK_F9; break; + case WXK_F10: keycode = kVK_F10; break; + case WXK_F11: keycode = kVK_F11; break; + case WXK_F12: keycode = kVK_F12; break; + case WXK_F13: keycode = kVK_F13; break; + case WXK_F14: keycode = kVK_F14; break; + case WXK_F15: keycode = kVK_F15; break; + case WXK_F16: keycode = kVK_F16; break; + case WXK_F17: keycode = kVK_F17; break; + case WXK_F18: keycode = kVK_F18; break; + case WXK_F19: keycode = kVK_F19; break; + case WXK_F20: keycode = kVK_F20; break; + + case WXK_PAGEUP: keycode = kVK_PageUp; break; + case WXK_PAGEDOWN: keycode = kVK_PageDown; break; + + case WXK_NUMPAD_DELETE: keycode = kVK_ANSI_KeypadClear; break; + case WXK_NUMPAD_EQUAL: keycode = kVK_ANSI_KeypadEquals; break; + case WXK_NUMPAD_MULTIPLY: keycode = kVK_ANSI_KeypadMultiply; break; + case WXK_NUMPAD_ADD: keycode = kVK_ANSI_KeypadPlus; break; + case WXK_NUMPAD_SUBTRACT: keycode = kVK_ANSI_KeypadMinus; break; + case WXK_NUMPAD_DECIMAL: keycode = kVK_ANSI_KeypadDecimal; break; + case WXK_NUMPAD_DIVIDE: keycode = kVK_ANSI_KeypadDivide; break; + + default: wxLogDebug( "Unrecognised keycode %d", code ); } - CFRelease(event); + + return keycode; } +} // anonymous namespace + bool wxUIActionSimulator::MouseDown(int button) { - CGPoint pos; - int x, y; - wxGetMousePosition(&x, &y); - pos.x = x; - pos.y = y; CGEventType type = CGEventTypeForMouseButton(button, true); - CGEventRef event = CGEventCreateMouseEvent(NULL, type, pos, button); + wxCFRef event( + CGEventCreateMouseEvent(NULL, type, GetMousePosition(), button)); + + if ( !event ) + return false; + CGEventSetType(event, type); + CGEventPost(tap, event); - if (event) - { - CGEventPost(tap, event); - } - CFRelease(event); return true; } @@ -78,56 +208,60 @@ bool wxUIActionSimulator::MouseMove(long x, long y) CGPoint pos; pos.x = x; pos.y = y; + CGEventType type = kCGEventMouseMoved; - CGEventRef event = CGEventCreateMouseEvent(NULL, type, pos, kCGMouseButtonLeft); - CGEventSetType(event, type); + wxCFRef event( + CGEventCreateMouseEvent(NULL, type, pos, kCGMouseButtonLeft)); - if (event) - { - CGEventPost(tap, event); - } - CFRelease(event); + if ( !event ) + return false; + + CGEventSetType(event, type); + CGEventPost(tap, event); return true; } bool wxUIActionSimulator::MouseUp(int button) { - CGPoint pos; - int x, y; - wxGetMousePosition(&x, &y); - pos.x = x; - pos.y = y; CGEventType type = CGEventTypeForMouseButton(button, false); - CGEventRef event = CGEventCreateMouseEvent(NULL, type, pos, button); - CGEventSetType(event, type); + wxCFRef event( + CGEventCreateMouseEvent(NULL, type, GetMousePosition(), button)); - if (event) - { - CGEventPost(tap, event); - } - CFRelease(event); + if ( !event ) + return false; + + CGEventSetType(event, type); + CGEventPost(tap, event); return true; } -bool wxUIActionSimulator::Key(int keycode, bool isDown, bool shiftDown, bool cmdDown, bool altDown) +bool wxUIActionSimulator::DoKey(int keycode, int modifiers, bool isDown) { - if (shiftDown) - SendCharCode((CGCharCode)56, true); - if (altDown) - SendCharCode((CGCharCode)58, true); - if (cmdDown) - SendCharCode((CGCharCode)55, true); - - SendCharCode((CGCharCode)keycode, isDown); - - if (shiftDown) - SendCharCode((CGCharCode)56, false); - if (altDown) - SendCharCode((CGCharCode)58, false); - if (cmdDown) - SendCharCode((CGCharCode)55, false); + if (isDown) + { + if (modifiers & wxMOD_SHIFT) + SendCharCode(kVK_Shift, true); + if (modifiers & wxMOD_ALT) + SendCharCode(kVK_Option, true); + if (modifiers & wxMOD_CMD) + SendCharCode(kVK_Command, true); + } + + CGKeyCode cgcode = wxCharCodeWXToOSX((wxKeyCode)keycode); + if ( !SendCharCode(cgcode, isDown) ) + return false; + + if(!isDown) + { + if (modifiers & wxMOD_SHIFT) + SendCharCode(kVK_Shift, false); + if (modifiers & wxMOD_ALT) + SendCharCode(kVK_Option, false); + if (modifiers & wxMOD_CMD) + SendCharCode(kVK_Command, false); + } return true; } diff --git a/src/unix/uiactionx11.cpp b/src/unix/uiactionx11.cpp index 778e9bb..975a65f 100644 --- a/src/unix/uiactionx11.cpp +++ b/src/unix/uiactionx11.cpp @@ -1,11 +1,13 @@ ///////////////////////////////////////////////////////////////////////////// // Name: src/unix/uiactionx11.cpp // Purpose: wxUIActionSimulator implementation -// Author: Kevin Ollivier +// Author: Kevin Ollivier, Steven Lamerton, Vadim Zeitlin // Modified by: // Created: 2010-03-06 // RCS-ID: $Id: menu.cpp 54129 2008-06-11 19:30:52Z SC $ // Copyright: (c) Kevin Ollivier +// (c) 2010 Steven Lamerton +// (c) 2010 Vadim Zeitlin // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -15,57 +17,62 @@ #include "wx/uiaction.h" -#include #include -#include + +#include "wx/unix/utilsx11.h" + +namespace +{ void SendButtonEvent(int button, bool isDown) { - int xbutton = 0; + int xbutton; switch (button) { case wxMOUSE_BTN_LEFT: xbutton = 1; break; - case wxMOUSE_BTN_RIGHT: + case wxMOUSE_BTN_MIDDLE: xbutton = 2; break; - case wxMOUSE_BTN_MIDDLE: + case wxMOUSE_BTN_RIGHT: xbutton = 3; break; default: wxFAIL_MSG("Unsupported button passed in."); + return; } - XEvent event; - - Display *display = XOpenDisplay(0); - wxASSERT_MSG(display, "No display available!"); + wxX11Display display; + wxCHECK_RET(display, "No display available!"); + XEvent event; memset(&event, 0x00, sizeof(event)); - if (isDown) - event.type = ButtonPress; - else - event.type = ButtonRelease; - + event.type = isDown ? ButtonPress : ButtonRelease; event.xbutton.button = xbutton; event.xbutton.same_screen = True; - XQueryPointer(display, RootWindow(display, DefaultScreen(display)), &event.xbutton.root, &event.xbutton.window, &event.xbutton.x_root, &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y, &event.xbutton.state); + XQueryPointer(display, 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); event.xbutton.subwindow = event.xbutton.window; while (event.xbutton.subwindow) { event.xbutton.window = event.xbutton.subwindow; - XQueryPointer(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); + XQueryPointer(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); - XFlush(display); - XCloseDisplay(display); } +} // anonymous namespace + bool wxUIActionSimulator::MouseDown(int button) { SendButtonEvent(button, true); @@ -74,12 +81,12 @@ bool wxUIActionSimulator::MouseDown(int button) bool wxUIActionSimulator::MouseMove(long x, long y) { - Display *display = XOpenDisplay(0); + wxX11Display display; wxASSERT_MSG(display, "No display available!"); - Window root = DefaultRootWindow(display); + + Window root = display.DefaultRoot(); XWarpPointer(display, None, root, 0, 0, 0, 0, x, y); - XFlush(display); - XCloseDisplay(display); + return true; } @@ -89,37 +96,61 @@ bool wxUIActionSimulator::MouseUp(int button) return true; } -bool wxUIActionSimulator::Key(int keycode, bool isDown, bool WXUNUSED(shiftDown), bool WXUNUSED(cmdDown), bool WXUNUSED(altDown)) +bool wxUIActionSimulator::DoKey(int keycode, int modifiers, bool isDown) { - Display *display = XOpenDisplay(0); - wxASSERT_MSG(display, "No display available!"); + wxX11Display display; + wxCHECK_MSG(display, false, "No display available!"); - XKeyEvent event; - int mask = 0xfff; - memset(&event, 0x00, sizeof(event)); + int mask, type; - if (isDown) { - event.type = KeyPress; + if ( isDown ) + { + type = KeyPress; mask = KeyPressMask; } - else { - event.type = KeyRelease; + else + { + type = KeyRelease; mask = KeyReleaseMask; } - event.same_screen = True; - XQueryPointer(display, RootWindow(display, DefaultScreen(display)), &event.root, &event.window, &event.x_root, &event.y_root, &event.x, &event.y, &event.state); - event.subwindow = event.window; + WXKeySym xkeysym = wxCharCodeWXToX(keycode); + KeyCode xkeycode = XKeysymToKeycode(display, xkeysym); + if ( xkeycode == NoSymbol ) + return false; - while (event.subwindow) - { - event.window = event.subwindow; - XQueryPointer(display, event.window, &event.root, &event.subwindow, &event.x_root, &event.y_root, &event.x, &event.y, &event.state); - } + Window focus; + int revert; + XGetInputFocus(display, &focus, &revert); + if (focus == None) + return false; + + int mod = 0; + + if (modifiers & wxMOD_SHIFT) + mod |= ShiftMask; + //Mod1 is alt in the vast majority of cases + if (modifiers & wxMOD_ALT) + mod |= Mod1Mask; + if (modifiers & wxMOD_CMD) + mod |= ControlMask; + + XKeyEvent event; + event.display = display; + event.window = focus; + event.root = DefaultRootWindow(event.display); + event.subwindow = None; + event.time = CurrentTime; + event.x = 1; + event.y = 1; + event.x_root = 1; + event.y_root = 1; + event.same_screen = True; + event.type = type; + event.state = mod; + event.keycode = xkeycode; - XSendEvent(display, PointerWindow, True, mask, (XEvent*) &event); - XFlush(display); - XCloseDisplay(display); + XSendEvent(event.display, event.window, True, mask, (XEvent*) &event); return true; } diff --git a/src/unix/utilsx11.cpp b/src/unix/utilsx11.cpp index 25f61e1..63a3200 100644 --- a/src/unix/utilsx11.cpp +++ b/src/unix/utilsx11.cpp @@ -537,7 +537,7 @@ void wxSetFullScreenStateX11(WXDisplay* display, WXWindow rootWindow, // FIXME what about tables?? -int wxCharCodeXToWX(KeySym keySym) +int wxCharCodeXToWX(WXKeySym keySym) { int id; switch (keySym) @@ -717,9 +717,9 @@ int wxCharCodeXToWX(KeySym keySym) return id; } -KeySym wxCharCodeWXToX(int id) +WXKeySym wxCharCodeWXToX(int id) { - KeySym keySym; + WXKeySym keySym; switch (id) { -- 2.7.4