reflexion 0.1.22 → 0.1.23

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.doc/ext/reflex/event.cpp +9 -1
  3. data/.doc/ext/reflex/key_event.cpp +3 -3
  4. data/.doc/ext/reflex/native.cpp +2 -0
  5. data/.doc/ext/reflex/pointer.cpp +158 -0
  6. data/.doc/ext/reflex/pointer_event.cpp +29 -88
  7. data/.doc/ext/reflex/selector.cpp +8 -0
  8. data/.doc/ext/reflex/view.cpp +57 -0
  9. data/.doc/ext/reflex/window.cpp +24 -0
  10. data/VERSION +1 -1
  11. data/ext/reflex/event.cpp +11 -2
  12. data/ext/reflex/key_event.cpp +3 -3
  13. data/ext/reflex/native.cpp +2 -0
  14. data/ext/reflex/pointer.cpp +170 -0
  15. data/ext/reflex/pointer_event.cpp +29 -94
  16. data/ext/reflex/selector.cpp +9 -0
  17. data/ext/reflex/view.cpp +67 -3
  18. data/ext/reflex/window.cpp +30 -3
  19. data/include/reflex/defs.h +0 -18
  20. data/include/reflex/event.h +26 -27
  21. data/include/reflex/pointer.h +107 -0
  22. data/include/reflex/ruby/pointer.h +41 -0
  23. data/include/reflex/ruby/view.h +9 -0
  24. data/include/reflex/ruby/window.h +9 -0
  25. data/include/reflex/selector.h +1 -1
  26. data/include/reflex/view.h +6 -4
  27. data/include/reflex/window.h +10 -8
  28. data/lib/reflex/key_event.rb +1 -1
  29. data/lib/reflex/pointer.rb +107 -0
  30. data/lib/reflex/pointer_event.rb +16 -54
  31. data/lib/reflex.rb +1 -0
  32. data/reflex.gemspec +5 -5
  33. data/src/event.cpp +189 -37
  34. data/src/event.h +32 -0
  35. data/src/ios/event.h +15 -3
  36. data/src/ios/event.mm +126 -11
  37. data/src/ios/view_controller.mm +49 -21
  38. data/src/osx/event.h +6 -3
  39. data/src/osx/event.mm +40 -22
  40. data/src/osx/native_window.mm +79 -16
  41. data/src/pointer.cpp +203 -0
  42. data/src/pointer.h +26 -0
  43. data/src/selector.cpp +1 -1
  44. data/src/view.cpp +83 -72
  45. data/src/view.h +0 -4
  46. data/src/window.cpp +321 -97
  47. data/src/window.h +22 -3
  48. data/test/test_event.rb +16 -2
  49. data/test/test_pointer.rb +149 -0
  50. data/test/test_pointer_event.rb +70 -104
  51. data/test/test_selector.rb +7 -0
  52. data/test/test_view.rb +38 -11
  53. data/test/test_window.rb +27 -25
  54. metadata +46 -35
data/src/window.cpp CHANGED
@@ -1,14 +1,25 @@
1
1
  #include "window.h"
2
2
 
3
3
 
4
+ #include <set>
4
5
  #include "reflex/exception.h"
5
6
  #include "view.h"
7
+ #include "event.h"
6
8
 
7
9
 
8
10
  namespace Reflex
9
11
  {
10
12
 
11
13
 
14
+ using ViewList = std::vector<View::Ref>;
15
+
16
+ using PointerMap = std::map<Pointer::ID, Pointer>;
17
+
18
+ using ExtractedPointerIDSet = std::set<Pointer::ID>;
19
+
20
+ using CaptureTargetIDList = Window::Data::CaptureTargetIDList;
21
+
22
+
12
23
  void
13
24
  Window_set_focus (Window* window, View* view)
14
25
  {
@@ -36,6 +47,80 @@ namespace Reflex
36
47
  }
37
48
  }
38
49
 
50
+ namespace global
51
+ {
52
+
53
+ static Window_CreateRootViewFun create_root_view_fun = NULL;
54
+
55
+ }// global
56
+
57
+ void
58
+ Window_set_create_root_view_fun (Window_CreateRootViewFun fun)
59
+ {
60
+ global::create_root_view_fun = fun;
61
+ }
62
+
63
+ static View*
64
+ create_root_view ()
65
+ {
66
+ return global::create_root_view_fun
67
+ ? global::create_root_view_fun()
68
+ : new View();
69
+ }
70
+
71
+ void
72
+ Window_register_capture (Window* window, View* view, Pointer::ID target)
73
+ {
74
+ assert(window);
75
+
76
+ if (!view)
77
+ argument_error(__FILE__, __LINE__);
78
+
79
+ if (view->window() != window)
80
+ invalid_state_error(__FILE__, __LINE__);
81
+
82
+ if (target < 0) return;
83
+
84
+ auto& targets = window->self->captures[view];
85
+ if (std::find(targets.begin(), targets.end(), target) != targets.end())
86
+ return;
87
+
88
+ targets.insert(
89
+ target == CAPTURE_ALL ? targets.begin() : targets.end(),
90
+ target);
91
+ }
92
+
93
+ void
94
+ Window_unregister_capture (Window* window, View* view, Pointer::ID target)
95
+ {
96
+ assert(window);
97
+
98
+ if (!view)
99
+ argument_error(__FILE__, __LINE__);
100
+
101
+ auto captures_it = window->self->captures.find(view);
102
+ if (captures_it == window->self->captures.end()) return;
103
+
104
+ auto& targets = captures_it->second;
105
+ auto targets_it = std::find(targets.begin(), targets.end(), target);
106
+ if (targets_it == targets.end()) return;
107
+
108
+ targets.erase(targets_it);
109
+ }
110
+
111
+ static void
112
+ cleanup_captures (Window* window)
113
+ {
114
+ assert(window);
115
+
116
+ auto& caps = window->self->captures;
117
+ for (auto it = caps.begin(), end = caps.end(); it != end;)
118
+ {
119
+ auto t = it++;
120
+ if (t->second.empty()) caps.erase(t);
121
+ }
122
+ }
123
+
39
124
  void
40
125
  Window_call_draw_event (Window* window, DrawEvent* event)
41
126
  {
@@ -63,66 +148,252 @@ namespace Reflex
63
148
  painter->end();
64
149
  }
65
150
 
66
- namespace global
151
+ static bool
152
+ is_capturing (
153
+ const View* view, const CaptureTargetIDList& targets, View::Capture type)
67
154
  {
155
+ return
156
+ !targets.empty() &&
157
+ targets[0] == CAPTURE_ALL &&
158
+ (view->capture() & type) == type;
159
+ }
68
160
 
69
- static Window_CreateRootViewFun create_root_view_fun = NULL;
161
+ void
162
+ Window_call_key_event (Window* window, KeyEvent* event)
163
+ {
164
+ assert(window);
70
165
 
71
- }// global
166
+ if (!event)
167
+ argument_error(__FILE__, __LINE__);
72
168
 
73
- void
74
- Window_set_create_root_view_fun (Window_CreateRootViewFun fun)
169
+ window->on_key(event);
170
+
171
+ switch (event->type)
172
+ {
173
+ case KeyEvent::DOWN: window->on_key_down(event); break;
174
+ case KeyEvent::UP: window->on_key_up(event); break;
175
+ default: break;
176
+ }
177
+
178
+ for (auto& [view, targets] : window->self->captures)
179
+ {
180
+ if (!is_capturing(view.get(), targets, View::CAPTURE_KEY))
181
+ continue;
182
+
183
+ KeyEvent e = *event;
184
+ e.captured = true;
185
+ View_call_key_event(const_cast<View*>(view.get()), e);
186
+ }
187
+
188
+ if (window->self->focus)
189
+ View_call_key_event(window->self->focus.get(), *event);
190
+
191
+ cleanup_captures(window);
192
+ }
193
+
194
+ static void
195
+ get_views_capturing_all_pointers (Window* window, ViewList* result)
75
196
  {
76
- global::create_root_view_fun = fun;
197
+ assert(window && result);
198
+
199
+ result->clear();
200
+ for (const auto& [view, targets] : window->self->captures)
201
+ {
202
+ if (is_capturing(view.get(), targets, View::CAPTURE_POINTER))
203
+ result->emplace_back(view);
204
+ }
77
205
  }
78
206
 
79
- static View*
80
- create_root_view ()
207
+ static void
208
+ capture_all_pointers (
209
+ Window* window, const PointerEvent& event, ViewList& views_capturing_all)
81
210
  {
82
- return global::create_root_view_fun
83
- ? global::create_root_view_fun()
84
- : new View();
211
+ assert(window);
212
+
213
+ if (views_capturing_all.empty()) return;
214
+
215
+ PointerEvent_each_pointer(&event, [&](const auto& pointer)
216
+ {
217
+ if (pointer.action() == Pointer::DOWN)
218
+ {
219
+ for (auto& view : views_capturing_all)
220
+ Window_register_capture(window, view, pointer.id());
221
+ }
222
+ });
85
223
  }
86
224
 
87
- void
88
- View_register_capture (View* view)
225
+ static void
226
+ extract_pointer (
227
+ PointerEvent* event, ExtractedPointerIDSet* extracteds,
228
+ const Pointer& pointer)
89
229
  {
90
- if (!view)
91
- argument_error(__FILE__, __LINE__);
230
+ assert(event && extracteds);
231
+
232
+ PointerEvent_add_pointer(event, pointer);
233
+ extracteds->insert(pointer.id());
234
+ }
92
235
 
93
- const Window* window = view->window();
94
- if (!window)
95
- invalid_state_error(__FILE__, __LINE__, "this view does not belong to any Window.");
236
+ static void
237
+ extract_targeted_pointers (
238
+ PointerEvent* event, ExtractedPointerIDSet* extracteds,
239
+ const CaptureTargetIDList& targets, const PointerMap& pointers)
240
+ {
241
+ assert(event && event->empty() && extracteds);
96
242
 
97
- window->self->capturing_views[view] = true;
243
+ for (auto pointer_id : targets)
244
+ {
245
+ auto it = pointers.find(pointer_id);
246
+ if (it != pointers.end())
247
+ extract_pointer(event, extracteds, it->second);
248
+ }
98
249
  }
99
250
 
100
- void
101
- View_unregister_capture (View* view)
251
+ static void
252
+ capture_targeted_pointers_and_call_events (
253
+ ExtractedPointerIDSet* extracteds,
254
+ Window* window, const PointerMap& pointers)
102
255
  {
103
- if (!view)
104
- argument_error(__FILE__, __LINE__);
256
+ assert(extracteds && window);
105
257
 
106
- const Window* window = view->window();
107
- if (!window) return;
258
+ for (auto& [view, targets] : window->self->captures)
259
+ {
260
+ if (targets.empty()) continue;
108
261
 
109
- auto it = window->self->capturing_views.find(view);
110
- if (it == window->self->capturing_views.end()) return;
262
+ PointerEvent e(true);
263
+ extract_targeted_pointers(&e, extracteds, targets, pointers);
264
+ if (e.empty()) continue;
111
265
 
112
- it->second = false;
266
+ PointerEvent_update_for_capturing_view(&e, view);
267
+ View_call_pointer_event(const_cast<View*>(view.get()), e);
268
+ }
113
269
  }
114
270
 
115
271
  static void
116
- cleanup_capturing_views (Window* window)
272
+ extract_hovering_pointers (
273
+ PointerEvent* event, ExtractedPointerIDSet* extracteds,
274
+ const PointerMap& pointers)
117
275
  {
118
- auto end = window->self->capturing_views.end();
119
- for (auto it = window->self->capturing_views.begin(); it != end;)
276
+ assert(event && event->empty() && extracteds);
277
+
278
+ for (const auto& [_, pointer] : pointers)
120
279
  {
121
- auto t = it++;
122
- if (!t->second) window->self->capturing_views.erase(t);
280
+ // dragging pointers is captured as a targeted
281
+ if (pointer.is_drag()) continue;
282
+
283
+ extract_pointer(event, extracteds, pointer);
284
+ }
285
+ }
286
+
287
+ static void
288
+ capture_hovering_pointers_and_call_events (
289
+ ExtractedPointerIDSet* extracteds,
290
+ const ViewList& views_capturing_all, const PointerMap& pointers)
291
+ {
292
+ assert(extracteds);
293
+
294
+ if (views_capturing_all.empty()) return;
295
+
296
+ PointerEvent event(true);
297
+ extract_hovering_pointers(&event, extracteds, pointers);
298
+ if (event.empty()) return;
299
+
300
+ for (auto& view : views_capturing_all)
301
+ {
302
+ PointerEvent e = event;
303
+ PointerEvent_update_for_capturing_view(&e, view);
304
+ View_call_pointer_event(const_cast<View*>(view.get()), e);
123
305
  }
124
306
  }
125
307
 
308
+ static void
309
+ erase_extracted_pointers (
310
+ PointerMap* pointers, const ExtractedPointerIDSet& extracteds)
311
+ {
312
+ assert(pointers);
313
+
314
+ for (auto id : extracteds)
315
+ {
316
+ auto it = pointers->find(id);
317
+ if (it != pointers->end()) pointers->erase(it);
318
+ }
319
+ }
320
+
321
+ static void
322
+ erase_extracted_pointers (
323
+ PointerEvent* event, const ExtractedPointerIDSet& extracteds)
324
+ {
325
+ assert(event);
326
+
327
+ for (auto id : extracteds)
328
+ PointerEvent_erase_pointer(event, id);
329
+ }
330
+
331
+ static void
332
+ call_captured_pointer_events (Window* window, PointerEvent* event)
333
+ {
334
+ assert(window && event);
335
+
336
+ ViewList views_capturing_all;
337
+ get_views_capturing_all_pointers(window, &views_capturing_all);
338
+ capture_all_pointers(window, *event, views_capturing_all);
339
+
340
+ PointerMap pointers;
341
+ PointerEvent_each_pointer(event, [&](const auto& pointer)
342
+ {
343
+ if (pointer.id() >= 0) pointers[pointer.id()] = pointer;
344
+ });
345
+
346
+ ExtractedPointerIDSet extracteds;
347
+ capture_targeted_pointers_and_call_events(&extracteds, window, pointers);
348
+ erase_extracted_pointers(&pointers, extracteds);
349
+
350
+ capture_hovering_pointers_and_call_events(&extracteds, views_capturing_all, pointers);
351
+ erase_extracted_pointers(event, extracteds);
352
+ }
353
+
354
+ void
355
+ Window_call_pointer_event (Window* window, PointerEvent* event)
356
+ {
357
+ assert(window);
358
+
359
+ if (!event)
360
+ argument_error(__FILE__, __LINE__);
361
+
362
+ window->on_pointer(event);
363
+
364
+ switch ((*event)[0].action())
365
+ {
366
+ case Pointer::DOWN: window->on_pointer_down(event); break;
367
+ case Pointer::UP: window->on_pointer_up(event); break;
368
+ case Pointer::MOVE: window->on_pointer_move(event); break;
369
+ case Pointer::CANCEL: window->on_pointer_cancel(event); break;
370
+ default: break;
371
+ }
372
+
373
+ call_captured_pointer_events(window, event);
374
+
375
+ if (!event->empty())
376
+ {
377
+ PointerEvent_update_for_child_view(event, window->root());
378
+ View_call_pointer_event(window->root(), *event);
379
+ }
380
+
381
+ cleanup_captures(window);
382
+ }
383
+
384
+ void
385
+ Window_call_wheel_event (Window* window, WheelEvent* event)
386
+ {
387
+ assert(window);
388
+
389
+ if (!event)
390
+ argument_error(__FILE__, __LINE__);
391
+
392
+ window->on_wheel(event);
393
+
394
+ View_call_wheel_event(window->root(), *event);
395
+ }
396
+
126
397
 
127
398
  Window::Window ()
128
399
  : self(Window_create_data())
@@ -191,6 +462,18 @@ namespace Reflex
191
462
  self->redraw = true;
192
463
  }
193
464
 
465
+ Point
466
+ Window::from_screen (const Point& point) const
467
+ {
468
+ return point - frame().position();
469
+ }
470
+
471
+ Point
472
+ Window::to_screen (const Point& point) const
473
+ {
474
+ return point + frame().position();
475
+ }
476
+
194
477
  void
195
478
  Window::set_title (const char* title)
196
479
  {
@@ -275,20 +558,6 @@ namespace Reflex
275
558
  return const_cast<Window*>(this)->painter();
276
559
  }
277
560
 
278
- Point
279
- Window::from_screen (const Point& point) const
280
- {
281
- not_implemented_error(__FILE__, __LINE__);
282
- return 0;
283
- }
284
-
285
- Point
286
- Window::to_screen (const Point& point) const
287
- {
288
- not_implemented_error(__FILE__, __LINE__);
289
- return 0;
290
- }
291
-
292
561
  void
293
562
  Window::on_show (Event* e)
294
563
  {
@@ -327,28 +596,6 @@ namespace Reflex
327
596
  void
328
597
  Window::on_key (KeyEvent* e)
329
598
  {
330
- if (!e)
331
- argument_error(__FILE__, __LINE__);
332
-
333
- switch (e->type)
334
- {
335
- case KeyEvent::DOWN: on_key_down(e); break;
336
- case KeyEvent::UP: on_key_up(e); break;
337
- case KeyEvent::NONE: break;
338
- }
339
-
340
- auto end = self->capturing_views.end();
341
- for (auto it = self->capturing_views.begin(); it != end; ++it)
342
- {
343
- KeyEvent event = *e;
344
- event.capture = true;
345
- View_call_key_event(const_cast<View*>(it->first.get()), event);
346
- }
347
-
348
- if (self->focus)
349
- View_call_key_event(self->focus.get(), *e);
350
-
351
- cleanup_capturing_views(this);
352
599
  }
353
600
 
354
601
  void
@@ -364,30 +611,6 @@ namespace Reflex
364
611
  void
365
612
  Window::on_pointer (PointerEvent* e)
366
613
  {
367
- if (!e)
368
- argument_error(__FILE__, __LINE__);
369
-
370
- switch (e->type)
371
- {
372
- case PointerEvent::DOWN: on_pointer_down(e); break;
373
- case PointerEvent::UP: on_pointer_up(e); break;
374
- case PointerEvent::MOVE: on_pointer_move(e); break;
375
- case PointerEvent::NONE: break;
376
- }
377
-
378
- auto end = self->capturing_views.end();
379
- for (auto it = self->capturing_views.begin(); it != end; ++it)
380
- {
381
- PointerEvent event = *e;
382
- event.capture = true;
383
- for (size_t i = 0; i < event.size; ++i)
384
- event[i] = it->first.get()->from_window(event[i]);
385
- View_call_pointer_event(const_cast<View*>(it->first.get()), event);
386
- }
387
-
388
- View_call_pointer_event(root(), *e);
389
-
390
- cleanup_capturing_views(this);
391
614
  }
392
615
 
393
616
  void
@@ -406,12 +629,13 @@ namespace Reflex
406
629
  }
407
630
 
408
631
  void
409
- Window::on_wheel (WheelEvent* e)
632
+ Window::on_pointer_cancel (PointerEvent* e)
410
633
  {
411
- if (!e)
412
- argument_error(__FILE__, __LINE__);
634
+ }
413
635
 
414
- View_call_wheel_event(root(), *e);
636
+ void
637
+ Window::on_wheel (WheelEvent* e)
638
+ {
415
639
  }
416
640
 
417
641
  Window::operator bool () const
data/src/window.h CHANGED
@@ -4,22 +4,29 @@
4
4
  #define __REFLEX_SRC_WINDOW_H__
5
5
 
6
6
 
7
+ #include <vector>
7
8
  #include <map>
8
9
  #include <xot/time.h>
9
10
  #include <rays/point.h>
10
11
  #include <rays/painter.h>
11
12
  #include <reflex/window.h>
12
13
  #include <reflex/view.h>
14
+ #include "pointer.h"
13
15
 
14
16
 
15
17
  namespace Reflex
16
18
  {
17
19
 
18
20
 
21
+ enum {CAPTURE_ALL = INT_MAX};
22
+
23
+
19
24
  struct Window::Data
20
25
  {
21
26
 
22
- typedef std::map<View::Ref, bool> CapturingViews;
27
+ typedef std::vector<Pointer::ID> CaptureTargetIDList;
28
+
29
+ typedef std::map<View::Ref, CaptureTargetIDList> CaptureMap;
23
30
 
24
31
  int hide_count = 1;
25
32
 
@@ -33,7 +40,7 @@ namespace Reflex
33
40
 
34
41
  double prev_time_update, prev_time_draw, prev_fps = 0;
35
42
 
36
- CapturingViews capturing_views;
43
+ CaptureMap captures;
37
44
 
38
45
  Data ()
39
46
  {
@@ -84,7 +91,19 @@ namespace Reflex
84
91
 
85
92
  void Window_set_focus (Window* window, View* view);
86
93
 
87
- void Window_call_draw_event (Window* window, DrawEvent* event);
94
+ void Window_register_capture (
95
+ Window* window, View* view, Pointer::ID target = CAPTURE_ALL);
96
+
97
+ void Window_unregister_capture (
98
+ Window* window, View* view, Pointer::ID target = CAPTURE_ALL);
99
+
100
+ void Window_call_draw_event (Window* window, DrawEvent* event);
101
+
102
+ void Window_call_key_event (Window* window, KeyEvent* event);
103
+
104
+ void Window_call_pointer_event (Window* window, PointerEvent* event);
105
+
106
+ void Window_call_wheel_event (Window* window, WheelEvent* event);
88
107
 
89
108
  float Window_get_pixel_density (const Window& window);
90
109
 
data/test/test_event.rb CHANGED
@@ -10,11 +10,25 @@ class TestEvent < Test::Unit::TestCase
10
10
  Reflex::Event.new
11
11
  end
12
12
 
13
+ def test_dup()
14
+ e1 = event
15
+ e2 = e1.dup
16
+ e1.block
17
+ e3 = e1.dup
18
+ assert_equal true, e1.blocked?
19
+ assert_equal false, e2.blocked?
20
+ assert_equal true, e3.blocked?
21
+ end
22
+
13
23
  def test_block()
14
24
  e = event
15
- assert_equal false, e.block?
25
+ assert_equal false, e.blocked?
16
26
  e.block
17
- assert_equal true, e.block?
27
+ assert_equal true, e.blocked?
28
+ end
29
+
30
+ def test_time()
31
+ assert_in_delta Time.now.to_f, event.time, 0.001
18
32
  end
19
33
 
20
34
  end# TestEvent