]> git.saurik.com Git - wxWidgets.git/blob - src/unix/uiactionx11.cpp
Fix horizontal mouse wheel scrolling in wxGTK.
[wxWidgets.git] / src / unix / uiactionx11.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/unix/uiactionx11.cpp
3 // Purpose: wxUIActionSimulator implementation
4 // Author: Kevin Ollivier, Steven Lamerton, Vadim Zeitlin
5 // Modified by:
6 // Created: 2010-03-06
7 // Copyright: (c) Kevin Ollivier
8 // (c) 2010 Steven Lamerton
9 // (c) 2010 Vadim Zeitlin
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
12
13 #include "wx/defs.h"
14
15 #if wxUSE_UIACTIONSIMULATOR
16
17 #include "wx/uiaction.h"
18 #include "wx/event.h"
19 #include "wx/evtloop.h"
20
21 #include <X11/Xlib.h>
22 #include <X11/Xutil.h>
23
24 #include "wx/unix/utilsx11.h"
25
26 namespace
27 {
28
29 void SendButtonEvent(int button, bool isDown)
30 {
31 int xbutton;
32 switch (button)
33 {
34 case wxMOUSE_BTN_LEFT:
35 xbutton = 1;
36 break;
37 case wxMOUSE_BTN_MIDDLE:
38 xbutton = 2;
39 break;
40 case wxMOUSE_BTN_RIGHT:
41 xbutton = 3;
42 break;
43 default:
44 wxFAIL_MSG("Unsupported button passed in.");
45 return;
46 }
47
48 wxX11Display display;
49 wxCHECK_RET(display, "No display available!");
50
51 XEvent event;
52 memset(&event, 0x00, sizeof(event));
53
54 event.type = isDown ? ButtonPress : ButtonRelease;
55 event.xbutton.button = xbutton;
56 event.xbutton.same_screen = True;
57
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);
62 event.xbutton.subwindow = event.xbutton.window;
63
64 while (event.xbutton.subwindow)
65 {
66 event.xbutton.window = event.xbutton.subwindow;
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);
71 }
72
73 XSendEvent(display, PointerWindow, True, 0xfff, &event);
74 }
75
76 } // anonymous namespace
77
78 bool wxUIActionSimulator::MouseDown(int button)
79 {
80 SendButtonEvent(button, true);
81 return true;
82 }
83
84 bool wxUIActionSimulator::MouseMove(long x, long y)
85 {
86 wxX11Display display;
87 wxASSERT_MSG(display, "No display available!");
88
89 Window root = display.DefaultRoot();
90 XWarpPointer(display, None, root, 0, 0, 0, 0, x, y);
91
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
101 return true;
102 }
103
104 bool wxUIActionSimulator::MouseUp(int button)
105 {
106 SendButtonEvent(button, false);
107 return true;
108 }
109
110 bool wxUIActionSimulator::DoKey(int keycode, int modifiers, bool isDown)
111 {
112 wxX11Display display;
113 wxCHECK_MSG(display, false, "No display available!");
114
115 int mask, type;
116
117 if ( isDown )
118 {
119 type = KeyPress;
120 mask = KeyPressMask;
121 }
122 else
123 {
124 type = KeyRelease;
125 mask = KeyReleaseMask;
126 }
127
128 WXKeySym xkeysym = wxCharCodeWXToX(keycode);
129 KeyCode xkeycode = XKeysymToKeycode(display, xkeysym);
130 if ( xkeycode == NoSymbol )
131 return false;
132
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;
163
164 XSendEvent(event.display, event.window, True, mask, (XEvent*) &event);
165
166 return true;
167 }
168
169 #endif // wxUSE_UIACTIONSIMULATOR