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
data/src/win32/event.cpp CHANGED
@@ -1,6 +1,8 @@
1
1
  #include "event.h"
2
2
 
3
3
 
4
+ #include <string>
5
+ #include <vector>
4
6
  #include <xot/time.h>
5
7
  #include "reflex/exception.h"
6
8
  #include "reflex/debug.h"
@@ -42,6 +44,90 @@ namespace Reflex
42
44
  }
43
45
 
44
46
 
47
+ static std::wstring
48
+ get_composition_string (HIMC himc, DWORD index)
49
+ {
50
+ LONG size = ImmGetCompositionStringW(himc, index, NULL, 0);
51
+ if (size <= 0) return {};
52
+
53
+ std::wstring text(size / sizeof(wchar_t), L'\0');
54
+ ImmGetCompositionStringW(himc, index, text.data(), size);
55
+ return text;
56
+ }
57
+
58
+ static int
59
+ to_char_index (const std::wstring& str, size_t utf16_index)
60
+ {
61
+ size_t length = str.size();
62
+ if (utf16_index > length) utf16_index = length;
63
+
64
+ int index = 0;
65
+ for (size_t i = 0; i < utf16_index; ++i, ++index)
66
+ {
67
+ if (!IS_HIGH_SURROGATE(str[i]) || i + 1 >= length)
68
+ continue;
69
+
70
+ if (IS_LOW_SURROGATE(str[i + 1])) ++i;
71
+ }
72
+ return index;
73
+ }
74
+
75
+ static void
76
+ get_selection (
77
+ HIMC himc, const std::wstring& text, int* offset, int* size)
78
+ {
79
+ *offset = *size = 0;
80
+
81
+ LONG attr_size = ImmGetCompositionStringW(himc, GCS_COMPATTR, NULL, 0);
82
+ if (attr_size > 0)
83
+ {
84
+ std::vector<char> attrs(attr_size);
85
+ ImmGetCompositionStringW(himc, GCS_COMPATTR, attrs.data(), attr_size);
86
+
87
+ int begin = -1, end = 0;
88
+ for (LONG i = 0; i < attr_size; ++i)
89
+ {
90
+ if (
91
+ attrs[i] != ATTR_TARGET_CONVERTED &&
92
+ attrs[i] != ATTR_TARGET_NOTCONVERTED)
93
+ {
94
+ continue;
95
+ }
96
+
97
+ if (begin < 0) begin = (int) i;
98
+ end = (int) i + 1;
99
+ }
100
+
101
+ if (begin >= 0)
102
+ {
103
+ *offset = to_char_index(text, begin);
104
+ *size = to_char_index(text, end) - *offset;
105
+ return;
106
+ }
107
+ }
108
+
109
+ LONG pos = ImmGetCompositionStringW(himc, GCS_CURSORPOS, NULL, 0);
110
+ *offset = to_char_index(text, pos >= 0 ? (size_t) pos : text.size());
111
+ }
112
+
113
+ static TextEvent
114
+ to_text_event (TextEvent::Action action, HIMC himc, DWORD index)
115
+ {
116
+ std::wstring text = get_composition_string(himc, index);
117
+
118
+ int offset = -1, size = 0;
119
+ if (action == TextEvent::PREEDIT)
120
+ get_selection(himc, text, &offset, &size);
121
+
122
+ return TextEvent(action, String(text.c_str(), text.size()), offset, size);
123
+ }
124
+
125
+ NativeTextEvent::NativeTextEvent (Action action, HIMC himc, DWORD index)
126
+ : TextEvent(to_text_event(action, himc, index))
127
+ {
128
+ }
129
+
130
+
45
131
  static uint
46
132
  get_mouse_type (UINT msg, WPARAM wp)
47
133
  {
@@ -68,6 +154,7 @@ namespace Reflex
68
154
  break;
69
155
 
70
156
  case WM_MOUSEMOVE:
157
+ case WM_MOUSELEAVE:
71
158
  type |= Reflex::Pointer::MOUSE;
72
159
  break;
73
160
  }
@@ -96,6 +183,9 @@ namespace Reflex
96
183
  case WM_MOUSEMOVE:
97
184
  return Reflex::Pointer::MOVE;
98
185
 
186
+ case WM_MOUSELEAVE:
187
+ return Reflex::Pointer::LEAVE;
188
+
99
189
  default:
100
190
  return Reflex::Pointer::ACTION_NONE;
101
191
  }
@@ -127,13 +217,20 @@ namespace Reflex
127
217
  }
128
218
  }
129
219
 
130
- NativePointerEvent::NativePointerEvent (UINT msg, WPARAM wp, LPARAM lp)
220
+ NativePointerEvent::NativePointerEvent (
221
+ const Window& window, UINT msg, WPARAM wp, LPARAM lp)
222
+ : NativePointerEvent(window, msg, wp, lp, get_mouse_action(msg))
223
+ {
224
+ }
225
+
226
+ NativePointerEvent::NativePointerEvent (
227
+ const Window& window, UINT msg, WPARAM wp, LPARAM lp, Pointer::Action action)
131
228
  {
132
229
  PointerEvent_add_pointer(this, Pointer(
133
230
  0,
134
231
  get_mouse_type(msg, wp),
135
- get_mouse_action(msg),
136
- Point(GET_X_LPARAM(lp), GET_Y_LPARAM(lp)),
232
+ action,
233
+ Window_from_native_coord(window, GET_X_LPARAM(lp), GET_Y_LPARAM(lp)),
137
234
  KeyEvent_get_modifiers(),
138
235
  get_mouse_click_count(msg),
139
236
  is_mouse_dragging(msg, wp),
@@ -158,19 +255,19 @@ namespace Reflex
158
255
  }
159
256
 
160
257
  static Point
161
- get_touch_position (HWND hwnd, const TOUCHINPUT& touch)
258
+ get_touch_position (const Window& window, const TOUCHINPUT& touch)
162
259
  {
163
260
  coord x = (coord) touch.x / 100;
164
261
  coord y = (coord) touch.y / 100;
165
262
 
166
263
  POINT point = {0, 0};
167
- if (ClientToScreen(hwnd, &point))
264
+ if (ClientToScreen(Window_get_hwnd(&window), &point))
168
265
  {
169
266
  x -= point.x;
170
267
  y -= point.y;
171
268
  }
172
269
 
173
- return Point(x, y);
270
+ return Window_from_native_coord(window, x, y);
174
271
  }
175
272
 
176
273
  static double
@@ -183,7 +280,7 @@ namespace Reflex
183
280
  }
184
281
 
185
282
  NativePointerEvent::NativePointerEvent (
186
- HWND hwnd, const TOUCHINPUT* touches, size_t size)
283
+ const Window& window, const TOUCHINPUT* touches, size_t size)
187
284
  {
188
285
  for (size_t i = 0; i < size; ++i)
189
286
  {
@@ -194,7 +291,7 @@ namespace Reflex
194
291
  0,
195
292
  get_touch_type(touch),
196
293
  action,
197
- get_touch_position(hwnd, touch),
294
+ get_touch_position(window, touch),
198
295
  KeyEvent_get_modifiers(),
199
296
  action == Pointer::DOWN ? 1 : 0,
200
297
  action == Pointer::MOVE,
@@ -207,10 +304,25 @@ namespace Reflex
207
304
  }
208
305
 
209
306
 
210
- NativeWheelEvent::NativeWheelEvent (WPARAM wp_x, WPARAM wp_y, LPARAM lp)
307
+ static Point
308
+ get_pointer_position (const Window& window, LPARAM lp)
309
+ {
310
+ POINT pos = {GET_X_LPARAM(lp), GET_Y_LPARAM(lp)};
311
+ ScreenToClient(Window_get_hwnd(&window), &pos);
312
+ return Window_from_native_coord(window, pos.x, pos.y);
313
+ }
314
+
315
+ static coord
316
+ to_wheel_pixels (WPARAM wp)
317
+ {
318
+ return (coord) GET_WHEEL_DELTA_WPARAM(wp) / WHEEL_DELTA * WHEEL_PIXELS_PER_NOTCH;
319
+ }
320
+
321
+ NativeWheelEvent::NativeWheelEvent (
322
+ const Window& window, WPARAM wp_x, WPARAM wp_y, LPARAM lp)
211
323
  : WheelEvent(
212
- GET_X_LPARAM(lp), GET_Y_LPARAM(lp), 0,
213
- GET_WHEEL_DELTA_WPARAM(wp_x), -GET_WHEEL_DELTA_WPARAM(wp_y), 0,
324
+ get_pointer_position(window, lp),
325
+ Point(to_wheel_pixels(wp_x), -to_wheel_pixels(wp_y), 0),
214
326
  KeyEvent_get_modifiers())
215
327
  {
216
328
  }
data/src/win32/event.h CHANGED
@@ -5,6 +5,8 @@
5
5
 
6
6
 
7
7
  #include <xot/windows.h>
8
+ #include <imm.h>
9
+
8
10
  #include "../event.h"
9
11
 
10
12
 
@@ -22,14 +24,31 @@ namespace Reflex
22
24
  };// NativeKeyEvent
23
25
 
24
26
 
27
+ class NativeTextEvent : public TextEvent
28
+ {
29
+
30
+ public:
31
+
32
+ NativeTextEvent (Action action, HIMC himc, DWORD index);
33
+
34
+ };// NativeTextEvent
35
+
36
+
37
+ class Window;
38
+
39
+
25
40
  class NativePointerEvent : public PointerEvent
26
41
  {
27
42
 
28
43
  public:
29
44
 
30
- NativePointerEvent (UINT msg, WPARAM wp, LPARAM lp);
45
+ NativePointerEvent (const Window& window, UINT msg, WPARAM wp, LPARAM lp);
46
+
47
+ NativePointerEvent (
48
+ const Window& window, UINT msg, WPARAM wp, LPARAM lp, Pointer::Action action);
31
49
 
32
- NativePointerEvent (HWND hwnd, const TOUCHINPUT* touches, size_t size);
50
+ NativePointerEvent (
51
+ const Window& window, const TOUCHINPUT* touches, size_t size);
33
52
 
34
53
  };// NativePointerEvent
35
54
 
@@ -39,7 +58,7 @@ namespace Reflex
39
58
 
40
59
  public:
41
60
 
42
- NativeWheelEvent (WPARAM wp_x, WPARAM wp_y, LPARAM lp);
61
+ NativeWheelEvent (const Window& window, WPARAM wp_x, WPARAM wp_y, LPARAM lp);
43
62
 
44
63
  };// NativeWheelEvent
45
64
 
@@ -0,0 +1,226 @@
1
+ #include "../file_dialog.h"
2
+
3
+
4
+ #include <wchar.h>
5
+ #include <string>
6
+ #include <xot/windows.h>
7
+ #include <shobjidl.h>
8
+ #include <xot/noncopyable.h>
9
+ #include "reflex/exception.h"
10
+ #include "window.h"
11
+
12
+
13
+ namespace Reflex
14
+ {
15
+
16
+
17
+ template <typename T>
18
+ struct ComPtr : public Xot::NonCopyable
19
+ {
20
+
21
+ T* ptr = NULL;
22
+
23
+ ~ComPtr () {if (ptr) ptr->Release();}
24
+
25
+ T* operator -> () {return ptr;}
26
+
27
+ operator bool () const {return ptr != NULL;}
28
+
29
+ };// ComPtr
30
+
31
+
32
+ static std::wstring
33
+ to_native_path (const char* path)
34
+ {
35
+ std::wstring result = String(path).to_wstr();
36
+ for (auto& c : result)
37
+ {
38
+ if (c == L'/') c = L'\\';
39
+ }
40
+ return result;
41
+ }
42
+
43
+ static String
44
+ from_native_path (PCWSTR path, size_t size)
45
+ {
46
+ String result(path, size);
47
+ for (auto& c : result)
48
+ {
49
+ if (c == '\\') c = '/';
50
+ }
51
+ return result;
52
+ }
53
+
54
+ static void
55
+ setup_options (IFileDialog* nativedialog, FileDialog::Data::Mode mode)
56
+ {
57
+ FILEOPENDIALOGOPTIONS options = 0;
58
+ if (FAILED(nativedialog->GetOptions(&options)))
59
+ system_error(__FILE__, __LINE__);
60
+
61
+ options |= FOS_FORCEFILESYSTEM;
62
+ if (mode == FileDialog::Data::OPEN_DIRECTORY) options |= FOS_PICKFOLDERS;
63
+ if (mode == FileDialog::Data::OPEN_FILES) options |= FOS_ALLOWMULTISELECT;
64
+
65
+ if (FAILED(nativedialog->SetOptions(options)))
66
+ system_error(__FILE__, __LINE__);
67
+ }
68
+
69
+ static void
70
+ setup_file_types (
71
+ std::wstring* joined,
72
+ IFileDialog* nativedialog, const FileDialog* dialog, FileDialog::Data::Mode mode)
73
+ {
74
+ if (mode == FileDialog::Data::OPEN_DIRECTORY)
75
+ return;
76
+
77
+ const StringList& extensions = dialog->extensions();
78
+ if (extensions.empty())
79
+ return;
80
+
81
+ for (const auto& extension : extensions)
82
+ {
83
+ if (!joined->empty()) *joined += L';';
84
+ *joined += ("*." + extension).to_wstr();
85
+ }
86
+
87
+ COMDLG_FILTERSPEC spec = {L"Files", joined->c_str()};
88
+ nativedialog->SetFileTypes(1, &spec);
89
+ }
90
+
91
+ static void
92
+ add_path (StringList* paths, IShellItem* item)
93
+ {
94
+ PWSTR wpath = NULL;
95
+ if (FAILED(item->GetDisplayName(SIGDN_FILESYSPATH, &wpath)) || !wpath)
96
+ return;
97
+
98
+ paths->emplace_back(from_native_path(wpath, wcslen(wpath)));
99
+ CoTaskMemFree(wpath);
100
+ }
101
+
102
+ static bool
103
+ is_missing_result (HRESULT hresult)
104
+ {
105
+ // closing the last window ends the modal loop of Show() with a WM_QUIT,
106
+ // and it answers S_OK though nothing was ever chosen. asking for the
107
+ // result then gives E_FAIL, which is this dialog being over, not an error
108
+ return hresult == E_FAIL;
109
+ }
110
+
111
+ static void
112
+ get_open_paths (StringList* paths, IFileOpenDialog* nativedialog)
113
+ {
114
+ ComPtr<IShellItemArray> items;
115
+ HRESULT result = nativedialog->GetResults(&items.ptr);
116
+ if (is_missing_result(result))
117
+ return;
118
+ if (FAILED(result) || !items)
119
+ system_error(__FILE__, __LINE__);
120
+
121
+ DWORD count = 0;
122
+ if (FAILED(items->GetCount(&count)))
123
+ system_error(__FILE__, __LINE__);
124
+
125
+ for (DWORD i = 0; i < count; ++i)
126
+ {
127
+ ComPtr<IShellItem> item;
128
+ if (FAILED(items->GetItemAt(i, &item.ptr)) || !item)
129
+ continue;
130
+
131
+ add_path(paths, item.ptr);
132
+ }
133
+ }
134
+
135
+ static void
136
+ get_save_path (StringList* paths, IFileDialog* nativedialog)
137
+ {
138
+ ComPtr<IShellItem> item;
139
+ HRESULT result = nativedialog->GetResult(&item.ptr);
140
+ if (is_missing_result(result))
141
+ return;
142
+ if (FAILED(result) || !item)
143
+ system_error(__FILE__, __LINE__);
144
+
145
+ add_path(paths, item.ptr);
146
+ }
147
+
148
+ static void
149
+ set_folder (IFileDialog* nativedialog, const char* dir)
150
+ {
151
+ // SetFolder overrides the folder the user last visited, so it is only
152
+ // called when a directory was explicitly given
153
+ ComPtr<IShellItem> item;
154
+ HRESULT result = SHCreateItemFromParsingName(
155
+ to_native_path(dir).c_str(), NULL, IID_IShellItem, (void**) &item.ptr);
156
+ if (SUCCEEDED(result) && item)
157
+ nativedialog->SetFolder(item.ptr);
158
+ }
159
+
160
+ void
161
+ FileDialog_show (
162
+ FileDialog* pdialog, FileDialog::Data::Mode mode,
163
+ const char* dir, const char* name)
164
+ {
165
+ if (!pdialog)
166
+ argument_error(__FILE__, __LINE__);
167
+
168
+ FileDialog::Ref dialog = pdialog;
169
+ bool save = mode == FileDialog::Data::SAVE_FILE;
170
+
171
+ ComPtr<IFileOpenDialog> opendialog;
172
+ ComPtr<IFileDialog> savedialog;
173
+ HRESULT result = CoCreateInstance(
174
+ save ? CLSID_FileSaveDialog : CLSID_FileOpenDialog,
175
+ NULL,
176
+ CLSCTX_INPROC_SERVER,
177
+ save ? IID_IFileDialog : IID_IFileOpenDialog,
178
+ save ? (void**) &savedialog.ptr : (void**) &opendialog.ptr);
179
+ if (FAILED(result))
180
+ system_error(__FILE__, __LINE__);
181
+
182
+ IFileDialog* nativedialog = save ? savedialog.ptr : (IFileDialog*) opendialog.ptr;
183
+ setup_options(nativedialog, mode);
184
+
185
+ std::wstring joined;// keeps the filter string alive until Show()
186
+ setup_file_types(&joined, nativedialog, dialog, mode);
187
+
188
+ const char* title = dialog->title();
189
+ if (*title)
190
+ nativedialog->SetTitle(String(title).to_wstr().c_str());
191
+
192
+ if (dir && *dir)
193
+ set_folder(nativedialog, dir);
194
+
195
+ if (save && name && *name)
196
+ nativedialog->SetFileName(String(name).to_wstr().c_str());
197
+
198
+ Window* owner = dialog->owner();
199
+ HWND hwnd = owner ? Window_get_hwnd(owner) : NULL;
200
+ result = nativedialog->Show(hwnd);// runs a modal loop
201
+
202
+ StringList paths;
203
+ if (SUCCEEDED(result))
204
+ {
205
+ if (save)
206
+ get_save_path(&paths, savedialog.ptr);
207
+ else
208
+ get_open_paths(&paths, opendialog.ptr);
209
+ }
210
+
211
+ if (!paths.empty())
212
+ {
213
+ FileEvent e(save ? FileEvent::SAVE : FileEvent::OPEN, paths);
214
+ FileDialog_call_file_event(dialog, &e);
215
+ }
216
+ else if (SUCCEEDED(result) || result == HRESULT_FROM_WIN32(ERROR_CANCELLED))
217
+ {
218
+ Event e;
219
+ FileDialog_call_cancel_event(dialog, &e);
220
+ }
221
+ else
222
+ system_error(__FILE__, __LINE__);
223
+ }
224
+
225
+
226
+ }// Reflex
@@ -72,20 +72,27 @@ namespace Reflex
72
72
  handle_gamepad_trigger_event(win, state.Gamepad.bRightTrigger, prev_state.Gamepad.bRightTrigger, KEY_GAMEPAD_RTRIGGER);
73
73
  }
74
74
 
75
+ static bool polling = false;
76
+
75
77
  void
76
- Gamepad_init (Application* app)
78
+ Gamepad_init_native (Application* app)
77
79
  {
80
+ polling = true;
78
81
  }
79
82
 
80
83
  void
81
- Gamepad_fin (Application* app)
84
+ Gamepad_fin_native (Application* app)
82
85
  {
86
+ polling = false;
87
+
83
88
  Gamepad_remove_all(app);
84
89
  }
85
90
 
86
91
  void
87
92
  Gamepad_poll ()
88
93
  {
94
+ if (!polling) return;
95
+
89
96
  static XINPUT_STATE prev_state;
90
97
  static bool prev_detected = false;
91
98