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.
Files changed (309) hide show
  1. checksums.yaml +4 -4
  2. data/.doc/ext/reflex/application.cpp +56 -7
  3. data/.doc/ext/reflex/capture_event.cpp +1 -1
  4. data/.doc/ext/reflex/chase_constraint.cpp +84 -0
  5. data/.doc/ext/reflex/clipboard.cpp +65 -0
  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 +135 -0
  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 +178 -0
  26. data/.doc/ext/reflex/menu.cpp +303 -0
  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 +40 -10
  31. data/.doc/ext/reflex/note_event.cpp +1 -1
  32. data/.doc/ext/reflex/pin.cpp +156 -0
  33. data/.doc/ext/reflex/pointer.cpp +3 -1
  34. data/.doc/ext/reflex/pointer_event.cpp +3 -3
  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 +606 -237
  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 +5 -5
  41. data/.doc/ext/reflex/shape.cpp +1 -1
  42. data/.doc/ext/reflex/snap_constraint.cpp +125 -0
  43. data/.doc/ext/reflex/style.cpp +1 -1
  44. data/.doc/ext/reflex/style_length.cpp +4 -3
  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 +206 -79
  50. data/.doc/ext/reflex/wheel_constraint.cpp +142 -0
  51. data/.doc/ext/reflex/wheel_event.cpp +1 -1
  52. data/.doc/ext/reflex/window.cpp +282 -31
  53. data/.github/workflows/release-gem.yml +2 -40
  54. data/.github/workflows/tag.yml +5 -28
  55. data/.github/workflows/test.yml +1 -28
  56. data/ChangeLog.md +79 -0
  57. data/Gemfile.lock +13 -8
  58. data/README.md +1 -0
  59. data/Rakefile +13 -2
  60. data/Reflex.podspec +2 -2
  61. data/VERSION +1 -1
  62. data/ext/reflex/application.cpp +62 -7
  63. data/ext/reflex/capture_event.cpp +1 -1
  64. data/ext/reflex/chase_constraint.cpp +89 -0
  65. data/ext/reflex/clipboard.cpp +69 -0
  66. data/ext/reflex/color_event.cpp +80 -0
  67. data/ext/reflex/color_picker.cpp +121 -0
  68. data/ext/reflex/constraint.cpp +146 -0
  69. data/ext/reflex/contact_event.cpp +1 -1
  70. data/ext/reflex/control_change_event.cpp +1 -1
  71. data/ext/reflex/device.cpp +1 -1
  72. data/ext/reflex/device_event.cpp +1 -1
  73. data/ext/reflex/draw_event.cpp +1 -1
  74. data/ext/reflex/ellipse_shape.cpp +1 -1
  75. data/ext/reflex/event.cpp +1 -1
  76. data/ext/reflex/extconf.rb +4 -2
  77. data/ext/reflex/file_dialog.cpp +194 -0
  78. data/ext/reflex/file_event.cpp +108 -0
  79. data/ext/reflex/filter.cpp +1 -1
  80. data/ext/reflex/focus_event.cpp +1 -1
  81. data/ext/reflex/frame_event.cpp +1 -1
  82. data/ext/reflex/gamepad.cpp +50 -0
  83. data/ext/reflex/image_view.cpp +1 -1
  84. data/ext/reflex/key_event.cpp +1 -275
  85. data/ext/reflex/line_shape.cpp +1 -1
  86. data/ext/reflex/link_constraint.cpp +194 -0
  87. data/ext/reflex/menu.cpp +331 -0
  88. data/ext/reflex/midi.cpp +11 -3
  89. data/ext/reflex/midi_event.cpp +1 -1
  90. data/ext/reflex/motion_event.cpp +1 -1
  91. data/ext/reflex/native.cpp +40 -10
  92. data/ext/reflex/note_event.cpp +1 -1
  93. data/ext/reflex/pin.cpp +165 -0
  94. data/ext/reflex/pointer.cpp +3 -1
  95. data/ext/reflex/pointer_event.cpp +3 -3
  96. data/ext/reflex/polygon_shape.cpp +1 -1
  97. data/ext/reflex/rect_shape.cpp +1 -1
  98. data/ext/reflex/reflex.cpp +608 -237
  99. data/ext/reflex/screen.cpp +31 -2
  100. data/ext/reflex/scroll_event.cpp +1 -1
  101. data/ext/reflex/selector.cpp +5 -5
  102. data/ext/reflex/selector.h +10 -10
  103. data/ext/reflex/shape.cpp +1 -1
  104. data/ext/reflex/snap_constraint.cpp +135 -0
  105. data/ext/reflex/style.cpp +1 -1
  106. data/ext/reflex/style_length.cpp +4 -3
  107. data/ext/reflex/text_event.cpp +111 -0
  108. data/ext/reflex/timer.cpp +1 -1
  109. data/ext/reflex/timer_event.cpp +1 -1
  110. data/ext/reflex/update_event.cpp +1 -1
  111. data/ext/reflex/view.cpp +236 -96
  112. data/ext/reflex/wheel_constraint.cpp +154 -0
  113. data/ext/reflex/wheel_event.cpp +1 -1
  114. data/ext/reflex/window.cpp +318 -40
  115. data/include/reflex/application.h +19 -0
  116. data/include/reflex/clipboard.h +53 -0
  117. data/include/reflex/color_picker.h +65 -0
  118. data/include/reflex/constraint.h +275 -0
  119. data/include/reflex/defs.h +204 -195
  120. data/include/reflex/event.h +180 -88
  121. data/include/reflex/file_dialog.h +73 -0
  122. data/include/reflex/gamepad.h +3 -0
  123. data/include/reflex/menu.h +120 -0
  124. data/include/reflex/midi.h +3 -0
  125. data/include/reflex/pin.h +68 -0
  126. data/include/reflex/pointer.h +4 -0
  127. data/include/reflex/reflex.h +2 -0
  128. data/include/reflex/ruby/application.h +6 -1
  129. data/include/reflex/ruby/clipboard.h +23 -0
  130. data/include/reflex/ruby/color_picker.h +89 -0
  131. data/include/reflex/ruby/constraint.h +94 -0
  132. data/include/reflex/ruby/event.h +62 -29
  133. data/include/reflex/ruby/file_dialog.h +89 -0
  134. data/include/reflex/ruby/gamepad.h +46 -0
  135. data/include/reflex/ruby/menu.h +103 -0
  136. data/include/reflex/ruby/pin.h +40 -0
  137. data/include/reflex/ruby/reflex.h +3 -0
  138. data/include/reflex/ruby/view.h +123 -39
  139. data/include/reflex/ruby/window.h +96 -19
  140. data/include/reflex/ruby.h +3 -0
  141. data/include/reflex/screen.h +11 -2
  142. data/include/reflex/view.h +66 -27
  143. data/include/reflex/window.h +57 -12
  144. data/include/reflex.h +8 -0
  145. data/lib/reflex/application.rb +5 -5
  146. data/lib/reflex/autoinit.rb +3 -1
  147. data/lib/reflex/button.rb +3 -3
  148. data/lib/reflex/chase_constraint.rb +15 -0
  149. data/lib/reflex/clipboard.rb +19 -0
  150. data/lib/reflex/color_event.rb +16 -0
  151. data/lib/reflex/color_picker.rb +45 -0
  152. data/lib/reflex/constraint.rb +29 -0
  153. data/lib/reflex/control_change_event.rb +17 -0
  154. data/lib/reflex/extension.rb +1 -1
  155. data/lib/reflex/file_dialog.rb +70 -0
  156. data/lib/reflex/file_event.rb +37 -0
  157. data/lib/reflex/helper.rb +79 -0
  158. data/lib/reflex/key_event.rb +14 -14
  159. data/lib/reflex/link_constraint.rb +31 -0
  160. data/lib/reflex/menu.rb +92 -0
  161. data/lib/reflex/model.rb +19 -19
  162. data/lib/reflex/note_event.rb +1 -1
  163. data/lib/reflex/pin.rb +39 -0
  164. data/lib/reflex/pointer.rb +30 -1
  165. data/lib/reflex/pointer_event.rb +13 -2
  166. data/lib/reflex/reflex.rb +5 -0
  167. data/lib/reflex/shape.rb +14 -14
  168. data/lib/reflex/snap_constraint.rb +28 -0
  169. data/lib/reflex/style.rb +16 -16
  170. data/lib/reflex/text_event.rb +40 -0
  171. data/lib/reflex/timer.rb +3 -3
  172. data/lib/reflex/view.rb +85 -18
  173. data/lib/reflex/wheel_constraint.rb +28 -0
  174. data/lib/reflex/wheel_event.rb +19 -1
  175. data/lib/reflex/window.rb +25 -13
  176. data/lib/reflex.rb +23 -8
  177. data/pod.rake +1 -1
  178. data/reflex.gemspec +4 -4
  179. data/samples/constraint.rb +152 -0
  180. data/samples/ime.rb +100 -0
  181. data/samples/ios/hello/hello.xcodeproj/project.pbxproj +236 -224
  182. data/samples/menu.rb +32 -0
  183. data/samples/model.rb +3 -3
  184. data/samples/test/alert.rb +93 -0
  185. data/samples/test/always_on.rb +76 -0
  186. data/samples/test/app_background.rb +51 -0
  187. data/samples/test/boundary.rb +75 -0
  188. data/samples/test/callback_exception.rb +101 -0
  189. data/samples/test/cancel.rb +53 -0
  190. data/samples/test/color_picker.rb +63 -0
  191. data/samples/test/file_dialog.rb +102 -0
  192. data/samples/window_style.rb +156 -0
  193. data/src/application.cpp +180 -20
  194. data/src/application.h +95 -5
  195. data/src/clipboard.cpp +81 -0
  196. data/src/color_picker.cpp +113 -0
  197. data/src/color_picker.h +36 -0
  198. data/src/constraint.cpp +1662 -0
  199. data/src/constraint.h +64 -0
  200. data/src/event.cpp +416 -252
  201. data/src/event.h +13 -2
  202. data/src/file_dialog.cpp +163 -0
  203. data/src/file_dialog.h +52 -0
  204. data/src/gamepad.cpp +42 -5
  205. data/src/gamepad.h +4 -0
  206. data/src/ios/app_delegate.mm +5 -3
  207. data/src/ios/application.mm +29 -0
  208. data/src/ios/clipboard.mm +44 -0
  209. data/src/ios/color_picker.mm +19 -0
  210. data/src/ios/event.h +6 -2
  211. data/src/ios/event.mm +31 -12
  212. data/src/ios/file_dialog.mm +21 -0
  213. data/src/ios/gamepad.mm +4 -4
  214. data/src/ios/menu.mm +41 -0
  215. data/src/ios/reflex.mm +8 -0
  216. data/src/ios/screen.mm +26 -0
  217. data/src/ios/view_controller.mm +47 -42
  218. data/src/ios/window.mm +44 -9
  219. data/src/menu.cpp +387 -0
  220. data/src/menu.h +81 -0
  221. data/src/midi.cpp +61 -31
  222. data/src/osx/app_delegate.h +4 -0
  223. data/src/osx/app_delegate.mm +168 -139
  224. data/src/osx/application.mm +103 -5
  225. data/src/osx/clipboard.mm +45 -0
  226. data/src/osx/color_picker.mm +112 -0
  227. data/src/osx/event.h +10 -0
  228. data/src/osx/event.mm +114 -30
  229. data/src/osx/file_dialog.mm +168 -0
  230. data/src/osx/gamepad.mm +2 -2
  231. data/src/osx/gamepad_hid.mm +1 -1
  232. data/src/osx/menu.h +25 -0
  233. data/src/osx/menu.mm +516 -0
  234. data/src/osx/native_window.h +16 -2
  235. data/src/osx/native_window.mm +141 -57
  236. data/src/osx/opengl_view.h +2 -1
  237. data/src/osx/opengl_view.mm +229 -37
  238. data/src/osx/reflex.mm +38 -0
  239. data/src/osx/screen.mm +36 -0
  240. data/src/osx/window.mm +117 -24
  241. data/src/pin.cpp +137 -0
  242. data/src/pointer.cpp +36 -16
  243. data/src/pointer.h +10 -0
  244. data/src/rays.h +46 -0
  245. data/src/sdl/application.cpp +73 -8
  246. data/src/sdl/clipboard.cpp +39 -0
  247. data/src/sdl/color_picker.cpp +18 -0
  248. data/src/sdl/event.cpp +44 -6
  249. data/src/sdl/event.h +18 -3
  250. data/src/sdl/file_dialog.cpp +20 -0
  251. data/src/sdl/gamepad.cpp +3 -7
  252. data/src/sdl/menu.cpp +40 -0
  253. data/src/sdl/reflex.cpp +20 -0
  254. data/src/sdl/screen.cpp +36 -0
  255. data/src/sdl/window.cpp +168 -37
  256. data/src/shape.cpp +15 -10
  257. data/src/view.cpp +583 -233
  258. data/src/view.h +22 -4
  259. data/src/vk.h +416 -0
  260. data/src/win32/application.cpp +167 -12
  261. data/src/win32/application.h +20 -0
  262. data/src/win32/clipboard.cpp +210 -0
  263. data/src/win32/color_picker.cpp +82 -0
  264. data/src/win32/event.cpp +123 -11
  265. data/src/win32/event.h +22 -3
  266. data/src/win32/file_dialog.cpp +226 -0
  267. data/src/win32/gamepad.cpp +9 -2
  268. data/src/win32/menu.cpp +490 -0
  269. data/src/win32/menu.h +35 -0
  270. data/src/win32/opengl.cpp +2 -9
  271. data/src/win32/reflex.cpp +44 -3
  272. data/src/win32/screen.cpp +164 -3
  273. data/src/win32/screen.h +8 -0
  274. data/src/win32/tray.cpp +191 -0
  275. data/src/win32/tray.h +22 -0
  276. data/src/win32/vk.cpp +11 -0
  277. data/src/win32/window.cpp +858 -135
  278. data/src/win32/window.h +9 -0
  279. data/src/window.cpp +929 -183
  280. data/src/window.h +77 -33
  281. data/src/world.cpp +86 -15
  282. data/src/world.h +9 -2
  283. data/test/helper.rb +24 -0
  284. data/test/test_application.rb +101 -1
  285. data/test/test_chase_constraint.rb +122 -0
  286. data/test/test_clipboard.rb +54 -0
  287. data/test/test_color_event.rb +36 -0
  288. data/test/test_color_picker.rb +62 -0
  289. data/test/test_constraint.rb +184 -0
  290. data/test/test_event.rb +1 -1
  291. data/test/test_file_dialog.rb +48 -0
  292. data/test/test_file_event.rb +43 -0
  293. data/test/test_has_text_preedit.rb +54 -0
  294. data/test/test_key_event.rb +23 -2
  295. data/test/test_link_constraint.rb +237 -0
  296. data/test/test_menu.rb +237 -0
  297. data/test/test_pin.rb +65 -0
  298. data/test/test_pointer.rb +50 -26
  299. data/test/test_pointer_event.rb +25 -10
  300. data/test/test_reflex.rb +36 -0
  301. data/test/test_screen.rb +24 -2
  302. data/test/test_snap_constraint.rb +140 -0
  303. data/test/test_text_event.rb +54 -0
  304. data/test/test_view.rb +152 -25
  305. data/test/test_wheel_constraint.rb +125 -0
  306. data/test/test_wheel_event.rb +24 -10
  307. data/test/test_window.rb +205 -43
  308. metadata +154 -10
  309. data/.github/workflows/utils.rb +0 -127
@@ -6,10 +6,12 @@
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"
12
13
  #include "window.h"
14
+ #include "menu.h"
13
15
  #import "opengl_view.h"
14
16
 
15
17
 
@@ -18,7 +20,7 @@ default_style_mask ()
18
20
  {
19
21
  return Reflex::Window_make_style_mask(
20
22
  Reflex::Window_default_flags(),
21
- NSTitledWindowMask | NSTexturedBackgroundWindowMask);
23
+ NSWindowStyleMaskTitled);
22
24
  }
23
25
 
24
26
  static void
@@ -198,6 +200,49 @@ move_to_main_screen_origin (NativeWindow* window)
198
200
  timer = nil;
199
201
  }
200
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
+
201
246
  - (void) update: (NSTimer*) t
202
247
  {
203
248
  Reflex::Window* win = self.window;
@@ -207,39 +252,35 @@ move_to_main_screen_origin (NativeWindow* window)
207
252
 
208
253
  Window_call_update_event(win);
209
254
 
210
- if (win->self->redraw)
211
- {
255
+ if (Xot::check_and_remove_flag(&win->self->flags, Reflex::Window::Data::REDRAW))
212
256
  view.needsDisplay = YES;
213
- win->self->redraw = false;
214
- }
215
257
  }
216
258
 
217
259
  - (void) draw
218
260
  {
219
- Reflex::Window* win = self.window;
220
- 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;
221
266
 
222
- update_pixel_density(win);
267
+ update_pixel_density(win);
223
268
 
224
- if (update_count == 0)
225
- [self update];
269
+ if (update_count == 0)
270
+ [self update];
226
271
 
227
- double now = Xot::time();
228
- double dt = now - win->self->prev_time_draw;
229
- double fps = 1. / dt;
272
+ double now = Xot::time();
273
+ double dt = now - win->self->prev_time_draw;
274
+ double fps = 1. / dt;
230
275
 
231
- fps = win->self->prev_fps * 0.9 + fps * 0.1;// LPF
276
+ fps = win->self->prev_fps * 0.9 + fps * 0.1;// LPF
232
277
 
233
- win->self->prev_time_draw = now;
234
- win->self->prev_fps = fps;
278
+ win->self->prev_time_draw = now;
279
+ win->self->prev_fps = fps;
235
280
 
236
- Reflex::DrawEvent e(dt, fps);
237
- Window_call_draw_event(win, &e);
238
- }
239
-
240
- - (BOOL) hasFullScreenFlag
241
- {
242
- return self.styleMask & NSWindowStyleMaskFullScreen;
281
+ Reflex::DrawEvent e(dt, fps);
282
+ Window_call_draw_event(win, &e);
283
+ });
243
284
  }
244
285
 
245
286
  - (BOOL) windowShouldClose: (id) sender
@@ -247,7 +288,7 @@ move_to_main_screen_origin (NativeWindow* window)
247
288
  Reflex::Window* win = self.window;
248
289
  if (!win) return YES;
249
290
 
250
- win->close();
291
+ Window_call_close(win);
251
292
  return NO;
252
293
  }
253
294
 
@@ -261,6 +302,14 @@ move_to_main_screen_origin (NativeWindow* window)
261
302
  [self setDelegate: nil];
262
303
  }
263
304
 
305
+ - (void) windowDidBecomeMain: (NSNotification*) notification
306
+ {
307
+ Reflex::Window* win = self.window;
308
+ if (!win) return;
309
+
310
+ Menu_apply_to_main_menu(win->menu());
311
+ }
312
+
264
313
  - (void) windowWillMove: (NSNotification*) notification
265
314
  {
266
315
  Reflex::Window* win = self.window;
@@ -291,32 +340,7 @@ move_to_main_screen_origin (NativeWindow* window)
291
340
 
292
341
  - (void) frameChanged
293
342
  {
294
- Reflex::Window* win = self.window;
295
- if (!win) return;
296
-
297
- Rays::Bounds b = win->frame();
298
- Rays::Point dpos = b.position() - win->self->prev_position;
299
- Rays::Point dsize = b.size() - win->self->prev_size;
300
- win->self->prev_position = b.position();
301
- win->self->prev_size = b.size();
302
-
303
- if (dpos == 0 && dsize == 0) return;
304
-
305
- Reflex::FrameEvent e(b, dpos.x, dpos.y, 0, dsize.x, dsize.y, 0);
306
- if (dpos != 0) win->on_move(&e);
307
- if (dsize != 0)
308
- {
309
- Rays::Bounds b = win->frame();
310
- b.move_to(0, 0);
311
-
312
- if (win->painter())
313
- win->painter()->canvas(b, win->painter()->pixel_density());
314
-
315
- if (win->root())
316
- View_set_frame(win->root(), b);
317
-
318
- win->on_resize(&e);
319
- }
343
+ Window_call_frame_event(self.window);
320
344
  }
321
345
 
322
346
  - (void) windowWillEnterFullScreen: (NSNotification*) notification
@@ -400,6 +424,49 @@ move_to_main_screen_origin (NativeWindow* window)
400
424
  Window_call_key_event(win, &e);
401
425
  }
402
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
+
403
470
  - (void) mouseDown: (NSEvent*) event
404
471
  {
405
472
  Reflex::Window* win = self.window;
@@ -440,24 +507,41 @@ move_to_main_screen_origin (NativeWindow* window)
440
507
  Reflex::Window* win = self.window;
441
508
  if (!win) return;
442
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
+
443
516
  Reflex::NativePointerEvent e(event, view, Reflex::Pointer::MOVE);
444
517
  Window_call_pointer_event(win, &e);
445
518
  }
446
519
 
447
- - (void) scrollWheel: (NSEvent*) event
520
+ - (void) mouseEntered: (NSEvent*) event
448
521
  {
449
522
  Reflex::Window* win = self.window;
450
523
  if (!win) return;
451
524
 
452
- Reflex::NativeWheelEvent e(event, view);
453
- Window_call_wheel_event(win, &e);
525
+ Reflex::NativePointerEvent e(event, view, Reflex::Pointer::ENTER);
526
+ Window_call_pointer_event(win, &e);
454
527
  }
455
528
 
456
- + (NSRect) frameRectForContentRect: (NSRect) contentRect
529
+ - (void) mouseExited: (NSEvent*) event
457
530
  {
458
- return [NSWindow
459
- frameRectForContentRect: contentRect
460
- styleMask: default_style_mask()];
531
+ Reflex::Window* win = self.window;
532
+ if (!win) return;
533
+
534
+ Reflex::NativePointerEvent e(event, view, Reflex::Pointer::LEAVE);
535
+ Window_call_pointer_event(win, &e);
536
+ }
537
+
538
+ - (void) scrollWheel: (NSEvent*) event
539
+ {
540
+ Reflex::Window* win = self.window;
541
+ if (!win) return;
542
+
543
+ Reflex::NativeWheelEvent e(event, view);
544
+ Window_call_wheel_event(win, &e);
461
545
  }
462
546
 
463
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
 
@@ -8,13 +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;
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;
18
30
  }
19
31
 
20
32
  - (id) initWithFrame: (NSRect) frame
@@ -30,6 +42,12 @@
30
42
  if (!self) return nil;
31
43
 
32
44
  setup_context_done = false;
45
+ surface_opacity = 1;
46
+ tracking_area = nil;
47
+ marked_text = nil;
48
+ marked_selection = NSMakeRange(NSNotFound, 0);
49
+ was_marked = NO;
50
+ consumed_by_ime = NO;
33
51
 
34
52
  return self;
35
53
  }
@@ -45,12 +63,7 @@
45
63
  [self setOpenGLContext: context];
46
64
 
47
65
  GLint swapInterval = 1;
48
- [context setValues: &swapInterval forParameter: NSOpenGLCPSwapInterval];
49
-
50
- #ifdef TRANSPARENT_BACKGROUND
51
- GLint opacity = 0;
52
- [context setValues: &opacity forParameter: NSOpenGLCPSurfaceOpacity];
53
- #endif
66
+ [context setValues: &swapInterval forParameter: NSOpenGLContextParameterSwapInterval];
54
67
  }
55
68
 
56
69
  - (void) activateContext
@@ -58,8 +71,22 @@
58
71
  [self setupContext];
59
72
 
60
73
  NSOpenGLContext* context = self.openGLContext;
61
- 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
+
62
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
+ }
63
90
  }
64
91
 
65
92
  - (BOOL) acceptsFirstResponder
@@ -72,52 +99,87 @@
72
99
  return YES;
73
100
  }
74
101
 
75
- #ifdef TRANSPARENT_BACKGROUND
76
102
  - (BOOL) isOpaque
77
103
  {
78
- return YES;
104
+ return self.window ? self.window.isOpaque : YES;
105
+ }
106
+
107
+ - (BOOL) mouseDownCanMoveWindow
108
+ {
109
+ return NO;
79
110
  }
80
- #endif
81
111
 
82
112
  - (void) drawRect: (NSRect) rect
83
113
  {
84
- NativeWindow* win = (NativeWindow*) [self window];
114
+ NativeWindow* win = (NativeWindow*) self.window;
85
115
  if (!win) return;
86
116
 
87
117
  [self activateContext];
88
118
  [win draw];
89
119
  [[NSOpenGLContext currentContext] flushBuffer];
120
+
121
+ if (!win.isOpaque && win.hasShadow)
122
+ [win invalidateShadow];// the shadow is made from what was drawn
90
123
  }
91
124
 
92
125
  - (void) viewDidMoveToWindow
93
126
  {
94
- [[self window] setAcceptsMouseMovedEvents: YES];
95
- [[self window] makeFirstResponder: self];
127
+ [self.window setAcceptsMouseMovedEvents: YES];
128
+ [self.window makeFirstResponder: self];
129
+ }
96
130
 
97
- #ifdef TRANSPARENT_BACKGROUND
98
- [[self window] setBackgroundColor: [NSColor clearColor]];
99
- [[self window] setOpaque: NO];
100
- #endif
131
+ - (void) updateTrackingAreas
132
+ {
133
+ [super updateTrackingAreas];
134
+
135
+ if (tracking_area)
136
+ {
137
+ [self removeTrackingArea: tracking_area];
138
+ [tracking_area release];
139
+ }
140
+
141
+ // to track pointer enter/leave event of the window bounds
142
+ tracking_area = [[NSTrackingArea alloc]
143
+ initWithRect: NSZeroRect
144
+ options:
145
+ NSTrackingMouseEnteredAndExited |
146
+ NSTrackingActiveAlways |
147
+ NSTrackingInVisibleRect
148
+ owner: self
149
+ userInfo: nil];
150
+ [self addTrackingArea: tracking_area];
101
151
  }
102
152
 
103
- - (void) insertText: (id) str
153
+ - (void) dealloc
104
154
  {
105
- //NSLog(@"interText: %@", str);
155
+ if (tracking_area)
156
+ {
157
+ [self removeTrackingArea: tracking_area];
158
+ [tracking_area release];
159
+ tracking_area = nil;
160
+ }
161
+ [self clearMarkedText];
162
+ [super dealloc];
106
163
  }
107
164
 
108
165
  - (void) keyDown: (NSEvent*) event
109
166
  {
110
- //[self interpretKeyEvents: [NSArray arrayWithObject: event]];
111
-
112
- NativeWindow* win = (NativeWindow*) [self window];
167
+ NativeWindow* win = (NativeWindow*) self.window;
113
168
  if (!win) return;
114
169
 
115
- [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];
116
178
  }
117
179
 
118
180
  - (void) keyUp: (NSEvent*) event
119
181
  {
120
- NativeWindow* win = (NativeWindow*) [self window];
182
+ NativeWindow* win = (NativeWindow*) self.window;
121
183
  if (!win) return;
122
184
 
123
185
  [win keyUp: event];
@@ -125,7 +187,7 @@
125
187
 
126
188
  - (void) flagsChanged: (NSEvent*) event
127
189
  {
128
- NativeWindow* win = (NativeWindow*) [self window];
190
+ NativeWindow* win = (NativeWindow*) self.window;
129
191
  if (!win) return;
130
192
 
131
193
  [win flagsChanged: event];
@@ -133,7 +195,7 @@
133
195
 
134
196
  - (void) mouseDown: (NSEvent*) event
135
197
  {
136
- NativeWindow* win = (NativeWindow*) [self window];
198
+ NativeWindow* win = (NativeWindow*) self.window;
137
199
  if (!win) return;
138
200
 
139
201
  [win mouseDown: event];
@@ -141,7 +203,7 @@
141
203
 
142
204
  - (void) mouseUp: (NSEvent*) event
143
205
  {
144
- NativeWindow* win = (NativeWindow*) [self window];
206
+ NativeWindow* win = (NativeWindow*) self.window;
145
207
  if (!win) return;
146
208
 
147
209
  [win mouseUp: event];
@@ -149,7 +211,7 @@
149
211
 
150
212
  - (void) mouseDragged: (NSEvent*) event
151
213
  {
152
- NativeWindow* win = (NativeWindow*) [self window];
214
+ NativeWindow* win = (NativeWindow*) self.window;
153
215
  if (!win) return;
154
216
 
155
217
  [win mouseDragged: event];
@@ -157,7 +219,7 @@
157
219
 
158
220
  - (void) rightMouseDown: (NSEvent*) event
159
221
  {
160
- NativeWindow* win = (NativeWindow*) [self window];
222
+ NativeWindow* win = (NativeWindow*) self.window;
161
223
  if (!win) return;
162
224
 
163
225
  [win mouseDown: event];
@@ -165,7 +227,7 @@
165
227
 
166
228
  - (void) rightMouseUp: (NSEvent*) event
167
229
  {
168
- NativeWindow* win = (NativeWindow*) [self window];
230
+ NativeWindow* win = (NativeWindow*) self.window;
169
231
  if (!win) return;
170
232
 
171
233
  [win mouseUp: event];
@@ -173,7 +235,7 @@
173
235
 
174
236
  - (void) rightMouseDragged: (NSEvent*) event
175
237
  {
176
- NativeWindow* win = (NativeWindow*) [self window];
238
+ NativeWindow* win = (NativeWindow*) self.window;
177
239
  if (!win) return;
178
240
 
179
241
  [win mouseDragged: event];
@@ -181,7 +243,7 @@
181
243
 
182
244
  - (void) otherMouseDown: (NSEvent*) event
183
245
  {
184
- NativeWindow* win = (NativeWindow*) [self window];
246
+ NativeWindow* win = (NativeWindow*) self.window;
185
247
  if (!win) return;
186
248
 
187
249
  [win mouseDown: event];
@@ -189,7 +251,7 @@
189
251
 
190
252
  - (void) otherMouseUp: (NSEvent*) event
191
253
  {
192
- NativeWindow* win = (NativeWindow*) [self window];
254
+ NativeWindow* win = (NativeWindow*) self.window;
193
255
  if (!win) return;
194
256
 
195
257
  [win mouseUp: event];
@@ -197,7 +259,7 @@
197
259
 
198
260
  - (void) otherMouseDragged: (NSEvent*) event
199
261
  {
200
- NativeWindow* win = (NativeWindow*) [self window];
262
+ NativeWindow* win = (NativeWindow*) self.window;
201
263
  if (!win) return;
202
264
 
203
265
  [win mouseDragged: event];
@@ -205,10 +267,140 @@
205
267
 
206
268
  - (void) mouseMoved: (NSEvent*) event
207
269
  {
208
- NativeWindow* win = (NativeWindow*) [self window];
270
+ NativeWindow* win = (NativeWindow*) self.window;
209
271
  if (!win) return;
210
272
 
211
273
  [win mouseMoved: event];
212
274
  }
213
275
 
276
+ - (void) mouseEntered: (NSEvent*) event
277
+ {
278
+ NativeWindow* win = (NativeWindow*) self.window;
279
+ if (!win) return;
280
+
281
+ [win mouseEntered: event];
282
+ }
283
+
284
+ - (void) mouseExited: (NSEvent*) event
285
+ {
286
+ NativeWindow* win = (NativeWindow*) self.window;
287
+ if (!win) return;
288
+
289
+ [win mouseExited: event];
290
+ }
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
+
214
406
  @end// OpenGLView