reflexion 0.3.15 → 0.4.1
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/key_event.cpp +3 -3
- data/.github/workflows/release-gem.yml +2 -16
- data/ChangeLog.md +19 -0
- data/README.md +205 -6
- data/VERSION +1 -1
- data/ext/reflex/key_event.cpp +3 -3
- data/include/reflex/defs.h +24 -24
- data/reflex.gemspec +3 -3
- data/samples/bats.rb +2 -2
- data/samples/ios/hello/hello/main.cpp +3 -3
- data/samples/ios/hello/hello.xcodeproj/project.pbxproj +868 -588
- data/samples/osx/hello/hello/main.cpp +4 -4
- data/samples/osx/hello/hello.xcodeproj/project.pbxproj +902 -594
- data/src/ios/event.h +25 -1
- data/src/ios/event.mm +95 -12
- data/src/ios/view_controller.mm +204 -5
- data/src/osx/event.h +1 -1
- data/src/osx/event.mm +3 -5
- data/src/osx/native_window.mm +19 -6
- metadata +8 -8
data/src/ios/event.h
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
#define __REFLEX_SRC_IOS_EVENT_H__
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
#import <UIKit/
|
|
7
|
+
#import <UIKit/UIKit.h>
|
|
8
8
|
#include "../event.h"
|
|
9
9
|
|
|
10
10
|
|
|
@@ -12,6 +12,17 @@ namespace Reflex
|
|
|
12
12
|
{
|
|
13
13
|
|
|
14
14
|
|
|
15
|
+
class NativeKeyEvent : public KeyEvent
|
|
16
|
+
{
|
|
17
|
+
|
|
18
|
+
public:
|
|
19
|
+
|
|
20
|
+
NativeKeyEvent (UIPress* press, Action action, int repeat = 0)
|
|
21
|
+
API_AVAILABLE(ios(13.4));
|
|
22
|
+
|
|
23
|
+
};// NativeKeyEvent
|
|
24
|
+
|
|
25
|
+
|
|
15
26
|
class NativePointerEvent : public PointerEvent
|
|
16
27
|
{
|
|
17
28
|
|
|
@@ -19,9 +30,22 @@ namespace Reflex
|
|
|
19
30
|
|
|
20
31
|
NativePointerEvent (NSSet* touches, UIEvent* event, UIView* view);
|
|
21
32
|
|
|
33
|
+
NativePointerEvent (UIHoverGestureRecognizer* recognizer, UIView* view);
|
|
34
|
+
|
|
22
35
|
};// NativePointerEvent
|
|
23
36
|
|
|
24
37
|
|
|
38
|
+
class NativeWheelEvent : public WheelEvent
|
|
39
|
+
{
|
|
40
|
+
|
|
41
|
+
public:
|
|
42
|
+
|
|
43
|
+
NativeWheelEvent (
|
|
44
|
+
UIPanGestureRecognizer* recognizer, UIView* view, CGPoint position);
|
|
45
|
+
|
|
46
|
+
};// NativeWheelEvent
|
|
47
|
+
|
|
48
|
+
|
|
25
49
|
}// Reflex
|
|
26
50
|
|
|
27
51
|
|
data/src/ios/event.mm
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
#include <assert.h>
|
|
6
|
+
#include <xot/util.h>
|
|
6
7
|
#include "window.h"
|
|
7
8
|
|
|
8
9
|
|
|
@@ -11,7 +12,23 @@ namespace Reflex
|
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
static uint
|
|
14
|
-
|
|
15
|
+
get_mouse_button_types (UIEvent* event)
|
|
16
|
+
{
|
|
17
|
+
if (!event) return 0;
|
|
18
|
+
|
|
19
|
+
uint ret = 0;
|
|
20
|
+
if (@available(iOS 13.4, *))
|
|
21
|
+
{
|
|
22
|
+
UIEventButtonMask mask = event.buttonMask;
|
|
23
|
+
if (mask & UIEventButtonMaskPrimary) ret |= Pointer::MOUSE_LEFT;
|
|
24
|
+
if (mask & UIEventButtonMaskSecondary) ret |= Pointer::MOUSE_RIGHT;
|
|
25
|
+
if (mask & UIEventButtonMaskForButtonNumber(3)) ret |= Pointer::MOUSE_MIDDLE;
|
|
26
|
+
}
|
|
27
|
+
return ret;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
static uint
|
|
31
|
+
get_type (UITouch* touch, UIEvent* event)
|
|
15
32
|
{
|
|
16
33
|
assert(touch);
|
|
17
34
|
|
|
@@ -22,8 +39,15 @@ namespace Reflex
|
|
|
22
39
|
{
|
|
23
40
|
case UITouchTypeDirect: return Pointer::TOUCH;
|
|
24
41
|
case UITouchTypePencil: return Pointer::PEN;
|
|
25
|
-
default: return Pointer::TYPE_NONE;
|
|
26
42
|
}
|
|
43
|
+
|
|
44
|
+
if (@available(iOS 13.4, *))
|
|
45
|
+
{
|
|
46
|
+
if (type == UITouchTypeIndirectPointer)
|
|
47
|
+
return Pointer::MOUSE | get_mouse_button_types(event);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return Pointer::TYPE_NONE;
|
|
27
51
|
}
|
|
28
52
|
|
|
29
53
|
static Pointer::Action
|
|
@@ -52,14 +76,8 @@ namespace Reflex
|
|
|
52
76
|
}
|
|
53
77
|
|
|
54
78
|
static uint
|
|
55
|
-
|
|
79
|
+
to_modifiers (NSInteger flags)
|
|
56
80
|
{
|
|
57
|
-
if (!event) return 0;
|
|
58
|
-
|
|
59
|
-
NSInteger flags = 0;
|
|
60
|
-
if (@available(iOS 13.4, *))
|
|
61
|
-
flags = event.modifierFlags;
|
|
62
|
-
|
|
63
81
|
return
|
|
64
82
|
(flags & UIKeyModifierAlphaShift) ? MOD_CAPS : 0 |
|
|
65
83
|
(flags & UIKeyModifierShift) ? MOD_SHIFT : 0 |
|
|
@@ -69,6 +87,18 @@ namespace Reflex
|
|
|
69
87
|
(flags & UIKeyModifierNumericPad) ? MOD_NUMPAD : 0;
|
|
70
88
|
}
|
|
71
89
|
|
|
90
|
+
static uint
|
|
91
|
+
get_modifiers (const UIEvent* event)
|
|
92
|
+
{
|
|
93
|
+
if (!event) return 0;
|
|
94
|
+
|
|
95
|
+
NSInteger flags = 0;
|
|
96
|
+
if (@available(iOS 13.4, *))
|
|
97
|
+
flags = event.modifierFlags;
|
|
98
|
+
|
|
99
|
+
return to_modifiers(flags);
|
|
100
|
+
}
|
|
101
|
+
|
|
72
102
|
uint
|
|
73
103
|
KeyEvent_get_modifiers ()
|
|
74
104
|
{
|
|
@@ -76,25 +106,45 @@ namespace Reflex
|
|
|
76
106
|
}
|
|
77
107
|
|
|
78
108
|
|
|
109
|
+
static const char*
|
|
110
|
+
get_chars (UIKey* key) API_AVAILABLE(ios(13.4))
|
|
111
|
+
{
|
|
112
|
+
NSString* s = key.characters;
|
|
113
|
+
if (!s || [s hasPrefix: @"UIKeyInput"])
|
|
114
|
+
return NULL;
|
|
115
|
+
return s.UTF8String;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
NativeKeyEvent::NativeKeyEvent (UIPress* press, Action action, int repeat)
|
|
119
|
+
: KeyEvent(
|
|
120
|
+
action, get_chars(press.key), (int) press.key.keyCode,
|
|
121
|
+
to_modifiers(press.key.modifierFlags), repeat)
|
|
122
|
+
{
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
|
|
79
126
|
NativePointerEvent::NativePointerEvent (
|
|
80
127
|
NSSet* touches, UIEvent* event, UIView* view)
|
|
81
128
|
{
|
|
82
129
|
for (UITouch* touch in touches)
|
|
83
130
|
{
|
|
84
131
|
Pointer::Action action = get_action(touch);
|
|
132
|
+
uint type = get_type(touch, event);
|
|
85
133
|
|
|
86
134
|
Pointer pointer(
|
|
87
135
|
0,
|
|
88
|
-
|
|
136
|
+
type,
|
|
89
137
|
action,
|
|
90
138
|
to_point([touch locationInView: view]),
|
|
91
139
|
get_modifiers(event),
|
|
92
140
|
(uint) touch.tapCount,
|
|
93
141
|
action == Pointer::MOVE,
|
|
94
142
|
touch.timestamp);
|
|
95
|
-
Pointer_set_system_id(&pointer, (Pointer::ID) touch);
|
|
96
143
|
|
|
97
|
-
if (
|
|
144
|
+
if (!(type & Pointer::MOUSE))
|
|
145
|
+
Pointer_set_system_id(&pointer, (Pointer::ID) touch);
|
|
146
|
+
|
|
147
|
+
if (action != Pointer::DOWN)
|
|
98
148
|
{
|
|
99
149
|
Pointer_set_prev_position(
|
|
100
150
|
&pointer, to_point([touch previousLocationInView: view]));
|
|
@@ -105,5 +155,38 @@ namespace Reflex
|
|
|
105
155
|
}
|
|
106
156
|
}
|
|
107
157
|
|
|
158
|
+
NativePointerEvent::NativePointerEvent (
|
|
159
|
+
UIHoverGestureRecognizer* recognizer, UIView* view)
|
|
160
|
+
{
|
|
161
|
+
assert(recognizer && view);
|
|
162
|
+
|
|
163
|
+
Pointer pointer(
|
|
164
|
+
0,
|
|
165
|
+
Pointer::MOUSE,
|
|
166
|
+
Pointer::MOVE,
|
|
167
|
+
to_point([recognizer locationInView: view]),
|
|
168
|
+
get_modifiers(nil),
|
|
169
|
+
0,
|
|
170
|
+
false,
|
|
171
|
+
Xot::time());
|
|
172
|
+
|
|
173
|
+
if (pointer)
|
|
174
|
+
PointerEvent_add_pointer(this, pointer);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
NativeWheelEvent::NativeWheelEvent (
|
|
179
|
+
UIPanGestureRecognizer* recognizer, UIView* view, CGPoint position)
|
|
180
|
+
: WheelEvent(0, 0, 0, 0, 0, 0, get_modifiers(nil))
|
|
181
|
+
{
|
|
182
|
+
assert(recognizer && view);
|
|
183
|
+
|
|
184
|
+
WheelEvent_set_position(this, to_point(position));
|
|
185
|
+
|
|
186
|
+
CGPoint delta = [recognizer translationInView: view];
|
|
187
|
+
this->dposition().x = delta.x;
|
|
188
|
+
this->dposition().y = delta.y;
|
|
189
|
+
}
|
|
190
|
+
|
|
108
191
|
|
|
109
192
|
}// Reflex
|
data/src/ios/view_controller.mm
CHANGED
|
@@ -65,6 +65,14 @@ show_reflex_view_controller (
|
|
|
65
65
|
[top presentViewController: reflex_vc animated: YES completion: nil];
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
static BOOL
|
|
69
|
+
is_modifier_key (long keyCode) API_AVAILABLE(ios(13.4))
|
|
70
|
+
{
|
|
71
|
+
return
|
|
72
|
+
keyCode >= UIKeyboardHIDUsageKeyboardLeftControl &&
|
|
73
|
+
keyCode <= UIKeyboardHIDUsageKeyboardRightGUI;
|
|
74
|
+
}
|
|
75
|
+
|
|
68
76
|
|
|
69
77
|
namespace global
|
|
70
78
|
{
|
|
@@ -121,12 +129,18 @@ ReflexViewController_get_show_fun ()
|
|
|
121
129
|
@end
|
|
122
130
|
|
|
123
131
|
|
|
124
|
-
@interface ReflexViewController () <GLKViewDelegate>
|
|
132
|
+
@interface ReflexViewController () <GLKViewDelegate, UIGestureRecognizerDelegate>
|
|
125
133
|
|
|
126
134
|
@property(nonatomic, strong) ReflexView* reflexView;
|
|
127
135
|
|
|
128
136
|
@property(nonatomic, strong) CADisplayLink* displayLink;
|
|
129
137
|
|
|
138
|
+
@property(nonatomic, strong) UIHoverGestureRecognizer* hoverRecognizer;
|
|
139
|
+
|
|
140
|
+
@property(nonatomic, strong) UIPress* repeatingKeyPress;
|
|
141
|
+
|
|
142
|
+
@property(nonatomic, strong) NSTimer* repeatingKeyTimer;
|
|
143
|
+
|
|
130
144
|
@end
|
|
131
145
|
|
|
132
146
|
|
|
@@ -136,6 +150,7 @@ ReflexViewController_get_show_fun ()
|
|
|
136
150
|
Reflex::Window *pwindow, *ptr_for_rebind;
|
|
137
151
|
int update_count;
|
|
138
152
|
int touching_count;
|
|
153
|
+
int repeating_key_count;
|
|
139
154
|
}
|
|
140
155
|
|
|
141
156
|
- (id) init
|
|
@@ -143,10 +158,11 @@ ReflexViewController_get_show_fun ()
|
|
|
143
158
|
self = [super init];
|
|
144
159
|
if (!self) return nil;
|
|
145
160
|
|
|
146
|
-
pwindow
|
|
147
|
-
ptr_for_rebind
|
|
148
|
-
update_count
|
|
149
|
-
touching_count
|
|
161
|
+
pwindow =
|
|
162
|
+
ptr_for_rebind = NULL;
|
|
163
|
+
update_count = 0;
|
|
164
|
+
touching_count = 0;
|
|
165
|
+
repeating_key_count = 0;
|
|
150
166
|
|
|
151
167
|
return self;
|
|
152
168
|
}
|
|
@@ -264,15 +280,43 @@ ReflexViewController_get_show_fun ()
|
|
|
264
280
|
//view.drawableMultisample = GLKViewDrawableMultisample4X;
|
|
265
281
|
|
|
266
282
|
[self.view addSubview: view];
|
|
283
|
+
[self setupMouseRecognizers: view];
|
|
267
284
|
|
|
268
285
|
self.reflexView = view;
|
|
269
286
|
}
|
|
270
287
|
|
|
288
|
+
- (void) setupMouseRecognizers: (UIView*) view
|
|
289
|
+
{
|
|
290
|
+
if (@available(iOS 13.4, *))
|
|
291
|
+
{
|
|
292
|
+
UIHoverGestureRecognizer* hover = [[[UIHoverGestureRecognizer alloc]
|
|
293
|
+
initWithTarget: self action: @selector(hoverChanged:)]
|
|
294
|
+
autorelease];
|
|
295
|
+
hover.delegate = self;
|
|
296
|
+
[view addGestureRecognizer: hover];
|
|
297
|
+
self.hoverRecognizer = hover;
|
|
298
|
+
|
|
299
|
+
UIPanGestureRecognizer* pan = [[[UIPanGestureRecognizer alloc]
|
|
300
|
+
initWithTarget: self action: @selector(scrollChanged:)]
|
|
301
|
+
autorelease];
|
|
302
|
+
pan.allowedScrollTypesMask = UIScrollTypeMaskAll;
|
|
303
|
+
// 0/0 touches means the recognizer only fires from indirect scroll
|
|
304
|
+
// (mouse wheel / trackpad scroll) — touch-based panning is left to
|
|
305
|
+
// the touchesBegan/etc. path so this won't intercept finger pans.
|
|
306
|
+
pan.minimumNumberOfTouches = 0;
|
|
307
|
+
pan.maximumNumberOfTouches = 0;
|
|
308
|
+
pan.delegate = self;
|
|
309
|
+
[view addGestureRecognizer: pan];
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
271
313
|
- (void) cleanupReflexView
|
|
272
314
|
{
|
|
273
315
|
ReflexView* view = self.reflexView;
|
|
274
316
|
if (!view) return;
|
|
275
317
|
|
|
318
|
+
[self stopKeyRepeat];
|
|
319
|
+
|
|
276
320
|
if (view.context && view.context == [EAGLContext currentContext])
|
|
277
321
|
Rays::activate_offscreen_context();
|
|
278
322
|
|
|
@@ -299,10 +343,15 @@ ReflexViewController_get_show_fun ()
|
|
|
299
343
|
selector: @selector(willResignActive)
|
|
300
344
|
name: UIApplicationWillResignActiveNotification
|
|
301
345
|
object: nil];
|
|
346
|
+
|
|
347
|
+
[self becomeFirstResponder];
|
|
302
348
|
}
|
|
303
349
|
|
|
304
350
|
- (void) viewDidDisappear: (BOOL) animated
|
|
305
351
|
{
|
|
352
|
+
[self stopKeyRepeat];
|
|
353
|
+
[self resignFirstResponder];
|
|
354
|
+
|
|
306
355
|
[NSNotificationCenter.defaultCenter
|
|
307
356
|
removeObserver: self
|
|
308
357
|
name: UIApplicationDidBecomeActiveNotification
|
|
@@ -325,6 +374,7 @@ ReflexViewController_get_show_fun ()
|
|
|
325
374
|
|
|
326
375
|
- (void) willResignActive
|
|
327
376
|
{
|
|
377
|
+
[self stopKeyRepeat];
|
|
328
378
|
Window_call_deactivate_event(self.window);
|
|
329
379
|
}
|
|
330
380
|
|
|
@@ -334,6 +384,11 @@ ReflexViewController_get_show_fun ()
|
|
|
334
384
|
self.reflexView.frame = self.view.bounds;
|
|
335
385
|
}
|
|
336
386
|
|
|
387
|
+
- (BOOL) canBecomeFirstResponder
|
|
388
|
+
{
|
|
389
|
+
return YES;
|
|
390
|
+
}
|
|
391
|
+
|
|
337
392
|
- (void) startTimer
|
|
338
393
|
{
|
|
339
394
|
[self startTimer: 60];
|
|
@@ -509,4 +564,148 @@ ReflexViewController_get_show_fun ()
|
|
|
509
564
|
Window_call_pointer_event(win, &e);
|
|
510
565
|
}
|
|
511
566
|
|
|
567
|
+
- (void) hoverChanged: (UIHoverGestureRecognizer*) recognizer
|
|
568
|
+
API_AVAILABLE(ios(13.4))
|
|
569
|
+
{
|
|
570
|
+
Reflex::Window* win = self.window;
|
|
571
|
+
if (!win) return;
|
|
572
|
+
|
|
573
|
+
if (touching_count > 0) return;
|
|
574
|
+
|
|
575
|
+
if (
|
|
576
|
+
recognizer.state != UIGestureRecognizerStateBegan &&
|
|
577
|
+
recognizer.state != UIGestureRecognizerStateChanged)
|
|
578
|
+
{
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
Reflex::NativePointerEvent e(recognizer, self.reflexView);
|
|
583
|
+
if (e.size() > 0)
|
|
584
|
+
Window_call_pointer_event(win, &e);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
- (void) scrollChanged: (UIPanGestureRecognizer*) recognizer
|
|
588
|
+
API_AVAILABLE(ios(13.4))
|
|
589
|
+
{
|
|
590
|
+
Reflex::Window* win = self.window;
|
|
591
|
+
if (!win) return;
|
|
592
|
+
|
|
593
|
+
if (
|
|
594
|
+
recognizer.state != UIGestureRecognizerStateBegan &&
|
|
595
|
+
recognizer.state != UIGestureRecognizerStateChanged)
|
|
596
|
+
{
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
// The pan recognizer's locationInView drifts with the synthetic scroll
|
|
601
|
+
// touch, so use the hover recognizer's location — it tracks the actual
|
|
602
|
+
// cursor and exposes the last known position regardless of its state.
|
|
603
|
+
CGPoint pos = [self.hoverRecognizer locationInView: self.reflexView];
|
|
604
|
+
|
|
605
|
+
Reflex::NativeWheelEvent e(recognizer, self.reflexView, pos);
|
|
606
|
+
Window_call_wheel_event(win, &e);
|
|
607
|
+
|
|
608
|
+
// reset translation so subsequent deltas are incremental
|
|
609
|
+
[recognizer setTranslation: CGPointZero inView: self.reflexView];
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
- (BOOL) gestureRecognizer: (UIGestureRecognizer*) recognizer
|
|
613
|
+
shouldRecognizeSimultaneouslyWithGestureRecognizer: (UIGestureRecognizer*) other
|
|
614
|
+
{
|
|
615
|
+
// UIKit only calls this delegate method when at least one of the two
|
|
616
|
+
// recognizers has us set as its delegate, and we only set ourselves as
|
|
617
|
+
// the delegate for our mouse recognizers (hover / indirect scroll). So
|
|
618
|
+
// every call here already involves one of ours, and we want it to run
|
|
619
|
+
// alongside whatever else is on the view (touches, app-added gestures).
|
|
620
|
+
return YES;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
- (void) pressesBegan: (NSSet<UIPress*>*) presses
|
|
624
|
+
withEvent: (UIPressesEvent*) event
|
|
625
|
+
{
|
|
626
|
+
if (@available(iOS 13.4, *))
|
|
627
|
+
[self handlePresses: presses action: Reflex::KeyEvent::DOWN];
|
|
628
|
+
[super pressesBegan: presses withEvent: event];
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
- (void) pressesEnded: (NSSet<UIPress*>*) presses
|
|
632
|
+
withEvent: (UIPressesEvent*) event
|
|
633
|
+
{
|
|
634
|
+
if (@available(iOS 13.4, *))
|
|
635
|
+
[self handlePresses: presses action: Reflex::KeyEvent::UP];
|
|
636
|
+
[super pressesEnded: presses withEvent: event];
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
- (void) pressesCancelled: (NSSet<UIPress*>*) presses
|
|
640
|
+
withEvent: (UIPressesEvent*) event
|
|
641
|
+
{
|
|
642
|
+
if (@available(iOS 13.4, *))
|
|
643
|
+
[self handlePresses: presses action: Reflex::KeyEvent::UP];
|
|
644
|
+
[super pressesCancelled: presses withEvent: event];
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
- (void) handlePresses: (NSSet<UIPress*>*) presses
|
|
648
|
+
action: (Reflex::KeyEvent::Action) action
|
|
649
|
+
API_AVAILABLE(ios(13.4))
|
|
650
|
+
{
|
|
651
|
+
Reflex::Window* win = self.window;
|
|
652
|
+
if (!win) return;
|
|
653
|
+
|
|
654
|
+
for (UIPress* press in presses)
|
|
655
|
+
{
|
|
656
|
+
if (!press.key) continue;
|
|
657
|
+
Reflex::NativeKeyEvent e(press, action);
|
|
658
|
+
Window_call_key_event(win, &e);
|
|
659
|
+
|
|
660
|
+
if (action == Reflex::KeyEvent::DOWN)
|
|
661
|
+
{
|
|
662
|
+
if (!is_modifier_key(press.key.keyCode))
|
|
663
|
+
[self startKeyRepeat: press];
|
|
664
|
+
}
|
|
665
|
+
else if (
|
|
666
|
+
self.repeatingKeyPress &&
|
|
667
|
+
press.key.keyCode == self.repeatingKeyPress.key.keyCode)
|
|
668
|
+
{
|
|
669
|
+
[self stopKeyRepeat];
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
- (void) startKeyRepeat: (UIPress*) press
|
|
675
|
+
API_AVAILABLE(ios(13.4))
|
|
676
|
+
{
|
|
677
|
+
[self stopKeyRepeat];
|
|
678
|
+
|
|
679
|
+
repeating_key_count = 0;
|
|
680
|
+
self.repeatingKeyPress = press;
|
|
681
|
+
self.repeatingKeyTimer = [NSTimer scheduledTimerWithTimeInterval: 0.4
|
|
682
|
+
target: self selector: @selector(keyRepeatFired:) userInfo: nil repeats: NO];
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
- (void) keyRepeatFired: (NSTimer*) timer
|
|
686
|
+
API_AVAILABLE(ios(13.4))
|
|
687
|
+
{
|
|
688
|
+
Reflex::Window* win = self.window;
|
|
689
|
+
UIPress* press = self.repeatingKeyPress;
|
|
690
|
+
if (!win || !press || !press.key)
|
|
691
|
+
{
|
|
692
|
+
[self stopKeyRepeat];
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
Reflex::NativeKeyEvent e(press, Reflex::KeyEvent::DOWN, ++repeating_key_count);
|
|
697
|
+
Window_call_key_event(win, &e);
|
|
698
|
+
|
|
699
|
+
self.repeatingKeyTimer = [NSTimer scheduledTimerWithTimeInterval: 0.1
|
|
700
|
+
target: self selector: @selector(keyRepeatFired:) userInfo: nil repeats: NO];
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
- (void) stopKeyRepeat
|
|
704
|
+
{
|
|
705
|
+
[self.repeatingKeyTimer invalidate];
|
|
706
|
+
self.repeatingKeyTimer = nil;
|
|
707
|
+
self.repeatingKeyPress = nil;
|
|
708
|
+
repeating_key_count = 0;
|
|
709
|
+
}
|
|
710
|
+
|
|
512
711
|
@end// ReflexViewController
|
data/src/osx/event.h
CHANGED
data/src/osx/event.mm
CHANGED
|
@@ -52,10 +52,8 @@ namespace Reflex
|
|
|
52
52
|
return [chars UTF8String];
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
NativeKeyEvent::NativeKeyEvent (NSEvent* e, Action action)
|
|
56
|
-
: KeyEvent(
|
|
57
|
-
action, get_chars(e), [e keyCode],
|
|
58
|
-
get_modifiers(e), [e isARepeat] ? 1 : 0)
|
|
55
|
+
NativeKeyEvent::NativeKeyEvent (NSEvent* e, Action action, int repeat)
|
|
56
|
+
: KeyEvent(action, get_chars(e), [e keyCode], get_modifiers(e), repeat)
|
|
59
57
|
{
|
|
60
58
|
}
|
|
61
59
|
|
|
@@ -163,7 +161,7 @@ namespace Reflex
|
|
|
163
161
|
|
|
164
162
|
|
|
165
163
|
NativeWheelEvent::NativeWheelEvent (NSEvent* e, NSView* view)
|
|
166
|
-
: WheelEvent(0, 0, 0, [e deltaX], [e deltaY], [e deltaZ], get_modifiers(e))
|
|
164
|
+
: WheelEvent(0, 0, 0, [e deltaX], -[e deltaY], [e deltaZ], get_modifiers(e))
|
|
167
165
|
{
|
|
168
166
|
WheelEvent_set_position(this, get_pointer_position(e, view));
|
|
169
167
|
}
|
data/src/osx/native_window.mm
CHANGED
|
@@ -56,6 +56,8 @@ move_to_main_screen_origin (NativeWindow* window)
|
|
|
56
56
|
OpenGLView* view;
|
|
57
57
|
NSTimer* timer;
|
|
58
58
|
int update_count;
|
|
59
|
+
int repeating_key_code;
|
|
60
|
+
int repeating_key_count;
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
- (id) init
|
|
@@ -67,11 +69,13 @@ move_to_main_screen_origin (NativeWindow* window)
|
|
|
67
69
|
defer: NO];
|
|
68
70
|
if (!self) return nil;
|
|
69
71
|
|
|
70
|
-
pwindow
|
|
71
|
-
ptr_for_rebind
|
|
72
|
-
view
|
|
73
|
-
timer
|
|
74
|
-
update_count
|
|
72
|
+
pwindow =
|
|
73
|
+
ptr_for_rebind = NULL;
|
|
74
|
+
view = nil;
|
|
75
|
+
timer = nil;
|
|
76
|
+
update_count = 0;
|
|
77
|
+
repeating_key_code = -1;
|
|
78
|
+
repeating_key_count = 0;
|
|
75
79
|
|
|
76
80
|
[self setDelegate: self];
|
|
77
81
|
[self setupContentView];
|
|
@@ -365,7 +369,16 @@ move_to_main_screen_origin (NativeWindow* window)
|
|
|
365
369
|
Reflex::Window* win = self.window;
|
|
366
370
|
if (!win) return;
|
|
367
371
|
|
|
368
|
-
|
|
372
|
+
int code = (int) event.keyCode;
|
|
373
|
+
if (event.isARepeat && code == repeating_key_code)
|
|
374
|
+
++repeating_key_count;
|
|
375
|
+
else
|
|
376
|
+
{
|
|
377
|
+
repeating_key_code = code;
|
|
378
|
+
repeating_key_count = 0;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
Reflex::NativeKeyEvent e(event, Reflex::KeyEvent::DOWN, repeating_key_count);
|
|
369
382
|
Window_call_key_event(win, &e);
|
|
370
383
|
}
|
|
371
384
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: reflexion
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- xordog
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-05-
|
|
11
|
+
date: 2026-05-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: xot
|
|
@@ -16,42 +16,42 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 0.3.
|
|
19
|
+
version: 0.3.13
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 0.3.
|
|
26
|
+
version: 0.3.13
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: rucy
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: 0.3.
|
|
33
|
+
version: 0.3.13
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: 0.3.
|
|
40
|
+
version: 0.3.13
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: rays
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: 0.3.
|
|
47
|
+
version: 0.3.14
|
|
48
48
|
type: :runtime
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: 0.3.
|
|
54
|
+
version: 0.3.14
|
|
55
55
|
description: This library helps you to develop interactive graphical user interface.
|
|
56
56
|
email: xordog@gmail.com
|
|
57
57
|
executables: []
|