Nux

Merge lp:~3v1n0/nux/emit-mouse-leave-on-new-over-area into lp:nux

Proposed by Marco Trevisan (Treviño)
Status: Merged
Approved by: Andrea Azzarone
Approved revision: 872
Merged at revision: 867
Proposed branch: lp:~3v1n0/nux/emit-mouse-leave-on-new-over-area
Merge into: lp:nux
Diff against target: 254 lines (+158/-29)
2 files modified
Nux/WindowCompositor.cpp (+37/-13)
tests/gtest-nux-windowcompositor.cpp (+121/-16)
To merge this branch: bzr merge lp:~3v1n0/nux/emit-mouse-leave-on-new-over-area
Reviewer Review Type Date Requested Status
Andrea Azzarone (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+271218@code.launchpad.net

Commit message

WindowCompositor: emit mouse_leave signal when releasing mouse over a new area

When the mouse button is released we update the mouse over area, but we also need
to signal the old mouse over area that mouse is not hovering it anymore.
Otherwise IsMouseInside will still be true for that (sicne it caches this value).

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Andrea Azzarone (azzar1) wrote :

LGTM

review: Approve
873. By Marco Trevisan (Treviño)

WindowCompositor: ensure that we don't access to an invalid area

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Nux/WindowCompositor.cpp'
2--- Nux/WindowCompositor.cpp 2014-10-03 22:52:46 +0000
3+++ Nux/WindowCompositor.cpp 2015-09-17 18:03:27 +0000
4@@ -245,9 +245,13 @@
5 if (mouse_owner_area_ == area)
6 return;
7
8+ auto* old_owner = mouse_owner_area_.GetPointer();
9 mouse_owner_area_ = area;
10 dnd_safety_x_ = 0;
11 dnd_safety_y_ = 0;
12+
13+ if (old_owner)
14+ old_owner->EmitMouseCancelSignal();
15 }
16
17 ObjectWeakPtr<InputArea> const& WindowCompositor::GetMouseOwnerArea() const
18@@ -520,7 +524,26 @@
19 }
20 else if (event.type == NUX_MOUSE_RELEASED)
21 {
22- mouse_over_area_ = new_area_under_mouse;
23+ if (new_area_under_mouse != mouse_over_area_)
24+ {
25+ if (mouse_over_area_ == mouse_owner_area_)
26+ {
27+ mouse_owner_area_->EmitMouseLeaveSignal(mouse_owner_x, mouse_owner_y,
28+ event.GetMouseState(),
29+ event.GetKeyState());
30+ }
31+
32+ mouse_over_area_ = new_area_under_mouse;
33+
34+ if (mouse_over_area_.IsValid())
35+ {
36+ auto const& over_geo = mouse_over_area_->GetAbsoluteGeometry();
37+ mouse_over_area_->EmitMouseEnterSignal(event.x - over_geo.x,
38+ event.y - over_geo.y,
39+ event.GetMouseState(),
40+ event.GetKeyState());
41+ }
42+ }
43 }
44 }
45
46@@ -614,20 +637,21 @@
47 Geometry const& mouse_owner_geo = mouse_owner_area_->GetAbsoluteGeometry();
48 int mouse_owner_x = event.x - mouse_owner_geo.x;
49 int mouse_owner_y = event.y - mouse_owner_geo.y;
50-
51- mouse_owner_area_->EmitMouseUpSignal(mouse_owner_x, mouse_owner_y,
52- event.GetMouseState(),
53- event.GetKeyState());
54-
55- if (mouse_owner_area_.IsValid() && mouse_over_area_ == mouse_owner_area_ &&
56- (!mouse_over_area_->DoubleClickEnabled() || (event.mouse_state & NUX_STATE_FIRST_EVENT) != 0))
57- {
58- mouse_owner_area_->EmitMouseClickSignal(mouse_owner_x, mouse_owner_y,
59- event.GetMouseState(),
60- event.GetKeyState());
61- }
62+ auto* old_mouse_owner_area = mouse_owner_area_.GetPointer();
63
64 SetMouseOwnerArea(NULL);
65+
66+ old_mouse_owner_area->EmitMouseUpSignal(mouse_owner_x, mouse_owner_y,
67+ event.GetMouseState(),
68+ event.GetKeyState());
69+
70+ if (mouse_over_area_ == old_mouse_owner_area &&
71+ (!mouse_over_area_->DoubleClickEnabled() || (event.mouse_state & NUX_STATE_FIRST_EVENT) != 0))
72+ {
73+ old_mouse_owner_area->EmitMouseClickSignal(mouse_owner_x, mouse_owner_y,
74+ event.GetMouseState(),
75+ event.GetKeyState());
76+ }
77 }
78 }
79 }
80
81=== modified file 'tests/gtest-nux-windowcompositor.cpp'
82--- tests/gtest-nux-windowcompositor.cpp 2013-10-31 01:10:43 +0000
83+++ tests/gtest-nux-windowcompositor.cpp 2015-09-17 18:03:27 +0000
84@@ -686,6 +686,111 @@
85 EXPECT_EQ(area.GetPointer(), nullptr);
86 }
87
88+TEST_F(TestWindowCompositor, UpdateInputAreaMouseInsideOnRelease)
89+{
90+ Event ev;
91+ ObjectPtr<TestBaseWindow> ia1(new TestBaseWindow());
92+
93+ ev.type = EVENT_MOUSE_DOWN;
94+ nux::GetWindowCompositor().ProcessEvent(ev);
95+
96+ ASSERT_TRUE(ia1->input_area->IsMouseInside());
97+ ASSERT_TRUE(ia1->input_area->IsMouseOwner());
98+
99+ ObjectPtr<TestBaseWindow> ia2(new TestBaseWindow());
100+ ev.type = EVENT_MOUSE_UP;
101+ nux::GetWindowCompositor().ProcessEvent(ev);
102+
103+ EXPECT_FALSE(ia1->input_area->IsMouseOwner());
104+ EXPECT_FALSE(ia1->input_area->IsMouseInside());
105+ EXPECT_NE(GetMouseOverArea(), ia1->input_area.GetPointer());
106+}
107+
108+TEST_F(TestWindowCompositor, UpdateNewInputAreaMouseInsideOnRelease)
109+{
110+ Event ev;
111+ ObjectPtr<TestBaseWindow> ia1(new TestBaseWindow());
112+
113+ ev.type = EVENT_MOUSE_DOWN;
114+ nux::GetWindowCompositor().ProcessEvent(ev);
115+
116+ ASSERT_TRUE(ia1->input_area->IsMouseInside());
117+ ASSERT_TRUE(ia1->input_area->IsMouseOwner());
118+
119+ ObjectPtr<TestBaseWindow> ia2(new TestBaseWindow());
120+ ev.type = EVENT_MOUSE_UP;
121+ nux::GetWindowCompositor().ProcessEvent(ev);
122+
123+ EXPECT_FALSE(ia2->input_area->IsMouseOwner());
124+ EXPECT_TRUE(ia2->input_area->IsMouseInside());
125+ EXPECT_EQ(GetMouseOverArea(), ia2->input_area.GetPointer());
126+}
127+
128+TEST_F(TestWindowCompositor, UpdateNewInputAreaMouseOwnerBeforeSignalEmission)
129+{
130+ Event ev;
131+ ObjectPtr<TestBaseWindow> ia1(new TestBaseWindow());
132+
133+ ev.type = EVENT_MOUSE_DOWN;
134+ nux::GetWindowCompositor().ProcessEvent(ev);
135+ ASSERT_TRUE(ia1->input_area->IsMouseInside());
136+ ASSERT_TRUE(ia1->input_area->IsMouseOwner());
137+
138+ bool got_cb = false;
139+ ia1->input_area->mouse_up.connect([this, &ia1, &got_cb] (int, int, unsigned long, unsigned long) {
140+ got_cb = true;
141+ EXPECT_TRUE(ia1->input_area->IsMouseInside());
142+ EXPECT_FALSE(ia1->input_area->IsMouseOwner());
143+ });
144+
145+ ev.type = EVENT_MOUSE_UP;
146+ nux::GetWindowCompositor().ProcessEvent(ev);
147+
148+ ASSERT_TRUE(got_cb);
149+ EXPECT_TRUE(ia1->input_area->IsMouseInside());
150+ EXPECT_FALSE(ia1->input_area->IsMouseOwner());
151+ EXPECT_EQ(GetMouseOverArea(), ia1->input_area.GetPointer());
152+}
153+
154+TEST_F(TestWindowCompositor, InvalidMouseOverAreaOnReleaseDontCrash)
155+{
156+ Event ev;
157+ ObjectPtr<TestBaseWindow> ia1(new TestBaseWindow());
158+
159+ ev.type = EVENT_MOUSE_DOWN;
160+ nux::GetWindowCompositor().ProcessEvent(ev);
161+ ASSERT_TRUE(ia1->input_area->IsMouseInside());
162+ ASSERT_TRUE(ia1->input_area->IsMouseOwner());
163+
164+ // We save a copy of the input area, so that WC still things it's alive but
165+ // the test window won't return it as the target area for events.
166+ auto old_mouse_owner_area = ia1->input_area; (void)old_mouse_owner_area;
167+ ia1->input_area.Release();
168+
169+ ev.type = EVENT_MOUSE_UP;
170+ nux::GetWindowCompositor().ProcessEvent(ev);
171+}
172+
173+TEST_F(TestWindowCompositor, EmitMouseCancelOnReleasedMouseOwner)
174+{
175+ Event ev;
176+ ObjectPtr<TestBaseWindow> ia1(new TestBaseWindow());
177+
178+ ev.type = EVENT_MOUSE_DOWN;
179+ nux::GetWindowCompositor().ProcessEvent(ev);
180+ ASSERT_TRUE(ia1->input_area->IsMouseOwner());
181+
182+ bool mouse_cancel_called = false;
183+ ia1->input_area->mouse_cancel.connect([this, &mouse_cancel_called] {
184+ mouse_cancel_called = true;
185+ });
186+
187+ ev.type = EVENT_MOUSE_UP;
188+ nux::GetWindowCompositor().ProcessEvent(ev);
189+
190+ EXPECT_TRUE(mouse_cancel_called);
191+}
192+
193 class DraggedWindow : public nux::BaseWindow
194 {
195 public:
196@@ -770,17 +875,17 @@
197 bool wants_mouse_ownership;
198
199 protected:
200- virtual void EmitMouseUpSignal(int x, int y,
201- unsigned long mouse_button_state,
202- unsigned long special_keys_state)
203+ virtual void EmitMouseUpSignal(int, int,
204+ unsigned long,
205+ unsigned long)
206 {
207 ++mouse_up_emission_count;
208 }
209
210- virtual void EmitMouseDragSignal(int x, int y,
211+ virtual void EmitMouseDragSignal(int, int,
212 int dx, int dy,
213- unsigned long mouse_button_state,
214- unsigned long special_keys_state)
215+ unsigned long,
216+ unsigned long)
217 {
218 ++mouse_drag_emission_count;
219 mouse_drag_dx = dx;
220@@ -804,24 +909,24 @@
221 {}
222
223 protected:
224- virtual void EmitMouseDownSignal(int x, int y,
225- unsigned long mouse_button_state,
226- unsigned long special_keys_state)
227+ virtual void EmitMouseDownSignal(int, int,
228+ unsigned long,
229+ unsigned long)
230 {
231 ++mouse_down_emission_count;
232 }
233
234- virtual void EmitMouseUpSignal(int x, int y,
235- unsigned long mouse_button_state,
236- unsigned long special_keys_state)
237+ virtual void EmitMouseUpSignal(int, int,
238+ unsigned long,
239+ unsigned long)
240 {
241 ++mouse_up_emission_count;
242 }
243
244- virtual void EmitMouseDragSignal(int x, int y,
245- int dx, int dy,
246- unsigned long mouse_button_state,
247- unsigned long special_keys_state)
248+ virtual void EmitMouseDragSignal(int, int,
249+ int, int,
250+ unsigned long,
251+ unsigned long)
252 {
253 ++mouse_drag_emission_count;
254 }

Subscribers

People subscribed via source and target branches