]> git.saurik.com Git - wxWidgets.git/blobdiff - src/unix/uiactionx11.cpp
avoid duplicate move events
[wxWidgets.git] / src / unix / uiactionx11.cpp
index 05497efa036a6e36ba5b2fe37f7339de2b70ded7..a19a3d2284ae51f5269bc240219fe5cb733f8298 100644 (file)
@@ -1,68 +1,80 @@
 /////////////////////////////////////////////////////////////////////////////
 // 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
 /////////////////////////////////////////////////////////////////////////////
 
-#include <wx/defs.h>
-#include <wx/uiaction.h>
+#include "wx/defs.h"
+
+#if wxUSE_UIACTIONSIMULATOR
+
+#include "wx/uiaction.h"
+#include "wx/event.h"
+#include "wx/evtloop.h"
 
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
-#include <X11/extensions/XTest.h>
+
+#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;
     }
 
+    wxX11Display display;
+    wxCHECK_RET(display, "No display available!");
+
     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.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);
@@ -70,13 +82,22 @@ 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);
+
+    // 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;
 }
 
@@ -86,38 +107,63 @@ 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!");
-    
-    XKeyEvent event;
-    int mask = 0xfff;
-    memset(&event, 0x00, sizeof(event));
-    
-    if (isDown) {
-        event.type = KeyPress;
+    wxX11Display display;
+    wxCHECK_MSG(display, false, "No display available!");
+
+    int mask, type;
+
+    if ( isDown )
+    {
+        type = KeyPress;
         mask = KeyPressMask;
     }
-    else {
-        event.type = KeyRelease;
+    else
+    {
+        type = KeyRelease;
         mask = KeyReleaseMask;
     }
+
+    WXKeySym xkeysym = wxCharCodeWXToX(keycode);
+    KeyCode xkeycode = XKeysymToKeycode(display, xkeysym);
+    if ( xkeycode == NoSymbol )
+        return false;
+
+    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;
-    
-    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);
+    event.type = type;
+    event.state = mod;
+    event.keycode = xkeycode;
+
+    XSendEvent(event.display, event.window, True, mask, (XEvent*) &event);
 
     return true;
 }
 
+#endif // wxUSE_UIACTIONSIMULATOR