reflexion 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.doc/ext/reflex/application.cpp +37 -6
- data/.doc/ext/reflex/capture_event.cpp +1 -1
- data/.doc/ext/reflex/chase_constraint.cpp +1 -1
- data/.doc/ext/reflex/clipboard.cpp +1 -1
- data/.doc/ext/reflex/color_event.cpp +76 -0
- data/.doc/ext/reflex/color_picker.cpp +113 -0
- data/.doc/ext/reflex/constraint.cpp +1 -1
- data/.doc/ext/reflex/contact_event.cpp +1 -1
- data/.doc/ext/reflex/control_change_event.cpp +1 -1
- data/.doc/ext/reflex/device.cpp +1 -1
- data/.doc/ext/reflex/device_event.cpp +1 -1
- data/.doc/ext/reflex/draw_event.cpp +1 -1
- data/.doc/ext/reflex/ellipse_shape.cpp +1 -1
- data/.doc/ext/reflex/event.cpp +1 -1
- data/.doc/ext/reflex/file_dialog.cpp +181 -0
- data/.doc/ext/reflex/file_event.cpp +103 -0
- data/.doc/ext/reflex/filter.cpp +1 -1
- data/.doc/ext/reflex/focus_event.cpp +1 -1
- data/.doc/ext/reflex/frame_event.cpp +1 -1
- data/.doc/ext/reflex/gamepad.cpp +48 -0
- data/.doc/ext/reflex/image_view.cpp +1 -1
- data/.doc/ext/reflex/key_event.cpp +1 -274
- data/.doc/ext/reflex/line_shape.cpp +1 -1
- data/.doc/ext/reflex/link_constraint.cpp +1 -1
- data/.doc/ext/reflex/menu.cpp +6 -5
- data/.doc/ext/reflex/midi.cpp +9 -2
- data/.doc/ext/reflex/midi_event.cpp +1 -1
- data/.doc/ext/reflex/motion_event.cpp +1 -1
- data/.doc/ext/reflex/native.cpp +18 -6
- data/.doc/ext/reflex/note_event.cpp +1 -1
- data/.doc/ext/reflex/pin.cpp +1 -1
- data/.doc/ext/reflex/pointer.cpp +1 -1
- data/.doc/ext/reflex/pointer_event.cpp +2 -2
- data/.doc/ext/reflex/polygon_shape.cpp +1 -1
- data/.doc/ext/reflex/rect_shape.cpp +1 -1
- data/.doc/ext/reflex/reflex.cpp +566 -232
- data/.doc/ext/reflex/screen.cpp +27 -1
- data/.doc/ext/reflex/scroll_event.cpp +1 -1
- data/.doc/ext/reflex/selector.cpp +1 -1
- data/.doc/ext/reflex/shape.cpp +1 -1
- data/.doc/ext/reflex/snap_constraint.cpp +1 -1
- data/.doc/ext/reflex/style.cpp +1 -1
- data/.doc/ext/reflex/style_length.cpp +1 -1
- data/.doc/ext/reflex/text_event.cpp +104 -0
- data/.doc/ext/reflex/timer.cpp +1 -1
- data/.doc/ext/reflex/timer_event.cpp +1 -1
- data/.doc/ext/reflex/update_event.cpp +1 -1
- data/.doc/ext/reflex/view.cpp +110 -56
- data/.doc/ext/reflex/wheel_constraint.cpp +1 -1
- data/.doc/ext/reflex/wheel_event.cpp +1 -1
- data/.doc/ext/reflex/window.cpp +226 -17
- data/.github/workflows/release-gem.yml +2 -49
- data/.github/workflows/tag.yml +5 -28
- data/.github/workflows/test.yml +1 -37
- data/ChangeLog.md +54 -0
- data/Gemfile.lock +13 -8
- data/Rakefile +13 -2
- data/Reflex.podspec +2 -2
- data/VERSION +1 -1
- data/ext/reflex/application.cpp +41 -6
- data/ext/reflex/capture_event.cpp +1 -1
- data/ext/reflex/chase_constraint.cpp +1 -1
- data/ext/reflex/clipboard.cpp +1 -1
- data/ext/reflex/color_event.cpp +80 -0
- data/ext/reflex/color_picker.cpp +121 -0
- data/ext/reflex/constraint.cpp +1 -1
- data/ext/reflex/contact_event.cpp +1 -1
- data/ext/reflex/control_change_event.cpp +1 -1
- data/ext/reflex/device.cpp +1 -1
- data/ext/reflex/device_event.cpp +1 -1
- data/ext/reflex/draw_event.cpp +1 -1
- data/ext/reflex/ellipse_shape.cpp +1 -1
- data/ext/reflex/event.cpp +1 -1
- data/ext/reflex/extconf.rb +4 -2
- data/ext/reflex/file_dialog.cpp +194 -0
- data/ext/reflex/file_event.cpp +108 -0
- data/ext/reflex/filter.cpp +1 -1
- data/ext/reflex/focus_event.cpp +1 -1
- data/ext/reflex/frame_event.cpp +1 -1
- data/ext/reflex/gamepad.cpp +50 -0
- data/ext/reflex/image_view.cpp +1 -1
- data/ext/reflex/key_event.cpp +1 -275
- data/ext/reflex/line_shape.cpp +1 -1
- data/ext/reflex/link_constraint.cpp +1 -1
- data/ext/reflex/menu.cpp +8 -7
- data/ext/reflex/midi.cpp +11 -3
- data/ext/reflex/midi_event.cpp +1 -1
- data/ext/reflex/motion_event.cpp +1 -1
- data/ext/reflex/native.cpp +18 -6
- data/ext/reflex/note_event.cpp +1 -1
- data/ext/reflex/pin.cpp +1 -1
- data/ext/reflex/pointer.cpp +1 -1
- data/ext/reflex/pointer_event.cpp +2 -2
- data/ext/reflex/polygon_shape.cpp +1 -1
- data/ext/reflex/rect_shape.cpp +1 -1
- data/ext/reflex/reflex.cpp +568 -232
- data/ext/reflex/screen.cpp +31 -2
- data/ext/reflex/scroll_event.cpp +1 -1
- data/ext/reflex/selector.cpp +1 -1
- data/ext/reflex/selector.h +9 -9
- data/ext/reflex/shape.cpp +1 -1
- data/ext/reflex/snap_constraint.cpp +1 -1
- data/ext/reflex/style.cpp +1 -1
- data/ext/reflex/style_length.cpp +1 -1
- data/ext/reflex/text_event.cpp +111 -0
- data/ext/reflex/timer.cpp +1 -1
- data/ext/reflex/timer_event.cpp +1 -1
- data/ext/reflex/update_event.cpp +1 -1
- data/ext/reflex/view.cpp +121 -61
- data/ext/reflex/wheel_constraint.cpp +1 -1
- data/ext/reflex/wheel_event.cpp +1 -1
- data/ext/reflex/window.cpp +256 -25
- data/include/reflex/application.h +10 -0
- data/include/reflex/color_picker.h +65 -0
- data/include/reflex/event.h +178 -88
- data/include/reflex/file_dialog.h +73 -0
- data/include/reflex/gamepad.h +3 -0
- data/include/reflex/menu.h +3 -3
- data/include/reflex/midi.h +3 -0
- data/include/reflex/reflex.h +2 -0
- data/include/reflex/ruby/application.h +6 -1
- data/include/reflex/ruby/color_picker.h +89 -0
- data/include/reflex/ruby/event.h +62 -29
- data/include/reflex/ruby/file_dialog.h +89 -0
- data/include/reflex/ruby/gamepad.h +46 -0
- data/include/reflex/ruby/reflex.h +3 -0
- data/include/reflex/ruby/view.h +92 -44
- data/include/reflex/ruby/window.h +60 -1
- data/include/reflex/ruby.h +3 -0
- data/include/reflex/screen.h +11 -2
- data/include/reflex/view.h +28 -16
- data/include/reflex/window.h +40 -8
- data/include/reflex.h +3 -0
- data/lib/reflex/application.rb +5 -5
- data/lib/reflex/autoinit.rb +3 -1
- data/lib/reflex/button.rb +3 -3
- data/lib/reflex/color_event.rb +16 -0
- data/lib/reflex/color_picker.rb +45 -0
- data/lib/reflex/control_change_event.rb +17 -0
- data/lib/reflex/file_dialog.rb +70 -0
- data/lib/reflex/file_event.rb +37 -0
- data/lib/reflex/helper.rb +58 -7
- data/lib/reflex/key_event.rb +9 -4
- data/lib/reflex/menu.rb +17 -1
- data/lib/reflex/model.rb +19 -19
- data/lib/reflex/note_event.rb +1 -1
- data/lib/reflex/pointer.rb +14 -3
- data/lib/reflex/pointer_event.rb +12 -1
- data/lib/reflex/reflex.rb +5 -0
- data/lib/reflex/shape.rb +14 -14
- data/lib/reflex/style.rb +16 -16
- data/lib/reflex/text_event.rb +40 -0
- data/lib/reflex/timer.rb +3 -3
- data/lib/reflex/view.rb +29 -14
- data/lib/reflex/wheel_event.rb +12 -3
- data/lib/reflex/window.rb +25 -13
- data/lib/reflex.rb +8 -2
- data/reflex.gemspec +4 -4
- data/samples/ime.rb +100 -0
- data/samples/ios/hello/hello.xcodeproj/project.pbxproj +236 -224
- data/samples/menu.rb +4 -1
- data/samples/model.rb +3 -3
- data/samples/test/alert.rb +93 -0
- data/samples/test/always_on.rb +76 -0
- data/samples/test/app_background.rb +51 -0
- data/samples/test/boundary.rb +75 -0
- data/samples/test/callback_exception.rb +101 -0
- data/samples/test/cancel.rb +53 -0
- data/samples/test/color_picker.rb +63 -0
- data/samples/test/file_dialog.rb +102 -0
- data/samples/window_style.rb +156 -0
- data/src/application.cpp +159 -18
- data/src/application.h +92 -7
- data/src/color_picker.cpp +113 -0
- data/src/color_picker.h +36 -0
- data/src/event.cpp +410 -252
- data/src/event.h +12 -0
- data/src/file_dialog.cpp +163 -0
- data/src/file_dialog.h +52 -0
- data/src/gamepad.cpp +42 -5
- data/src/gamepad.h +4 -0
- data/src/ios/app_delegate.mm +5 -3
- data/src/ios/application.mm +24 -0
- data/src/ios/color_picker.mm +19 -0
- data/src/ios/file_dialog.mm +21 -0
- data/src/ios/gamepad.mm +4 -4
- data/src/ios/menu.mm +5 -0
- data/src/ios/reflex.mm +8 -0
- data/src/ios/screen.mm +26 -0
- data/src/ios/view_controller.mm +2 -30
- data/src/ios/window.mm +38 -9
- data/src/menu.cpp +66 -4
- data/src/menu.h +17 -1
- data/src/midi.cpp +61 -31
- data/src/osx/app_delegate.h +4 -0
- data/src/osx/app_delegate.mm +102 -22
- data/src/osx/application.mm +88 -6
- data/src/osx/color_picker.mm +112 -0
- data/src/osx/event.h +10 -0
- data/src/osx/event.mm +84 -30
- data/src/osx/file_dialog.mm +168 -0
- data/src/osx/gamepad.mm +2 -2
- data/src/osx/gamepad_hid.mm +1 -1
- data/src/osx/menu.mm +177 -33
- data/src/osx/native_window.h +16 -2
- data/src/osx/native_window.mm +114 -57
- data/src/osx/opengl_view.h +2 -1
- data/src/osx/opengl_view.mm +184 -43
- data/src/osx/reflex.mm +38 -0
- data/src/osx/screen.mm +36 -0
- data/src/osx/window.mm +106 -24
- data/src/pointer.cpp +13 -4
- data/src/pointer.h +4 -0
- data/src/rays.h +46 -0
- data/src/sdl/application.cpp +68 -8
- data/src/sdl/color_picker.cpp +18 -0
- data/src/sdl/event.cpp +24 -3
- data/src/sdl/event.h +12 -0
- data/src/sdl/file_dialog.cpp +20 -0
- data/src/sdl/gamepad.cpp +3 -7
- data/src/sdl/menu.cpp +5 -0
- data/src/sdl/reflex.cpp +20 -0
- data/src/sdl/screen.cpp +36 -0
- data/src/sdl/window.cpp +142 -29
- data/src/shape.cpp +15 -10
- data/src/view.cpp +287 -198
- data/src/view.h +4 -2
- data/src/vk.h +416 -0
- data/src/win32/application.cpp +162 -12
- data/src/win32/application.h +20 -0
- data/src/win32/color_picker.cpp +82 -0
- data/src/win32/event.cpp +114 -12
- data/src/win32/event.h +21 -4
- data/src/win32/file_dialog.cpp +226 -0
- data/src/win32/gamepad.cpp +9 -2
- data/src/win32/menu.cpp +191 -53
- data/src/win32/menu.h +9 -1
- data/src/win32/opengl.cpp +2 -9
- data/src/win32/reflex.cpp +44 -3
- data/src/win32/screen.cpp +164 -3
- data/src/win32/screen.h +8 -0
- data/src/win32/tray.cpp +191 -0
- data/src/win32/tray.h +22 -0
- data/src/win32/vk.cpp +11 -0
- data/src/win32/window.cpp +809 -148
- data/src/win32/window.h +6 -0
- data/src/window.cpp +718 -185
- data/src/window.h +66 -33
- data/src/world.cpp +9 -1
- data/test/helper.rb +17 -0
- data/test/test_application.rb +90 -1
- data/test/test_chase_constraint.rb +1 -3
- data/test/test_color_event.rb +36 -0
- data/test/test_color_picker.rb +62 -0
- data/test/test_constraint.rb +2 -4
- data/test/test_event.rb +1 -1
- data/test/test_file_dialog.rb +48 -0
- data/test/test_file_event.rb +43 -0
- data/test/test_has_text_preedit.rb +54 -0
- data/test/test_key_event.rb +20 -5
- data/test/test_link_constraint.rb +1 -3
- data/test/test_menu.rb +40 -10
- data/test/test_pointer.rb +33 -23
- data/test/test_pointer_event.rb +24 -9
- data/test/test_reflex.rb +36 -0
- data/test/test_screen.rb +24 -2
- data/test/test_snap_constraint.rb +1 -3
- data/test/test_text_event.rb +54 -0
- data/test/test_view.rb +41 -4
- data/test/test_wheel_constraint.rb +1 -3
- data/test/test_wheel_event.rb +13 -5
- data/test/test_window.rb +196 -44
- metadata +80 -10
- data/.github/workflows/utils.rb +0 -127
data/src/window.cpp
CHANGED
|
@@ -2,12 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
#include <assert.h>
|
|
5
|
+
#include <math.h>
|
|
5
6
|
#include <algorithm>
|
|
6
7
|
#include <set>
|
|
8
|
+
#include <rays/rays.h>
|
|
7
9
|
#include "reflex/exception.h"
|
|
8
10
|
#include "reflex/debug.h"
|
|
11
|
+
#include "application.h"
|
|
9
12
|
#include "view.h"
|
|
10
13
|
#include "event.h"
|
|
14
|
+
#include "midi.h"
|
|
15
|
+
#include "rays.h"
|
|
11
16
|
|
|
12
17
|
|
|
13
18
|
namespace Reflex
|
|
@@ -23,6 +28,31 @@ namespace Reflex
|
|
|
23
28
|
using WeakViewList = Window::Data::WeakViewList;
|
|
24
29
|
|
|
25
30
|
|
|
31
|
+
Window::Data::Data ()
|
|
32
|
+
: flags(Window_default_flags() | REDRAW)
|
|
33
|
+
{
|
|
34
|
+
prev_time_update = prev_time_draw = Xot::time();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
Window::Data::~Data ()
|
|
38
|
+
{
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
static Window_CreateRootViewFun create_root_view_fun = NULL;
|
|
43
|
+
|
|
44
|
+
void
|
|
45
|
+
Window_set_create_root_view_fun (Window_CreateRootViewFun fun)
|
|
46
|
+
{
|
|
47
|
+
create_root_view_fun = fun;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
static View*
|
|
51
|
+
create_root_view ()
|
|
52
|
+
{
|
|
53
|
+
return create_root_view_fun ? create_root_view_fun() : new View();
|
|
54
|
+
}
|
|
55
|
+
|
|
26
56
|
void
|
|
27
57
|
Window_register (Window* win)
|
|
28
58
|
{
|
|
@@ -64,15 +94,11 @@ namespace Reflex
|
|
|
64
94
|
return NULL;
|
|
65
95
|
}
|
|
66
96
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
: flags(Window_default_flags())
|
|
70
|
-
{
|
|
71
|
-
prev_time_update = prev_time_draw = Xot::time();
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
Window::Data::~Data ()
|
|
97
|
+
void
|
|
98
|
+
Window_skip_update_time_of_all (double seconds)
|
|
75
99
|
{
|
|
100
|
+
for (auto& window : Window_all())
|
|
101
|
+
window->self->prev_time_update += seconds;
|
|
76
102
|
}
|
|
77
103
|
|
|
78
104
|
|
|
@@ -104,20 +130,6 @@ namespace Reflex
|
|
|
104
130
|
}
|
|
105
131
|
}
|
|
106
132
|
|
|
107
|
-
static Window_CreateRootViewFun create_root_view_fun = NULL;
|
|
108
|
-
|
|
109
|
-
void
|
|
110
|
-
Window_set_create_root_view_fun (Window_CreateRootViewFun fun)
|
|
111
|
-
{
|
|
112
|
-
create_root_view_fun = fun;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
static View*
|
|
116
|
-
create_root_view ()
|
|
117
|
-
{
|
|
118
|
-
return create_root_view_fun ? create_root_view_fun() : new View();
|
|
119
|
-
}
|
|
120
|
-
|
|
121
133
|
void
|
|
122
134
|
Window_register_capture (Window* window, View* view, Pointer::ID target)
|
|
123
135
|
{
|
|
@@ -167,18 +179,84 @@ namespace Reflex
|
|
|
167
179
|
}
|
|
168
180
|
}
|
|
169
181
|
|
|
182
|
+
static const uint MOUSE_BUTTONS =
|
|
183
|
+
Pointer::MOUSE_LEFT |
|
|
184
|
+
Pointer::MOUSE_RIGHT |
|
|
185
|
+
Pointer::MOUSE_MIDDLE;
|
|
186
|
+
|
|
187
|
+
void
|
|
188
|
+
Window_cancel_active_pointers (Window* window)
|
|
189
|
+
{
|
|
190
|
+
assert(window);
|
|
191
|
+
|
|
192
|
+
// synthesizes a cancel for every pointer being pressed and delivers
|
|
193
|
+
// it through the normal path, so the existing up/cancel handling
|
|
194
|
+
// releases captures and pressed states
|
|
195
|
+
|
|
196
|
+
Window::Data* self = window->self.get();
|
|
197
|
+
|
|
198
|
+
double now = Xot::time();
|
|
199
|
+
|
|
200
|
+
PointerEvent event;
|
|
201
|
+
|
|
202
|
+
const auto& mouse = self->prev_mouse_pointer;
|
|
203
|
+
uint pressed = Pointer_mask_flag(mouse, MOUSE_BUTTONS);
|
|
204
|
+
if (pressed != 0)
|
|
205
|
+
{
|
|
206
|
+
Pointer pointer = mouse;
|
|
207
|
+
Pointer_set_types(&pointer, Pointer::MOUSE | pressed);
|
|
208
|
+
Pointer_set_action(&pointer, Pointer::CANCEL);
|
|
209
|
+
Pointer_set_time(&pointer, now);
|
|
210
|
+
PointerEvent_add_pointer(&event, pointer);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
for (const auto& p : self->prev_pointers)
|
|
214
|
+
{
|
|
215
|
+
if (!p.down()) continue;
|
|
216
|
+
Pointer pointer = p;
|
|
217
|
+
Pointer_set_action(&pointer, Pointer::CANCEL);
|
|
218
|
+
Pointer_set_time(&pointer, now);
|
|
219
|
+
PointerEvent_add_pointer(&event, pointer);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (event.empty()) return;
|
|
223
|
+
|
|
224
|
+
++self->pointer_cancels;
|
|
225
|
+
Window_call_pointer_event(window, &event);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
uint
|
|
229
|
+
Window_get_pointer_cancels (const Window& window)
|
|
230
|
+
{
|
|
231
|
+
return window.self->pointer_cancels;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
void
|
|
235
|
+
Window_call_close (Window* window)
|
|
236
|
+
{
|
|
237
|
+
if (!window) return;
|
|
238
|
+
|
|
239
|
+
Application_guard([&]()
|
|
240
|
+
{
|
|
241
|
+
window->close();
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
170
245
|
void
|
|
171
246
|
Window_call_activate_event (Window* window)
|
|
172
247
|
{
|
|
173
248
|
if (!window) return;
|
|
174
249
|
|
|
175
|
-
|
|
250
|
+
Application_guard([&]()
|
|
251
|
+
{
|
|
252
|
+
Xot::add_flag(&window->self->flags, Window::Data::ACTIVE);
|
|
176
253
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
254
|
+
Event e;
|
|
255
|
+
window->on_activate(&e);
|
|
256
|
+
if (e.is_blocked()) return;
|
|
180
257
|
|
|
181
|
-
|
|
258
|
+
View_activate_tree(window->root(), &e);
|
|
259
|
+
});
|
|
182
260
|
}
|
|
183
261
|
|
|
184
262
|
void
|
|
@@ -186,28 +264,186 @@ namespace Reflex
|
|
|
186
264
|
{
|
|
187
265
|
if (!window) return;
|
|
188
266
|
|
|
189
|
-
|
|
267
|
+
Application_guard([&]()
|
|
268
|
+
{
|
|
269
|
+
Xot::remove_flag(&window->self->flags, Window::Data::ACTIVE);
|
|
190
270
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
271
|
+
Event e;
|
|
272
|
+
window->on_deactivate(&e);
|
|
273
|
+
if (e.is_blocked()) return;
|
|
274
|
+
|
|
275
|
+
View_deactivate_tree(window->root(), &e);
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
static bool
|
|
280
|
+
is_pointer_through_by_alpha (const Window::Data& self)
|
|
281
|
+
{
|
|
282
|
+
return
|
|
283
|
+
Xot::has_flag(self.flags, Window::FLAG_POINTER_THROUGH) &&
|
|
284
|
+
self.pointer_through_alpha < 1;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
static bool
|
|
288
|
+
has_pressed_pointer (const Window::Data& self)
|
|
289
|
+
{
|
|
290
|
+
if (Pointer_mask_flag(self.prev_mouse_pointer, MOUSE_BUTTONS) != 0)
|
|
291
|
+
return true;
|
|
292
|
+
|
|
293
|
+
for (const auto& p : self.prev_pointers)
|
|
294
|
+
{
|
|
295
|
+
if (p.down())
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
static float
|
|
302
|
+
get_cache_alpha (Window::Data* self, const Point& position)
|
|
303
|
+
{
|
|
304
|
+
if (!self->draw_cache)
|
|
305
|
+
return 0;
|
|
306
|
+
|
|
307
|
+
Rays::activate_offscreen_context();
|
|
308
|
+
|
|
309
|
+
Color color;
|
|
310
|
+
bool ret = Rays::Painter_get_pixel(
|
|
311
|
+
&color, &self->draw_cache_painter, position.x, position.y);
|
|
312
|
+
return ret ? color.alpha : 0;
|
|
313
|
+
}
|
|
194
314
|
|
|
195
|
-
|
|
315
|
+
static void
|
|
316
|
+
apply_pointer_through (Window* window)
|
|
317
|
+
{
|
|
318
|
+
using Data = Window::Data;
|
|
319
|
+
|
|
320
|
+
Data* self = window->self.get();
|
|
321
|
+
|
|
322
|
+
if (!is_pointer_through_by_alpha(*self))
|
|
323
|
+
{
|
|
324
|
+
Xot::remove_flag(
|
|
325
|
+
&self->flags,
|
|
326
|
+
Data::POINTER_THROUGH_PAUSED | Data::POINTER_THROUGH_ENTERED);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
Window_set_pointer_through(
|
|
330
|
+
window,
|
|
331
|
+
Xot::has_flag(self->flags, Window::FLAG_POINTER_THROUGH) &&
|
|
332
|
+
!Xot::has_flag(self->flags, Data::POINTER_THROUGH_PAUSED));
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
static bool is_inside_window (Window* window, const Point& position);
|
|
336
|
+
|
|
337
|
+
static void call_pointer_event (Window* window, PointerEvent* event);
|
|
338
|
+
|
|
339
|
+
static void
|
|
340
|
+
update_pointer_through (Window* window)
|
|
341
|
+
{
|
|
342
|
+
using Data = Window::Data;
|
|
343
|
+
|
|
344
|
+
Data* self = window->self.get();
|
|
345
|
+
if (!is_pointer_through_by_alpha(*self))
|
|
346
|
+
return;
|
|
347
|
+
if (has_pressed_pointer(*self))
|
|
348
|
+
return;
|
|
349
|
+
|
|
350
|
+
Point pos;
|
|
351
|
+
bool over_and_uncov = Window_is_pointer_over_and_uncovered(&pos, *window);
|
|
352
|
+
bool inside = over_and_uncov && is_inside_window(window, pos);
|
|
353
|
+
bool opaque =
|
|
354
|
+
over_and_uncov &&
|
|
355
|
+
(!inside || get_cache_alpha(self, pos) > self->pointer_through_alpha);
|
|
356
|
+
if (opaque != Xot::has_flag(self->flags, Data::POINTER_THROUGH_PAUSED))
|
|
357
|
+
{
|
|
358
|
+
Xot::update_flag(&self->flags, Data::POINTER_THROUGH_PAUSED, opaque);
|
|
359
|
+
apply_pointer_through(window);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
bool entered = opaque && inside;
|
|
363
|
+
if (entered == Xot::has_flag(self->flags, Data::POINTER_THROUGH_ENTERED))
|
|
364
|
+
return;
|
|
365
|
+
|
|
366
|
+
Xot::update_flag(&self->flags, Data::POINTER_THROUGH_ENTERED, entered);
|
|
367
|
+
|
|
368
|
+
PointerEvent event;
|
|
369
|
+
PointerEvent_add_pointer(&event, Pointer(
|
|
370
|
+
0, Pointer::MOUSE,
|
|
371
|
+
entered ? Pointer::ENTER : Pointer::LEAVE,
|
|
372
|
+
entered ? pos : self->prev_mouse_pointer.position(),
|
|
373
|
+
0, 0, false, Xot::time()));
|
|
374
|
+
call_pointer_event(window, &event);
|
|
196
375
|
}
|
|
197
376
|
|
|
198
377
|
void
|
|
199
378
|
Window_call_update_event (Window* window)
|
|
200
379
|
{
|
|
201
|
-
|
|
380
|
+
Application_guard([&]()
|
|
381
|
+
{
|
|
382
|
+
Window::Data* self = window->self.get();
|
|
202
383
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
384
|
+
MIDI_process_events();
|
|
385
|
+
|
|
386
|
+
update_pointer_through(window);
|
|
206
387
|
|
|
207
|
-
|
|
208
|
-
|
|
388
|
+
double now = Xot::time();
|
|
389
|
+
UpdateEvent e(now, std::max(now - self->prev_time_update, 0.0));
|
|
390
|
+
self->prev_time_update = now;
|
|
209
391
|
|
|
210
|
-
|
|
392
|
+
window->on_update(&e);
|
|
393
|
+
if (!e.is_blocked())
|
|
394
|
+
View_update_tree(window->root(), e);
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
static bool
|
|
399
|
+
use_draw_cache (const Window::Data& self)
|
|
400
|
+
{
|
|
401
|
+
return is_pointer_through_by_alpha(self);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
static void
|
|
405
|
+
setup_draw_cache (Window::Data* self, const Bounds& bounds, float density)
|
|
406
|
+
{
|
|
407
|
+
int w = (int) ceil(bounds.width);
|
|
408
|
+
int h = (int) ceil(bounds.height);
|
|
409
|
+
if (w == 0 || h == 0 || !use_draw_cache(*self))
|
|
410
|
+
{
|
|
411
|
+
if (self->draw_cache)
|
|
412
|
+
{
|
|
413
|
+
self->draw_cache = Image();
|
|
414
|
+
self->draw_cache_painter = Painter();
|
|
415
|
+
}
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
Image& cache = self->draw_cache;
|
|
420
|
+
if (
|
|
421
|
+
!cache ||
|
|
422
|
+
cache.width() != w ||
|
|
423
|
+
cache.height() != h ||
|
|
424
|
+
cache.pixel_density() != density)
|
|
425
|
+
{
|
|
426
|
+
self->draw_cache = Image(w, h, Rays::RGBA, density);
|
|
427
|
+
self->draw_cache_painter = self->draw_cache.painter();
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
static void
|
|
432
|
+
draw_window (Window* window, DrawEvent* event)
|
|
433
|
+
{
|
|
434
|
+
Painter* painter = event->painter();
|
|
435
|
+
|
|
436
|
+
painter->begin();
|
|
437
|
+
painter->push_state();
|
|
438
|
+
{
|
|
439
|
+
painter->clear();
|
|
440
|
+
|
|
441
|
+
window->on_draw(event);
|
|
442
|
+
if (!event->is_blocked())
|
|
443
|
+
View_draw_tree(window->root(), event, 0, event->bounds());
|
|
444
|
+
}
|
|
445
|
+
painter->pop_state();
|
|
446
|
+
painter->end();
|
|
211
447
|
}
|
|
212
448
|
|
|
213
449
|
void
|
|
@@ -218,25 +454,74 @@ namespace Reflex
|
|
|
218
454
|
if (!event)
|
|
219
455
|
argument_error(__FILE__, __LINE__);
|
|
220
456
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
457
|
+
Application_guard([&]()
|
|
458
|
+
{
|
|
459
|
+
Window::Data* self = window->self.get();
|
|
224
460
|
|
|
225
|
-
|
|
461
|
+
Painter* painter = window->painter();
|
|
462
|
+
if (!painter)
|
|
463
|
+
Xot::invalid_state_error(__FILE__, __LINE__);
|
|
226
464
|
|
|
227
|
-
|
|
228
|
-
|
|
465
|
+
Bounds bounds = window->frame().move_to(0);
|
|
466
|
+
setup_draw_cache(self, bounds, painter->pixel_density());
|
|
229
467
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
painter->clear();
|
|
468
|
+
DrawEvent_set_painter(event, painter);
|
|
469
|
+
DrawEvent_set_bounds(event, bounds);
|
|
233
470
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
471
|
+
if (self->draw_cache)
|
|
472
|
+
{
|
|
473
|
+
painter->bind(self->draw_cache);
|
|
474
|
+
draw_window(window, event);
|
|
475
|
+
painter->unbind();
|
|
237
476
|
|
|
238
|
-
|
|
239
|
-
|
|
477
|
+
painter->begin();
|
|
478
|
+
painter->push_state();
|
|
479
|
+
{
|
|
480
|
+
painter->clear();
|
|
481
|
+
painter->set_fill(1);
|
|
482
|
+
painter->no_stroke();
|
|
483
|
+
painter->no_shader();
|
|
484
|
+
painter->image(self->draw_cache, 0, 0);
|
|
485
|
+
}
|
|
486
|
+
painter->pop_state();
|
|
487
|
+
painter->end();
|
|
488
|
+
}
|
|
489
|
+
else
|
|
490
|
+
draw_window(window, event);
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
void
|
|
495
|
+
Window_call_frame_event (Window* window)
|
|
496
|
+
{
|
|
497
|
+
if (!window) return;
|
|
498
|
+
|
|
499
|
+
Application_guard([&]()
|
|
500
|
+
{
|
|
501
|
+
Rays::Bounds b = window->frame();
|
|
502
|
+
Rays::Point dpos = b.position() - window->self->prev_position;
|
|
503
|
+
Rays::Point dsize = b.size() - window->self->prev_size;
|
|
504
|
+
window->self->prev_position = b.position();
|
|
505
|
+
window->self->prev_size = b.size();
|
|
506
|
+
|
|
507
|
+
if (dpos == 0 && dsize == 0) return;
|
|
508
|
+
|
|
509
|
+
FrameEvent e(b, dpos.x, dpos.y, 0, dsize.x, dsize.y, 0);
|
|
510
|
+
if (dpos != 0) window->on_move(&e);
|
|
511
|
+
if (dsize != 0)
|
|
512
|
+
{
|
|
513
|
+
Rays::Bounds b = window->frame();
|
|
514
|
+
b.move_to(0, 0);
|
|
515
|
+
|
|
516
|
+
if (window->painter())
|
|
517
|
+
window->painter()->canvas(b, window->painter()->pixel_density());
|
|
518
|
+
|
|
519
|
+
if (window->root())
|
|
520
|
+
View_set_frame(window->root(), b);
|
|
521
|
+
|
|
522
|
+
window->on_resize(&e);
|
|
523
|
+
}
|
|
524
|
+
});
|
|
240
525
|
}
|
|
241
526
|
|
|
242
527
|
static bool
|
|
@@ -249,49 +534,117 @@ namespace Reflex
|
|
|
249
534
|
(view->capture() & type) == type;
|
|
250
535
|
}
|
|
251
536
|
|
|
537
|
+
static void
|
|
538
|
+
each_capture (Window* window, auto&& fun)
|
|
539
|
+
{
|
|
540
|
+
assert(window);
|
|
541
|
+
|
|
542
|
+
auto& captures = window->self->captures;
|
|
543
|
+
|
|
544
|
+
ViewList views;
|
|
545
|
+
views.reserve(captures.size());
|
|
546
|
+
for (const auto& [view, targets] : captures)
|
|
547
|
+
views.emplace_back(view);
|
|
548
|
+
|
|
549
|
+
for (auto& view : views)
|
|
550
|
+
{
|
|
551
|
+
if (!view->window()) continue;
|
|
552
|
+
|
|
553
|
+
auto it = captures.find(view);
|
|
554
|
+
if (it == captures.end() || it->second.empty()) continue;
|
|
555
|
+
|
|
556
|
+
fun(const_cast<View*>(view.get()), it->second);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
static void
|
|
561
|
+
each_capturing_view (Window* window, View::Capture type, auto&& fun)
|
|
562
|
+
{
|
|
563
|
+
each_capture(window, [&](View* view, const CaptureTargetIDList& targets)
|
|
564
|
+
{
|
|
565
|
+
if (is_capturing(view, targets, type))
|
|
566
|
+
fun(view);
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
|
|
252
570
|
void
|
|
253
|
-
Window_call_key_event (Window* window, KeyEvent* event)
|
|
571
|
+
Window_call_key_event (Window* window, KeyEvent* event, bool capture)
|
|
254
572
|
{
|
|
255
573
|
assert(window);
|
|
256
574
|
|
|
257
575
|
if (!event)
|
|
258
576
|
argument_error(__FILE__, __LINE__);
|
|
259
577
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
if (!event->is_blocked())
|
|
578
|
+
Application_guard([&]()
|
|
263
579
|
{
|
|
264
|
-
|
|
580
|
+
window->on_key(event);
|
|
581
|
+
|
|
582
|
+
if (!event->is_blocked())
|
|
265
583
|
{
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
584
|
+
switch (event->action())
|
|
585
|
+
{
|
|
586
|
+
case KeyEvent::DOWN: window->on_key_down(event); break;
|
|
587
|
+
case KeyEvent::UP: window->on_key_up(event); break;
|
|
588
|
+
default: break;
|
|
589
|
+
}
|
|
269
590
|
}
|
|
270
|
-
}
|
|
271
591
|
|
|
272
|
-
|
|
273
|
-
{
|
|
274
|
-
for (auto& [view, targets] : window->self->captures)
|
|
592
|
+
if (capture && !event->is_blocked())
|
|
275
593
|
{
|
|
276
|
-
|
|
277
|
-
!view->window() ||
|
|
278
|
-
!is_capturing(view.get(), targets, View::CAPTURE_KEY))
|
|
594
|
+
each_capturing_view(window, View::CAPTURE_KEY, [&](View* view)
|
|
279
595
|
{
|
|
280
|
-
|
|
281
|
-
|
|
596
|
+
KeyEvent e = event->dup();
|
|
597
|
+
KeyEvent_set_captured(&e, true);
|
|
598
|
+
View_call_key_event(view, &e);
|
|
599
|
+
|
|
600
|
+
if (e.is_blocked()) event->block();
|
|
601
|
+
});
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
if (!event->is_blocked() && window->self->focus)
|
|
605
|
+
View_call_key_event(window->self->focus.get(), event);
|
|
606
|
+
|
|
607
|
+
if (capture)
|
|
608
|
+
cleanup_captures(window);
|
|
609
|
+
});
|
|
610
|
+
}
|
|
282
611
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
612
|
+
void
|
|
613
|
+
Window_call_text_event (
|
|
614
|
+
Window* window, TextEvent* event, bool synthesize_key_events)
|
|
615
|
+
{
|
|
616
|
+
assert(window);
|
|
617
|
+
|
|
618
|
+
if (!event)
|
|
619
|
+
argument_error(__FILE__, __LINE__);
|
|
620
|
+
|
|
621
|
+
Application_guard([&]()
|
|
622
|
+
{
|
|
623
|
+
window->on_text(event);
|
|
624
|
+
if (event->is_blocked()) return;
|
|
286
625
|
|
|
287
|
-
|
|
626
|
+
switch (event->action())
|
|
627
|
+
{
|
|
628
|
+
case TextEvent::PREEDIT: window->on_text_preedit(event); break;
|
|
629
|
+
case TextEvent::COMMIT: window->on_text_commit(event); break;
|
|
630
|
+
default: break;
|
|
288
631
|
}
|
|
289
|
-
|
|
632
|
+
if (event->is_blocked()) return;
|
|
290
633
|
|
|
291
|
-
|
|
292
|
-
|
|
634
|
+
if (window->self->focus)
|
|
635
|
+
{
|
|
636
|
+
View_call_text_event(window->self->focus.get(), event);
|
|
637
|
+
if (event->is_blocked()) return;
|
|
638
|
+
}
|
|
293
639
|
|
|
294
|
-
|
|
640
|
+
if (synthesize_key_events)
|
|
641
|
+
{
|
|
642
|
+
KeyEvent down(KeyEvent::DOWN, event->text(), KEY_NONE);
|
|
643
|
+
KeyEvent up( KeyEvent::UP, event->text(), KEY_NONE);
|
|
644
|
+
Window_call_key_event(window, &down, false);
|
|
645
|
+
Window_call_key_event(window, &up, false);
|
|
646
|
+
}
|
|
647
|
+
});
|
|
295
648
|
}
|
|
296
649
|
|
|
297
650
|
static bool
|
|
@@ -299,7 +652,8 @@ namespace Reflex
|
|
|
299
652
|
{
|
|
300
653
|
return
|
|
301
654
|
pointer.action() == Pointer::DOWN ||
|
|
302
|
-
prev_pointer.action() == Pointer::UP
|
|
655
|
+
prev_pointer.action() == Pointer::UP ||
|
|
656
|
+
prev_pointer.action() == Pointer::CANCEL;
|
|
303
657
|
}
|
|
304
658
|
|
|
305
659
|
static Pointer::ID
|
|
@@ -311,11 +665,6 @@ namespace Reflex
|
|
|
311
665
|
static void
|
|
312
666
|
setup_mouse_pointer (Window* window, Pointer* pointer)
|
|
313
667
|
{
|
|
314
|
-
static const uint MOUSE_BUTTONS =
|
|
315
|
-
Pointer::MOUSE_LEFT |
|
|
316
|
-
Pointer::MOUSE_RIGHT |
|
|
317
|
-
Pointer::MOUSE_MIDDLE;
|
|
318
|
-
|
|
319
668
|
Window::Data* self = window->self.get();
|
|
320
669
|
|
|
321
670
|
auto& prev_pointer = self->prev_mouse_pointer;
|
|
@@ -412,6 +761,23 @@ namespace Reflex
|
|
|
412
761
|
}
|
|
413
762
|
}
|
|
414
763
|
|
|
764
|
+
static void
|
|
765
|
+
reject_unpaired_up_pointers (PointerEvent* event)
|
|
766
|
+
{
|
|
767
|
+
// a canceled pointer must deliver nothing until its next down, so
|
|
768
|
+
// an up whose down was never delivered stays silent
|
|
769
|
+
|
|
770
|
+
std::vector<Pointer::ID> ids;
|
|
771
|
+
PointerEvent_each_pointer(event, [&](const auto& pointer)
|
|
772
|
+
{
|
|
773
|
+
if (pointer.action() == Pointer::UP && !pointer.down())
|
|
774
|
+
ids.emplace_back(pointer.id());
|
|
775
|
+
});
|
|
776
|
+
|
|
777
|
+
for (auto id : ids)
|
|
778
|
+
PointerEvent_erase_pointer(event, id);
|
|
779
|
+
}
|
|
780
|
+
|
|
415
781
|
static void
|
|
416
782
|
setup_pointer_event (Window* window, PointerEvent* event)
|
|
417
783
|
{
|
|
@@ -423,6 +789,8 @@ namespace Reflex
|
|
|
423
789
|
else
|
|
424
790
|
setup_pointer(window, &pointer);
|
|
425
791
|
}
|
|
792
|
+
|
|
793
|
+
reject_unpaired_up_pointers(event);
|
|
426
794
|
}
|
|
427
795
|
|
|
428
796
|
static void
|
|
@@ -485,20 +853,18 @@ namespace Reflex
|
|
|
485
853
|
ExtractedPointerIDSet* extracteds, bool* blocked,
|
|
486
854
|
Window* window, const PointerMap& pointers)
|
|
487
855
|
{
|
|
488
|
-
|
|
856
|
+
each_capture(window, [&](View* view, const CaptureTargetIDList& targets)
|
|
489
857
|
{
|
|
490
|
-
if (!view->window() || targets.empty()) continue;
|
|
491
|
-
|
|
492
858
|
PointerEvent event;
|
|
493
859
|
PointerEvent_set_captured(&event, true);
|
|
494
860
|
extract_targeted_pointers(&event, extracteds, targets, pointers);
|
|
495
|
-
if (event.empty())
|
|
861
|
+
if (event.empty()) return;
|
|
496
862
|
|
|
497
863
|
PointerEvent_to_view_coord(&event, view);
|
|
498
|
-
View_call_pointer_event(
|
|
864
|
+
View_call_pointer_event(view, &event);
|
|
499
865
|
|
|
500
866
|
if (event.is_blocked()) *blocked = true;
|
|
501
|
-
}
|
|
867
|
+
});
|
|
502
868
|
}
|
|
503
869
|
|
|
504
870
|
static void
|
|
@@ -595,6 +961,65 @@ namespace Reflex
|
|
|
595
961
|
if (blocked) event->block();
|
|
596
962
|
}
|
|
597
963
|
|
|
964
|
+
static bool
|
|
965
|
+
is_inside_window (Window* window, const Point& position)
|
|
966
|
+
{
|
|
967
|
+
View* root = window->root();
|
|
968
|
+
return root && Bounds(root->frame().size()).is_include(position);
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
static bool
|
|
972
|
+
is_inside_window (Window* window, const Pointer& pointer)
|
|
973
|
+
{
|
|
974
|
+
// a boundary event says which side the pointer came out on and is taken
|
|
975
|
+
// at its word; the position it carries cannot be, since sdl reports the
|
|
976
|
+
// last one inside and win32 the one under a menu
|
|
977
|
+
auto action = pointer.action();
|
|
978
|
+
if (action == Pointer::ENTER) return true;
|
|
979
|
+
if (action == Pointer::LEAVE) return false;
|
|
980
|
+
|
|
981
|
+
// a pointer that ends here is nowhere afterwards: a lifted finger, or a
|
|
982
|
+
// pen taken out of hover range
|
|
983
|
+
return
|
|
984
|
+
is_inside_window(window, pointer.position()) &&
|
|
985
|
+
!is_last_pointer_event(pointer);
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
static Pointer::Action
|
|
989
|
+
get_window_boundary_transition (Window* window, const Pointer& pointer)
|
|
990
|
+
{
|
|
991
|
+
const Pointer* prev = pointer.prev();
|
|
992
|
+
bool is_inside = is_inside_window(window, pointer);
|
|
993
|
+
bool was_inside = prev && is_inside_window(window, *prev);
|
|
994
|
+
|
|
995
|
+
if ( is_inside && !was_inside) return Pointer::ENTER;
|
|
996
|
+
if (!is_inside && was_inside) return Pointer::LEAVE;
|
|
997
|
+
return Pointer::ACTION_NONE;
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
static void
|
|
1001
|
+
call_pointer_window_boundary_events (
|
|
1002
|
+
Window* window, const auto& pointers, Pointer::Action action)
|
|
1003
|
+
{
|
|
1004
|
+
for (const auto& pointer : pointers)
|
|
1005
|
+
{
|
|
1006
|
+
if (get_window_boundary_transition(window, pointer) != action)
|
|
1007
|
+
continue;
|
|
1008
|
+
|
|
1009
|
+
Pointer p = pointer;
|
|
1010
|
+
Pointer_set_action(&p, action);
|
|
1011
|
+
|
|
1012
|
+
PointerEvent event(&p, 1);
|
|
1013
|
+
window->on_pointer(&event);
|
|
1014
|
+
if (event.is_blocked()) continue;
|
|
1015
|
+
|
|
1016
|
+
if (action == Pointer::ENTER)
|
|
1017
|
+
window->on_pointer_enter(&event);
|
|
1018
|
+
else
|
|
1019
|
+
window->on_pointer_leave(&event);
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
|
|
598
1023
|
static void
|
|
599
1024
|
get_current_hovered_views (
|
|
600
1025
|
ViewList* result, Window* window, const Pointer& pointer)
|
|
@@ -720,96 +1145,162 @@ namespace Reflex
|
|
|
720
1145
|
}
|
|
721
1146
|
}
|
|
722
1147
|
|
|
723
|
-
static
|
|
724
|
-
|
|
725
|
-
{
|
|
726
|
-
return action == Pointer::ENTER || action == Pointer::LEAVE;
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
void
|
|
730
|
-
Window_call_pointer_event (Window* window, PointerEvent* event)
|
|
1148
|
+
static void
|
|
1149
|
+
do_call_pointer_event (Window* window, PointerEvent* event)
|
|
731
1150
|
{
|
|
732
|
-
|
|
1151
|
+
auto action = (*event)[0].action();
|
|
1152
|
+
bool boundary = action == Pointer::ENTER || action == Pointer::LEAVE;
|
|
733
1153
|
|
|
734
|
-
|
|
735
|
-
|
|
1154
|
+
std::vector<Pointer> pointers;
|
|
1155
|
+
PointerEvent_each_pointer(event, [&](const auto& p)
|
|
1156
|
+
{
|
|
1157
|
+
pointers.emplace_back(p);
|
|
1158
|
+
});
|
|
736
1159
|
|
|
737
|
-
|
|
1160
|
+
call_pointer_window_boundary_events(window, pointers, Pointer::ENTER);
|
|
1161
|
+
call_pointer_enter_events(window, pointers);
|
|
738
1162
|
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
1163
|
+
if (!boundary)
|
|
1164
|
+
{
|
|
1165
|
+
uint cancels = Window_get_pointer_cancels(*window);
|
|
1166
|
+
auto block_if_canceled = [&]()
|
|
1167
|
+
{
|
|
1168
|
+
if (Window_get_pointer_cancels(*window) != cancels)
|
|
1169
|
+
event->block();
|
|
1170
|
+
return event->is_blocked();
|
|
1171
|
+
};
|
|
742
1172
|
|
|
743
|
-
if (!event->empty())
|
|
744
1173
|
window->on_pointer(event);
|
|
745
1174
|
|
|
746
|
-
|
|
747
|
-
{
|
|
748
|
-
switch ((*event)[0].action())
|
|
1175
|
+
if (!block_if_canceled())
|
|
749
1176
|
{
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
1177
|
+
switch (action)
|
|
1178
|
+
{
|
|
1179
|
+
case Pointer::DOWN: window->on_pointer_down(event); break;
|
|
1180
|
+
case Pointer::UP: window->on_pointer_up(event); break;
|
|
1181
|
+
case Pointer::MOVE: window->on_pointer_move(event); break;
|
|
1182
|
+
case Pointer::CANCEL: window->on_pointer_cancel(event); break;
|
|
1183
|
+
default: break;
|
|
1184
|
+
}
|
|
757
1185
|
}
|
|
758
|
-
}
|
|
759
1186
|
|
|
760
|
-
|
|
761
|
-
if (!boundary)
|
|
762
|
-
{
|
|
763
|
-
if (!event->empty() && !event->is_blocked())
|
|
1187
|
+
if (!block_if_canceled())
|
|
764
1188
|
call_captured_pointer_events(window, event);
|
|
765
1189
|
|
|
766
|
-
if (!
|
|
1190
|
+
if (!block_if_canceled())
|
|
767
1191
|
{
|
|
768
1192
|
PointerEvent_update_for_child_view(event, window->root());
|
|
769
1193
|
View_call_pointer_event(window->root(), event);
|
|
770
1194
|
}
|
|
771
1195
|
}
|
|
1196
|
+
|
|
772
1197
|
call_pointer_leave_events(window, pointers);
|
|
1198
|
+
call_pointer_window_boundary_events(window, pointers, Pointer::LEAVE);
|
|
1199
|
+
}
|
|
773
1200
|
|
|
774
|
-
|
|
1201
|
+
static void
|
|
1202
|
+
call_pointer_event (Window* window, PointerEvent* event)
|
|
1203
|
+
{
|
|
1204
|
+
Application_guard([&]()
|
|
1205
|
+
{
|
|
1206
|
+
setup_pointer_event(window, event);
|
|
1207
|
+
if (!event->empty())
|
|
1208
|
+
do_call_pointer_event(window, event);
|
|
1209
|
+
|
|
1210
|
+
cleanup_captures(window);
|
|
1211
|
+
});
|
|
775
1212
|
}
|
|
776
1213
|
|
|
777
1214
|
void
|
|
778
|
-
|
|
1215
|
+
Window_call_pointer_event (Window* window, PointerEvent* event)
|
|
779
1216
|
{
|
|
780
1217
|
assert(window);
|
|
781
1218
|
|
|
782
1219
|
if (!event)
|
|
783
1220
|
argument_error(__FILE__, __LINE__);
|
|
784
1221
|
|
|
785
|
-
|
|
786
|
-
window->on_wheel(event);
|
|
1222
|
+
const Window::Data& self = *window->self;
|
|
787
1223
|
|
|
788
|
-
if (!event->
|
|
789
|
-
|
|
1224
|
+
if (is_pointer_through_by_alpha(self) && !event->empty())
|
|
1225
|
+
{
|
|
1226
|
+
// with pointers going through by alpha, update_pointer_through()
|
|
1227
|
+
// decides when the pointer is in the content area, so the native
|
|
1228
|
+
// enter and leave at the edge are dropped, and so is any event in
|
|
1229
|
+
// the content area before it says the pointer is there: macos moves
|
|
1230
|
+
// the key window's pointer wherever it is, ignored or not, and a
|
|
1231
|
+
// move from the titlebar lands a frame before the pixel under it
|
|
1232
|
+
// is judged
|
|
1233
|
+
|
|
1234
|
+
const auto& pointer0 = (*event)[0];
|
|
1235
|
+
auto action = pointer0.action();
|
|
1236
|
+
if (action == Pointer::ENTER || action == Pointer::LEAVE)
|
|
1237
|
+
return;
|
|
1238
|
+
|
|
1239
|
+
if (
|
|
1240
|
+
!Xot::has_flag(self.flags, Window::Data::POINTER_THROUGH_ENTERED) &&
|
|
1241
|
+
is_inside_window(window, pointer0.position()))
|
|
1242
|
+
{
|
|
1243
|
+
return;
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
call_pointer_event(window, event);
|
|
790
1248
|
}
|
|
791
1249
|
|
|
792
|
-
|
|
793
|
-
|
|
1250
|
+
void
|
|
1251
|
+
Window_call_wheel_event (Window* window, WheelEvent* event)
|
|
794
1252
|
{
|
|
795
1253
|
assert(window);
|
|
796
1254
|
|
|
797
1255
|
if (!event)
|
|
798
1256
|
argument_error(__FILE__, __LINE__);
|
|
799
1257
|
|
|
800
|
-
|
|
1258
|
+
Application_guard([&]()
|
|
801
1259
|
{
|
|
802
|
-
if (
|
|
803
|
-
|
|
804
|
-
|
|
1260
|
+
if (!event->is_blocked())
|
|
1261
|
+
window->on_wheel(event);
|
|
1262
|
+
|
|
1263
|
+
if (!event->is_blocked())
|
|
1264
|
+
View_call_wheel_event(window->root(), event);
|
|
1265
|
+
});
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
void
|
|
1269
|
+
Window_call_file_event (Window* window, FileEvent* event)
|
|
1270
|
+
{
|
|
1271
|
+
if (!window)
|
|
1272
|
+
argument_error(__FILE__, __LINE__);
|
|
1273
|
+
if (!event)
|
|
1274
|
+
argument_error(__FILE__, __LINE__);
|
|
1275
|
+
|
|
1276
|
+
Application_guard([&]()
|
|
1277
|
+
{
|
|
1278
|
+
window->on_file(event);
|
|
1279
|
+
if (event->is_blocked()) return;
|
|
1280
|
+
|
|
1281
|
+
switch (event->action())
|
|
805
1282
|
{
|
|
806
|
-
|
|
1283
|
+
case FileEvent::OPEN: window->on_file_open(event); break;
|
|
1284
|
+
case FileEvent::SAVE: window->on_file_save(event); break;
|
|
1285
|
+
default: break;
|
|
807
1286
|
}
|
|
1287
|
+
});
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
static void
|
|
1291
|
+
Window_call_note_event (Window* window, NoteEvent* event)
|
|
1292
|
+
{
|
|
1293
|
+
assert(window);
|
|
808
1294
|
|
|
1295
|
+
if (!event)
|
|
1296
|
+
argument_error(__FILE__, __LINE__);
|
|
1297
|
+
|
|
1298
|
+
each_capturing_view(window, View::CAPTURE_MIDI, [&](View* view)
|
|
1299
|
+
{
|
|
809
1300
|
NoteEvent e = event->dup();
|
|
810
1301
|
NoteEvent_set_captured(&e, true);
|
|
811
|
-
View_call_note_event(
|
|
812
|
-
}
|
|
1302
|
+
View_call_note_event(view, &e);
|
|
1303
|
+
});
|
|
813
1304
|
|
|
814
1305
|
if (!event->is_blocked())
|
|
815
1306
|
window->on_note(event);
|
|
@@ -836,19 +1327,12 @@ namespace Reflex
|
|
|
836
1327
|
if (!event)
|
|
837
1328
|
argument_error(__FILE__, __LINE__);
|
|
838
1329
|
|
|
839
|
-
|
|
1330
|
+
each_capturing_view(window, View::CAPTURE_MIDI, [&](View* view)
|
|
840
1331
|
{
|
|
841
|
-
if (
|
|
842
|
-
!view->window() ||
|
|
843
|
-
!is_capturing(view.get(), targets, View::CAPTURE_MIDI))
|
|
844
|
-
{
|
|
845
|
-
continue;
|
|
846
|
-
}
|
|
847
|
-
|
|
848
1332
|
ControlChangeEvent e = event->dup();
|
|
849
1333
|
ControlChangeEvent_set_captured(&e, true);
|
|
850
|
-
View_call_control_change_event(
|
|
851
|
-
}
|
|
1334
|
+
View_call_control_change_event(view, &e);
|
|
1335
|
+
});
|
|
852
1336
|
|
|
853
1337
|
if (!event->is_blocked())
|
|
854
1338
|
window->on_control_change(event);
|
|
@@ -865,38 +1349,34 @@ namespace Reflex
|
|
|
865
1349
|
if (!event)
|
|
866
1350
|
argument_error(__FILE__, __LINE__);
|
|
867
1351
|
|
|
868
|
-
|
|
1352
|
+
Application_guard([&]()
|
|
869
1353
|
{
|
|
870
|
-
|
|
871
|
-
!view->window() ||
|
|
872
|
-
!is_capturing(view.get(), targets, View::CAPTURE_MIDI))
|
|
1354
|
+
each_capturing_view(window, View::CAPTURE_MIDI, [&](View* view)
|
|
873
1355
|
{
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
MIDIEvent_set_captured(&e, true);
|
|
879
|
-
View_call_midi_event(const_cast<View*>(view.get()), &e);
|
|
880
|
-
}
|
|
1356
|
+
MIDIEvent e = event->dup();
|
|
1357
|
+
MIDIEvent_set_captured(&e, true);
|
|
1358
|
+
View_call_midi_event(view, &e);
|
|
1359
|
+
});
|
|
881
1360
|
|
|
882
|
-
|
|
883
|
-
|
|
1361
|
+
if (!event->is_blocked())
|
|
1362
|
+
window->on_midi(event);
|
|
884
1363
|
|
|
885
|
-
|
|
886
|
-
|
|
1364
|
+
if (!event->is_blocked() && window->self->focus)
|
|
1365
|
+
View_call_midi_event(window->self->focus.get(), event);
|
|
887
1366
|
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
1367
|
+
if (!event->is_blocked())
|
|
1368
|
+
{
|
|
1369
|
+
NoteEvent note_e;
|
|
1370
|
+
if (MIDIEvent_to_note_event(¬e_e, *event))
|
|
1371
|
+
Window_call_note_event(window, ¬e_e);
|
|
893
1372
|
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
1373
|
+
ControlChangeEvent cc_e;
|
|
1374
|
+
if (MIDIEvent_to_control_change_event(&cc_e, *event))
|
|
1375
|
+
Window_call_control_change_event(window, &cc_e);
|
|
1376
|
+
}
|
|
898
1377
|
|
|
899
|
-
|
|
1378
|
+
cleanup_captures(window);
|
|
1379
|
+
});
|
|
900
1380
|
}
|
|
901
1381
|
|
|
902
1382
|
|
|
@@ -958,6 +1438,8 @@ namespace Reflex
|
|
|
958
1438
|
void
|
|
959
1439
|
Window::close (bool force)
|
|
960
1440
|
{
|
|
1441
|
+
if (!*this) return;
|
|
1442
|
+
|
|
961
1443
|
Event e;
|
|
962
1444
|
on_close(&e);
|
|
963
1445
|
if (!force && e.is_blocked()) return;
|
|
@@ -972,7 +1454,7 @@ namespace Reflex
|
|
|
972
1454
|
void
|
|
973
1455
|
Window::redraw ()
|
|
974
1456
|
{
|
|
975
|
-
self->
|
|
1457
|
+
Xot::add_flag(&self->flags, Data::REDRAW);
|
|
976
1458
|
}
|
|
977
1459
|
|
|
978
1460
|
Point
|
|
@@ -1043,17 +1525,44 @@ namespace Reflex
|
|
|
1043
1525
|
}
|
|
1044
1526
|
|
|
1045
1527
|
void
|
|
1046
|
-
Window::
|
|
1528
|
+
Window::set_pointer_through_alpha (float alpha)
|
|
1047
1529
|
{
|
|
1048
|
-
|
|
1530
|
+
if (alpha < 0 || 1 < alpha)
|
|
1531
|
+
argument_error(__FILE__, __LINE__);
|
|
1532
|
+
|
|
1533
|
+
if (alpha == self->pointer_through_alpha)
|
|
1534
|
+
return;
|
|
1049
1535
|
|
|
1536
|
+
self->pointer_through_alpha = alpha;
|
|
1537
|
+
apply_pointer_through(this);
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
float
|
|
1541
|
+
Window::pointer_through_alpha () const
|
|
1542
|
+
{
|
|
1543
|
+
return self->pointer_through_alpha;
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
static const uint PUBLIC_FLAGS = (Window::FLAG_LAST << 1) - 1;
|
|
1547
|
+
|
|
1548
|
+
void
|
|
1549
|
+
Window::set_flags (uint flags)
|
|
1550
|
+
{
|
|
1551
|
+
flags &= PUBLIC_FLAGS;
|
|
1552
|
+
flags |= self->flags & ~PUBLIC_FLAGS;
|
|
1553
|
+
if (flags == self->flags)
|
|
1554
|
+
return;
|
|
1555
|
+
|
|
1556
|
+
Window_set_flags(this, flags);
|
|
1050
1557
|
self->flags = flags;
|
|
1558
|
+
|
|
1559
|
+
apply_pointer_through(this);
|
|
1051
1560
|
}
|
|
1052
1561
|
|
|
1053
1562
|
uint
|
|
1054
1563
|
Window::flags () const
|
|
1055
1564
|
{
|
|
1056
|
-
return self->flags;
|
|
1565
|
+
return self->flags & PUBLIC_FLAGS;
|
|
1057
1566
|
}
|
|
1058
1567
|
|
|
1059
1568
|
void
|
|
@@ -1061,10 +1570,7 @@ namespace Reflex
|
|
|
1061
1570
|
{
|
|
1062
1571
|
uint value = self->flags;
|
|
1063
1572
|
Xot::add_flag(&value, flags);
|
|
1064
|
-
|
|
1065
|
-
Window_set_flags(this, value);
|
|
1066
|
-
|
|
1067
|
-
self->flags = value;
|
|
1573
|
+
set_flags(value);
|
|
1068
1574
|
}
|
|
1069
1575
|
|
|
1070
1576
|
void
|
|
@@ -1072,16 +1578,13 @@ namespace Reflex
|
|
|
1072
1578
|
{
|
|
1073
1579
|
uint value = self->flags;
|
|
1074
1580
|
Xot::remove_flag(&value, flags);
|
|
1075
|
-
|
|
1076
|
-
Window_set_flags(this, value);
|
|
1077
|
-
|
|
1078
|
-
self->flags = value;
|
|
1581
|
+
set_flags(value);
|
|
1079
1582
|
}
|
|
1080
1583
|
|
|
1081
1584
|
bool
|
|
1082
1585
|
Window::has_flag (uint flags) const
|
|
1083
1586
|
{
|
|
1084
|
-
return Xot::has_flag(
|
|
1587
|
+
return Xot::has_flag(this->flags(), flags);
|
|
1085
1588
|
}
|
|
1086
1589
|
|
|
1087
1590
|
Screen
|
|
@@ -1186,6 +1689,21 @@ namespace Reflex
|
|
|
1186
1689
|
{
|
|
1187
1690
|
}
|
|
1188
1691
|
|
|
1692
|
+
void
|
|
1693
|
+
Window::on_text (TextEvent* e)
|
|
1694
|
+
{
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1697
|
+
void
|
|
1698
|
+
Window::on_text_preedit (TextEvent* e)
|
|
1699
|
+
{
|
|
1700
|
+
}
|
|
1701
|
+
|
|
1702
|
+
void
|
|
1703
|
+
Window::on_text_commit (TextEvent* e)
|
|
1704
|
+
{
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1189
1707
|
void
|
|
1190
1708
|
Window::on_pointer (PointerEvent* e)
|
|
1191
1709
|
{
|
|
@@ -1226,6 +1744,21 @@ namespace Reflex
|
|
|
1226
1744
|
{
|
|
1227
1745
|
}
|
|
1228
1746
|
|
|
1747
|
+
void
|
|
1748
|
+
Window::on_file (FileEvent* e)
|
|
1749
|
+
{
|
|
1750
|
+
}
|
|
1751
|
+
|
|
1752
|
+
void
|
|
1753
|
+
Window::on_file_open (FileEvent* e)
|
|
1754
|
+
{
|
|
1755
|
+
}
|
|
1756
|
+
|
|
1757
|
+
void
|
|
1758
|
+
Window::on_file_save (FileEvent* e)
|
|
1759
|
+
{
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1229
1762
|
void
|
|
1230
1763
|
Window::on_midi (MIDIEvent* e)
|
|
1231
1764
|
{
|