Merge lp:~brandontschaefer/unity/move-pointer-barrier-to-xi-1.6.99.1 into lp:unity
- move-pointer-barrier-to-xi-1.6.99.1
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 3407 |
Proposed branch: | lp:~brandontschaefer/unity/move-pointer-barrier-to-xi-1.6.99.1 |
Merge into: | lp:unity |
Diff against target: |
703 lines (+261/-152) 8 files modified
CMakeLists.txt (+2/-1) debian/changelog (+4/-3) debian/control (+1/-0) launcher/EdgeBarrierController.cpp (+126/-3) launcher/EdgeBarrierControllerPrivate.h (+9/-0) launcher/PointerBarrier.cpp (+82/-94) launcher/PointerBarrier.h (+7/-5) tests/test_pointer_barrier.cpp (+30/-46) |
To merge this branch: | bzr merge lp:~brandontschaefer/unity/move-pointer-barrier-to-xi-1.6.99.1 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Needs Fixing | |
Andrea Azzarone (community) | Approve | ||
Review via email: mp+150175@code.launchpad.net |
Commit message
Move unity to the new libxi changes, along with the new 1.14 xserver.
Description of the change
Some big changes. Updating pointer barrier logic new versions of xfixes and xi (1.6.99.1).
Had to move a bunch of things around, due to the fact that we didn't handle any kind of XI2 events before. Also re worked somethings so they only run once now...before we had a bunch of things being ran every time a barrier was being created that was not necessary.
So now the new logic, simplified:
Mouse hits barrier, XIBarrierEvent generated and sent off.
Nux receives XEvent and passes it back to EdgeBarrierCont
In HandleEventCB we check to see of the opcode matches, if so pass it to HandleEvent
In HandleEvent we check if its a type XI_BarrierHit
If so, then find the barrier wrapper the event belongs to.
(XGetEventData works onces per event, so the logic we had before didn't work).
From here we pass it to PointerBarrier.
Here we are pretty much back to where we were before the changed :).
Andrea Azzarone (azzar1) : | # |
Sebastien Bacher (seb128) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:3175
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Timo Jyrinki (timo-jyrinki) wrote : | # |
Continuing at https:/
Preview Diff
1 | === modified file 'CMakeLists.txt' | |||
2 | --- CMakeLists.txt 2013-06-26 14:29:55 +0000 | |||
3 | +++ CMakeLists.txt 2013-07-03 16:16:23 +0000 | |||
4 | @@ -10,7 +10,7 @@ | |||
5 | 10 | set (PROJECT_NAME "unity") | 10 | set (PROJECT_NAME "unity") |
6 | 11 | set (UNITY_MAJOR 7) | 11 | set (UNITY_MAJOR 7) |
7 | 12 | set (UNITY_MINOR 0) | 12 | set (UNITY_MINOR 0) |
9 | 13 | set (UNITY_MICRO 1) | 13 | set (UNITY_MICRO 2) |
10 | 14 | set (UNITY_VERSION "${UNITY_MAJOR}.${UNITY_MINOR}.${UNITY_MICRO}") | 14 | set (UNITY_VERSION "${UNITY_MAJOR}.${UNITY_MINOR}.${UNITY_MICRO}") |
11 | 15 | set (UNITY_API_VERSION "6.0") | 15 | set (UNITY_API_VERSION "6.0") |
12 | 16 | set (UNITY_COMPONENTS_VERSION "6") | 16 | set (UNITY_COMPONENTS_VERSION "6") |
13 | @@ -244,6 +244,7 @@ | |||
14 | 244 | libgeis | 244 | libgeis |
15 | 245 | x11 | 245 | x11 |
16 | 246 | xfixes | 246 | xfixes |
17 | 247 | xi>=1.6.99.1 | ||
18 | 247 | xrender>=0.9 | 248 | xrender>=0.9 |
19 | 248 | ) | 249 | ) |
20 | 249 | endif () | 250 | endif () |
21 | 250 | 251 | ||
22 | === modified file 'debian/changelog' | |||
23 | --- debian/changelog 2013-07-03 04:03:34 +0000 | |||
24 | +++ debian/changelog 2013-07-03 16:16:23 +0000 | |||
25 | @@ -401,9 +401,6 @@ | |||
26 | 401 | unity (7.0.0daily13.05.08ubuntu.unity.next-0ubuntu1) raring; urgency=low | 401 | unity (7.0.0daily13.05.08ubuntu.unity.next-0ubuntu1) raring; urgency=low |
27 | 402 | 402 | ||
28 | 403 | * Automatic snapshot from revision 3317 (ubuntu-unity/next) | 403 | * Automatic snapshot from revision 3317 (ubuntu-unity/next) |
29 | 404 | |||
30 | 405 | -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Wed, 08 May 2013 04:57:49 +0000 | ||
31 | 406 | |||
32 | 407 | unity (7.0.0daily13.05.01.1ubuntu.unity.next-0ubuntu1) raring; urgency=low | 404 | unity (7.0.0daily13.05.01.1ubuntu.unity.next-0ubuntu1) raring; urgency=low |
33 | 408 | 405 | ||
34 | 409 | [ Sebastien Bacher ] | 406 | [ Sebastien Bacher ] |
35 | @@ -942,6 +939,10 @@ | |||
36 | 942 | [ Automatic PS uploader ] | 939 | [ Automatic PS uploader ] |
37 | 943 | * Automatic snapshot from revision 3140 | 940 | * Automatic snapshot from revision 3140 |
38 | 944 | 941 | ||
39 | 942 | [ Brandon Schaefer ] | ||
40 | 943 | * Moved PointerBarrier logic to the new xserver 1.14 (libXi 1.6.99.1) | ||
41 | 944 | version. | ||
42 | 945 | |||
43 | 945 | -- Automatic PS uploader <ps-jenkins@lists.canonical.com> Fri, 08 Feb 2013 04:02:00 +0000 | 946 | -- Automatic PS uploader <ps-jenkins@lists.canonical.com> Fri, 08 Feb 2013 04:02:00 +0000 |
44 | 946 | 947 | ||
45 | 947 | unity (6.12.0daily13.02.07-0ubuntu1) raring; urgency=low | 948 | unity (6.12.0daily13.02.07-0ubuntu1) raring; urgency=low |
46 | 948 | 949 | ||
47 | === modified file 'debian/control' | |||
48 | --- debian/control 2013-07-02 09:30:43 +0000 | |||
49 | +++ debian/control 2013-07-03 16:16:23 +0000 | |||
50 | @@ -44,6 +44,7 @@ | |||
51 | 44 | libunity-scopes-json-def-desktop, | 44 | libunity-scopes-json-def-desktop, |
52 | 45 | libzeitgeist-dev (>= 0.3.18), | 45 | libzeitgeist-dev (>= 0.3.18), |
53 | 46 | libxfixes-dev (>= 1:5.0-4ubuntu4), | 46 | libxfixes-dev (>= 1:5.0-4ubuntu4), |
54 | 47 | libxi-dev (>= 1.6.99.1), | ||
55 | 47 | libxpathselect-dev (>=1.3), | 48 | libxpathselect-dev (>=1.3), |
56 | 48 | libgtest-dev, | 49 | libgtest-dev, |
57 | 49 | google-mock, | 50 | google-mock, |
58 | 50 | 51 | ||
59 | === modified file 'launcher/EdgeBarrierController.cpp' | |||
60 | --- launcher/EdgeBarrierController.cpp 2013-04-02 01:57:03 +0000 | |||
61 | +++ launcher/EdgeBarrierController.cpp 2013-07-03 16:16:23 +0000 | |||
62 | @@ -21,6 +21,7 @@ | |||
63 | 21 | #include "EdgeBarrierController.h" | 21 | #include "EdgeBarrierController.h" |
64 | 22 | #include "EdgeBarrierControllerPrivate.h" | 22 | #include "EdgeBarrierControllerPrivate.h" |
65 | 23 | #include "Decaymulator.h" | 23 | #include "Decaymulator.h" |
66 | 24 | #include <NuxCore/Logger.h> | ||
67 | 24 | #include "unity-shared/UScreen.h" | 25 | #include "unity-shared/UScreen.h" |
68 | 25 | #include "UnityCore/GLibSource.h" | 26 | #include "UnityCore/GLibSource.h" |
69 | 26 | 27 | ||
70 | @@ -32,11 +33,50 @@ | |||
71 | 32 | namespace | 33 | namespace |
72 | 33 | { | 34 | { |
73 | 34 | int const Y_BREAK_BUFFER = 20; | 35 | int const Y_BREAK_BUFFER = 20; |
76 | 35 | } | 36 | int const MAJOR = 2; |
77 | 36 | 37 | int const MINOR = 3; | |
78 | 38 | } | ||
79 | 39 | |||
80 | 40 | DECLARE_LOGGER(logger, "unity.edge_barrier_controller"); | ||
81 | 41 | |||
82 | 42 | int GetXI2OpCode() | ||
83 | 43 | { | ||
84 | 44 | Display *dpy = nux::GetGraphicsDisplay()->GetX11Display(); | ||
85 | 45 | |||
86 | 46 | int opcode, event_base, error_base; | ||
87 | 47 | if (!XQueryExtension(dpy, "XFIXES", | ||
88 | 48 | &opcode, | ||
89 | 49 | &event_base, | ||
90 | 50 | &error_base)) | ||
91 | 51 | { | ||
92 | 52 | LOG_ERROR(logger) << "Missing XFixes"; | ||
93 | 53 | return -1; | ||
94 | 54 | } | ||
95 | 55 | |||
96 | 56 | if (!XQueryExtension (dpy, "XInputExtension", | ||
97 | 57 | &opcode, | ||
98 | 58 | &event_base, | ||
99 | 59 | &error_base)) | ||
100 | 60 | { | ||
101 | 61 | LOG_ERROR(logger) << "Missing XInput"; | ||
102 | 62 | return -1; | ||
103 | 63 | } | ||
104 | 64 | |||
105 | 65 | int maj = MAJOR; | ||
106 | 66 | int min = MINOR; | ||
107 | 67 | |||
108 | 68 | if (XIQueryVersion(dpy, &maj, &min) == BadRequest) | ||
109 | 69 | { | ||
110 | 70 | LOG_ERROR(logger) << "Need XInput version 2.3"; | ||
111 | 71 | return -1; | ||
112 | 72 | } | ||
113 | 73 | |||
114 | 74 | return opcode; | ||
115 | 75 | } | ||
116 | 37 | 76 | ||
117 | 38 | EdgeBarrierController::Impl::Impl(EdgeBarrierController *parent) | 77 | EdgeBarrierController::Impl::Impl(EdgeBarrierController *parent) |
119 | 39 | : edge_overcome_pressure_(0) | 78 | : xi2_opcode_(-1) |
120 | 79 | , edge_overcome_pressure_(0) | ||
121 | 40 | , parent_(parent) | 80 | , parent_(parent) |
122 | 41 | { | 81 | { |
123 | 42 | UScreen *uscreen = UScreen::GetDefault(); | 82 | UScreen *uscreen = UScreen::GetDefault(); |
124 | @@ -68,6 +108,13 @@ | |||
125 | 68 | }); | 108 | }); |
126 | 69 | SetupBarriers(UScreen::GetDefault()->GetMonitors()); | 109 | SetupBarriers(UScreen::GetDefault()->GetMonitors()); |
127 | 70 | }); | 110 | }); |
128 | 111 | |||
129 | 112 | xi2_opcode_ = GetXI2OpCode(); | ||
130 | 113 | } | ||
131 | 114 | |||
132 | 115 | EdgeBarrierController::Impl::~Impl() | ||
133 | 116 | { | ||
134 | 117 | nux::GetGraphicsDisplay()->RemoveEventFilter(this); | ||
135 | 71 | } | 118 | } |
136 | 72 | 119 | ||
137 | 73 | void EdgeBarrierController::Impl::ResizeBarrierList(std::vector<nux::Geometry> const& layout) | 120 | void EdgeBarrierController::Impl::ResizeBarrierList(std::vector<nux::Geometry> const& layout) |
138 | @@ -86,6 +133,18 @@ | |||
139 | 86 | } | 133 | } |
140 | 87 | } | 134 | } |
141 | 88 | 135 | ||
142 | 136 | void SetupXI2Events() | ||
143 | 137 | { | ||
144 | 138 | Display *dpy = nux::GetGraphicsDisplay()->GetX11Display(); | ||
145 | 139 | |||
146 | 140 | unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 }; | ||
147 | 141 | XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits }; | ||
148 | 142 | |||
149 | 143 | XISetMask(mask.mask, XI_BarrierHit); | ||
150 | 144 | XISetMask(mask.mask, XI_BarrierLeave); | ||
151 | 145 | XISelectEvents (dpy, DefaultRootWindow(dpy), &mask, 1); | ||
152 | 146 | } | ||
153 | 147 | |||
154 | 89 | void EdgeBarrierController::Impl::SetupBarriers(std::vector<nux::Geometry> const& layout) | 148 | void EdgeBarrierController::Impl::SetupBarriers(std::vector<nux::Geometry> const& layout) |
155 | 90 | { | 149 | { |
156 | 91 | bool edge_resist = parent_->sticky_edges(); | 150 | bool edge_resist = parent_->sticky_edges(); |
157 | @@ -112,6 +171,9 @@ | |||
158 | 112 | barrier->ConstructBarrier(); | 171 | barrier->ConstructBarrier(); |
159 | 113 | } | 172 | } |
160 | 114 | 173 | ||
161 | 174 | SetupXI2Events(); | ||
162 | 175 | AddEventFilter(); | ||
163 | 176 | |||
164 | 115 | float decay_responsiveness_mult = ((parent_->options()->edge_responsiveness() - 1) * .3f) + 1; | 177 | float decay_responsiveness_mult = ((parent_->options()->edge_responsiveness() - 1) * .3f) + 1; |
165 | 116 | decaymulator_.rate_of_decay = parent_->options()->edge_decay_rate() * decay_responsiveness_mult; | 178 | decaymulator_.rate_of_decay = parent_->options()->edge_decay_rate() * decay_responsiveness_mult; |
166 | 117 | 179 | ||
167 | @@ -119,6 +181,67 @@ | |||
168 | 119 | edge_overcome_pressure_ = parent_->options()->edge_overcome_pressure() * overcome_responsiveness_mult; | 181 | edge_overcome_pressure_ = parent_->options()->edge_overcome_pressure() * overcome_responsiveness_mult; |
169 | 120 | } | 182 | } |
170 | 121 | 183 | ||
171 | 184 | void EdgeBarrierController::Impl::AddEventFilter() | ||
172 | 185 | { | ||
173 | 186 | // Remove an old one, if it exists | ||
174 | 187 | nux::GetGraphicsDisplay()->RemoveEventFilter(this); | ||
175 | 188 | |||
176 | 189 | nux::GraphicsDisplay::EventFilterArg event_filter; | ||
177 | 190 | event_filter.filter = &HandleEventCB; | ||
178 | 191 | event_filter.data = this; | ||
179 | 192 | |||
180 | 193 | nux::GetGraphicsDisplay()->AddEventFilter(event_filter); | ||
181 | 194 | } | ||
182 | 195 | |||
183 | 196 | bool EdgeBarrierController::Impl::HandleEvent(XEvent xevent) | ||
184 | 197 | { | ||
185 | 198 | Display *dpy = nux::GetGraphicsDisplay()->GetX11Display(); | ||
186 | 199 | XGenericEventCookie *cookie = &xevent.xcookie; | ||
187 | 200 | bool ret = false; | ||
188 | 201 | |||
189 | 202 | switch (cookie->evtype) | ||
190 | 203 | { | ||
191 | 204 | case (XI_BarrierHit): | ||
192 | 205 | { | ||
193 | 206 | if (XGetEventData(dpy, cookie)) | ||
194 | 207 | { | ||
195 | 208 | XIBarrierEvent* barrier_event = (XIBarrierEvent*)cookie->data; | ||
196 | 209 | PointerBarrierWrapper::Ptr wrapper = FindBarrierEventOwner(barrier_event); | ||
197 | 210 | |||
198 | 211 | if (wrapper) | ||
199 | 212 | ret = wrapper->HandleBarrierEvent(barrier_event); | ||
200 | 213 | } | ||
201 | 214 | |||
202 | 215 | XFreeEventData(dpy, cookie); | ||
203 | 216 | break; | ||
204 | 217 | } | ||
205 | 218 | default: | ||
206 | 219 | break; | ||
207 | 220 | } | ||
208 | 221 | |||
209 | 222 | return ret; | ||
210 | 223 | } | ||
211 | 224 | |||
212 | 225 | bool EdgeBarrierController::Impl::HandleEventCB(XEvent xevent, void* data) | ||
213 | 226 | { | ||
214 | 227 | auto edge_barrier_controller = static_cast<EdgeBarrierController::Impl*>(data); | ||
215 | 228 | int const xi2_opcode = edge_barrier_controller->xi2_opcode_; | ||
216 | 229 | |||
217 | 230 | if (xevent.type != GenericEvent || xevent.xcookie.extension != xi2_opcode) | ||
218 | 231 | return false; | ||
219 | 232 | |||
220 | 233 | return edge_barrier_controller->HandleEvent(xevent); | ||
221 | 234 | } | ||
222 | 235 | |||
223 | 236 | PointerBarrierWrapper::Ptr EdgeBarrierController::Impl::FindBarrierEventOwner(XIBarrierEvent* barrier_event) | ||
224 | 237 | { | ||
225 | 238 | for (auto barrier : barriers_) | ||
226 | 239 | if (barrier->OwnsBarrierEvent(barrier_event->barrier)) | ||
227 | 240 | return barrier; | ||
228 | 241 | |||
229 | 242 | return nullptr; | ||
230 | 243 | } | ||
231 | 244 | |||
232 | 122 | void EdgeBarrierController::Impl::BarrierReset() | 245 | void EdgeBarrierController::Impl::BarrierReset() |
233 | 123 | { | 246 | { |
234 | 124 | decaymulator_.value = 0; | 247 | decaymulator_.value = 0; |
235 | 125 | 248 | ||
236 | === modified file 'launcher/EdgeBarrierControllerPrivate.h' | |||
237 | --- launcher/EdgeBarrierControllerPrivate.h 2013-02-13 19:21:49 +0000 | |||
238 | +++ launcher/EdgeBarrierControllerPrivate.h 2013-07-03 16:16:23 +0000 | |||
239 | @@ -33,6 +33,7 @@ | |||
240 | 33 | struct EdgeBarrierController::Impl | 33 | struct EdgeBarrierController::Impl |
241 | 34 | { | 34 | { |
242 | 35 | Impl(EdgeBarrierController *parent); | 35 | Impl(EdgeBarrierController *parent); |
243 | 36 | ~Impl(); | ||
244 | 36 | 37 | ||
245 | 37 | void ResizeBarrierList(std::vector<nux::Geometry> const& layout); | 38 | void ResizeBarrierList(std::vector<nux::Geometry> const& layout); |
246 | 38 | void SetupBarriers(std::vector<nux::Geometry> const& layout); | 39 | void SetupBarriers(std::vector<nux::Geometry> const& layout); |
247 | @@ -44,10 +45,18 @@ | |||
248 | 44 | 45 | ||
249 | 45 | bool EventIsInsideYBreakZone(BarrierEvent::Ptr const& event); | 46 | bool EventIsInsideYBreakZone(BarrierEvent::Ptr const& event); |
250 | 46 | 47 | ||
251 | 48 | void AddEventFilter(); | ||
252 | 49 | |||
253 | 50 | PointerBarrierWrapper::Ptr FindBarrierEventOwner(XIBarrierEvent* barrier_event); | ||
254 | 51 | |||
255 | 52 | static bool HandleEventCB(XEvent event, void* data); | ||
256 | 53 | bool HandleEvent(XEvent event); | ||
257 | 54 | |||
258 | 47 | std::vector<PointerBarrierWrapper::Ptr> barriers_; | 55 | std::vector<PointerBarrierWrapper::Ptr> barriers_; |
259 | 48 | std::vector<EdgeBarrierSubscriber*> subscribers_; | 56 | std::vector<EdgeBarrierSubscriber*> subscribers_; |
260 | 49 | Decaymulator decaymulator_; | 57 | Decaymulator decaymulator_; |
261 | 50 | glib::Source::UniquePtr release_timeout_; | 58 | glib::Source::UniquePtr release_timeout_; |
262 | 59 | int xi2_opcode_; | ||
263 | 51 | float edge_overcome_pressure_; | 60 | float edge_overcome_pressure_; |
264 | 52 | EdgeBarrierController* parent_; | 61 | EdgeBarrierController* parent_; |
265 | 53 | }; | 62 | }; |
266 | 54 | 63 | ||
267 | === modified file 'launcher/PointerBarrier.cpp' | |||
268 | --- launcher/PointerBarrier.cpp 2013-02-11 23:57:09 +0000 | |||
269 | +++ launcher/PointerBarrier.cpp 2013-07-03 16:16:23 +0000 | |||
270 | @@ -13,12 +13,14 @@ | |||
271 | 13 | * | 13 | * |
272 | 14 | * You should have received a copy of the GNU General Public License | 14 | * You should have received a copy of the GNU General Public License |
273 | 15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
274 | 16 | * | ||
275 | 17 | * Authored by: Jason Smith <jason.smith@canonical.com> | ||
276 | 18 | * Brandon Schaefer <brandon.schaefer@canonical.com> | ||
277 | 19 | * | ||
278 | 16 | */ | 20 | */ |
279 | 17 | 21 | ||
280 | 18 | #include <unistd.h> | 22 | #include <unistd.h> |
281 | 19 | #include <stdlib.h> | 23 | #include <stdlib.h> |
282 | 20 | #include <stdio.h> | ||
283 | 21 | #include <X11/extensions/Xfixes.h> | ||
284 | 22 | 24 | ||
285 | 23 | #include "PointerBarrier.h" | 25 | #include "PointerBarrier.h" |
286 | 24 | 26 | ||
287 | @@ -27,14 +29,6 @@ | |||
288 | 27 | namespace ui | 29 | namespace ui |
289 | 28 | { | 30 | { |
290 | 29 | 31 | ||
291 | 30 | namespace local | ||
292 | 31 | { | ||
293 | 32 | namespace | ||
294 | 33 | { | ||
295 | 34 | bool is_selected_for = false; | ||
296 | 35 | } | ||
297 | 36 | } | ||
298 | 37 | |||
299 | 38 | PointerBarrierWrapper::PointerBarrierWrapper() | 32 | PointerBarrierWrapper::PointerBarrierWrapper() |
300 | 39 | : active(false) | 33 | : active(false) |
301 | 40 | , released(false) | 34 | , released(false) |
302 | @@ -42,10 +36,11 @@ | |||
303 | 42 | , smoothing(75) | 36 | , smoothing(75) |
304 | 43 | , max_velocity_multiplier(1.0f) | 37 | , max_velocity_multiplier(1.0f) |
305 | 44 | , direction(BOTH) | 38 | , direction(BOTH) |
307 | 45 | , event_base_(0) | 39 | , xi2_opcode_(0) |
308 | 46 | , last_event_(0) | 40 | , last_event_(0) |
309 | 41 | , current_device_(0) | ||
310 | 47 | , first_event_(false) | 42 | , first_event_(false) |
312 | 48 | , barrier(0) | 43 | , barrier_(0) |
313 | 49 | , smoothing_count_(0) | 44 | , smoothing_count_(0) |
314 | 50 | , smoothing_accum_(0) | 45 | , smoothing_accum_(0) |
315 | 51 | {} | 46 | {} |
316 | @@ -62,34 +57,14 @@ | |||
317 | 62 | 57 | ||
318 | 63 | Display *dpy = nux::GetGraphicsDisplay()->GetX11Display(); | 58 | Display *dpy = nux::GetGraphicsDisplay()->GetX11Display(); |
319 | 64 | 59 | ||
340 | 65 | int error_base; | 60 | barrier_ = XFixesCreatePointerBarrier(dpy, |
341 | 66 | XFixesQueryExtension(dpy, &event_base_, &error_base); | 61 | DefaultRootWindow(dpy), |
342 | 67 | 62 | x1, y1, | |
343 | 68 | int maj,min; | 63 | x2, y2, |
344 | 69 | XFixesQueryVersion(dpy, &maj, &min); | 64 | static_cast<int>(direction), |
345 | 70 | 65 | 0, NULL); | |
326 | 71 | barrier = XFixesCreatePointerBarrierVelocity(dpy, | ||
327 | 72 | DefaultRootWindow(dpy), | ||
328 | 73 | x1, y1, | ||
329 | 74 | x2, y2, | ||
330 | 75 | static_cast<int>(direction), | ||
331 | 76 | threshold, | ||
332 | 77 | 0, | ||
333 | 78 | NULL); | ||
334 | 79 | |||
335 | 80 | if (!local::is_selected_for) | ||
336 | 81 | { | ||
337 | 82 | XFixesSelectBarrierInput(dpy, DefaultRootWindow(dpy), 0xdeadbeef); | ||
338 | 83 | local::is_selected_for = true; | ||
339 | 84 | } | ||
346 | 85 | 66 | ||
347 | 86 | active = true; | 67 | active = true; |
348 | 87 | |||
349 | 88 | nux::GraphicsDisplay::EventFilterArg event_filter; | ||
350 | 89 | event_filter.filter = &PointerBarrierWrapper::HandleEventWrapper; | ||
351 | 90 | event_filter.data = this; | ||
352 | 91 | |||
353 | 92 | nux::GetGraphicsDisplay()->AddEventFilter(event_filter); | ||
354 | 93 | } | 68 | } |
355 | 94 | 69 | ||
356 | 95 | void PointerBarrierWrapper::DestroyBarrier() | 70 | void PointerBarrierWrapper::DestroyBarrier() |
357 | @@ -100,14 +75,13 @@ | |||
358 | 100 | active = false; | 75 | active = false; |
359 | 101 | 76 | ||
360 | 102 | Display *dpy = nux::GetGraphicsDisplay()->GetX11Display(); | 77 | Display *dpy = nux::GetGraphicsDisplay()->GetX11Display(); |
364 | 103 | XFixesDestroyPointerBarrier(dpy, barrier); | 78 | XFixesDestroyPointerBarrier(dpy, barrier_); |
362 | 104 | |||
363 | 105 | nux::GetGraphicsDisplay()->RemoveEventFilter(this); | ||
365 | 106 | } | 79 | } |
366 | 107 | 80 | ||
367 | 108 | void PointerBarrierWrapper::ReleaseBarrier(int event_id) | 81 | void PointerBarrierWrapper::ReleaseBarrier(int event_id) |
368 | 109 | { | 82 | { |
370 | 110 | XFixesBarrierReleasePointer(nux::GetGraphicsDisplay()->GetX11Display(), barrier, event_id); | 83 | Display *dpy = nux::GetGraphicsDisplay()->GetX11Display(); |
371 | 84 | XIBarrierReleasePointer(dpy, current_device_, barrier_, event_id); | ||
372 | 111 | } | 85 | } |
373 | 112 | 86 | ||
374 | 113 | void PointerBarrierWrapper::EmitCurrentData(int event_id, int x, int y) | 87 | void PointerBarrierWrapper::EmitCurrentData(int event_id, int x, int y) |
375 | @@ -134,63 +108,77 @@ | |||
376 | 134 | return first_event_; | 108 | return first_event_; |
377 | 135 | } | 109 | } |
378 | 136 | 110 | ||
386 | 137 | bool PointerBarrierWrapper::HandleEvent(XEvent xevent) | 111 | int GetEventVelocity(XIBarrierEvent* event) |
387 | 138 | { | 112 | { |
388 | 139 | if (xevent.type - event_base_ == XFixesBarrierNotify) | 113 | double dx, dy; |
389 | 140 | { | 114 | double speed; |
390 | 141 | auto notify_event = reinterpret_cast<XFixesBarrierNotifyEvent*>(&xevent); | 115 | unsigned int millis; |
391 | 142 | 116 | ||
392 | 143 | if (notify_event->barrier == barrier && notify_event->subtype == XFixesBarrierHitNotify) | 117 | dx = event->dx; |
393 | 118 | dy = event->dy; | ||
394 | 119 | |||
395 | 120 | // Sometimes dtime is 0, if so we don't want to divide by zero! | ||
396 | 121 | millis = event->dtime ?: 1; | ||
397 | 122 | |||
398 | 123 | speed = sqrt(dx * dx + dy * dy) / millis * 1000; | ||
399 | 124 | |||
400 | 125 | return speed; | ||
401 | 126 | } | ||
402 | 127 | |||
403 | 128 | bool PointerBarrierWrapper::OwnsBarrierEvent(PointerBarrier const barrier) const | ||
404 | 129 | { | ||
405 | 130 | return barrier_ == barrier; | ||
406 | 131 | } | ||
407 | 132 | |||
408 | 133 | bool PointerBarrierWrapper::HandleBarrierEvent(XIBarrierEvent* barrier_event) | ||
409 | 134 | { | ||
410 | 135 | int velocity = GetEventVelocity(barrier_event); | ||
411 | 136 | smoothing_accum_ += velocity; | ||
412 | 137 | smoothing_count_++; | ||
413 | 138 | |||
414 | 139 | current_device_ = barrier_event->deviceid; | ||
415 | 140 | |||
416 | 141 | if (velocity > threshold) | ||
417 | 142 | { | ||
418 | 143 | smoothing_timeout_.reset(); | ||
419 | 144 | ReleaseBarrier(barrier_event->eventid); | ||
420 | 145 | } | ||
421 | 146 | else if (released) | ||
422 | 147 | { | ||
423 | 148 | /* If the barrier is released, just emit the current event without | ||
424 | 149 | * waiting, so there won't be any delay on releasing the barrier. */ | ||
425 | 150 | smoothing_timeout_.reset(); | ||
426 | 151 | |||
427 | 152 | SendBarrierEvent(barrier_event->root_x, barrier_event->root_y, | ||
428 | 153 | velocity, barrier_event->eventid); | ||
429 | 154 | } | ||
430 | 155 | else if (!smoothing_timeout_) | ||
431 | 156 | { | ||
432 | 157 | int x = barrier_event->root_x; | ||
433 | 158 | int y = barrier_event->root_y; | ||
434 | 159 | int event = barrier_event->eventid; | ||
435 | 160 | |||
436 | 161 | // If we are a new event, don't delay sending the first event | ||
437 | 162 | if (last_event_ != event) | ||
438 | 144 | { | 163 | { |
476 | 145 | smoothing_accum_ += notify_event->velocity; | 164 | first_event_ = true; |
477 | 146 | smoothing_count_++; | 165 | last_event_ = event; |
478 | 147 | 166 | ||
479 | 148 | if (released) | 167 | SendBarrierEvent(barrier_event->root_x, barrier_event->root_y, |
480 | 149 | { | 168 | velocity, barrier_event->eventid); |
481 | 150 | /* If the barrier is released, just emit the current event without | 169 | |
482 | 151 | * waiting, so there won't be any delay on releasing the barrier. */ | 170 | first_event_ = false; |
446 | 152 | smoothing_timeout_.reset(); | ||
447 | 153 | |||
448 | 154 | SendBarrierEvent(notify_event->x, notify_event->y, | ||
449 | 155 | notify_event->velocity, notify_event->event_id); | ||
450 | 156 | } | ||
451 | 157 | else if (!smoothing_timeout_) | ||
452 | 158 | { | ||
453 | 159 | int x = notify_event->x; | ||
454 | 160 | int y = notify_event->y; | ||
455 | 161 | int event = notify_event->event_id; | ||
456 | 162 | |||
457 | 163 | // If we are a new event, don't delay sending the first event | ||
458 | 164 | if (last_event_ != event) | ||
459 | 165 | { | ||
460 | 166 | first_event_ = true; | ||
461 | 167 | last_event_ = event; | ||
462 | 168 | |||
463 | 169 | SendBarrierEvent(notify_event->x, notify_event->y, | ||
464 | 170 | notify_event->velocity, notify_event->event_id); | ||
465 | 171 | |||
466 | 172 | first_event_ = false; | ||
467 | 173 | } | ||
468 | 174 | |||
469 | 175 | smoothing_timeout_.reset(new glib::Timeout(smoothing, [this, event, x, y] () { | ||
470 | 176 | EmitCurrentData(event, x, y); | ||
471 | 177 | |||
472 | 178 | smoothing_timeout_.reset(); | ||
473 | 179 | return false; | ||
474 | 180 | })); | ||
475 | 181 | } | ||
483 | 182 | } | 171 | } |
484 | 183 | 172 | ||
486 | 184 | return notify_event->barrier == barrier; | 173 | smoothing_timeout_.reset(new glib::Timeout(smoothing, [this, event, x, y] () { |
487 | 174 | EmitCurrentData(event, x, y); | ||
488 | 175 | |||
489 | 176 | smoothing_timeout_.reset(); | ||
490 | 177 | return false; | ||
491 | 178 | })); | ||
492 | 185 | } | 179 | } |
493 | 186 | 180 | ||
501 | 187 | return false; | 181 | return true; |
495 | 188 | } | ||
496 | 189 | |||
497 | 190 | bool PointerBarrierWrapper::HandleEventWrapper(XEvent event, void* data) | ||
498 | 191 | { | ||
499 | 192 | PointerBarrierWrapper* wrapper = (PointerBarrierWrapper*)data; | ||
500 | 193 | return wrapper->HandleEvent(event); | ||
502 | 194 | } | 182 | } |
503 | 195 | 183 | ||
504 | 196 | } | 184 | } |
505 | 197 | 185 | ||
506 | === modified file 'launcher/PointerBarrier.h' | |||
507 | --- launcher/PointerBarrier.h 2013-02-11 23:57:09 +0000 | |||
508 | +++ launcher/PointerBarrier.h 2013-07-03 16:16:23 +0000 | |||
509 | @@ -23,6 +23,7 @@ | |||
510 | 23 | #include <Nux/Nux.h> | 23 | #include <Nux/Nux.h> |
511 | 24 | #include <X11/Xlib.h> | 24 | #include <X11/Xlib.h> |
512 | 25 | #include <X11/extensions/Xfixes.h> | 25 | #include <X11/extensions/Xfixes.h> |
513 | 26 | #include <X11/extensions/XInput2.h> | ||
514 | 26 | #include <UnityCore/GLibSource.h> | 27 | #include <UnityCore/GLibSource.h> |
515 | 27 | 28 | ||
516 | 28 | namespace unity | 29 | namespace unity |
517 | @@ -88,19 +89,20 @@ | |||
518 | 88 | 89 | ||
519 | 89 | bool IsFirstEvent() const; | 90 | bool IsFirstEvent() const; |
520 | 90 | 91 | ||
521 | 92 | bool OwnsBarrierEvent(PointerBarrier const barrier) const; | ||
522 | 93 | bool HandleBarrierEvent(XIBarrierEvent* barrier_event); | ||
523 | 94 | |||
524 | 91 | protected: | 95 | protected: |
525 | 92 | void EmitCurrentData(int event_id, int x, int y); | 96 | void EmitCurrentData(int event_id, int x, int y); |
526 | 93 | bool HandleEvent(XEvent event); | ||
527 | 94 | 97 | ||
528 | 95 | private: | 98 | private: |
529 | 96 | static bool HandleEventWrapper(XEvent event, void* data); | ||
530 | 97 | |||
531 | 98 | void SendBarrierEvent(int x, int y, int velocity, int event_id); | 99 | void SendBarrierEvent(int x, int y, int velocity, int event_id); |
532 | 99 | 100 | ||
534 | 100 | int event_base_; | 101 | int xi2_opcode_; |
535 | 101 | int last_event_; | 102 | int last_event_; |
536 | 103 | int current_device_; | ||
537 | 102 | bool first_event_; | 104 | bool first_event_; |
539 | 103 | PointerBarrier barrier; | 105 | PointerBarrier barrier_; |
540 | 104 | 106 | ||
541 | 105 | int smoothing_count_; | 107 | int smoothing_count_; |
542 | 106 | int smoothing_accum_; | 108 | int smoothing_accum_; |
543 | 107 | 109 | ||
544 | === modified file 'tests/test_pointer_barrier.cpp' | |||
545 | --- tests/test_pointer_barrier.cpp 2013-02-12 23:48:23 +0000 | |||
546 | +++ tests/test_pointer_barrier.cpp 2013-07-03 16:16:23 +0000 | |||
547 | @@ -15,6 +15,7 @@ | |||
548 | 15 | * <http://www.gnu.org/licenses/> | 15 | * <http://www.gnu.org/licenses/> |
549 | 16 | * | 16 | * |
550 | 17 | * Authored by: Marco Trevisan (Treviño) <marco.trevisan@canonical.com> | 17 | * Authored by: Marco Trevisan (Treviño) <marco.trevisan@canonical.com> |
551 | 18 | * Brandon Schaefer <brandon.schaefer@canonical.com> | ||
552 | 18 | * | 19 | * |
553 | 19 | */ | 20 | */ |
554 | 20 | 21 | ||
555 | @@ -32,20 +33,21 @@ | |||
556 | 32 | class MockPointerBarrier : public PointerBarrierWrapper | 33 | class MockPointerBarrier : public PointerBarrierWrapper |
557 | 33 | { | 34 | { |
558 | 34 | public: | 35 | public: |
560 | 35 | bool HandleEvent(XEvent ev) { return PointerBarrierWrapper::HandleEvent(ev); } | 36 | bool HandleBarrierEvent(XIBarrierEvent* b_ev) { return PointerBarrierWrapper::HandleBarrierEvent(b_ev); } |
561 | 36 | }; | 37 | }; |
562 | 37 | 38 | ||
564 | 38 | XFixesBarrierNotifyEvent GetGenericEvent (unsigned int id) | 39 | XIBarrierEvent GetGenericEvent (unsigned int id) |
565 | 39 | { | 40 | { |
567 | 40 | XFixesBarrierNotifyEvent ev; | 41 | XIBarrierEvent ev; |
568 | 41 | 42 | ||
571 | 42 | ev.type = XFixesBarrierNotify; | 43 | ev.evtype = GenericEvent; |
570 | 43 | ev.subtype = XFixesBarrierHitNotify; | ||
572 | 44 | ev.barrier = 0; | 44 | ev.barrier = 0; |
577 | 45 | ev.event_id = id; | 45 | ev.eventid = id; |
578 | 46 | ev.x = 555; | 46 | ev.root_x = 555; |
579 | 47 | ev.y = 333; | 47 | ev.root_y = 333; |
580 | 48 | ev.velocity = std::numeric_limits<int>::max(); | 48 | ev.dx = 10; |
581 | 49 | ev.dy = 10; | ||
582 | 50 | ev.dtime = 15; | ||
583 | 49 | 51 | ||
584 | 50 | return ev; | 52 | return ev; |
585 | 51 | } | 53 | } |
586 | @@ -70,29 +72,11 @@ | |||
587 | 70 | EXPECT_EQ(bev.event_id, 4); | 72 | EXPECT_EQ(bev.event_id, 4); |
588 | 71 | } | 73 | } |
589 | 72 | 74 | ||
590 | 73 | TEST(TestPointerBarrier, HandleInvalidEvents) | ||
591 | 74 | { | ||
592 | 75 | MockPointerBarrier pb; | ||
593 | 76 | XFixesBarrierNotifyEvent ev; | ||
594 | 77 | auto xev = reinterpret_cast<XEvent*>(&ev); | ||
595 | 78 | |||
596 | 79 | ev.type = XFixesBarrierNotify + 1; | ||
597 | 80 | EXPECT_FALSE(pb.HandleEvent(*xev)); | ||
598 | 81 | |||
599 | 82 | ev.type = XFixesBarrierNotify; | ||
600 | 83 | ev.subtype = XFixesBarrierHitNotify + 1; | ||
601 | 84 | ev.barrier = 1; | ||
602 | 85 | EXPECT_FALSE(pb.HandleEvent(*xev)); | ||
603 | 86 | |||
604 | 87 | ev.barrier = 0; | ||
605 | 88 | EXPECT_TRUE(pb.HandleEvent(*xev)); | ||
606 | 89 | } | ||
607 | 90 | |||
608 | 91 | TEST(TestPointerBarrier, HandleHitNotifyEvents) | 75 | TEST(TestPointerBarrier, HandleHitNotifyEvents) |
609 | 92 | { | 76 | { |
610 | 93 | MockPointerBarrier pb; | 77 | MockPointerBarrier pb; |
613 | 94 | XFixesBarrierNotifyEvent ev = GetGenericEvent(0xdeadbeef); | 78 | pb.threshold = 1000; |
614 | 95 | auto xev = reinterpret_cast<XEvent*>(&ev); | 79 | XIBarrierEvent ev = GetGenericEvent(0xdeadbeef); |
615 | 96 | 80 | ||
616 | 97 | bool got_event = false; | 81 | bool got_event = false; |
617 | 98 | 82 | ||
618 | @@ -102,14 +86,14 @@ | |||
619 | 102 | got_event = true; | 86 | got_event = true; |
620 | 103 | 87 | ||
621 | 104 | EXPECT_EQ(pbw, &pb); | 88 | EXPECT_EQ(pbw, &pb); |
624 | 105 | EXPECT_EQ(bev->x, ev.x); | 89 | EXPECT_EQ(bev->x, ev.root_x); |
625 | 106 | EXPECT_EQ(bev->y, ev.y); | 90 | EXPECT_EQ(bev->y, ev.root_y); |
626 | 107 | EXPECT_EQ(bev->velocity, 600 * pb.max_velocity_multiplier); | 91 | EXPECT_EQ(bev->velocity, 600 * pb.max_velocity_multiplier); |
628 | 108 | EXPECT_EQ(bev->event_id, ev.event_id); | 92 | EXPECT_EQ(bev->event_id, ev.eventid); |
629 | 109 | } | 93 | } |
630 | 110 | }); | 94 | }); |
631 | 111 | 95 | ||
633 | 112 | EXPECT_TRUE(pb.HandleEvent(*xev)); | 96 | EXPECT_TRUE(pb.HandleBarrierEvent(&ev)); |
634 | 113 | EXPECT_FALSE(got_event); | 97 | EXPECT_FALSE(got_event); |
635 | 114 | 98 | ||
636 | 115 | Utils::WaitForTimeoutMSec(pb.smoothing()); | 99 | Utils::WaitForTimeoutMSec(pb.smoothing()); |
637 | @@ -120,30 +104,30 @@ | |||
638 | 120 | TEST(TestPointerBarrier, HandleHitNotifyReleasedEvents) | 104 | TEST(TestPointerBarrier, HandleHitNotifyReleasedEvents) |
639 | 121 | { | 105 | { |
640 | 122 | MockPointerBarrier pb; | 106 | MockPointerBarrier pb; |
643 | 123 | XFixesBarrierNotifyEvent ev = GetGenericEvent(0xabba); | 107 | pb.threshold = 1000; |
644 | 124 | auto xev = reinterpret_cast<XEvent*>(&ev); | 108 | XIBarrierEvent ev = GetGenericEvent(0xabba); |
645 | 125 | bool got_event = false; | 109 | bool got_event = false; |
646 | 126 | 110 | ||
647 | 127 | pb.barrier_event.connect([&] (PointerBarrierWrapper* pbw, BarrierEvent::Ptr bev) { | 111 | pb.barrier_event.connect([&] (PointerBarrierWrapper* pbw, BarrierEvent::Ptr bev) { |
648 | 128 | got_event = true; | 112 | got_event = true; |
649 | 129 | 113 | ||
650 | 130 | EXPECT_EQ(pbw, &pb); | 114 | EXPECT_EQ(pbw, &pb); |
655 | 131 | EXPECT_EQ(bev->x, ev.x); | 115 | EXPECT_EQ(bev->x, ev.root_x); |
656 | 132 | EXPECT_EQ(bev->y, ev.y); | 116 | EXPECT_EQ(bev->y, ev.root_y); |
657 | 133 | EXPECT_EQ(bev->velocity, ev.velocity); | 117 | EXPECT_GT(bev->velocity, 0); |
658 | 134 | EXPECT_EQ(bev->event_id, ev.event_id); | 118 | EXPECT_EQ(bev->event_id, ev.eventid); |
659 | 135 | }); | 119 | }); |
660 | 136 | 120 | ||
661 | 137 | pb.released = true; | 121 | pb.released = true; |
663 | 138 | EXPECT_TRUE(pb.HandleEvent(*xev)); | 122 | EXPECT_TRUE(pb.HandleBarrierEvent(&ev)); |
664 | 139 | EXPECT_TRUE(got_event); | 123 | EXPECT_TRUE(got_event); |
665 | 140 | } | 124 | } |
666 | 141 | 125 | ||
667 | 142 | TEST(TestPointerBarrier, ReciveFirstEvent) | 126 | TEST(TestPointerBarrier, ReciveFirstEvent) |
668 | 143 | { | 127 | { |
669 | 144 | MockPointerBarrier pb; | 128 | MockPointerBarrier pb; |
672 | 145 | XFixesBarrierNotifyEvent ev = GetGenericEvent(0xabba); | 129 | pb.threshold = 1000; |
673 | 146 | auto xev = reinterpret_cast<XEvent*>(&ev); | 130 | XIBarrierEvent ev = GetGenericEvent(0xabba); |
674 | 147 | 131 | ||
675 | 148 | bool first_is_true = false; | 132 | bool first_is_true = false; |
676 | 149 | 133 | ||
677 | @@ -151,15 +135,15 @@ | |||
678 | 151 | first_is_true = true; | 135 | first_is_true = true; |
679 | 152 | }); | 136 | }); |
680 | 153 | 137 | ||
682 | 154 | EXPECT_TRUE(pb.HandleEvent(*xev)); | 138 | EXPECT_TRUE(pb.HandleBarrierEvent(&ev)); |
683 | 155 | EXPECT_TRUE(first_is_true); | 139 | EXPECT_TRUE(first_is_true); |
684 | 156 | } | 140 | } |
685 | 157 | 141 | ||
686 | 158 | TEST(TestPointerBarrier, ReciveSecondEventFirstFalse) | 142 | TEST(TestPointerBarrier, ReciveSecondEventFirstFalse) |
687 | 159 | { | 143 | { |
688 | 160 | MockPointerBarrier pb; | 144 | MockPointerBarrier pb; |
691 | 161 | XFixesBarrierNotifyEvent ev = GetGenericEvent(0xabba); | 145 | pb.threshold = 1000; |
692 | 162 | auto xev = reinterpret_cast<XEvent*>(&ev); | 146 | XIBarrierEvent ev = GetGenericEvent(0xabba); |
693 | 163 | int events_recived = 0; | 147 | int events_recived = 0; |
694 | 164 | 148 | ||
695 | 165 | pb.barrier_event.connect([&] (PointerBarrierWrapper* pbw, BarrierEvent::Ptr bev) { | 149 | pb.barrier_event.connect([&] (PointerBarrierWrapper* pbw, BarrierEvent::Ptr bev) { |
696 | @@ -171,7 +155,7 @@ | |||
697 | 171 | EXPECT_FALSE(pbw->IsFirstEvent()); | 155 | EXPECT_FALSE(pbw->IsFirstEvent()); |
698 | 172 | }); | 156 | }); |
699 | 173 | 157 | ||
701 | 174 | EXPECT_TRUE(pb.HandleEvent(*xev)); | 158 | EXPECT_TRUE(pb.HandleBarrierEvent(&ev)); |
702 | 175 | 159 | ||
703 | 176 | Utils::WaitForTimeoutMSec(pb.smoothing()); | 160 | Utils::WaitForTimeoutMSec(pb.smoothing()); |
704 | 177 | 161 |
trying to build with the old libxfixes it fails on:
"/usr/include/ X11/extensions/ XInput2. h:173:22: error: conflicting declaration ‘typedef unsigned int BarrierEventID’
typedef unsigned int BarrierEventID;
the requirement/ build-depends on that one should probably be bumped as well
works fine otherwise ;-)