src/common/textentrycmn.cpp
src/common/toplvcmn.cpp
src/common/treebase.cpp
+ src/common/uiactioncmn.cpp
src/common/valgen.cpp
src/common/validate.cpp
src/common/valtext.cpp
wx/treebase.h
wx/treebook.h
wx/treectrl.h
+ wx/uiaction.h
wx/valgen.h
wx/vidmode.h
wx/vlbox.h
src/generic/caret.cpp
src/generic/imaglist.cpp
src/unix/dialup.cpp
+ src/unix/displayx11.cpp
src/unix/fontenum.cpp
src/unix/fontutil.cpp
+ src/unix/uiactionx11.cpp
src/unix/utilsx11.cpp
- src/unix/displayx11.cpp
</set>
<set var="XWIN_LOWLEVEL_HDR" hints="files">
wx/generic/caret.h
src/msw/textentry.cpp
src/msw/tglbtn.cpp
src/msw/treectrl.cpp
+ src/msw/uiaction.cpp
</set>
<set var="MSW_HDR" hints="files">
wx/generic/clrpickerg.h
src/osx/textctrl_osx.cpp
src/osx/tglbtn_osx.cpp
src/osx/toolbar_osx.cpp
+ src/osx/uiaction_osx.cpp
<!-- wxWebKit files -->
src/html/htmlctrl/webkit/webkit.mm
<!-- Native color/font dialogs -->
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: include/wx/uiaction.cpp
+// 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 _UIACTIONSIMULATOR_H_
+#define _UIACTIONSIMULATOR_H_
+
+#include <wx/defs.h>
+#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
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: uiaction.h
+// Purpose: interface of wxUIActionSimulator
+// Author: wxWidgets team
+// RCS-ID: $Id$
+// Licence: wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+/**
+ @class wxUIActionSimulator
+
+ wxUIActionSimulator is a class used to simulate user interface actions
+ such as a mouse click or a key press.
+
+ 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 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.
+
+ @library{wxcore}
+*/
+
+class wxUIActionSimulator
+{
+ public:
+ /**
+ Constructor.
+ */
+ wxUIActionSimulator();
+ ~wxUIActionSimulator();
+
+ /**
+ Move the mouse to the specified coordinates.
+
+ @param x
+ x coordinate to move to, in screen coordinates.
+
+ @param y
+ y coordinate to move to, in screen coordinates.
+ */
+ bool MouseMove(long x, long y);
+
+ /**
+ Press a mouse button.
+
+ @param button
+ Button to press. Valid constants are wxMOUSE_BTN_LEFT, wxMOUSE_BTN_MIDDLE, and wxMOUSE_BTN_RIGHT.
+ */
+ 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.
+ */
+ 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.
+ */
+ 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.
+ */
+ bool MouseDblClick(int button = wxMOUSE_BTN_LEFT);
+
+ /**
+ Perform a drag and drop operation.
+
+ @param x1
+ x start coordinate, in screen coordinates.
+
+ @param y1
+ y start coordinate, in screen coordinates.
+
+ @param x2
+ x desintation coordinate, in screen coordinates.
+
+ @param y2
+ y destination coordinate, in screen coordinates.
+
+ @param button
+ 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);
+
+ /**
+ Press 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.
+
+ @param altDown
+ true if the alt key should be pressed, false otherwise.
+ */
+ bool KeyDown(int keycode, bool shiftDown=false, bool cmdDown=false, bool altDown=false);
+
+ /**
+ 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.
+
+ @param altDown
+ true if the alt key should be pressed, false otherwise.
+ */
+ bool KeyUp(int keycode, bool shiftDown=false, bool cmdDown=false, bool altDown=false);
+
+ /**
+ Press and 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.
+
+ @param altDown
+ true if the alt key should be pressed, false otherwise.
+ */
+ bool Char(int keycode, bool shiftDown=false, bool cmdDown=false, bool altDown=false);
+};
+
+#endif
<subproject id="toolbar" template="sub"/>
<subproject id="treectrl" template="sub"/>
<subproject id="typetest" template="sub"/>
+ <subproject id="uiaction" template="sub"/>
<subproject id="validate" template="sub"/>
<subproject id="vscroll" template="sub"/>
<subproject id="widgets" template="sub"/>
--- /dev/null
+<?xml version="1.0" ?>
+<!-- $Id$ -->
+
+<makefile>
+
+ <include file="../../build/bakefiles/common_samples.bkl"/>
+
+ <exe id="uiaction" template="wx_sample" template_append="wx_append">
+ <sources>uiaction.cpp</sources>
+ <wx-lib>core</wx-lib>
+ <wx-lib>base</wx-lib>
+ <uid type="creatorid">wx06</uid>
+ </exe>
+
+</makefile>
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: uiaction.cpp
+// Purpose: wxUIActionSimulator sample
+// Author: Kevin Ollivier
+// Modified by:
+// Created: 04/01/98
+// RCS-ID: $Id$
+// Copyright: (c) Kevin Ollivier
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+
+// for all others, include the necessary headers (this file is usually all you
+// need because it includes almost all "standard" wxWidgets headers)
+#ifndef WX_PRECOMP
+ #include "wx/wx.h"
+#endif
+
+#include "wx/uiaction.h"
+
+// ----------------------------------------------------------------------------
+// resources
+// ----------------------------------------------------------------------------
+
+// the application icon (under Windows and OS/2 it is in resources and even
+// though we could still include the XPM here it would be unused)
+#if !defined(__WXMSW__) && !defined(__WXPM__)
+ #include "../sample.xpm"
+#endif
+
+// ----------------------------------------------------------------------------
+// private classes
+// ----------------------------------------------------------------------------
+
+// Define a new application type, each program should derive a class from wxApp
+class MyApp : public wxApp
+{
+public:
+ virtual bool OnInit();
+};
+
+// Define a new frame type: this is going to be our main frame
+class MyFrame : public wxFrame
+{
+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; }
+
+private:
+ bool m_buttonPressed;
+ bool m_menuSelected;
+};
+
+// ----------------------------------------------------------------------------
+// constants
+// ----------------------------------------------------------------------------
+
+// IDs for the controls and the menu commands
+enum
+{
+ // menu items
+ TheButton = wxID_ANY,
+ RunSimulation = wxID_ANY
+};
+
+IMPLEMENT_APP(MyApp)
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// the application class
+// ----------------------------------------------------------------------------
+
+bool MyApp::OnInit()
+{
+ if ( !wxApp::OnInit() )
+ return false;
+
+ MyFrame *frame = new MyFrame("wxUIActionSimulator sample application");
+ frame->Show(true);
+
+ return true;
+}
+
+// ----------------------------------------------------------------------------
+// main frame
+// ----------------------------------------------------------------------------
+
+// frame constructor
+MyFrame::MyFrame(const wxString& title)
+ : wxFrame(NULL, wxID_ANY, title)
+{
+ SetIcon(wxICON(sample));
+
+ m_buttonPressed = false;
+ m_menuSelected = false;
+
+#if wxUSE_MENUS
+ // create a menu bar
+ wxMenu *fileMenu = new wxMenu;
+
+ fileMenu->Append(wxID_NEW, "&New File...", "Open a new file");
+ fileMenu->Append(RunSimulation, "&Run Simulation...", "Run the UI action simulation");
+
+ fileMenu->Append(wxID_EXIT, "E&xit\tAlt-X", "Quit this program");
+
+ wxMenuBar *menuBar = new wxMenuBar();
+ menuBar->Append(fileMenu, "&File");
+
+ SetMenuBar(menuBar);
+#endif // wxUSE_MENUS
+
+ wxButton* button = new wxButton(this, TheButton, "Button");
+ button->SetName("TheButton");
+ Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MyFrame::OnButtonPressed, this, button->GetId());
+ Bind(wxEVT_COMMAND_MENU_SELECTED, &MyFrame::OnRunSimulation, this, RunSimulation);
+}
+
+
+// event handlers
+
+void MyFrame::OnRunSimulation(wxCommandEvent&)
+{
+ wxUIActionSimulator sim;
+ wxWindow* button = FindWindow(wxString("TheButton"));
+ wxPoint globalPoint = button->ClientToScreen(wxPoint(20, 10));
+ sim.MouseMove(globalPoint.x, globalPoint.y);
+ sim.MouseClick(wxMOUSE_BTN_LEFT);
+
+ wxYield();
+
+ if (ButtonPressed())
+ wxMessageBox("Button automagically pressed!");
+}
+
+void MyFrame::OnButtonPressed(wxCommandEvent&)
+{
+ m_buttonPressed = true;
+}
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/common/uiactioncmn.cpp
+// Purpose: wxUIActionSimulator common implementation
+// 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
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#include "wx/uiaction.h"
+
+wxUIActionSimulator::wxUIActionSimulator()
+{
+}
+
+wxUIActionSimulator::~wxUIActionSimulator()
+{
+}
+
+
+bool wxUIActionSimulator::MouseClick(int button)
+{
+ MouseDown(button);
+ MouseUp(button);
+
+ return true;
+}
+
+bool wxUIActionSimulator::MouseDblClick(int button)
+{
+ MouseDown(button);
+ MouseUp(button);
+ MouseDown(button);
+ MouseUp(button);
+
+ return true;
+}
+
+bool wxUIActionSimulator::MouseDragDrop(long x1, long y1, long x2, long y2, int button)
+{
+ MouseMove(x1, y1);
+ MouseDown(button);
+ MouseMove(x2, y2);
+ MouseUp(button);
+
+ return true;
+}
+
+bool wxUIActionSimulator::Char(int keycode, bool shiftDown, bool cmdDown, bool altDown)
+{
+ Key(keycode, false, shiftDown, cmdDown, altDown);
+ Key(keycode, true, shiftDown, cmdDown, altDown);
+
+ return true;
+}
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/msw/uiaction.cpp
+// Purpose: wxUIActionSimulator implementation
+// 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
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/wxprec.h"
+
+#ifndef WX_PRECOMP
+#include "wx/defs.h"
+#endif
+
+#include "wx/uiaction.h"
+
+#include <windows.h>
+
+DWORD EventTypeForMouseButton(int button, bool isDown)
+{
+ switch (button)
+ {
+ case wxMOUSE_BTN_LEFT:
+ if (isDown)
+ return MOUSEEVENTF_LEFTDOWN;
+ else
+ return MOUSEEVENTF_LEFTUP;
+ case wxMOUSE_BTN_RIGHT:
+ if (isDown)
+ return MOUSEEVENTF_RIGHTDOWN;
+ else
+ return MOUSEEVENTF_RIGHTUP;
+ case wxMOUSE_BTN_MIDDLE:
+ if (isDown)
+ return MOUSEEVENTF_MIDDLEDOWN;
+ else
+ return MOUSEEVENTF_MIDDLEUP;
+
+ default:
+ wxFAIL_MSG("Unsupported button passed in.");
+ return -1;
+ }
+}
+
+bool wxUIActionSimulator::MouseDown(int button)
+{
+ POINT p;
+ GetCursorPos(&p);
+ mouse_event(EventTypeForMouseButton(button, true), p.x, p.y, 0, 0);
+ return true;
+}
+
+bool wxUIActionSimulator::MouseMove(long x, long y)
+{
+ mouse_event(MOUSEEVENTF_MOVE, x, y, 0, 0);
+ return true;
+}
+
+bool wxUIActionSimulator::MouseUp(int button)
+{
+ POINT p;
+ GetCursorPos(&p);
+ mouse_event(EventTypeForMouseButton(button, false), p.x, p.y, 0, 0);
+ return true;
+}
+
+bool wxUIActionSimulator::Key(int keycode, bool isDown, bool shiftDown, bool cmdDown, bool altDown)
+{
+ DWORD flags = 0;
+ if (!isDown)
+ flags = KEYEVENTF_KEYUP;
+ keybd_event(keycode, 0, flags, 0);
+ return true;
+}
+
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/osx/uiaction_osx.cpp
+// Purpose: wxUIActionSimulator implementation
+// 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
+/////////////////////////////////////////////////////////////////////////////
+
+#include <wx/defs.h>
+#include <wx/uiaction.h>
+
+#include <ApplicationServices/ApplicationServices.h>
+
+CGEventTapLocation tap = kCGSessionEventTap;
+
+CGEventType CGEventTypeForMouseButton(int button, bool isDown)
+{
+ switch (button)
+ {
+ case wxMOUSE_BTN_LEFT:
+ if (isDown)
+ return kCGEventLeftMouseDown;
+ else
+ return kCGEventLeftMouseUp;
+ case wxMOUSE_BTN_RIGHT:
+ if (isDown)
+ return kCGEventRightMouseDown;
+ else
+ return kCGEventRightMouseUp;
+
+ // Apparently all other buttons use the constant OtherMouseDown
+
+ default:
+ if (isDown)
+ return kCGEventOtherMouseDown;
+ else
+ return kCGEventOtherMouseUp;
+ }
+}
+
+void SendCharCode(CGCharCode keycode, bool isDown)
+{
+ CGEventRef event = CGEventCreateKeyboardEvent(NULL, keycode, isDown);
+ if (event)
+ {
+ CGEventPost(kCGHIDEventTap, event);
+ }
+ CFRelease(event);
+}
+
+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);
+ CGEventSetType(event, type);
+
+ if (event)
+ {
+ CGEventPost(tap, event);
+ }
+ CFRelease(event);
+ return true;
+}
+
+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);
+
+ if (event)
+ {
+ CGEventPost(tap, event);
+ }
+ CFRelease(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);
+
+ if (event)
+ {
+ CGEventPost(tap, event);
+ }
+ CFRelease(event);
+
+ return true;
+}
+
+bool wxUIActionSimulator::Key(int keycode, bool isDown, bool shiftDown, bool cmdDown, bool altDown)
+{
+ 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);
+
+ return true;
+}
+
+
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: src/unix/uiactionx11.cpp
+// Purpose: wxUIActionSimulator implementation
+// 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
+/////////////////////////////////////////////////////////////////////////////
+
+#include <wx/defs.h>
+#include <wx/uiaction.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/extensions/XTest.h>
+
+void SendButtonEvent(int button, bool isDown)
+{
+ int xbutton = 0;
+ switch (button)
+ {
+ case wxMOUSE_BTN_LEFT:
+ xbutton = 1;
+ break;
+ case wxMOUSE_BTN_RIGHT:
+ xbutton = 2;
+ break;
+ case wxMOUSE_BTN_MIDDLE:
+ xbutton = 3;
+ break;
+ default:
+ wxFAIL_MSG("Unsupported button passed in.");
+ }
+
+ XEvent event;
+
+ Display *display = XOpenDisplay(0);
+ wxASSERT_MSG(display, "No display available!");
+
+ memset(&event, 0x00, sizeof(event));
+
+ if (isDown)
+ event.type = ButtonPress;
+ else
+ event.type = 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);
+ 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);
+ }
+
+ XSendEvent(display, PointerWindow, True, 0xfff, &event);
+ XFlush(display);
+ XCloseDisplay(display);
+}
+
+bool wxUIActionSimulator::MouseDown(int button)
+{
+ SendButtonEvent(button, true);
+ return true;
+}
+
+bool wxUIActionSimulator::MouseMove(long x, long y)
+{
+ Display *display = XOpenDisplay(0);
+ wxASSERT_MSG(display, "No display available!");
+ Window root = DefaultRootWindow(display);
+ XWarpPointer(display, None, root, 0, 0, 0, 0, x, y);
+ XFlush(display);
+ XCloseDisplay(display);
+ return true;
+}
+
+bool wxUIActionSimulator::MouseUp(int button)
+{
+ SendButtonEvent(button, false);
+ return true;
+}
+
+bool wxUIActionSimulator::Key(int keycode, bool isDown, bool WXUNUSED(shiftDown), bool WXUNUSED(cmdDown), bool WXUNUSED(altDown))
+{
+ Display *display = XOpenDisplay(0);
+ wxASSERT_MSG(display, "No display available!");
+
+ XKeyEvent event;
+ int mask = 0xfff;
+ memset(&event, 0x00, sizeof(event));
+
+ if (isDown) {
+ event.type = KeyPress;
+ mask = KeyPressMask;
+ }
+ else {
+ event.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;
+
+ 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);
+ }
+
+ XSendEvent(display, PointerWindow, True, mask, (XEvent*) &event);
+ XFlush(display);
+ XCloseDisplay(display);
+
+ return true;
+}
+