]> git.saurik.com Git - wxWidgets.git/blame - src/unix/uiactionx11.cpp
avoid duplicate move events
[wxWidgets.git] / src / unix / uiactionx11.cpp
CommitLineData
a02a5cfc
KO
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/unix/uiactionx11.cpp
3// Purpose: wxUIActionSimulator implementation
571d991b 4// Author: Kevin Ollivier, Steven Lamerton, Vadim Zeitlin
a02a5cfc
KO
5// Modified by:
6// Created: 2010-03-06
a02a5cfc 7// Copyright: (c) Kevin Ollivier
571d991b
VZ
8// (c) 2010 Steven Lamerton
9// (c) 2010 Vadim Zeitlin
a02a5cfc
KO
10// Licence: wxWindows licence
11/////////////////////////////////////////////////////////////////////////////
12
9b7e0226
VZ
13#include "wx/defs.h"
14
15#if wxUSE_UIACTIONSIMULATOR
16
17#include "wx/uiaction.h"
bdbdb4d1
VZ
18#include "wx/event.h"
19#include "wx/evtloop.h"
a02a5cfc 20
beee38cb 21#include <X11/Xlib.h>
a02a5cfc 22#include <X11/Xutil.h>
571d991b
VZ
23
24#include "wx/unix/utilsx11.h"
25
26namespace
27{
a02a5cfc
KO
28
29void SendButtonEvent(int button, bool isDown)
30{
571d991b 31 int xbutton;
a02a5cfc
KO
32 switch (button)
33 {
34 case wxMOUSE_BTN_LEFT:
35 xbutton = 1;
36 break;
571d991b 37 case wxMOUSE_BTN_MIDDLE:
a02a5cfc
KO
38 xbutton = 2;
39 break;
571d991b 40 case wxMOUSE_BTN_RIGHT:
a02a5cfc
KO
41 xbutton = 3;
42 break;
43 default:
44 wxFAIL_MSG("Unsupported button passed in.");
571d991b 45 return;
a02a5cfc
KO
46 }
47
571d991b
VZ
48 wxX11Display display;
49 wxCHECK_RET(display, "No display available!");
9b7e0226 50
571d991b 51 XEvent event;
a02a5cfc 52 memset(&event, 0x00, sizeof(event));
9b7e0226 53
571d991b 54 event.type = isDown ? ButtonPress : ButtonRelease;
a02a5cfc
KO
55 event.xbutton.button = xbutton;
56 event.xbutton.same_screen = True;
9b7e0226 57
571d991b
VZ
58 XQueryPointer(display, display.DefaultRoot(),
59 &event.xbutton.root, &event.xbutton.window,
60 &event.xbutton.x_root, &event.xbutton.y_root,
61 &event.xbutton.x, &event.xbutton.y, &event.xbutton.state);
a02a5cfc 62 event.xbutton.subwindow = event.xbutton.window;
9b7e0226 63
a02a5cfc
KO
64 while (event.xbutton.subwindow)
65 {
66 event.xbutton.window = event.xbutton.subwindow;
571d991b
VZ
67 XQueryPointer(display, event.xbutton.window,
68 &event.xbutton.root, &event.xbutton.subwindow,
69 &event.xbutton.x_root, &event.xbutton.y_root,
70 &event.xbutton.x, &event.xbutton.y, &event.xbutton.state);
a02a5cfc 71 }
9b7e0226 72
a02a5cfc 73 XSendEvent(display, PointerWindow, True, 0xfff, &event);
a02a5cfc
KO
74}
75
571d991b
VZ
76} // anonymous namespace
77
a02a5cfc
KO
78bool wxUIActionSimulator::MouseDown(int button)
79{
80 SendButtonEvent(button, true);
81 return true;
82}
83
84bool wxUIActionSimulator::MouseMove(long x, long y)
9b7e0226 85{
571d991b 86 wxX11Display display;
a02a5cfc 87 wxASSERT_MSG(display, "No display available!");
571d991b
VZ
88
89 Window root = display.DefaultRoot();
a02a5cfc 90 XWarpPointer(display, None, root, 0, 0, 0, 0, x, y);
571d991b 91
bdbdb4d1
VZ
92 // At least with wxGTK we must always process the pending events before the
93 // mouse position change really takes effect, so just do it from here
94 // instead of forcing the client code using this function to always use
95 // wxYield() which is unnecessary under the other platforms.
96 if ( wxEventLoopBase* const loop = wxEventLoop::GetActive() )
97 {
98 loop->YieldFor(wxEVT_CATEGORY_USER_INPUT);
99 }
100
a02a5cfc
KO
101 return true;
102}
103
104bool wxUIActionSimulator::MouseUp(int button)
105{
106 SendButtonEvent(button, false);
107 return true;
108}
109
571d991b 110bool wxUIActionSimulator::DoKey(int keycode, int modifiers, bool isDown)
a02a5cfc 111{
571d991b
VZ
112 wxX11Display display;
113 wxCHECK_MSG(display, false, "No display available!");
9b7e0226 114
571d991b 115 int mask, type;
9b7e0226 116
571d991b
VZ
117 if ( isDown )
118 {
119 type = KeyPress;
a02a5cfc
KO
120 mask = KeyPressMask;
121 }
571d991b
VZ
122 else
123 {
124 type = KeyRelease;
a02a5cfc
KO
125 mask = KeyReleaseMask;
126 }
9b7e0226 127
571d991b
VZ
128 WXKeySym xkeysym = wxCharCodeWXToX(keycode);
129 KeyCode xkeycode = XKeysymToKeycode(display, xkeysym);
130 if ( xkeycode == NoSymbol )
131 return false;
9b7e0226 132
571d991b
VZ
133 Window focus;
134 int revert;
135 XGetInputFocus(display, &focus, &revert);
136 if (focus == None)
137 return false;
138
139 int mod = 0;
140
141 if (modifiers & wxMOD_SHIFT)
142 mod |= ShiftMask;
143 //Mod1 is alt in the vast majority of cases
144 if (modifiers & wxMOD_ALT)
145 mod |= Mod1Mask;
146 if (modifiers & wxMOD_CMD)
147 mod |= ControlMask;
148
149 XKeyEvent event;
150 event.display = display;
151 event.window = focus;
152 event.root = DefaultRootWindow(event.display);
153 event.subwindow = None;
154 event.time = CurrentTime;
155 event.x = 1;
156 event.y = 1;
157 event.x_root = 1;
158 event.y_root = 1;
159 event.same_screen = True;
160 event.type = type;
161 event.state = mod;
162 event.keycode = xkeycode;
9b7e0226 163
571d991b 164 XSendEvent(event.display, event.window, True, mask, (XEvent*) &event);
a02a5cfc
KO
165
166 return true;
167}
168
9b7e0226 169#endif // wxUSE_UIACTIONSIMULATOR