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.
Files changed (275) hide show
  1. checksums.yaml +4 -4
  2. data/.doc/ext/reflex/application.cpp +37 -6
  3. data/.doc/ext/reflex/capture_event.cpp +1 -1
  4. data/.doc/ext/reflex/chase_constraint.cpp +1 -1
  5. data/.doc/ext/reflex/clipboard.cpp +1 -1
  6. data/.doc/ext/reflex/color_event.cpp +76 -0
  7. data/.doc/ext/reflex/color_picker.cpp +113 -0
  8. data/.doc/ext/reflex/constraint.cpp +1 -1
  9. data/.doc/ext/reflex/contact_event.cpp +1 -1
  10. data/.doc/ext/reflex/control_change_event.cpp +1 -1
  11. data/.doc/ext/reflex/device.cpp +1 -1
  12. data/.doc/ext/reflex/device_event.cpp +1 -1
  13. data/.doc/ext/reflex/draw_event.cpp +1 -1
  14. data/.doc/ext/reflex/ellipse_shape.cpp +1 -1
  15. data/.doc/ext/reflex/event.cpp +1 -1
  16. data/.doc/ext/reflex/file_dialog.cpp +181 -0
  17. data/.doc/ext/reflex/file_event.cpp +103 -0
  18. data/.doc/ext/reflex/filter.cpp +1 -1
  19. data/.doc/ext/reflex/focus_event.cpp +1 -1
  20. data/.doc/ext/reflex/frame_event.cpp +1 -1
  21. data/.doc/ext/reflex/gamepad.cpp +48 -0
  22. data/.doc/ext/reflex/image_view.cpp +1 -1
  23. data/.doc/ext/reflex/key_event.cpp +1 -274
  24. data/.doc/ext/reflex/line_shape.cpp +1 -1
  25. data/.doc/ext/reflex/link_constraint.cpp +1 -1
  26. data/.doc/ext/reflex/menu.cpp +6 -5
  27. data/.doc/ext/reflex/midi.cpp +9 -2
  28. data/.doc/ext/reflex/midi_event.cpp +1 -1
  29. data/.doc/ext/reflex/motion_event.cpp +1 -1
  30. data/.doc/ext/reflex/native.cpp +18 -6
  31. data/.doc/ext/reflex/note_event.cpp +1 -1
  32. data/.doc/ext/reflex/pin.cpp +1 -1
  33. data/.doc/ext/reflex/pointer.cpp +1 -1
  34. data/.doc/ext/reflex/pointer_event.cpp +2 -2
  35. data/.doc/ext/reflex/polygon_shape.cpp +1 -1
  36. data/.doc/ext/reflex/rect_shape.cpp +1 -1
  37. data/.doc/ext/reflex/reflex.cpp +566 -232
  38. data/.doc/ext/reflex/screen.cpp +27 -1
  39. data/.doc/ext/reflex/scroll_event.cpp +1 -1
  40. data/.doc/ext/reflex/selector.cpp +1 -1
  41. data/.doc/ext/reflex/shape.cpp +1 -1
  42. data/.doc/ext/reflex/snap_constraint.cpp +1 -1
  43. data/.doc/ext/reflex/style.cpp +1 -1
  44. data/.doc/ext/reflex/style_length.cpp +1 -1
  45. data/.doc/ext/reflex/text_event.cpp +104 -0
  46. data/.doc/ext/reflex/timer.cpp +1 -1
  47. data/.doc/ext/reflex/timer_event.cpp +1 -1
  48. data/.doc/ext/reflex/update_event.cpp +1 -1
  49. data/.doc/ext/reflex/view.cpp +110 -56
  50. data/.doc/ext/reflex/wheel_constraint.cpp +1 -1
  51. data/.doc/ext/reflex/wheel_event.cpp +1 -1
  52. data/.doc/ext/reflex/window.cpp +226 -17
  53. data/.github/workflows/release-gem.yml +2 -49
  54. data/.github/workflows/tag.yml +5 -28
  55. data/.github/workflows/test.yml +1 -37
  56. data/ChangeLog.md +54 -0
  57. data/Gemfile.lock +13 -8
  58. data/Rakefile +13 -2
  59. data/Reflex.podspec +2 -2
  60. data/VERSION +1 -1
  61. data/ext/reflex/application.cpp +41 -6
  62. data/ext/reflex/capture_event.cpp +1 -1
  63. data/ext/reflex/chase_constraint.cpp +1 -1
  64. data/ext/reflex/clipboard.cpp +1 -1
  65. data/ext/reflex/color_event.cpp +80 -0
  66. data/ext/reflex/color_picker.cpp +121 -0
  67. data/ext/reflex/constraint.cpp +1 -1
  68. data/ext/reflex/contact_event.cpp +1 -1
  69. data/ext/reflex/control_change_event.cpp +1 -1
  70. data/ext/reflex/device.cpp +1 -1
  71. data/ext/reflex/device_event.cpp +1 -1
  72. data/ext/reflex/draw_event.cpp +1 -1
  73. data/ext/reflex/ellipse_shape.cpp +1 -1
  74. data/ext/reflex/event.cpp +1 -1
  75. data/ext/reflex/extconf.rb +4 -2
  76. data/ext/reflex/file_dialog.cpp +194 -0
  77. data/ext/reflex/file_event.cpp +108 -0
  78. data/ext/reflex/filter.cpp +1 -1
  79. data/ext/reflex/focus_event.cpp +1 -1
  80. data/ext/reflex/frame_event.cpp +1 -1
  81. data/ext/reflex/gamepad.cpp +50 -0
  82. data/ext/reflex/image_view.cpp +1 -1
  83. data/ext/reflex/key_event.cpp +1 -275
  84. data/ext/reflex/line_shape.cpp +1 -1
  85. data/ext/reflex/link_constraint.cpp +1 -1
  86. data/ext/reflex/menu.cpp +8 -7
  87. data/ext/reflex/midi.cpp +11 -3
  88. data/ext/reflex/midi_event.cpp +1 -1
  89. data/ext/reflex/motion_event.cpp +1 -1
  90. data/ext/reflex/native.cpp +18 -6
  91. data/ext/reflex/note_event.cpp +1 -1
  92. data/ext/reflex/pin.cpp +1 -1
  93. data/ext/reflex/pointer.cpp +1 -1
  94. data/ext/reflex/pointer_event.cpp +2 -2
  95. data/ext/reflex/polygon_shape.cpp +1 -1
  96. data/ext/reflex/rect_shape.cpp +1 -1
  97. data/ext/reflex/reflex.cpp +568 -232
  98. data/ext/reflex/screen.cpp +31 -2
  99. data/ext/reflex/scroll_event.cpp +1 -1
  100. data/ext/reflex/selector.cpp +1 -1
  101. data/ext/reflex/selector.h +9 -9
  102. data/ext/reflex/shape.cpp +1 -1
  103. data/ext/reflex/snap_constraint.cpp +1 -1
  104. data/ext/reflex/style.cpp +1 -1
  105. data/ext/reflex/style_length.cpp +1 -1
  106. data/ext/reflex/text_event.cpp +111 -0
  107. data/ext/reflex/timer.cpp +1 -1
  108. data/ext/reflex/timer_event.cpp +1 -1
  109. data/ext/reflex/update_event.cpp +1 -1
  110. data/ext/reflex/view.cpp +121 -61
  111. data/ext/reflex/wheel_constraint.cpp +1 -1
  112. data/ext/reflex/wheel_event.cpp +1 -1
  113. data/ext/reflex/window.cpp +256 -25
  114. data/include/reflex/application.h +10 -0
  115. data/include/reflex/color_picker.h +65 -0
  116. data/include/reflex/event.h +178 -88
  117. data/include/reflex/file_dialog.h +73 -0
  118. data/include/reflex/gamepad.h +3 -0
  119. data/include/reflex/menu.h +3 -3
  120. data/include/reflex/midi.h +3 -0
  121. data/include/reflex/reflex.h +2 -0
  122. data/include/reflex/ruby/application.h +6 -1
  123. data/include/reflex/ruby/color_picker.h +89 -0
  124. data/include/reflex/ruby/event.h +62 -29
  125. data/include/reflex/ruby/file_dialog.h +89 -0
  126. data/include/reflex/ruby/gamepad.h +46 -0
  127. data/include/reflex/ruby/reflex.h +3 -0
  128. data/include/reflex/ruby/view.h +92 -44
  129. data/include/reflex/ruby/window.h +60 -1
  130. data/include/reflex/ruby.h +3 -0
  131. data/include/reflex/screen.h +11 -2
  132. data/include/reflex/view.h +28 -16
  133. data/include/reflex/window.h +40 -8
  134. data/include/reflex.h +3 -0
  135. data/lib/reflex/application.rb +5 -5
  136. data/lib/reflex/autoinit.rb +3 -1
  137. data/lib/reflex/button.rb +3 -3
  138. data/lib/reflex/color_event.rb +16 -0
  139. data/lib/reflex/color_picker.rb +45 -0
  140. data/lib/reflex/control_change_event.rb +17 -0
  141. data/lib/reflex/file_dialog.rb +70 -0
  142. data/lib/reflex/file_event.rb +37 -0
  143. data/lib/reflex/helper.rb +58 -7
  144. data/lib/reflex/key_event.rb +9 -4
  145. data/lib/reflex/menu.rb +17 -1
  146. data/lib/reflex/model.rb +19 -19
  147. data/lib/reflex/note_event.rb +1 -1
  148. data/lib/reflex/pointer.rb +14 -3
  149. data/lib/reflex/pointer_event.rb +12 -1
  150. data/lib/reflex/reflex.rb +5 -0
  151. data/lib/reflex/shape.rb +14 -14
  152. data/lib/reflex/style.rb +16 -16
  153. data/lib/reflex/text_event.rb +40 -0
  154. data/lib/reflex/timer.rb +3 -3
  155. data/lib/reflex/view.rb +29 -14
  156. data/lib/reflex/wheel_event.rb +12 -3
  157. data/lib/reflex/window.rb +25 -13
  158. data/lib/reflex.rb +8 -2
  159. data/reflex.gemspec +4 -4
  160. data/samples/ime.rb +100 -0
  161. data/samples/ios/hello/hello.xcodeproj/project.pbxproj +236 -224
  162. data/samples/menu.rb +4 -1
  163. data/samples/model.rb +3 -3
  164. data/samples/test/alert.rb +93 -0
  165. data/samples/test/always_on.rb +76 -0
  166. data/samples/test/app_background.rb +51 -0
  167. data/samples/test/boundary.rb +75 -0
  168. data/samples/test/callback_exception.rb +101 -0
  169. data/samples/test/cancel.rb +53 -0
  170. data/samples/test/color_picker.rb +63 -0
  171. data/samples/test/file_dialog.rb +102 -0
  172. data/samples/window_style.rb +156 -0
  173. data/src/application.cpp +159 -18
  174. data/src/application.h +92 -7
  175. data/src/color_picker.cpp +113 -0
  176. data/src/color_picker.h +36 -0
  177. data/src/event.cpp +410 -252
  178. data/src/event.h +12 -0
  179. data/src/file_dialog.cpp +163 -0
  180. data/src/file_dialog.h +52 -0
  181. data/src/gamepad.cpp +42 -5
  182. data/src/gamepad.h +4 -0
  183. data/src/ios/app_delegate.mm +5 -3
  184. data/src/ios/application.mm +24 -0
  185. data/src/ios/color_picker.mm +19 -0
  186. data/src/ios/file_dialog.mm +21 -0
  187. data/src/ios/gamepad.mm +4 -4
  188. data/src/ios/menu.mm +5 -0
  189. data/src/ios/reflex.mm +8 -0
  190. data/src/ios/screen.mm +26 -0
  191. data/src/ios/view_controller.mm +2 -30
  192. data/src/ios/window.mm +38 -9
  193. data/src/menu.cpp +66 -4
  194. data/src/menu.h +17 -1
  195. data/src/midi.cpp +61 -31
  196. data/src/osx/app_delegate.h +4 -0
  197. data/src/osx/app_delegate.mm +102 -22
  198. data/src/osx/application.mm +88 -6
  199. data/src/osx/color_picker.mm +112 -0
  200. data/src/osx/event.h +10 -0
  201. data/src/osx/event.mm +84 -30
  202. data/src/osx/file_dialog.mm +168 -0
  203. data/src/osx/gamepad.mm +2 -2
  204. data/src/osx/gamepad_hid.mm +1 -1
  205. data/src/osx/menu.mm +177 -33
  206. data/src/osx/native_window.h +16 -2
  207. data/src/osx/native_window.mm +114 -57
  208. data/src/osx/opengl_view.h +2 -1
  209. data/src/osx/opengl_view.mm +184 -43
  210. data/src/osx/reflex.mm +38 -0
  211. data/src/osx/screen.mm +36 -0
  212. data/src/osx/window.mm +106 -24
  213. data/src/pointer.cpp +13 -4
  214. data/src/pointer.h +4 -0
  215. data/src/rays.h +46 -0
  216. data/src/sdl/application.cpp +68 -8
  217. data/src/sdl/color_picker.cpp +18 -0
  218. data/src/sdl/event.cpp +24 -3
  219. data/src/sdl/event.h +12 -0
  220. data/src/sdl/file_dialog.cpp +20 -0
  221. data/src/sdl/gamepad.cpp +3 -7
  222. data/src/sdl/menu.cpp +5 -0
  223. data/src/sdl/reflex.cpp +20 -0
  224. data/src/sdl/screen.cpp +36 -0
  225. data/src/sdl/window.cpp +142 -29
  226. data/src/shape.cpp +15 -10
  227. data/src/view.cpp +287 -198
  228. data/src/view.h +4 -2
  229. data/src/vk.h +416 -0
  230. data/src/win32/application.cpp +162 -12
  231. data/src/win32/application.h +20 -0
  232. data/src/win32/color_picker.cpp +82 -0
  233. data/src/win32/event.cpp +114 -12
  234. data/src/win32/event.h +21 -4
  235. data/src/win32/file_dialog.cpp +226 -0
  236. data/src/win32/gamepad.cpp +9 -2
  237. data/src/win32/menu.cpp +191 -53
  238. data/src/win32/menu.h +9 -1
  239. data/src/win32/opengl.cpp +2 -9
  240. data/src/win32/reflex.cpp +44 -3
  241. data/src/win32/screen.cpp +164 -3
  242. data/src/win32/screen.h +8 -0
  243. data/src/win32/tray.cpp +191 -0
  244. data/src/win32/tray.h +22 -0
  245. data/src/win32/vk.cpp +11 -0
  246. data/src/win32/window.cpp +809 -148
  247. data/src/win32/window.h +6 -0
  248. data/src/window.cpp +718 -185
  249. data/src/window.h +66 -33
  250. data/src/world.cpp +9 -1
  251. data/test/helper.rb +17 -0
  252. data/test/test_application.rb +90 -1
  253. data/test/test_chase_constraint.rb +1 -3
  254. data/test/test_color_event.rb +36 -0
  255. data/test/test_color_picker.rb +62 -0
  256. data/test/test_constraint.rb +2 -4
  257. data/test/test_event.rb +1 -1
  258. data/test/test_file_dialog.rb +48 -0
  259. data/test/test_file_event.rb +43 -0
  260. data/test/test_has_text_preedit.rb +54 -0
  261. data/test/test_key_event.rb +20 -5
  262. data/test/test_link_constraint.rb +1 -3
  263. data/test/test_menu.rb +40 -10
  264. data/test/test_pointer.rb +33 -23
  265. data/test/test_pointer_event.rb +24 -9
  266. data/test/test_reflex.rb +36 -0
  267. data/test/test_screen.rb +24 -2
  268. data/test/test_snap_constraint.rb +1 -3
  269. data/test/test_text_event.rb +54 -0
  270. data/test/test_view.rb +41 -4
  271. data/test/test_wheel_constraint.rb +1 -3
  272. data/test/test_wheel_event.rb +13 -5
  273. data/test/test_window.rb +196 -44
  274. metadata +80 -10
  275. data/.github/workflows/utils.rb +0 -127
@@ -8,14 +8,25 @@
8
8
  #import "native_window.h"
9
9
 
10
10
 
11
- //#define TRANSPARENT_BACKGROUND
12
-
13
11
 
14
12
  @implementation OpenGLView
15
13
 
16
14
  {
17
15
  bool setup_context_done;
16
+ GLint surface_opacity;
18
17
  NSTrackingArea* tracking_area;
18
+
19
+ // the text being composed by the input method
20
+ NSString* marked_text;
21
+
22
+ // the clause being converted, relative to marked_text
23
+ NSRange marked_selection;
24
+
25
+ // whether marked text existed when the current keyDown: started
26
+ BOOL was_marked;
27
+
28
+ // whether the input method handled the key in the current keyDown:
29
+ BOOL consumed_by_ime;
19
30
  }
20
31
 
21
32
  - (id) initWithFrame: (NSRect) frame
@@ -31,7 +42,12 @@
31
42
  if (!self) return nil;
32
43
 
33
44
  setup_context_done = false;
45
+ surface_opacity = 1;
34
46
  tracking_area = nil;
47
+ marked_text = nil;
48
+ marked_selection = NSMakeRange(NSNotFound, 0);
49
+ was_marked = NO;
50
+ consumed_by_ime = NO;
35
51
 
36
52
  return self;
37
53
  }
@@ -47,12 +63,7 @@
47
63
  [self setOpenGLContext: context];
48
64
 
49
65
  GLint swapInterval = 1;
50
- [context setValues: &swapInterval forParameter: NSOpenGLCPSwapInterval];
51
-
52
- #ifdef TRANSPARENT_BACKGROUND
53
- GLint opacity = 0;
54
- [context setValues: &opacity forParameter: NSOpenGLCPSurfaceOpacity];
55
- #endif
66
+ [context setValues: &swapInterval forParameter: NSOpenGLContextParameterSwapInterval];
56
67
  }
57
68
 
58
69
  - (void) activateContext
@@ -60,8 +71,22 @@
60
71
  [self setupContext];
61
72
 
62
73
  NSOpenGLContext* context = self.openGLContext;
63
- if (context.view != self) [context setView: self];
74
+
75
+ // these have no replacement but Metal
76
+ #pragma GCC diagnostic push
77
+ #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
78
+ BOOL moved = context.view != self;
79
+ if (moved) [context setView: self];
80
+ #pragma GCC diagnostic pop
81
+
64
82
  [context makeCurrentContext];
83
+
84
+ GLint opacity = !self.window || self.window.isOpaque ? 1 : 0;
85
+ if (moved || opacity != surface_opacity)
86
+ {
87
+ surface_opacity = opacity;
88
+ [context setValues: &opacity forParameter: NSOpenGLContextParameterSurfaceOpacity];
89
+ }
65
90
  }
66
91
 
67
92
  - (BOOL) acceptsFirstResponder
@@ -74,32 +99,33 @@
74
99
  return YES;
75
100
  }
76
101
 
77
- #ifdef TRANSPARENT_BACKGROUND
78
102
  - (BOOL) isOpaque
79
103
  {
80
- return YES;
104
+ return self.window ? self.window.isOpaque : YES;
105
+ }
106
+
107
+ - (BOOL) mouseDownCanMoveWindow
108
+ {
109
+ return NO;
81
110
  }
82
- #endif
83
111
 
84
112
  - (void) drawRect: (NSRect) rect
85
113
  {
86
- NativeWindow* win = (NativeWindow*) [self window];
114
+ NativeWindow* win = (NativeWindow*) self.window;
87
115
  if (!win) return;
88
116
 
89
117
  [self activateContext];
90
118
  [win draw];
91
119
  [[NSOpenGLContext currentContext] flushBuffer];
120
+
121
+ if (!win.isOpaque && win.hasShadow)
122
+ [win invalidateShadow];// the shadow is made from what was drawn
92
123
  }
93
124
 
94
125
  - (void) viewDidMoveToWindow
95
126
  {
96
- [[self window] setAcceptsMouseMovedEvents: YES];
97
- [[self window] makeFirstResponder: self];
98
-
99
- #ifdef TRANSPARENT_BACKGROUND
100
- [[self window] setBackgroundColor: [NSColor clearColor]];
101
- [[self window] setOpaque: NO];
102
- #endif
127
+ [self.window setAcceptsMouseMovedEvents: YES];
128
+ [self.window makeFirstResponder: self];
103
129
  }
104
130
 
105
131
  - (void) updateTrackingAreas
@@ -132,27 +158,28 @@
132
158
  [tracking_area release];
133
159
  tracking_area = nil;
134
160
  }
161
+ [self clearMarkedText];
135
162
  [super dealloc];
136
163
  }
137
164
 
138
- - (void) insertText: (id) str
139
- {
140
- //NSLog(@"interText: %@", str);
141
- }
142
-
143
165
  - (void) keyDown: (NSEvent*) event
144
166
  {
145
- //[self interpretKeyEvents: [NSArray arrayWithObject: event]];
146
-
147
- NativeWindow* win = (NativeWindow*) [self window];
167
+ NativeWindow* win = (NativeWindow*) self.window;
148
168
  if (!win) return;
149
169
 
150
- [win keyDown: event];
170
+ was_marked = self.hasMarkedText;
171
+ consumed_by_ime = NO;
172
+
173
+ if (win.isTextInputEnabled)
174
+ [self interpretKeyEvents: [NSArray arrayWithObject: event]];
175
+
176
+ if (!consumed_by_ime)
177
+ [win keyDown: event];
151
178
  }
152
179
 
153
180
  - (void) keyUp: (NSEvent*) event
154
181
  {
155
- NativeWindow* win = (NativeWindow*) [self window];
182
+ NativeWindow* win = (NativeWindow*) self.window;
156
183
  if (!win) return;
157
184
 
158
185
  [win keyUp: event];
@@ -160,7 +187,7 @@
160
187
 
161
188
  - (void) flagsChanged: (NSEvent*) event
162
189
  {
163
- NativeWindow* win = (NativeWindow*) [self window];
190
+ NativeWindow* win = (NativeWindow*) self.window;
164
191
  if (!win) return;
165
192
 
166
193
  [win flagsChanged: event];
@@ -168,7 +195,7 @@
168
195
 
169
196
  - (void) mouseDown: (NSEvent*) event
170
197
  {
171
- NativeWindow* win = (NativeWindow*) [self window];
198
+ NativeWindow* win = (NativeWindow*) self.window;
172
199
  if (!win) return;
173
200
 
174
201
  [win mouseDown: event];
@@ -176,7 +203,7 @@
176
203
 
177
204
  - (void) mouseUp: (NSEvent*) event
178
205
  {
179
- NativeWindow* win = (NativeWindow*) [self window];
206
+ NativeWindow* win = (NativeWindow*) self.window;
180
207
  if (!win) return;
181
208
 
182
209
  [win mouseUp: event];
@@ -184,7 +211,7 @@
184
211
 
185
212
  - (void) mouseDragged: (NSEvent*) event
186
213
  {
187
- NativeWindow* win = (NativeWindow*) [self window];
214
+ NativeWindow* win = (NativeWindow*) self.window;
188
215
  if (!win) return;
189
216
 
190
217
  [win mouseDragged: event];
@@ -192,7 +219,7 @@
192
219
 
193
220
  - (void) rightMouseDown: (NSEvent*) event
194
221
  {
195
- NativeWindow* win = (NativeWindow*) [self window];
222
+ NativeWindow* win = (NativeWindow*) self.window;
196
223
  if (!win) return;
197
224
 
198
225
  [win mouseDown: event];
@@ -200,7 +227,7 @@
200
227
 
201
228
  - (void) rightMouseUp: (NSEvent*) event
202
229
  {
203
- NativeWindow* win = (NativeWindow*) [self window];
230
+ NativeWindow* win = (NativeWindow*) self.window;
204
231
  if (!win) return;
205
232
 
206
233
  [win mouseUp: event];
@@ -208,7 +235,7 @@
208
235
 
209
236
  - (void) rightMouseDragged: (NSEvent*) event
210
237
  {
211
- NativeWindow* win = (NativeWindow*) [self window];
238
+ NativeWindow* win = (NativeWindow*) self.window;
212
239
  if (!win) return;
213
240
 
214
241
  [win mouseDragged: event];
@@ -216,7 +243,7 @@
216
243
 
217
244
  - (void) otherMouseDown: (NSEvent*) event
218
245
  {
219
- NativeWindow* win = (NativeWindow*) [self window];
246
+ NativeWindow* win = (NativeWindow*) self.window;
220
247
  if (!win) return;
221
248
 
222
249
  [win mouseDown: event];
@@ -224,7 +251,7 @@
224
251
 
225
252
  - (void) otherMouseUp: (NSEvent*) event
226
253
  {
227
- NativeWindow* win = (NativeWindow*) [self window];
254
+ NativeWindow* win = (NativeWindow*) self.window;
228
255
  if (!win) return;
229
256
 
230
257
  [win mouseUp: event];
@@ -232,7 +259,7 @@
232
259
 
233
260
  - (void) otherMouseDragged: (NSEvent*) event
234
261
  {
235
- NativeWindow* win = (NativeWindow*) [self window];
262
+ NativeWindow* win = (NativeWindow*) self.window;
236
263
  if (!win) return;
237
264
 
238
265
  [win mouseDragged: event];
@@ -240,7 +267,7 @@
240
267
 
241
268
  - (void) mouseMoved: (NSEvent*) event
242
269
  {
243
- NativeWindow* win = (NativeWindow*) [self window];
270
+ NativeWindow* win = (NativeWindow*) self.window;
244
271
  if (!win) return;
245
272
 
246
273
  [win mouseMoved: event];
@@ -248,7 +275,7 @@
248
275
 
249
276
  - (void) mouseEntered: (NSEvent*) event
250
277
  {
251
- NativeWindow* win = (NativeWindow*) [self window];
278
+ NativeWindow* win = (NativeWindow*) self.window;
252
279
  if (!win) return;
253
280
 
254
281
  [win mouseEntered: event];
@@ -256,10 +283,124 @@
256
283
 
257
284
  - (void) mouseExited: (NSEvent*) event
258
285
  {
259
- NativeWindow* win = (NativeWindow*) [self window];
286
+ NativeWindow* win = (NativeWindow*) self.window;
260
287
  if (!win) return;
261
288
 
262
289
  [win mouseExited: event];
263
290
  }
264
291
 
292
+ static NSString*
293
+ to_string (id str)
294
+ {
295
+ return [str isKindOfClass: NSAttributedString.class]
296
+ ? [(NSAttributedString*) str string]
297
+ : (NSString*) str;
298
+ }
299
+
300
+ - (void) insertText: (id) string replacementRange: (NSRange) range
301
+ {
302
+ NativeWindow* win = (NativeWindow*) self.window;
303
+ if (!win) return;
304
+
305
+ // text committed from a composition session, or inserted without a key
306
+ // event (candidate window, emoji palette, dictation), has no key to
307
+ // report, so a key event is synthesized for it.
308
+ // otherwise, let keyDown: deliver the original key event.
309
+ BOOL synthesize = was_marked || NSApp.currentEvent.type != NSEventTypeKeyDown;
310
+ consumed_by_ime = synthesize;
311
+
312
+ [self clearMarkedText];
313
+ [win textCommit: to_string(string) synthesizeKeyEvent: synthesize];
314
+ }
315
+
316
+ - (void) setMarkedText: (id) string
317
+ selectedRange: (NSRange) selection
318
+ replacementRange: (NSRange) range
319
+ {
320
+ NativeWindow* win = (NativeWindow*) self.window;
321
+ if (!win) return;
322
+
323
+ NSString* text = to_string(string);
324
+ consumed_by_ime = YES;
325
+
326
+ [self clearMarkedText];
327
+ if (text.length > 0)
328
+ {
329
+ marked_text = [text retain];
330
+ marked_selection = selection;
331
+ }
332
+
333
+ [win textPreedit: text selection: selection];
334
+ }
335
+
336
+ - (void) unmarkText
337
+ {
338
+ if (!marked_text) return;
339
+
340
+ NativeWindow* win = (NativeWindow*) self.window;
341
+ if (!win) return;
342
+
343
+ [self clearMarkedText];
344
+ [win textPreedit: @"" selection: NSMakeRange(NSNotFound, 0)];
345
+ }
346
+
347
+ - (BOOL) hasMarkedText
348
+ {
349
+ return marked_text != nil;
350
+ }
351
+
352
+ - (NSRange) markedRange
353
+ {
354
+ return marked_text
355
+ ? NSMakeRange(0, marked_text.length)
356
+ : NSMakeRange(NSNotFound, 0);
357
+ }
358
+
359
+ - (NSRange) selectedRange
360
+ {
361
+ return marked_selection;
362
+ }
363
+
364
+ - (void) clearMarkedText
365
+ {
366
+ if (marked_text)
367
+ {
368
+ [marked_text release];
369
+ marked_text = nil;
370
+ }
371
+ marked_selection = NSMakeRange(NSNotFound, 0);
372
+ }
373
+
374
+ - (NSRect) firstRectForCharacterRange: (NSRange) range
375
+ actualRange: (NSRangePointer) actual
376
+ {
377
+ NativeWindow* win = (NativeWindow*) self.window;
378
+ if (!win) return NSZeroRect;
379
+
380
+ NSRect rect = win.textInputBounds;
381
+ return [win convertRectToScreen: [self convertRect: rect toView: nil]];
382
+ }
383
+
384
+ - (NSAttributedString*) attributedSubstringForProposedRange: (NSRange) range
385
+ actualRange: (NSRangePointer) actual
386
+ {
387
+ return nil;
388
+ }
389
+
390
+ - (NSUInteger) characterIndexForPoint: (NSPoint) point
391
+ {
392
+ return NSNotFound;
393
+ }
394
+
395
+ - (NSArray*) validAttributesForMarkedText
396
+ {
397
+ return [NSArray array];
398
+ }
399
+
400
+ - (void) doCommandBySelector: (SEL) selector
401
+ {
402
+ // NSResponder's default beeps for unhandled selectors, and keyDown:
403
+ // delivers the event as a key event anyway.
404
+ }
405
+
265
406
  @end// OpenGLView
data/src/osx/reflex.mm CHANGED
@@ -4,6 +4,7 @@
4
4
 
5
5
  #import <Cocoa/Cocoa.h>
6
6
  #include "reflex/exception.h"
7
+ #include "../vk.h"
7
8
 
8
9
 
9
10
  namespace Reflex
@@ -37,5 +38,42 @@ namespace Reflex
37
38
  global::pool = nil;
38
39
  }
39
40
 
41
+ static void
42
+ activate_app ()
43
+ {
44
+ NSApplication* app = NSApplication.sharedApplication;
45
+ if (app.activationPolicy == NSApplicationActivationPolicyProhibited)
46
+ [app setActivationPolicy: NSApplicationActivationPolicyRegular];
47
+
48
+ [app activateIgnoringOtherApps: YES];
49
+ }
50
+
51
+ void
52
+ alert (const char* message, const char* title)
53
+ {
54
+ if (!message)
55
+ argument_error(__FILE__, __LINE__);
56
+
57
+ activate_app();
58
+
59
+ NSAlert* alert = [[[NSAlert alloc] init] autorelease];
60
+ NSString* text = [NSString stringWithUTF8String: message];
61
+ if (title && *title)
62
+ {
63
+ alert.messageText = [NSString stringWithUTF8String: title];
64
+ alert.informativeText = text;
65
+ }
66
+ else
67
+ alert.messageText = text;
68
+
69
+ // in front of the other apps once runModal shows it, as macOS 14 or
70
+ // later lets no app launched from a terminal take the focus from it
71
+ [alert.window
72
+ performSelector: @selector(orderFrontRegardless)
73
+ withObject: nil afterDelay: 0 inModes: @[NSModalPanelRunLoopMode]];
74
+
75
+ [alert runModal];
76
+ }
77
+
40
78
 
41
79
  }// Reflex
data/src/osx/screen.mm CHANGED
@@ -2,6 +2,7 @@
2
2
  #include "screen.h"
3
3
 
4
4
 
5
+ #import <AppKit/AppKit.h>
5
6
  #include "reflex/exception.h"
6
7
 
7
8
 
@@ -43,6 +44,19 @@ namespace Reflex
43
44
  {
44
45
  }
45
46
 
47
+ String
48
+ Screen::name () const
49
+ {
50
+ if (!*this)
51
+ invalid_state_error(__FILE__, __LINE__);
52
+
53
+ const char* name = NULL;
54
+ if (@available(macOS 10.15, *))
55
+ name = self->screen.localizedName.UTF8String;
56
+
57
+ return name ? name : "";
58
+ }
59
+
46
60
  Bounds
47
61
  Screen::frame () const
48
62
  {
@@ -57,6 +71,15 @@ namespace Reflex
57
71
  f.size.height);
58
72
  }
59
73
 
74
+ float
75
+ Screen::pixel_density () const
76
+ {
77
+ if (!*this)
78
+ invalid_state_error(__FILE__, __LINE__);
79
+
80
+ return self->screen.backingScaleFactor;
81
+ }
82
+
60
83
  Screen::operator bool () const
61
84
  {
62
85
  return self->screen;
@@ -68,5 +91,18 @@ namespace Reflex
68
91
  return !operator bool();
69
92
  }
70
93
 
94
+ Screen::List
95
+ Screen::all ()
96
+ {
97
+ List list;
98
+ for (NSScreen* screen in NSScreen.screens)
99
+ {
100
+ Screen s;
101
+ Screen_initialize(&s, screen);
102
+ list.emplace_back(s);
103
+ }
104
+ return list;
105
+ }
106
+
71
107
 
72
108
  }// Reflex
data/src/osx/window.mm CHANGED
@@ -36,20 +36,18 @@ namespace Reflex
36
36
  NSWindowStyleMask
37
37
  Window_make_style_mask (uint flags, NSWindowStyleMask styleMask)
38
38
  {
39
- if (Xot::has_flag(flags, Window::FLAG_CLOSABLE))
40
- styleMask |= NSWindowStyleMaskClosable;
41
- else
42
- styleMask &= ~NSWindowStyleMaskClosable;
43
-
44
- if (Xot::has_flag(flags, Window::FLAG_MINIMIZABLE))
45
- styleMask |= NSWindowStyleMaskMiniaturizable;
46
- else
47
- styleMask &= ~NSWindowStyleMaskMiniaturizable;
48
-
49
- if (Xot::has_flag(flags, Window::FLAG_RESIZABLE))
50
- styleMask |= NSWindowStyleMaskResizable;
51
- else
52
- styleMask &= ~NSWindowStyleMaskResizable;
39
+ Xot::update_flag(
40
+ &styleMask, NSWindowStyleMaskClosable,
41
+ Xot::has_flag(flags, Window::FLAG_CLOSABLE));
42
+ Xot::update_flag(
43
+ &styleMask, NSWindowStyleMaskMiniaturizable,
44
+ Xot::has_flag(flags, Window::FLAG_MINIMIZABLE));
45
+ Xot::update_flag(
46
+ &styleMask, NSWindowStyleMaskResizable,
47
+ Xot::has_flag(flags, Window::FLAG_RESIZABLE));
48
+ Xot::update_flag(
49
+ &styleMask, NSWindowStyleMaskFullSizeContentView,
50
+ !Xot::has_flag(flags, Window::FLAG_TITLEBAR_BACKGROUND));
53
51
 
54
52
  return styleMask;
55
53
  }
@@ -75,9 +73,12 @@ namespace Reflex
75
73
  Window_default_flags ()
76
74
  {
77
75
  return
78
- Window::FLAG_CLOSABLE |
79
- Window::FLAG_RESIZABLE |
80
- Window::FLAG_MINIMIZABLE;
76
+ Window::FLAG_CLOSABLE |
77
+ Window::FLAG_MINIMIZABLE |
78
+ Window::FLAG_RESIZABLE |
79
+ Window::FLAG_TITLEBAR_BUTTONS |
80
+ Window::FLAG_TITLEBAR_BACKGROUND |
81
+ Window::FLAG_SHADOW;
81
82
  }
82
83
 
83
84
  void
@@ -127,10 +128,12 @@ namespace Reflex
127
128
  void
128
129
  Window_set_frame (Window* window, coord x, coord y, coord w, coord h)
129
130
  {
130
- NSRect f = [NativeWindow frameRectForContentRect: NSMakeRect(x, y, w, h)];
131
- f.origin.y = primary_screen_height() - (f.origin.y + h);
131
+ NativeWindow* native = get_native(window);
132
132
 
133
- [get_native(window) setFrame: f display: NO animate: NO];
133
+ NSRect r = [native frameRectForContentRect: NSMakeRect(x, y, w, h)];
134
+ r.origin.y = primary_screen_height() - (y + h);
135
+
136
+ [native setFrame: r display: NO animate: NO];
134
137
  }
135
138
 
136
139
  Bounds
@@ -138,10 +141,10 @@ namespace Reflex
138
141
  {
139
142
  NativeWindow* native = get_native(&window);
140
143
 
141
- NSRect f = [native contentRectForFrameRect: native.frame];
142
- f.origin.y = primary_screen_height() - (f.origin.y + f.size.height);
144
+ NSRect r = [native contentRectForFrameRect: native.frame];
145
+ r.origin.y = primary_screen_height() - (r.origin.y + r.size.height);
143
146
 
144
- return Bounds(f.origin.x, f.origin.y, f.size.width, f.size.height);
147
+ return Bounds(r.origin.x, r.origin.y, r.size.width, r.size.height);
145
148
  }
146
149
 
147
150
  void
@@ -174,13 +177,47 @@ namespace Reflex
174
177
 
175
178
  NativeWindow* native = get_native(window);
176
179
  NSWindowStyleMask styleMask =
177
- Window_make_style_mask(window->self->flags, native.styleMask);
180
+ Window_make_style_mask(flags, native.styleMask);
178
181
 
179
182
  if (styleMask != native.styleMask)
183
+ {
184
+ NSRect content = [native contentRectForFrameRect: native.frame];
180
185
  native.styleMask = styleMask;
186
+ [native setFrame: [native frameRectForContentRect: content] display: YES];
187
+ }
188
+
189
+ bool buttons = Xot::has_flag(flags, Window::FLAG_TITLEBAR_BUTTONS);
190
+ bool background = Xot::has_flag(flags, Window::FLAG_TITLEBAR_BACKGROUND);
191
+ [native setTitlebarButtonsVisible: buttons];
192
+ [native setTitlebarBackgroundVisible: background];
193
+ [native setTitlebarContainerVisible: buttons || background];
194
+
195
+ NSWindowCollectionBehavior behavior = native.collectionBehavior;
196
+ if (Xot::has_flag(flags, Window::FLAG_UNLISTED))
197
+ {
198
+ behavior &= ~NSWindowCollectionBehaviorManaged;
199
+ behavior |= NSWindowCollectionBehaviorTransient;
200
+ }
201
+ else
202
+ {
203
+ behavior &= ~NSWindowCollectionBehaviorTransient;
204
+ behavior |= NSWindowCollectionBehaviorManaged;
205
+ }
206
+ native.collectionBehavior = behavior;
207
+
208
+ native.hasShadow = Xot::has_flag(flags, Window::FLAG_SHADOW);
209
+
210
+ [native setBackgroundTransparent: Xot::has_flag(flags, Window::FLAG_TRANSPARENT)];
181
211
 
182
212
  if (native.hasFullScreenFlag != Xot::has_flag(flags, Window::FLAG_FULLSCREEN))
183
213
  [native toggleFullScreen: native];
214
+
215
+ if (Xot::has_flag(flags, Window::FLAG_ALWAYS_ON_TOP))
216
+ native.level = NSFloatingWindowLevel;
217
+ else if (Xot::has_flag(flags, Window::FLAG_ALWAYS_ON_BOTTOM))
218
+ native.level = NSNormalWindowLevel - 1;
219
+ else
220
+ native.level = NSNormalWindowLevel;
184
221
  }
185
222
 
186
223
  float
@@ -189,5 +226,50 @@ namespace Reflex
189
226
  return get_native(&window).backingScaleFactor;
190
227
  }
191
228
 
229
+ void
230
+ Window_set_pointer_through (Window* window, bool through)
231
+ {
232
+ get_native(window).ignoresMouseEvents = through ? YES : NO;
233
+ }
234
+
235
+ static bool
236
+ is_covered_by_another_window (NativeWindow* native, NSPoint screen_pos)
237
+ {
238
+ // only a window that takes mouse events counts as covering. when
239
+ // the frontmost window at the point is also the frontmost behind
240
+ // this window, nothing sits between them, so nothing is in front
241
+ // of this window. this holds while the window ignores mouse events
242
+ // too, since the hit test then skips the window itself
243
+
244
+ NSInteger hit = [NSWindow
245
+ windowNumberAtPoint: screen_pos
246
+ belowWindowWithWindowNumber: 0];
247
+ if (hit == 0 || hit == native.windowNumber)
248
+ return false;
249
+
250
+ NSInteger behind = [NSWindow
251
+ windowNumberAtPoint: screen_pos
252
+ belowWindowWithWindowNumber: native.windowNumber];
253
+ return hit != behind;
254
+ }
255
+
256
+ bool
257
+ Window_is_pointer_over_and_uncovered (Point* position, const Window& window)
258
+ {
259
+ NativeWindow* native = get_native(&window);
260
+ NSPoint screen_pos = [NSEvent mouseLocation];
261
+ if (!NSPointInRect(screen_pos, native.frame))
262
+ return false;
263
+ if (is_covered_by_another_window(native, screen_pos))
264
+ return false;
265
+
266
+ NSRect screen_rect = NSMakeRect(screen_pos.x, screen_pos.y, 0, 0);
267
+ NSRect window_rect = [native convertRectFromScreen: screen_rect];
268
+ NSView* view = native.contentView;
269
+ NSPoint view_pos = [view convertPoint: window_rect.origin fromView: nil];
270
+ position->reset(view_pos.x, view.bounds.size.height - view_pos.y);
271
+ return true;
272
+ }
273
+
192
274
 
193
275
  }// Reflex
data/src/pointer.cpp CHANGED
@@ -86,19 +86,28 @@ namespace Reflex
86
86
  it->self->id = id;
87
87
  }
88
88
 
89
+ void
90
+ Pointer_set_types (Pointer* it, uint types)
91
+ {
92
+ it->self->types = types;
93
+ }
94
+
89
95
  void
90
96
  Pointer_set_action (Pointer* it, Pointer::Action action)
91
97
  {
92
98
  it->self->action = action;
93
99
  }
94
100
 
101
+ void
102
+ Pointer_set_time (Pointer* it, double time)
103
+ {
104
+ it->self->time = time;
105
+ }
106
+
95
107
  void
96
108
  Pointer_set_floatable (Pointer* it, bool floatable)
97
109
  {
98
- if (floatable)
99
- Xot::add_flag(&it->self->flags, Pointer::Data::FLOATABLE);
100
- else
101
- Xot::remove_flag(&it->self->flags, Pointer::Data::FLOATABLE);
110
+ Xot::update_flag(&it->self->flags, Pointer::Data::FLOATABLE, floatable);
102
111
  }
103
112
 
104
113
  bool