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
data/src/osx/menu.mm CHANGED
@@ -8,19 +8,13 @@
8
8
  #include "reflex/exception.h"
9
9
  #include "reflex/event.h"
10
10
  #include "reflex/view.h"
11
+ #include "../rays.h"
11
12
  #include "window.h"
12
13
  #include "screen.h"
13
14
  #import "native_window.h"
14
15
 
15
16
 
16
- namespace Rays
17
- {
18
- NSImage* Bitmap_get_nsimage (const Bitmap& bmp);
19
- }
20
-
21
-
22
17
  @interface ReflexMenuTarget : NSObject <NSMenuDelegate>
23
- - (void) handleMenuItem: (NSMenuItem*) sender;
24
18
  @end
25
19
 
26
20
 
@@ -149,6 +143,126 @@ namespace Reflex
149
143
  return new MenuData();
150
144
  }
151
145
 
146
+ void
147
+ Menu_validate_shortcut_modifiers (uint modifiers)
148
+ {
149
+ static const uint SUPPORTED =
150
+ MOD_SHIFT | MOD_CONTROL | MOD_ALT | MOD_OPTION | MOD_COMMAND;
151
+
152
+ if (modifiers & ~SUPPORTED)
153
+ {
154
+ argument_error(
155
+ __FILE__, __LINE__,
156
+ "modifiers 0x%X can not be used for a shortcut on macOS.",
157
+ modifiers & ~SUPPORTED);
158
+ }
159
+ }
160
+
161
+ static NSString*
162
+ get_keyequivalent_string (int key)
163
+ {
164
+ using namespace Reflex;
165
+ switch (key)
166
+ {
167
+ #define KEY_STR(key) [NSString stringWithFormat: @"%C", (unichar) (key)]
168
+
169
+ case KEY_A: return @"a";
170
+ case KEY_B: return @"b";
171
+ case KEY_C: return @"c";
172
+ case KEY_D: return @"d";
173
+ case KEY_E: return @"e";
174
+ case KEY_F: return @"f";
175
+ case KEY_G: return @"g";
176
+ case KEY_H: return @"h";
177
+ case KEY_I: return @"i";
178
+ case KEY_J: return @"j";
179
+ case KEY_K: return @"k";
180
+ case KEY_L: return @"l";
181
+ case KEY_M: return @"m";
182
+ case KEY_N: return @"n";
183
+ case KEY_O: return @"o";
184
+ case KEY_P: return @"p";
185
+ case KEY_Q: return @"q";
186
+ case KEY_R: return @"r";
187
+ case KEY_S: return @"s";
188
+ case KEY_T: return @"t";
189
+ case KEY_U: return @"u";
190
+ case KEY_V: return @"v";
191
+ case KEY_W: return @"w";
192
+ case KEY_X: return @"x";
193
+ case KEY_Y: return @"y";
194
+ case KEY_Z: return @"z";
195
+
196
+ case KEY_0: return @"0";
197
+ case KEY_1: return @"1";
198
+ case KEY_2: return @"2";
199
+ case KEY_3: return @"3";
200
+ case KEY_4: return @"4";
201
+ case KEY_5: return @"5";
202
+ case KEY_6: return @"6";
203
+ case KEY_7: return @"7";
204
+ case KEY_8: return @"8";
205
+ case KEY_9: return @"9";
206
+
207
+ case KEY_MINUS: return @"-";
208
+ case KEY_EQUAL: return @"=";
209
+ case KEY_COMMA: return @",";
210
+ case KEY_PERIOD: return @".";
211
+ case KEY_SEMICOLON: return @";";
212
+ case KEY_QUOTE: return @"'";
213
+ case KEY_SLASH: return @"/";
214
+ case KEY_BACKSLASH: return @"\\";
215
+ case KEY_GRAVE: return @"`";
216
+ case KEY_LBRACKET: return @"[";
217
+ case KEY_RBRACKET: return @"]";
218
+
219
+ case KEY_ENTER: return @"\r";
220
+ case KEY_SPACE: return @" ";
221
+ case KEY_TAB: return @"\t";
222
+ case KEY_ESCAPE: return @"\033";
223
+ case KEY_BACKSPACE: return @"\b";
224
+ case KEY_DELETE: return KEY_STR(NSDeleteFunctionKey);
225
+ case KEY_INSERT: return KEY_STR(NSInsertFunctionKey);
226
+
227
+ case KEY_LEFT: return KEY_STR(NSLeftArrowFunctionKey);
228
+ case KEY_RIGHT: return KEY_STR(NSRightArrowFunctionKey);
229
+ case KEY_UP: return KEY_STR(NSUpArrowFunctionKey);
230
+ case KEY_DOWN: return KEY_STR(NSDownArrowFunctionKey);
231
+ case KEY_HOME: return KEY_STR(NSHomeFunctionKey);
232
+ case KEY_END: return KEY_STR(NSEndFunctionKey);
233
+ case KEY_PAGEUP: return KEY_STR(NSPageUpFunctionKey);
234
+ case KEY_PAGEDOWN: return KEY_STR(NSPageDownFunctionKey);
235
+
236
+ case KEY_F1: return KEY_STR(NSF1FunctionKey);
237
+ case KEY_F2: return KEY_STR(NSF2FunctionKey);
238
+ case KEY_F3: return KEY_STR(NSF3FunctionKey);
239
+ case KEY_F4: return KEY_STR(NSF4FunctionKey);
240
+ case KEY_F5: return KEY_STR(NSF5FunctionKey);
241
+ case KEY_F6: return KEY_STR(NSF6FunctionKey);
242
+ case KEY_F7: return KEY_STR(NSF7FunctionKey);
243
+ case KEY_F8: return KEY_STR(NSF8FunctionKey);
244
+ case KEY_F9: return KEY_STR(NSF9FunctionKey);
245
+ case KEY_F10: return KEY_STR(NSF10FunctionKey);
246
+ case KEY_F11: return KEY_STR(NSF11FunctionKey);
247
+ case KEY_F12: return KEY_STR(NSF12FunctionKey);
248
+ case KEY_F13: return KEY_STR(NSF13FunctionKey);
249
+ case KEY_F14: return KEY_STR(NSF14FunctionKey);
250
+ case KEY_F15: return KEY_STR(NSF15FunctionKey);
251
+ case KEY_F16: return KEY_STR(NSF16FunctionKey);
252
+ case KEY_F17: return KEY_STR(NSF17FunctionKey);
253
+ case KEY_F18: return KEY_STR(NSF18FunctionKey);
254
+ case KEY_F19: return KEY_STR(NSF19FunctionKey);
255
+ case KEY_F20: return KEY_STR(NSF20FunctionKey);
256
+ case KEY_F21: return KEY_STR(NSF21FunctionKey);
257
+ case KEY_F22: return KEY_STR(NSF22FunctionKey);
258
+ case KEY_F23: return KEY_STR(NSF23FunctionKey);
259
+ case KEY_F24: return KEY_STR(NSF24FunctionKey);
260
+
261
+ #undef KEY_STR
262
+ }
263
+ return @"";
264
+ }
265
+
152
266
  static NSEventModifierFlags
153
267
  modifiers2mask (uint mods)
154
268
  {
@@ -197,7 +311,7 @@ namespace Reflex
197
311
  [self.nsitem setTitle: [NSString stringWithUTF8String: menu->label()]];
198
312
  [self.nsitem setEnabled: menu->is_enabled() ? YES : NO];
199
313
  [self.nsitem setState: menu->is_checked() ? NSControlStateValueOn : NSControlStateValueOff];
200
- [self.nsitem setKeyEquivalent: [NSString stringWithUTF8String: menu->shortcut_key()]];
314
+ [self.nsitem setKeyEquivalent: get_keyequivalent_string(menu->shortcut_key())];
201
315
  [self.nsitem setKeyEquivalentModifierMask: modifiers2mask(menu->shortcut_modifiers())];
202
316
  [self.nsitem setImage: menu->image() ? Rays::Bitmap_get_nsimage(menu->image().bitmap()) : nil];
203
317
  [self.nsitem setSubmenu: menu->empty() ? nil : self.nssubmenu];
@@ -206,6 +320,8 @@ namespace Reflex
206
320
  void
207
321
  Menu_popup (Menu* menu, View* view, coord x, coord y)
208
322
  {
323
+ Menu_cancel_active_pointers_for_popup(view);
324
+
209
325
  MenuData& self = get_data(menu);
210
326
 
211
327
  if (!self.nssubmenu)
@@ -289,15 +405,57 @@ namespace Reflex
289
405
  }// Reflex
290
406
 
291
407
 
408
+ static NSMenuItem*
409
+ find_key_equivalent_item (NSMenu* nsmenu, NSEvent* event)
410
+ {
411
+ static const NSEventModifierFlags KEY_EQUIVALENT_MODIFIER_MASK =
412
+ NSEventModifierFlagCommand |
413
+ NSEventModifierFlagShift |
414
+ NSEventModifierFlagOption |
415
+ NSEventModifierFlagControl;
416
+
417
+ if (event.type != NSEventTypeKeyDown)
418
+ return nil;
419
+
420
+ NSEventModifierFlags mods = event.modifierFlags & KEY_EQUIVALENT_MODIFIER_MASK;
421
+ NSString* chars = event.charactersIgnoringModifiers;
422
+
423
+ for (NSMenuItem* nsitem in nsmenu.itemArray)
424
+ {
425
+ if (!nsitem.enabled) continue;
426
+
427
+ if (nsitem.hasSubmenu)
428
+ {
429
+ NSMenuItem* found = find_key_equivalent_item(nsitem.submenu, event);
430
+ if (found) return found;
431
+ }
432
+ else if (
433
+ nsitem.keyEquivalent.length > 0 &&
434
+ nsitem.keyEquivalentModifierMask == mods &&
435
+ [nsitem.keyEquivalent isEqualToString: chars])
436
+ {
437
+ return nsitem;
438
+ }
439
+ }
440
+ return nil;
441
+ }
442
+
443
+
292
444
  @implementation ReflexMenuTarget
293
445
 
294
- - (void) handleMenuItem: (NSMenuItem*) nsitem
446
+ - (void) handleMenuItem: (id) sender
295
447
  {
448
+ NSMenuItem* nsitem = nil;
449
+ if ([sender isKindOfClass: NSMenuItem.class])
450
+ nsitem = (NSMenuItem*) sender;
451
+ else if ([sender isKindOfClass: NSMenu.class])
452
+ nsitem = find_key_equivalent_item((NSMenu*) sender, NSApp.currentEvent);
453
+
296
454
  Reflex::Menu* menu = get_owner(nsitem);
297
455
  if (!menu) return;
298
456
 
299
457
  Reflex::Event e;
300
- menu->on_click(&e);
458
+ Reflex::Menu_call_click_event(menu, &e);
301
459
  }
302
460
 
303
461
  - (void) menuWillOpen: (NSMenu*) nsmenu
@@ -308,7 +466,7 @@ namespace Reflex
308
466
  if (!menu) return;
309
467
 
310
468
  Reflex::Event e;
311
- menu->on_open_submenu(&e);
469
+ Reflex::Menu_call_open_submenu_event(menu, &e);
312
470
 
313
471
  for (NSMenuItem* nsitem in nsmenu.itemArray)
314
472
  {
@@ -316,7 +474,7 @@ namespace Reflex
316
474
  if (!child) continue;
317
475
 
318
476
  Reflex::Event ce;
319
- child->on_show(&ce);
477
+ Reflex::Menu_call_show_event(child, &ce);
320
478
  }
321
479
  }
322
480
 
@@ -331,11 +489,11 @@ namespace Reflex
331
489
  if (!child) continue;
332
490
 
333
491
  Reflex::Event ce;
334
- child->on_hide(&ce);
492
+ Reflex::Menu_call_hide_event(child, &ce);
335
493
  }
336
494
 
337
495
  Reflex::Event e;
338
- menu->on_close_submenu(&e);
496
+ Reflex::Menu_call_close_submenu_event(menu, &e);
339
497
  }
340
498
 
341
499
  - (BOOL) menuHasKeyEquivalent: (NSMenu*) nsmenu
@@ -346,27 +504,13 @@ namespace Reflex
346
504
  // answer key equivalent matching ourselves: AppKit's own scanning of
347
505
  // delegate-backed menus caches stale results across setMainMenu calls,
348
506
  // leaving every shortcut dead until the menu bar is clicked once
349
- static const NSEventModifierFlags MODIFIER_MASK =
350
- NSEventModifierFlagCommand |
351
- NSEventModifierFlagShift |
352
- NSEventModifierFlagOption |
353
- NSEventModifierFlagControl;
354
507
 
355
- NSEventModifierFlags mods = event.modifierFlags & MODIFIER_MASK;
356
- NSString* chars = event.charactersIgnoringModifiers;
508
+ NSMenuItem* nsitem = find_key_equivalent_item(nsmenu, event);
509
+ if (!nsitem) return NO;
357
510
 
358
- for (NSMenuItem* nsitem in nsmenu.itemArray)
359
- {
360
- if (nsitem.hasSubmenu || !nsitem.enabled) continue;
361
- if (nsitem.keyEquivalent.length == 0) continue;
362
- if (nsitem.keyEquivalentModifierMask != mods) continue;
363
- if (![nsitem.keyEquivalent isEqualToString: chars]) continue;
364
-
365
- *target = nsitem.target;
366
- *action = nsitem.action;
367
- return YES;
368
- }
369
- return NO;
511
+ *target = nsitem.target;
512
+ *action = nsitem.action;
513
+ return YES;
370
514
  }
371
515
 
372
516
  @end// ReflexMenuTarget
@@ -4,10 +4,24 @@
4
4
 
5
5
  @interface NativeWindow : NSWindow <NSWindowDelegate>
6
6
 
7
- - (void) draw;
7
+ - (void) setTitlebarBackgroundVisible: (BOOL) visible;
8
+
9
+ - (void) setTitlebarButtonsVisible: (BOOL) visible;
10
+
11
+ - (void) setTitlebarContainerVisible: (BOOL) visible;
12
+
13
+ - (void) setBackgroundTransparent: (BOOL) transparent;
8
14
 
9
15
  - (BOOL) hasFullScreenFlag;
10
16
 
11
- + (NSRect) frameRectForContentRect: (NSRect) contentRect;
17
+ - (void) draw;
18
+
19
+ - (BOOL) isTextInputEnabled;
20
+
21
+ - (void) textPreedit: (NSString*) text selection: (NSRange) selection;
22
+
23
+ - (void) textCommit: (NSString*) text synthesizeKeyEvent: (BOOL) synthesize;
24
+
25
+ - (NSRect) textInputBounds;
12
26
 
13
27
  @end// NativeWindow
@@ -6,6 +6,7 @@
6
6
  #import <Cocoa/Cocoa.h>
7
7
  #include <rays/rays.h>
8
8
  #include "reflex/exception.h"
9
+ #include "../application.h"
9
10
  #include "../view.h"
10
11
  #include "../pointer.h"
11
12
  #include "event.h"
@@ -19,7 +20,7 @@ default_style_mask ()
19
20
  {
20
21
  return Reflex::Window_make_style_mask(
21
22
  Reflex::Window_default_flags(),
22
- NSTitledWindowMask | NSTexturedBackgroundWindowMask);
23
+ NSWindowStyleMaskTitled);
23
24
  }
24
25
 
25
26
  static void
@@ -199,6 +200,49 @@ move_to_main_screen_origin (NativeWindow* window)
199
200
  timer = nil;
200
201
  }
201
202
 
203
+ - (void) setTitlebarBackgroundVisible: (BOOL) visible
204
+ {
205
+ self.titlebarAppearsTransparent = !visible;
206
+ self.titleVisibility =
207
+ visible ? NSWindowTitleVisible : NSWindowTitleHidden;
208
+ }
209
+
210
+ - (void) setTitlebarButtonsVisible: (BOOL) visible
211
+ {
212
+ NSWindowButton buttons[] = {
213
+ NSWindowCloseButton,
214
+ NSWindowMiniaturizeButton,
215
+ NSWindowZoomButton
216
+ };
217
+ for (auto button : buttons)
218
+ [self standardWindowButton: button].hidden = !visible;
219
+ }
220
+
221
+ - (void) setTitlebarContainerVisible: (BOOL) visible
222
+ {
223
+ // the titlebar keeps a backdrop that a see-through window shows as a shadow
224
+ NSView* container =
225
+ [self standardWindowButton: NSWindowCloseButton].superview.superview;
226
+ if ([container isKindOfClass: NSClassFromString(@"NSTitlebarContainerView")])
227
+ container.hidden = !visible;
228
+ }
229
+
230
+ - (void) setBackgroundTransparent: (BOOL) transparent
231
+ {
232
+ if (transparent == !self.opaque) return;
233
+
234
+ self.opaque = !transparent;
235
+ self.backgroundColor =
236
+ transparent ? NSColor.clearColor : NSColor.windowBackgroundColor;
237
+
238
+ [self invalidateShadow];
239
+ }
240
+
241
+ - (BOOL) hasFullScreenFlag
242
+ {
243
+ return self.styleMask & NSWindowStyleMaskFullScreen;
244
+ }
245
+
202
246
  - (void) update: (NSTimer*) t
203
247
  {
204
248
  Reflex::Window* win = self.window;
@@ -208,39 +252,35 @@ move_to_main_screen_origin (NativeWindow* window)
208
252
 
209
253
  Window_call_update_event(win);
210
254
 
211
- if (win->self->redraw)
212
- {
255
+ if (Xot::check_and_remove_flag(&win->self->flags, Reflex::Window::Data::REDRAW))
213
256
  view.needsDisplay = YES;
214
- win->self->redraw = false;
215
- }
216
257
  }
217
258
 
218
259
  - (void) draw
219
260
  {
220
- Reflex::Window* win = self.window;
221
- if (!win) return;
261
+ // guarded here too, since rays can throw before the draw event
262
+ Reflex::Application_guard([&]()
263
+ {
264
+ Reflex::Window* win = self.window;
265
+ if (!win) return;
222
266
 
223
- update_pixel_density(win);
267
+ update_pixel_density(win);
224
268
 
225
- if (update_count == 0)
226
- [self update];
269
+ if (update_count == 0)
270
+ [self update];
227
271
 
228
- double now = Xot::time();
229
- double dt = now - win->self->prev_time_draw;
230
- double fps = 1. / dt;
272
+ double now = Xot::time();
273
+ double dt = now - win->self->prev_time_draw;
274
+ double fps = 1. / dt;
231
275
 
232
- fps = win->self->prev_fps * 0.9 + fps * 0.1;// LPF
276
+ fps = win->self->prev_fps * 0.9 + fps * 0.1;// LPF
233
277
 
234
- win->self->prev_time_draw = now;
235
- win->self->prev_fps = fps;
278
+ win->self->prev_time_draw = now;
279
+ win->self->prev_fps = fps;
236
280
 
237
- Reflex::DrawEvent e(dt, fps);
238
- Window_call_draw_event(win, &e);
239
- }
240
-
241
- - (BOOL) hasFullScreenFlag
242
- {
243
- return self.styleMask & NSWindowStyleMaskFullScreen;
281
+ Reflex::DrawEvent e(dt, fps);
282
+ Window_call_draw_event(win, &e);
283
+ });
244
284
  }
245
285
 
246
286
  - (BOOL) windowShouldClose: (id) sender
@@ -248,7 +288,7 @@ move_to_main_screen_origin (NativeWindow* window)
248
288
  Reflex::Window* win = self.window;
249
289
  if (!win) return YES;
250
290
 
251
- win->close();
291
+ Window_call_close(win);
252
292
  return NO;
253
293
  }
254
294
 
@@ -300,32 +340,7 @@ move_to_main_screen_origin (NativeWindow* window)
300
340
 
301
341
  - (void) frameChanged
302
342
  {
303
- Reflex::Window* win = self.window;
304
- if (!win) return;
305
-
306
- Rays::Bounds b = win->frame();
307
- Rays::Point dpos = b.position() - win->self->prev_position;
308
- Rays::Point dsize = b.size() - win->self->prev_size;
309
- win->self->prev_position = b.position();
310
- win->self->prev_size = b.size();
311
-
312
- if (dpos == 0 && dsize == 0) return;
313
-
314
- Reflex::FrameEvent e(b, dpos.x, dpos.y, 0, dsize.x, dsize.y, 0);
315
- if (dpos != 0) win->on_move(&e);
316
- if (dsize != 0)
317
- {
318
- Rays::Bounds b = win->frame();
319
- b.move_to(0, 0);
320
-
321
- if (win->painter())
322
- win->painter()->canvas(b, win->painter()->pixel_density());
323
-
324
- if (win->root())
325
- View_set_frame(win->root(), b);
326
-
327
- win->on_resize(&e);
328
- }
343
+ Window_call_frame_event(self.window);
329
344
  }
330
345
 
331
346
  - (void) windowWillEnterFullScreen: (NSNotification*) notification
@@ -409,6 +424,49 @@ move_to_main_screen_origin (NativeWindow* window)
409
424
  Window_call_key_event(win, &e);
410
425
  }
411
426
 
427
+ - (BOOL) isTextInputEnabled
428
+ {
429
+ Reflex::Window* win = self.window;
430
+ if (!win) return NO;
431
+
432
+ const Reflex::View* focus = win->focus();
433
+ return focus && focus->accepts_text_input();
434
+ }
435
+
436
+ - (void) textPreedit: (NSString*) text selection: (NSRange) selection
437
+ {
438
+ Reflex::Window* win = self.window;
439
+ if (!win) return;
440
+
441
+ Reflex::NativeTextEvent e(Reflex::TextEvent::PREEDIT, text, selection);
442
+ Window_call_text_event(win, &e);
443
+ }
444
+
445
+ - (void) textCommit: (NSString*) text synthesizeKeyEvent: (BOOL) synthesize
446
+ {
447
+ Reflex::Window* win = self.window;
448
+ if (!win) return;
449
+
450
+ Reflex::NativeTextEvent e(
451
+ Reflex::TextEvent::COMMIT, text, NSMakeRange(NSNotFound, 0));
452
+ Window_call_text_event(win, &e, synthesize);
453
+ }
454
+
455
+ - (NSRect) textInputBounds
456
+ {
457
+ Reflex::Window* win = self.window;
458
+ if (!win) return NSZeroRect;
459
+
460
+ const Reflex::View* focus = win->focus();
461
+ if (!focus) return NSZeroRect;
462
+
463
+ Reflex::Bounds b = focus->text_input_bounds();
464
+ Reflex::Point p1 = focus->to_window(b.position());
465
+ Reflex::Point p2 = focus->to_window(b.position() + b.size());
466
+
467
+ return NSMakeRect(p1.x, view.bounds.size.height - p2.y, p2.x - p1.x, p2.y - p1.y);
468
+ }
469
+
412
470
  - (void) mouseDown: (NSEvent*) event
413
471
  {
414
472
  Reflex::Window* win = self.window;
@@ -449,6 +507,12 @@ move_to_main_screen_origin (NativeWindow* window)
449
507
  Reflex::Window* win = self.window;
450
508
  if (!win) return;
451
509
 
510
+ // macos delivers hover moves to the key window even outside its
511
+ // bounds, but no other platform can see them, so a cross-platform
512
+ // app must not either
513
+ NSPoint pos = [view convertPoint: event.locationInWindow fromView: nil];
514
+ if (!NSPointInRect(pos, view.bounds)) return;
515
+
452
516
  Reflex::NativePointerEvent e(event, view, Reflex::Pointer::MOVE);
453
517
  Window_call_pointer_event(win, &e);
454
518
  }
@@ -480,11 +544,4 @@ move_to_main_screen_origin (NativeWindow* window)
480
544
  Window_call_wheel_event(win, &e);
481
545
  }
482
546
 
483
- + (NSRect) frameRectForContentRect: (NSRect) contentRect
484
- {
485
- return [NSWindow
486
- frameRectForContentRect: contentRect
487
- styleMask: default_style_mask()];
488
- }
489
-
490
547
  @end// NativeWindow
@@ -1,8 +1,9 @@
1
1
  // -*- objc -*-
2
2
  #import <AppKit/NSOpenGLView.h>
3
+ #import <AppKit/NSTextInputClient.h>
3
4
 
4
5
 
5
- @interface OpenGLView : NSOpenGLView
6
+ @interface OpenGLView : NSOpenGLView <NSTextInputClient>
6
7
 
7
8
  - (id) initWithFrame: (NSRect) frame;
8
9