reflexion 0.5.3 → 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 +56 -7
- data/.doc/ext/reflex/capture_event.cpp +1 -1
- data/.doc/ext/reflex/chase_constraint.cpp +84 -0
- data/.doc/ext/reflex/clipboard.cpp +65 -0
- data/.doc/ext/reflex/color_event.cpp +76 -0
- data/.doc/ext/reflex/color_picker.cpp +113 -0
- data/.doc/ext/reflex/constraint.cpp +135 -0
- 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 +178 -0
- data/.doc/ext/reflex/menu.cpp +303 -0
- 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 +40 -10
- data/.doc/ext/reflex/note_event.cpp +1 -1
- data/.doc/ext/reflex/pin.cpp +156 -0
- data/.doc/ext/reflex/pointer.cpp +3 -1
- data/.doc/ext/reflex/pointer_event.cpp +3 -3
- data/.doc/ext/reflex/polygon_shape.cpp +1 -1
- data/.doc/ext/reflex/rect_shape.cpp +1 -1
- data/.doc/ext/reflex/reflex.cpp +606 -237
- data/.doc/ext/reflex/screen.cpp +27 -1
- data/.doc/ext/reflex/scroll_event.cpp +1 -1
- data/.doc/ext/reflex/selector.cpp +5 -5
- data/.doc/ext/reflex/shape.cpp +1 -1
- data/.doc/ext/reflex/snap_constraint.cpp +125 -0
- data/.doc/ext/reflex/style.cpp +1 -1
- data/.doc/ext/reflex/style_length.cpp +4 -3
- 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 +206 -79
- data/.doc/ext/reflex/wheel_constraint.cpp +142 -0
- data/.doc/ext/reflex/wheel_event.cpp +1 -1
- data/.doc/ext/reflex/window.cpp +282 -31
- data/.github/workflows/release-gem.yml +2 -40
- data/.github/workflows/tag.yml +5 -28
- data/.github/workflows/test.yml +1 -28
- data/ChangeLog.md +79 -0
- data/Gemfile.lock +13 -8
- data/README.md +1 -0
- data/Rakefile +13 -2
- data/Reflex.podspec +2 -2
- data/VERSION +1 -1
- data/ext/reflex/application.cpp +62 -7
- data/ext/reflex/capture_event.cpp +1 -1
- data/ext/reflex/chase_constraint.cpp +89 -0
- data/ext/reflex/clipboard.cpp +69 -0
- data/ext/reflex/color_event.cpp +80 -0
- data/ext/reflex/color_picker.cpp +121 -0
- data/ext/reflex/constraint.cpp +146 -0
- 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 +194 -0
- data/ext/reflex/menu.cpp +331 -0
- 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 +40 -10
- data/ext/reflex/note_event.cpp +1 -1
- data/ext/reflex/pin.cpp +165 -0
- data/ext/reflex/pointer.cpp +3 -1
- data/ext/reflex/pointer_event.cpp +3 -3
- data/ext/reflex/polygon_shape.cpp +1 -1
- data/ext/reflex/rect_shape.cpp +1 -1
- data/ext/reflex/reflex.cpp +608 -237
- data/ext/reflex/screen.cpp +31 -2
- data/ext/reflex/scroll_event.cpp +1 -1
- data/ext/reflex/selector.cpp +5 -5
- data/ext/reflex/selector.h +10 -10
- data/ext/reflex/shape.cpp +1 -1
- data/ext/reflex/snap_constraint.cpp +135 -0
- data/ext/reflex/style.cpp +1 -1
- data/ext/reflex/style_length.cpp +4 -3
- 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 +236 -96
- data/ext/reflex/wheel_constraint.cpp +154 -0
- data/ext/reflex/wheel_event.cpp +1 -1
- data/ext/reflex/window.cpp +318 -40
- data/include/reflex/application.h +19 -0
- data/include/reflex/clipboard.h +53 -0
- data/include/reflex/color_picker.h +65 -0
- data/include/reflex/constraint.h +275 -0
- data/include/reflex/defs.h +204 -195
- data/include/reflex/event.h +180 -88
- data/include/reflex/file_dialog.h +73 -0
- data/include/reflex/gamepad.h +3 -0
- data/include/reflex/menu.h +120 -0
- data/include/reflex/midi.h +3 -0
- data/include/reflex/pin.h +68 -0
- data/include/reflex/pointer.h +4 -0
- data/include/reflex/reflex.h +2 -0
- data/include/reflex/ruby/application.h +6 -1
- data/include/reflex/ruby/clipboard.h +23 -0
- data/include/reflex/ruby/color_picker.h +89 -0
- data/include/reflex/ruby/constraint.h +94 -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/menu.h +103 -0
- data/include/reflex/ruby/pin.h +40 -0
- data/include/reflex/ruby/reflex.h +3 -0
- data/include/reflex/ruby/view.h +123 -39
- data/include/reflex/ruby/window.h +96 -19
- data/include/reflex/ruby.h +3 -0
- data/include/reflex/screen.h +11 -2
- data/include/reflex/view.h +66 -27
- data/include/reflex/window.h +57 -12
- data/include/reflex.h +8 -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/chase_constraint.rb +15 -0
- data/lib/reflex/clipboard.rb +19 -0
- data/lib/reflex/color_event.rb +16 -0
- data/lib/reflex/color_picker.rb +45 -0
- data/lib/reflex/constraint.rb +29 -0
- data/lib/reflex/control_change_event.rb +17 -0
- data/lib/reflex/extension.rb +1 -1
- data/lib/reflex/file_dialog.rb +70 -0
- data/lib/reflex/file_event.rb +37 -0
- data/lib/reflex/helper.rb +79 -0
- data/lib/reflex/key_event.rb +14 -14
- data/lib/reflex/link_constraint.rb +31 -0
- data/lib/reflex/menu.rb +92 -0
- data/lib/reflex/model.rb +19 -19
- data/lib/reflex/note_event.rb +1 -1
- data/lib/reflex/pin.rb +39 -0
- data/lib/reflex/pointer.rb +30 -1
- data/lib/reflex/pointer_event.rb +13 -2
- data/lib/reflex/reflex.rb +5 -0
- data/lib/reflex/shape.rb +14 -14
- data/lib/reflex/snap_constraint.rb +28 -0
- 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 +85 -18
- data/lib/reflex/wheel_constraint.rb +28 -0
- data/lib/reflex/wheel_event.rb +19 -1
- data/lib/reflex/window.rb +25 -13
- data/lib/reflex.rb +23 -8
- data/pod.rake +1 -1
- data/reflex.gemspec +4 -4
- data/samples/constraint.rb +152 -0
- data/samples/ime.rb +100 -0
- data/samples/ios/hello/hello.xcodeproj/project.pbxproj +236 -224
- data/samples/menu.rb +32 -0
- 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 +180 -20
- data/src/application.h +95 -5
- data/src/clipboard.cpp +81 -0
- data/src/color_picker.cpp +113 -0
- data/src/color_picker.h +36 -0
- data/src/constraint.cpp +1662 -0
- data/src/constraint.h +64 -0
- data/src/event.cpp +416 -252
- data/src/event.h +13 -2
- 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 +29 -0
- data/src/ios/clipboard.mm +44 -0
- data/src/ios/color_picker.mm +19 -0
- data/src/ios/event.h +6 -2
- data/src/ios/event.mm +31 -12
- data/src/ios/file_dialog.mm +21 -0
- data/src/ios/gamepad.mm +4 -4
- data/src/ios/menu.mm +41 -0
- data/src/ios/reflex.mm +8 -0
- data/src/ios/screen.mm +26 -0
- data/src/ios/view_controller.mm +47 -42
- data/src/ios/window.mm +44 -9
- data/src/menu.cpp +387 -0
- data/src/menu.h +81 -0
- data/src/midi.cpp +61 -31
- data/src/osx/app_delegate.h +4 -0
- data/src/osx/app_delegate.mm +168 -139
- data/src/osx/application.mm +103 -5
- data/src/osx/clipboard.mm +45 -0
- data/src/osx/color_picker.mm +112 -0
- data/src/osx/event.h +10 -0
- data/src/osx/event.mm +114 -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.h +25 -0
- data/src/osx/menu.mm +516 -0
- data/src/osx/native_window.h +16 -2
- data/src/osx/native_window.mm +141 -57
- data/src/osx/opengl_view.h +2 -1
- data/src/osx/opengl_view.mm +229 -37
- data/src/osx/reflex.mm +38 -0
- data/src/osx/screen.mm +36 -0
- data/src/osx/window.mm +117 -24
- data/src/pin.cpp +137 -0
- data/src/pointer.cpp +36 -16
- data/src/pointer.h +10 -0
- data/src/rays.h +46 -0
- data/src/sdl/application.cpp +73 -8
- data/src/sdl/clipboard.cpp +39 -0
- data/src/sdl/color_picker.cpp +18 -0
- data/src/sdl/event.cpp +44 -6
- data/src/sdl/event.h +18 -3
- data/src/sdl/file_dialog.cpp +20 -0
- data/src/sdl/gamepad.cpp +3 -7
- data/src/sdl/menu.cpp +40 -0
- data/src/sdl/reflex.cpp +20 -0
- data/src/sdl/screen.cpp +36 -0
- data/src/sdl/window.cpp +168 -37
- data/src/shape.cpp +15 -10
- data/src/view.cpp +583 -233
- data/src/view.h +22 -4
- data/src/vk.h +416 -0
- data/src/win32/application.cpp +167 -12
- data/src/win32/application.h +20 -0
- data/src/win32/clipboard.cpp +210 -0
- data/src/win32/color_picker.cpp +82 -0
- data/src/win32/event.cpp +123 -11
- data/src/win32/event.h +22 -3
- data/src/win32/file_dialog.cpp +226 -0
- data/src/win32/gamepad.cpp +9 -2
- data/src/win32/menu.cpp +490 -0
- data/src/win32/menu.h +35 -0
- 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 +858 -135
- data/src/win32/window.h +9 -0
- data/src/window.cpp +929 -183
- data/src/window.h +77 -33
- data/src/world.cpp +86 -15
- data/src/world.h +9 -2
- data/test/helper.rb +24 -0
- data/test/test_application.rb +101 -1
- data/test/test_chase_constraint.rb +122 -0
- data/test/test_clipboard.rb +54 -0
- data/test/test_color_event.rb +36 -0
- data/test/test_color_picker.rb +62 -0
- data/test/test_constraint.rb +184 -0
- 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 +23 -2
- data/test/test_link_constraint.rb +237 -0
- data/test/test_menu.rb +237 -0
- data/test/test_pin.rb +65 -0
- data/test/test_pointer.rb +50 -26
- data/test/test_pointer_event.rb +25 -10
- data/test/test_reflex.rb +36 -0
- data/test/test_screen.rb +24 -2
- data/test/test_snap_constraint.rb +140 -0
- data/test/test_text_event.rb +54 -0
- data/test/test_view.rb +152 -25
- data/test/test_wheel_constraint.rb +125 -0
- data/test/test_wheel_event.rb +24 -10
- data/test/test_window.rb +205 -43
- metadata +154 -10
- data/.github/workflows/utils.rb +0 -127
data/src/window.cpp
CHANGED
|
@@ -2,26 +2,56 @@
|
|
|
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
|
|
14
19
|
{
|
|
15
20
|
|
|
16
21
|
|
|
17
|
-
using ViewList = std::vector<View::Ref>;
|
|
18
|
-
|
|
19
22
|
using PointerMap = std::map<Pointer::ID, Pointer>;
|
|
20
23
|
|
|
21
24
|
using ExtractedPointerIDSet = std::set<Pointer::ID>;
|
|
22
25
|
|
|
23
26
|
using CaptureTargetIDList = Window::Data::CaptureTargetIDList;
|
|
24
27
|
|
|
28
|
+
using WeakViewList = Window::Data::WeakViewList;
|
|
29
|
+
|
|
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
|
+
}
|
|
25
55
|
|
|
26
56
|
void
|
|
27
57
|
Window_register (Window* win)
|
|
@@ -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,15 +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
|
-
|
|
254
|
+
Event e;
|
|
255
|
+
window->on_activate(&e);
|
|
256
|
+
if (e.is_blocked()) return;
|
|
257
|
+
|
|
258
|
+
View_activate_tree(window->root(), &e);
|
|
259
|
+
});
|
|
179
260
|
}
|
|
180
261
|
|
|
181
262
|
void
|
|
@@ -183,25 +264,186 @@ namespace Reflex
|
|
|
183
264
|
{
|
|
184
265
|
if (!window) return;
|
|
185
266
|
|
|
186
|
-
|
|
187
|
-
|
|
267
|
+
Application_guard([&]()
|
|
268
|
+
{
|
|
269
|
+
Xot::remove_flag(&window->self->flags, Window::Data::ACTIVE);
|
|
270
|
+
|
|
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
|
+
}
|
|
314
|
+
|
|
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
|
+
}
|
|
188
328
|
|
|
189
|
-
|
|
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);
|
|
190
375
|
}
|
|
191
376
|
|
|
192
377
|
void
|
|
193
378
|
Window_call_update_event (Window* window)
|
|
194
379
|
{
|
|
195
|
-
|
|
380
|
+
Application_guard([&]()
|
|
381
|
+
{
|
|
382
|
+
Window::Data* self = window->self.get();
|
|
196
383
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
384
|
+
MIDI_process_events();
|
|
385
|
+
|
|
386
|
+
update_pointer_through(window);
|
|
200
387
|
|
|
201
|
-
|
|
202
|
-
|
|
388
|
+
double now = Xot::time();
|
|
389
|
+
UpdateEvent e(now, std::max(now - self->prev_time_update, 0.0));
|
|
390
|
+
self->prev_time_update = now;
|
|
203
391
|
|
|
204
|
-
|
|
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();
|
|
205
447
|
}
|
|
206
448
|
|
|
207
449
|
void
|
|
@@ -212,25 +454,74 @@ namespace Reflex
|
|
|
212
454
|
if (!event)
|
|
213
455
|
argument_error(__FILE__, __LINE__);
|
|
214
456
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
457
|
+
Application_guard([&]()
|
|
458
|
+
{
|
|
459
|
+
Window::Data* self = window->self.get();
|
|
218
460
|
|
|
219
|
-
|
|
461
|
+
Painter* painter = window->painter();
|
|
462
|
+
if (!painter)
|
|
463
|
+
Xot::invalid_state_error(__FILE__, __LINE__);
|
|
220
464
|
|
|
221
|
-
|
|
222
|
-
|
|
465
|
+
Bounds bounds = window->frame().move_to(0);
|
|
466
|
+
setup_draw_cache(self, bounds, painter->pixel_density());
|
|
223
467
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
painter->clear();
|
|
468
|
+
DrawEvent_set_painter(event, painter);
|
|
469
|
+
DrawEvent_set_bounds(event, bounds);
|
|
227
470
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
471
|
+
if (self->draw_cache)
|
|
472
|
+
{
|
|
473
|
+
painter->bind(self->draw_cache);
|
|
474
|
+
draw_window(window, event);
|
|
475
|
+
painter->unbind();
|
|
231
476
|
|
|
232
|
-
|
|
233
|
-
|
|
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
|
+
});
|
|
234
525
|
}
|
|
235
526
|
|
|
236
527
|
static bool
|
|
@@ -243,49 +534,126 @@ namespace Reflex
|
|
|
243
534
|
(view->capture() & type) == type;
|
|
244
535
|
}
|
|
245
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
|
+
|
|
246
570
|
void
|
|
247
|
-
Window_call_key_event (Window* window, KeyEvent* event)
|
|
571
|
+
Window_call_key_event (Window* window, KeyEvent* event, bool capture)
|
|
248
572
|
{
|
|
249
573
|
assert(window);
|
|
250
574
|
|
|
251
575
|
if (!event)
|
|
252
576
|
argument_error(__FILE__, __LINE__);
|
|
253
577
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
if (!event->is_blocked())
|
|
578
|
+
Application_guard([&]()
|
|
257
579
|
{
|
|
258
|
-
|
|
580
|
+
window->on_key(event);
|
|
581
|
+
|
|
582
|
+
if (!event->is_blocked())
|
|
259
583
|
{
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
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
|
+
}
|
|
263
590
|
}
|
|
264
|
-
}
|
|
265
591
|
|
|
266
|
-
|
|
267
|
-
{
|
|
268
|
-
for (auto& [view, targets] : window->self->captures)
|
|
592
|
+
if (capture && !event->is_blocked())
|
|
269
593
|
{
|
|
270
|
-
|
|
271
|
-
!view->window() ||
|
|
272
|
-
!is_capturing(view.get(), targets, View::CAPTURE_KEY))
|
|
594
|
+
each_capturing_view(window, View::CAPTURE_KEY, [&](View* view)
|
|
273
595
|
{
|
|
274
|
-
|
|
275
|
-
|
|
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
|
+
}
|
|
276
603
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
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
|
+
}
|
|
611
|
+
|
|
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;
|
|
625
|
+
|
|
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;
|
|
631
|
+
}
|
|
632
|
+
if (event->is_blocked()) return;
|
|
280
633
|
|
|
281
|
-
|
|
634
|
+
if (window->self->focus)
|
|
635
|
+
{
|
|
636
|
+
View_call_text_event(window->self->focus.get(), event);
|
|
637
|
+
if (event->is_blocked()) return;
|
|
282
638
|
}
|
|
283
|
-
}
|
|
284
639
|
|
|
285
|
-
|
|
286
|
-
|
|
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
|
+
});
|
|
648
|
+
}
|
|
287
649
|
|
|
288
|
-
|
|
650
|
+
static bool
|
|
651
|
+
need_next_pointer_id (const Pointer& pointer, const Pointer& prev_pointer)
|
|
652
|
+
{
|
|
653
|
+
return
|
|
654
|
+
pointer.action() == Pointer::DOWN ||
|
|
655
|
+
prev_pointer.action() == Pointer::UP ||
|
|
656
|
+
prev_pointer.action() == Pointer::CANCEL;
|
|
289
657
|
}
|
|
290
658
|
|
|
291
659
|
static Pointer::ID
|
|
@@ -297,21 +665,15 @@ namespace Reflex
|
|
|
297
665
|
static void
|
|
298
666
|
setup_mouse_pointer (Window* window, Pointer* pointer)
|
|
299
667
|
{
|
|
300
|
-
static const uint MOUSE_BUTTONS =
|
|
301
|
-
Pointer::MOUSE_LEFT |
|
|
302
|
-
Pointer::MOUSE_RIGHT |
|
|
303
|
-
Pointer::MOUSE_MIDDLE;
|
|
304
|
-
|
|
305
668
|
Window::Data* self = window->self.get();
|
|
306
669
|
|
|
307
|
-
auto action = pointer->action();
|
|
308
670
|
auto& prev_pointer = self->prev_mouse_pointer;
|
|
309
671
|
|
|
310
672
|
auto id = prev_pointer ? prev_pointer.id() : get_next_pointer_id(window);
|
|
311
673
|
auto* down = prev_pointer.down();
|
|
312
674
|
if (
|
|
313
675
|
Pointer_mask_flag(prev_pointer, MOUSE_BUTTONS) == 0 &&
|
|
314
|
-
(
|
|
676
|
+
need_next_pointer_id(*pointer, prev_pointer))
|
|
315
677
|
{
|
|
316
678
|
id = get_next_pointer_id(window);
|
|
317
679
|
down = NULL;
|
|
@@ -322,6 +684,7 @@ namespace Reflex
|
|
|
322
684
|
Pointer_set_prev(pointer, &prev_pointer);
|
|
323
685
|
Pointer_set_down(pointer, down);
|
|
324
686
|
|
|
687
|
+
auto action = pointer->action();
|
|
325
688
|
if (action == Pointer::DOWN)
|
|
326
689
|
Pointer_add_flag(pointer, pointer->types() & MOUSE_BUTTONS);
|
|
327
690
|
|
|
@@ -351,6 +714,21 @@ namespace Reflex
|
|
|
351
714
|
});
|
|
352
715
|
}
|
|
353
716
|
|
|
717
|
+
static bool
|
|
718
|
+
is_last_pointer_event (const Pointer& pointer)
|
|
719
|
+
{
|
|
720
|
+
auto action = pointer.action();
|
|
721
|
+
if (action == Pointer::UP || action == Pointer::CANCEL)
|
|
722
|
+
{
|
|
723
|
+
// a mouse cursor and a floatable pen (Apple Pencil) survive their
|
|
724
|
+
// up/cancel; a finger or non-floatable pen ends here.
|
|
725
|
+
return
|
|
726
|
+
!(pointer.types() & Pointer::MOUSE) &&
|
|
727
|
+
!Pointer_is_floatable(pointer);
|
|
728
|
+
}
|
|
729
|
+
return action == Pointer::LEAVE;
|
|
730
|
+
}
|
|
731
|
+
|
|
354
732
|
static void
|
|
355
733
|
setup_pointer (Window* window, Pointer* pointer)
|
|
356
734
|
{
|
|
@@ -362,22 +740,44 @@ namespace Reflex
|
|
|
362
740
|
|
|
363
741
|
if (prev_pointer)
|
|
364
742
|
{
|
|
365
|
-
|
|
743
|
+
if (need_next_pointer_id(*pointer, *prev_pointer))
|
|
744
|
+
Pointer_set_id(pointer, get_next_pointer_id(window));
|
|
745
|
+
else
|
|
746
|
+
{
|
|
747
|
+
Pointer_set_id(pointer, prev_pointer->id());
|
|
748
|
+
Pointer_set_down(pointer, prev_pointer->down());
|
|
749
|
+
}
|
|
750
|
+
Pointer_set_floatable(pointer, Pointer_is_floatable(*prev_pointer));
|
|
366
751
|
Pointer_set_prev(pointer, prev_pointer);
|
|
367
|
-
Pointer_set_down(pointer, prev_pointer->down());
|
|
368
752
|
prev_pointers.erase(it);
|
|
369
753
|
}
|
|
370
754
|
else
|
|
371
755
|
Pointer_set_id(pointer, get_next_pointer_id(window));
|
|
372
756
|
|
|
373
|
-
|
|
374
|
-
if (action != Pointer::UP && action != Pointer::CANCEL)
|
|
757
|
+
if (!is_last_pointer_event(*pointer))
|
|
375
758
|
{
|
|
376
759
|
prev_pointers.emplace_back(*pointer);
|
|
377
760
|
Pointer_set_prev(&prev_pointers.back(), NULL);
|
|
378
761
|
}
|
|
379
762
|
}
|
|
380
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
|
+
|
|
381
781
|
static void
|
|
382
782
|
setup_pointer_event (Window* window, PointerEvent* event)
|
|
383
783
|
{
|
|
@@ -389,6 +789,8 @@ namespace Reflex
|
|
|
389
789
|
else
|
|
390
790
|
setup_pointer(window, &pointer);
|
|
391
791
|
}
|
|
792
|
+
|
|
793
|
+
reject_unpaired_up_pointers(event);
|
|
392
794
|
}
|
|
393
795
|
|
|
394
796
|
static void
|
|
@@ -451,20 +853,18 @@ namespace Reflex
|
|
|
451
853
|
ExtractedPointerIDSet* extracteds, bool* blocked,
|
|
452
854
|
Window* window, const PointerMap& pointers)
|
|
453
855
|
{
|
|
454
|
-
|
|
856
|
+
each_capture(window, [&](View* view, const CaptureTargetIDList& targets)
|
|
455
857
|
{
|
|
456
|
-
if (!view->window() || targets.empty()) continue;
|
|
457
|
-
|
|
458
858
|
PointerEvent event;
|
|
459
859
|
PointerEvent_set_captured(&event, true);
|
|
460
860
|
extract_targeted_pointers(&event, extracteds, targets, pointers);
|
|
461
|
-
if (event.empty())
|
|
861
|
+
if (event.empty()) return;
|
|
462
862
|
|
|
463
|
-
|
|
464
|
-
View_call_pointer_event(
|
|
863
|
+
PointerEvent_to_view_coord(&event, view);
|
|
864
|
+
View_call_pointer_event(view, &event);
|
|
465
865
|
|
|
466
866
|
if (event.is_blocked()) *blocked = true;
|
|
467
|
-
}
|
|
867
|
+
});
|
|
468
868
|
}
|
|
469
869
|
|
|
470
870
|
static void
|
|
@@ -502,7 +902,7 @@ namespace Reflex
|
|
|
502
902
|
if (!view->window()) continue;
|
|
503
903
|
|
|
504
904
|
PointerEvent e = event.dup();
|
|
505
|
-
|
|
905
|
+
PointerEvent_to_view_coord(&e, view);
|
|
506
906
|
View_call_pointer_event(const_cast<View*>(view.get()), &e);
|
|
507
907
|
|
|
508
908
|
if (e.is_blocked()) *blocked = true;
|
|
@@ -561,79 +961,346 @@ namespace Reflex
|
|
|
561
961
|
if (blocked) event->block();
|
|
562
962
|
}
|
|
563
963
|
|
|
564
|
-
|
|
565
|
-
|
|
964
|
+
static bool
|
|
965
|
+
is_inside_window (Window* window, const Point& position)
|
|
566
966
|
{
|
|
567
|
-
|
|
967
|
+
View* root = window->root();
|
|
968
|
+
return root && Bounds(root->frame().size()).is_include(position);
|
|
969
|
+
}
|
|
568
970
|
|
|
569
|
-
|
|
570
|
-
|
|
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
|
+
}
|
|
571
987
|
|
|
572
|
-
|
|
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);
|
|
573
994
|
|
|
574
|
-
if (!
|
|
575
|
-
|
|
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
|
+
|
|
1023
|
+
static void
|
|
1024
|
+
get_current_hovered_views (
|
|
1025
|
+
ViewList* result, Window* window, const Pointer& pointer)
|
|
1026
|
+
{
|
|
1027
|
+
if (pointer.is_drag())
|
|
1028
|
+
{
|
|
1029
|
+
// while dragging, only the capturing view(s) take part in enter/leave,
|
|
1030
|
+
// tested against their own frame; views merely passed over are ignored.
|
|
1031
|
+
for (auto& [view, targets] : window->self->captures)
|
|
1032
|
+
{
|
|
1033
|
+
if (!view->window()) continue;
|
|
1034
|
+
if (std::find(targets.begin(), targets.end(), pointer.id()) == targets.end())
|
|
1035
|
+
continue;
|
|
1036
|
+
|
|
1037
|
+
Point pos = view->from_window(pointer.position());
|
|
1038
|
+
if (Bounds(view->frame().size()).is_include(pos))
|
|
1039
|
+
result->emplace_back(view);
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
else
|
|
1043
|
+
View_get_hovered_views(result, window->root(), pointer.position());
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
static WeakViewList*
|
|
1047
|
+
get_prev_hovered_views (Window* window, const Pointer& pointer)
|
|
1048
|
+
{
|
|
1049
|
+
// a mouse pointer gets a fresh id on every click, so follow the prev()
|
|
1050
|
+
// chain to keep tracking the same physical pointer across id changes.
|
|
1051
|
+
auto& map = window->self->hovered_views;
|
|
576
1052
|
|
|
577
|
-
|
|
1053
|
+
auto it = map.find(pointer.id());
|
|
1054
|
+
if (
|
|
1055
|
+
it == map.end() &&
|
|
1056
|
+
pointer.prev() && pointer.prev()->id() != pointer.id())
|
|
578
1057
|
{
|
|
579
|
-
|
|
1058
|
+
auto prev_it = map.find(pointer.prev()->id());
|
|
1059
|
+
if (prev_it != map.end())
|
|
580
1060
|
{
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
1061
|
+
it = map.emplace(pointer.id(), std::move(prev_it->second)).first;
|
|
1062
|
+
map.erase(prev_it);
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
return it != map.end() ? &it->second : NULL;
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
static void
|
|
1070
|
+
call_pointer_boundary_event (
|
|
1071
|
+
View* view, const Pointer& pointer, Pointer::Action action)
|
|
1072
|
+
{
|
|
1073
|
+
if (!view->window()) return;
|
|
1074
|
+
|
|
1075
|
+
Pointer p = pointer;
|
|
1076
|
+
Pointer_set_action(&p, action);
|
|
1077
|
+
|
|
1078
|
+
PointerEvent event(&p, 1);
|
|
1079
|
+
PointerEvent_to_view_coord(&event, view);
|
|
1080
|
+
View_call_pointer_event(view, &event);
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
static void
|
|
1084
|
+
call_pointer_boundary_events (
|
|
1085
|
+
Window* window, const Pointer& pointer, ViewList* news)
|
|
1086
|
+
{
|
|
1087
|
+
ViewList olds;
|
|
1088
|
+
if (auto* weak_views = get_prev_hovered_views(window, pointer))
|
|
1089
|
+
{
|
|
1090
|
+
for (auto& view : *weak_views)
|
|
1091
|
+
if (view) olds.emplace_back(view.get());
|
|
1092
|
+
|
|
1093
|
+
for (auto it = olds.rbegin(); it != olds.rend(); ++it)
|
|
1094
|
+
{
|
|
1095
|
+
if (std::find(news->begin(), news->end(), it->get()) != news->end())
|
|
1096
|
+
continue;
|
|
1097
|
+
call_pointer_boundary_event(it->get(), pointer, Pointer::LEAVE);
|
|
586
1098
|
}
|
|
587
1099
|
}
|
|
588
1100
|
|
|
589
|
-
|
|
590
|
-
|
|
1101
|
+
for (auto& view : *news)
|
|
1102
|
+
{
|
|
1103
|
+
if (std::find(olds.begin(), olds.end(), view.get()) != olds.end())
|
|
1104
|
+
continue;
|
|
1105
|
+
call_pointer_boundary_event(view.get(), pointer, Pointer::ENTER);
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
auto& map = window->self->hovered_views;
|
|
1109
|
+
if (news->empty())
|
|
1110
|
+
map.erase(pointer.id());
|
|
1111
|
+
else
|
|
1112
|
+
map[pointer.id()] = WeakViewList(news->begin(), news->end());
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
static void
|
|
1116
|
+
call_pointer_enter_events (Window* window, const auto& pointers)
|
|
1117
|
+
{
|
|
1118
|
+
for (const auto& pointer : pointers)
|
|
1119
|
+
{
|
|
1120
|
+
auto a = pointer.action();
|
|
1121
|
+
if (a == Pointer::DOWN || a == Pointer::MOVE || a == Pointer::ENTER)
|
|
1122
|
+
{
|
|
1123
|
+
ViewList views;
|
|
1124
|
+
get_current_hovered_views(&views, window, pointer);
|
|
1125
|
+
call_pointer_boundary_events(window, pointer, &views);
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
static void
|
|
1131
|
+
call_pointer_leave_events (Window* window, const auto& pointers)
|
|
1132
|
+
{
|
|
1133
|
+
for (const auto& pointer : pointers)
|
|
1134
|
+
{
|
|
1135
|
+
auto a = pointer.action();
|
|
1136
|
+
if (a == Pointer::UP || a == Pointer::CANCEL || a == Pointer::LEAVE)
|
|
1137
|
+
{
|
|
1138
|
+
// a pointer that survives this event keeps hovering whatever is under
|
|
1139
|
+
// it; a pointer that ends here hovers nothing and leaves every view.
|
|
1140
|
+
ViewList views;
|
|
1141
|
+
if (!is_last_pointer_event(pointer))
|
|
1142
|
+
get_current_hovered_views(&views, window, pointer);
|
|
1143
|
+
call_pointer_boundary_events(window, pointer, &views);
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
static void
|
|
1149
|
+
do_call_pointer_event (Window* window, PointerEvent* event)
|
|
1150
|
+
{
|
|
1151
|
+
auto action = (*event)[0].action();
|
|
1152
|
+
bool boundary = action == Pointer::ENTER || action == Pointer::LEAVE;
|
|
1153
|
+
|
|
1154
|
+
std::vector<Pointer> pointers;
|
|
1155
|
+
PointerEvent_each_pointer(event, [&](const auto& p)
|
|
1156
|
+
{
|
|
1157
|
+
pointers.emplace_back(p);
|
|
1158
|
+
});
|
|
591
1159
|
|
|
592
|
-
|
|
1160
|
+
call_pointer_window_boundary_events(window, pointers, Pointer::ENTER);
|
|
1161
|
+
call_pointer_enter_events(window, pointers);
|
|
1162
|
+
|
|
1163
|
+
if (!boundary)
|
|
593
1164
|
{
|
|
594
|
-
|
|
595
|
-
|
|
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
|
+
};
|
|
1172
|
+
|
|
1173
|
+
window->on_pointer(event);
|
|
1174
|
+
|
|
1175
|
+
if (!block_if_canceled())
|
|
1176
|
+
{
|
|
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
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
if (!block_if_canceled())
|
|
1188
|
+
call_captured_pointer_events(window, event);
|
|
1189
|
+
|
|
1190
|
+
if (!block_if_canceled())
|
|
1191
|
+
{
|
|
1192
|
+
PointerEvent_update_for_child_view(event, window->root());
|
|
1193
|
+
View_call_pointer_event(window->root(), event);
|
|
1194
|
+
}
|
|
596
1195
|
}
|
|
597
1196
|
|
|
598
|
-
|
|
1197
|
+
call_pointer_leave_events(window, pointers);
|
|
1198
|
+
call_pointer_window_boundary_events(window, pointers, Pointer::LEAVE);
|
|
1199
|
+
}
|
|
1200
|
+
|
|
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
|
+
});
|
|
599
1212
|
}
|
|
600
1213
|
|
|
601
1214
|
void
|
|
602
|
-
|
|
1215
|
+
Window_call_pointer_event (Window* window, PointerEvent* event)
|
|
603
1216
|
{
|
|
604
1217
|
assert(window);
|
|
605
1218
|
|
|
606
1219
|
if (!event)
|
|
607
1220
|
argument_error(__FILE__, __LINE__);
|
|
608
1221
|
|
|
609
|
-
|
|
610
|
-
window->on_wheel(event);
|
|
1222
|
+
const Window::Data& self = *window->self;
|
|
611
1223
|
|
|
612
|
-
if (!event->
|
|
613
|
-
|
|
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);
|
|
614
1248
|
}
|
|
615
1249
|
|
|
616
|
-
|
|
617
|
-
|
|
1250
|
+
void
|
|
1251
|
+
Window_call_wheel_event (Window* window, WheelEvent* event)
|
|
618
1252
|
{
|
|
619
1253
|
assert(window);
|
|
620
1254
|
|
|
621
1255
|
if (!event)
|
|
622
1256
|
argument_error(__FILE__, __LINE__);
|
|
623
1257
|
|
|
624
|
-
|
|
1258
|
+
Application_guard([&]()
|
|
625
1259
|
{
|
|
626
|
-
if (
|
|
627
|
-
|
|
628
|
-
|
|
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())
|
|
629
1282
|
{
|
|
630
|
-
|
|
1283
|
+
case FileEvent::OPEN: window->on_file_open(event); break;
|
|
1284
|
+
case FileEvent::SAVE: window->on_file_save(event); break;
|
|
1285
|
+
default: break;
|
|
631
1286
|
}
|
|
1287
|
+
});
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
static void
|
|
1291
|
+
Window_call_note_event (Window* window, NoteEvent* event)
|
|
1292
|
+
{
|
|
1293
|
+
assert(window);
|
|
1294
|
+
|
|
1295
|
+
if (!event)
|
|
1296
|
+
argument_error(__FILE__, __LINE__);
|
|
632
1297
|
|
|
1298
|
+
each_capturing_view(window, View::CAPTURE_MIDI, [&](View* view)
|
|
1299
|
+
{
|
|
633
1300
|
NoteEvent e = event->dup();
|
|
634
1301
|
NoteEvent_set_captured(&e, true);
|
|
635
|
-
View_call_note_event(
|
|
636
|
-
}
|
|
1302
|
+
View_call_note_event(view, &e);
|
|
1303
|
+
});
|
|
637
1304
|
|
|
638
1305
|
if (!event->is_blocked())
|
|
639
1306
|
window->on_note(event);
|
|
@@ -660,19 +1327,12 @@ namespace Reflex
|
|
|
660
1327
|
if (!event)
|
|
661
1328
|
argument_error(__FILE__, __LINE__);
|
|
662
1329
|
|
|
663
|
-
|
|
1330
|
+
each_capturing_view(window, View::CAPTURE_MIDI, [&](View* view)
|
|
664
1331
|
{
|
|
665
|
-
if (
|
|
666
|
-
!view->window() ||
|
|
667
|
-
!is_capturing(view.get(), targets, View::CAPTURE_MIDI))
|
|
668
|
-
{
|
|
669
|
-
continue;
|
|
670
|
-
}
|
|
671
|
-
|
|
672
1332
|
ControlChangeEvent e = event->dup();
|
|
673
1333
|
ControlChangeEvent_set_captured(&e, true);
|
|
674
|
-
View_call_control_change_event(
|
|
675
|
-
}
|
|
1334
|
+
View_call_control_change_event(view, &e);
|
|
1335
|
+
});
|
|
676
1336
|
|
|
677
1337
|
if (!event->is_blocked())
|
|
678
1338
|
window->on_control_change(event);
|
|
@@ -689,38 +1349,34 @@ namespace Reflex
|
|
|
689
1349
|
if (!event)
|
|
690
1350
|
argument_error(__FILE__, __LINE__);
|
|
691
1351
|
|
|
692
|
-
|
|
1352
|
+
Application_guard([&]()
|
|
693
1353
|
{
|
|
694
|
-
|
|
695
|
-
!view->window() ||
|
|
696
|
-
!is_capturing(view.get(), targets, View::CAPTURE_MIDI))
|
|
1354
|
+
each_capturing_view(window, View::CAPTURE_MIDI, [&](View* view)
|
|
697
1355
|
{
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
MIDIEvent_set_captured(&e, true);
|
|
703
|
-
View_call_midi_event(const_cast<View*>(view.get()), &e);
|
|
704
|
-
}
|
|
1356
|
+
MIDIEvent e = event->dup();
|
|
1357
|
+
MIDIEvent_set_captured(&e, true);
|
|
1358
|
+
View_call_midi_event(view, &e);
|
|
1359
|
+
});
|
|
705
1360
|
|
|
706
|
-
|
|
707
|
-
|
|
1361
|
+
if (!event->is_blocked())
|
|
1362
|
+
window->on_midi(event);
|
|
708
1363
|
|
|
709
|
-
|
|
710
|
-
|
|
1364
|
+
if (!event->is_blocked() && window->self->focus)
|
|
1365
|
+
View_call_midi_event(window->self->focus.get(), event);
|
|
711
1366
|
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
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);
|
|
717
1372
|
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
1373
|
+
ControlChangeEvent cc_e;
|
|
1374
|
+
if (MIDIEvent_to_control_change_event(&cc_e, *event))
|
|
1375
|
+
Window_call_control_change_event(window, &cc_e);
|
|
1376
|
+
}
|
|
722
1377
|
|
|
723
|
-
|
|
1378
|
+
cleanup_captures(window);
|
|
1379
|
+
});
|
|
724
1380
|
}
|
|
725
1381
|
|
|
726
1382
|
|
|
@@ -782,10 +1438,14 @@ namespace Reflex
|
|
|
782
1438
|
void
|
|
783
1439
|
Window::close (bool force)
|
|
784
1440
|
{
|
|
1441
|
+
if (!*this) return;
|
|
1442
|
+
|
|
785
1443
|
Event e;
|
|
786
1444
|
on_close(&e);
|
|
787
1445
|
if (!force && e.is_blocked()) return;
|
|
788
1446
|
|
|
1447
|
+
self->hovered_views.clear();
|
|
1448
|
+
|
|
789
1449
|
View_set_window(self->root.get(), NULL);
|
|
790
1450
|
|
|
791
1451
|
Window_close(this);
|
|
@@ -794,7 +1454,7 @@ namespace Reflex
|
|
|
794
1454
|
void
|
|
795
1455
|
Window::redraw ()
|
|
796
1456
|
{
|
|
797
|
-
self->
|
|
1457
|
+
Xot::add_flag(&self->flags, Data::REDRAW);
|
|
798
1458
|
}
|
|
799
1459
|
|
|
800
1460
|
Point
|
|
@@ -809,6 +1469,12 @@ namespace Reflex
|
|
|
809
1469
|
return point + frame().position();
|
|
810
1470
|
}
|
|
811
1471
|
|
|
1472
|
+
bool
|
|
1473
|
+
Window::active () const
|
|
1474
|
+
{
|
|
1475
|
+
return Xot::has_flag(self->flags, Data::ACTIVE);
|
|
1476
|
+
}
|
|
1477
|
+
|
|
812
1478
|
void
|
|
813
1479
|
Window::set_title (const char* title)
|
|
814
1480
|
{
|
|
@@ -840,17 +1506,63 @@ namespace Reflex
|
|
|
840
1506
|
}
|
|
841
1507
|
|
|
842
1508
|
void
|
|
843
|
-
Window::
|
|
1509
|
+
Window::set_menu (Menu* menu)
|
|
844
1510
|
{
|
|
845
|
-
|
|
1511
|
+
self->menu = menu;
|
|
1512
|
+
Window_set_menu(this, menu);
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
Menu*
|
|
1516
|
+
Window::menu ()
|
|
1517
|
+
{
|
|
1518
|
+
return self->menu.get();
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1521
|
+
const Menu*
|
|
1522
|
+
Window::menu () const
|
|
1523
|
+
{
|
|
1524
|
+
return const_cast<Window*>(this)->menu();
|
|
1525
|
+
}
|
|
846
1526
|
|
|
1527
|
+
void
|
|
1528
|
+
Window::set_pointer_through_alpha (float alpha)
|
|
1529
|
+
{
|
|
1530
|
+
if (alpha < 0 || 1 < alpha)
|
|
1531
|
+
argument_error(__FILE__, __LINE__);
|
|
1532
|
+
|
|
1533
|
+
if (alpha == self->pointer_through_alpha)
|
|
1534
|
+
return;
|
|
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);
|
|
847
1557
|
self->flags = flags;
|
|
1558
|
+
|
|
1559
|
+
apply_pointer_through(this);
|
|
848
1560
|
}
|
|
849
1561
|
|
|
850
1562
|
uint
|
|
851
1563
|
Window::flags () const
|
|
852
1564
|
{
|
|
853
|
-
return self->flags;
|
|
1565
|
+
return self->flags & PUBLIC_FLAGS;
|
|
854
1566
|
}
|
|
855
1567
|
|
|
856
1568
|
void
|
|
@@ -858,10 +1570,7 @@ namespace Reflex
|
|
|
858
1570
|
{
|
|
859
1571
|
uint value = self->flags;
|
|
860
1572
|
Xot::add_flag(&value, flags);
|
|
861
|
-
|
|
862
|
-
Window_set_flags(this, value);
|
|
863
|
-
|
|
864
|
-
self->flags = value;
|
|
1573
|
+
set_flags(value);
|
|
865
1574
|
}
|
|
866
1575
|
|
|
867
1576
|
void
|
|
@@ -869,16 +1578,13 @@ namespace Reflex
|
|
|
869
1578
|
{
|
|
870
1579
|
uint value = self->flags;
|
|
871
1580
|
Xot::remove_flag(&value, flags);
|
|
872
|
-
|
|
873
|
-
Window_set_flags(this, value);
|
|
874
|
-
|
|
875
|
-
self->flags = value;
|
|
1581
|
+
set_flags(value);
|
|
876
1582
|
}
|
|
877
1583
|
|
|
878
1584
|
bool
|
|
879
1585
|
Window::has_flag (uint flags) const
|
|
880
1586
|
{
|
|
881
|
-
return Xot::has_flag(
|
|
1587
|
+
return Xot::has_flag(this->flags(), flags);
|
|
882
1588
|
}
|
|
883
1589
|
|
|
884
1590
|
Screen
|
|
@@ -924,27 +1630,27 @@ namespace Reflex
|
|
|
924
1630
|
}
|
|
925
1631
|
|
|
926
1632
|
void
|
|
927
|
-
Window::
|
|
1633
|
+
Window::on_show (Event* e)
|
|
928
1634
|
{
|
|
929
1635
|
}
|
|
930
1636
|
|
|
931
1637
|
void
|
|
932
|
-
Window::
|
|
1638
|
+
Window::on_hide (Event* e)
|
|
933
1639
|
{
|
|
934
1640
|
}
|
|
935
1641
|
|
|
936
1642
|
void
|
|
937
|
-
Window::
|
|
1643
|
+
Window::on_close (Event* e)
|
|
938
1644
|
{
|
|
939
1645
|
}
|
|
940
1646
|
|
|
941
1647
|
void
|
|
942
|
-
Window::
|
|
1648
|
+
Window::on_activate (Event* e)
|
|
943
1649
|
{
|
|
944
1650
|
}
|
|
945
1651
|
|
|
946
1652
|
void
|
|
947
|
-
Window::
|
|
1653
|
+
Window::on_deactivate (Event* e)
|
|
948
1654
|
{
|
|
949
1655
|
}
|
|
950
1656
|
|
|
@@ -983,6 +1689,21 @@ namespace Reflex
|
|
|
983
1689
|
{
|
|
984
1690
|
}
|
|
985
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
|
+
|
|
986
1707
|
void
|
|
987
1708
|
Window::on_pointer (PointerEvent* e)
|
|
988
1709
|
{
|
|
@@ -1008,11 +1729,36 @@ namespace Reflex
|
|
|
1008
1729
|
{
|
|
1009
1730
|
}
|
|
1010
1731
|
|
|
1732
|
+
void
|
|
1733
|
+
Window::on_pointer_enter (PointerEvent* e)
|
|
1734
|
+
{
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1737
|
+
void
|
|
1738
|
+
Window::on_pointer_leave (PointerEvent* e)
|
|
1739
|
+
{
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1011
1742
|
void
|
|
1012
1743
|
Window::on_wheel (WheelEvent* e)
|
|
1013
1744
|
{
|
|
1014
1745
|
}
|
|
1015
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
|
+
|
|
1016
1762
|
void
|
|
1017
1763
|
Window::on_midi (MIDIEvent* e)
|
|
1018
1764
|
{
|