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/screen.cpp CHANGED
@@ -1,6 +1,11 @@
1
1
  #include "screen.h"
2
2
 
3
3
 
4
+ #include <math.h>
5
+ #include <wchar.h>
6
+ #include <algorithm>
7
+ #include <memory>
8
+ #include <vector>
4
9
  #include "reflex/exception.h"
5
10
 
6
11
 
@@ -22,6 +27,56 @@ namespace Reflex
22
27
  pthis->self->handle = hmonitor;
23
28
  }
24
29
 
30
+ float
31
+ Screen_get_pixel_density (HMONITOR hmonitor)
32
+ {
33
+ static float density = 0;
34
+ if (density <= 0)
35
+ {
36
+ std::shared_ptr<HDC__> dc(GetDC(NULL), [](HDC dc) {if (dc) ReleaseDC(NULL, dc);});
37
+ int dpi = dc ? GetDeviceCaps(dc.get(), LOGPIXELSX) : 0;
38
+ density = dpi > 0 ? dpi / (float) USER_DEFAULT_SCREEN_DPI : 1;
39
+ }
40
+ return density;
41
+ }
42
+
43
+ Bounds
44
+ Screen_from_native_coord (const RECT& rect)
45
+ {
46
+ float density = Screen_get_pixel_density(
47
+ MonitorFromRect(&rect, MONITOR_DEFAULTTONEAREST));
48
+ return Bounds(
49
+ rect.left / density,
50
+ rect.top / density,
51
+ (rect.right - rect.left) / density,
52
+ (rect.bottom - rect.top) / density);
53
+ }
54
+
55
+ POINT
56
+ Screen_to_native_coord (coord x, coord y)
57
+ {
58
+ // NULL: the monitor is unknown from points, but every monitor has the
59
+ // same system density for now
60
+ float density = Screen_get_pixel_density(NULL);
61
+
62
+ return {
63
+ (LONG) lround(x * density),
64
+ (LONG) lround(y * density)
65
+ };
66
+ }
67
+
68
+ RECT
69
+ Screen_to_native_coord (coord x, coord y, coord width, coord height)
70
+ {
71
+ float density = Screen_get_pixel_density(NULL);
72
+ return {
73
+ (LONG) lround( x * density),
74
+ (LONG) lround( y * density),
75
+ (LONG) lround((x + width) * density),
76
+ (LONG) lround((y + height) * density)
77
+ };
78
+ }
79
+
25
80
 
26
81
  Screen::Screen ()
27
82
  {
@@ -31,6 +86,73 @@ namespace Reflex
31
86
  {
32
87
  }
33
88
 
89
+ static String
90
+ get_monitor_name (const wchar_t* device)
91
+ {
92
+ UINT32 npaths = 0, nmodes = 0;
93
+ if (GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &npaths, &nmodes) != ERROR_SUCCESS)
94
+ return "";
95
+
96
+ std::vector<DISPLAYCONFIG_PATH_INFO> paths(npaths);
97
+ std::vector<DISPLAYCONFIG_MODE_INFO> modes(nmodes);
98
+ LONG ret = QueryDisplayConfig(
99
+ QDC_ONLY_ACTIVE_PATHS, &npaths, paths.data(), &nmodes, modes.data(), NULL);
100
+ if (ret != ERROR_SUCCESS)
101
+ return "";
102
+
103
+ for (UINT32 i = 0; i < npaths; ++i)
104
+ {
105
+ const auto& path = paths[i];
106
+
107
+ DISPLAYCONFIG_SOURCE_DEVICE_NAME source = {};
108
+ source.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
109
+ source.header.size = sizeof(source);
110
+ source.header.adapterId = path.sourceInfo.adapterId;
111
+ source.header.id = path.sourceInfo.id;
112
+ if (
113
+ DisplayConfigGetDeviceInfo(&source.header) != ERROR_SUCCESS ||
114
+ wcscmp(source.viewGdiDeviceName, device) != 0)
115
+ {
116
+ continue;
117
+ }
118
+
119
+ DISPLAYCONFIG_TARGET_DEVICE_NAME target = {};
120
+ target.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
121
+ target.header.size = sizeof(target);
122
+ target.header.adapterId = path.targetInfo.adapterId;
123
+ target.header.id = path.targetInfo.id;
124
+ if (DisplayConfigGetDeviceInfo(&target.header) != ERROR_SUCCESS)
125
+ continue;
126
+
127
+ const wchar_t* name = target.monitorFriendlyDeviceName;
128
+ if (*name)
129
+ return String(name, wcslen(name));
130
+ }
131
+ return "";
132
+ }
133
+
134
+ String
135
+ Screen::name () const
136
+ {
137
+ if (!*this)
138
+ invalid_state_error(__FILE__, __LINE__);
139
+
140
+ MONITORINFOEXW mi = {};
141
+ mi.cbSize = sizeof(mi);
142
+ if (!GetMonitorInfoW(self->handle, &mi))
143
+ system_error(__FILE__, __LINE__);
144
+
145
+ String name = get_monitor_name(mi.szDevice);
146
+ if (name.empty())
147
+ {
148
+ const wchar_t* device = mi.szDevice;
149
+ if (wcsncmp(device, L"\\\\.\\", 4) == 0) device += 4;
150
+ name = String(device, wcslen(device));
151
+ }
152
+
153
+ return name;
154
+ }
155
+
34
156
  Bounds
35
157
  Screen::frame () const
36
158
  {
@@ -39,11 +161,19 @@ namespace Reflex
39
161
 
40
162
  MONITORINFO mi = {0};
41
163
  mi.cbSize = sizeof(mi);
42
- if (!GetMonitorInfo(self->handle, &mi))
164
+ if (!GetMonitorInfoW(self->handle, &mi))
43
165
  system_error(__FILE__, __LINE__);
44
166
 
45
- const auto& r = mi.rcMonitor;
46
- return Bounds(r.left, r.top, r.right - r.left, r.bottom - r.top);
167
+ return Screen_from_native_coord(mi.rcMonitor);
168
+ }
169
+
170
+ float
171
+ Screen::pixel_density () const
172
+ {
173
+ if (!*this)
174
+ invalid_state_error(__FILE__, __LINE__);
175
+
176
+ return Screen_get_pixel_density(self->handle);
47
177
  }
48
178
 
49
179
  Screen::operator bool () const
@@ -57,5 +187,36 @@ namespace Reflex
57
187
  return !operator bool();
58
188
  }
59
189
 
190
+ static BOOL CALLBACK
191
+ add_screen (HMONITOR hmonitor, HDC, LPRECT, LPARAM lp)
192
+ {
193
+ Screen s;
194
+ Screen_initialize(&s, hmonitor);
195
+ ((Screen::List*) lp)->emplace_back(s);
196
+ return TRUE;
197
+ }
198
+
199
+ static bool
200
+ is_primary (const Screen& screen)
201
+ {
202
+ MONITORINFO mi = {0};
203
+ mi.cbSize = sizeof(mi);
204
+ if (!GetMonitorInfoW(screen.self->handle, &mi))
205
+ return false;
206
+
207
+ return mi.dwFlags & MONITORINFOF_PRIMARY;
208
+ }
209
+
210
+ Screen::List
211
+ Screen::all ()
212
+ {
213
+ List list;
214
+ if (!EnumDisplayMonitors(NULL, NULL, add_screen, (LPARAM) &list))
215
+ system_error(__FILE__, __LINE__);
216
+
217
+ std::stable_partition(list.begin(), list.end(), is_primary);
218
+ return list;
219
+ }
220
+
60
221
 
61
222
  }// Reflex
data/src/win32/screen.h CHANGED
@@ -14,6 +14,14 @@ namespace Reflex
14
14
 
15
15
  void Screen_initialize (Screen* pthis, HMONITOR hmonitor);
16
16
 
17
+ float Screen_get_pixel_density (HMONITOR hmonitor);
18
+
19
+ Bounds Screen_from_native_coord (const RECT& rect);
20
+
21
+ POINT Screen_to_native_coord (coord x, coord y);
22
+
23
+ RECT Screen_to_native_coord (coord x, coord y, coord width, coord height);
24
+
17
25
 
18
26
  }// Reflex
19
27
 
@@ -0,0 +1,191 @@
1
+ #include "tray.h"
2
+
3
+
4
+ #include <vector>
5
+ #include <xot/windows.h>
6
+ #include <shellapi.h>
7
+ #include "reflex/exception.h"
8
+ #include "../rays.h"
9
+ #include "application.h"
10
+ #include "menu.h"
11
+
12
+
13
+ namespace Reflex
14
+ {
15
+
16
+
17
+ enum {TRAY_ICON_ID = 1, WM_TRAY_ICON = WM_APP + 1};
18
+
19
+ static HWND tray_hwnd = NULL;
20
+
21
+ static Menu* tray_menu = NULL;
22
+
23
+ static HICON tray_icon = NULL;
24
+
25
+ static bool tray_shown = false;
26
+
27
+
28
+ static void
29
+ popup_tray_menu ()
30
+ {
31
+ if (!tray_hwnd || !tray_menu) return;
32
+
33
+ POINT pos;
34
+ if (!GetCursorPos(&pos)) return;
35
+
36
+ Menu_track_popup(
37
+ Menu_get_hmenu(tray_menu),
38
+ TPM_LEFTALIGN | TPM_BOTTOMALIGN | TPM_RIGHTBUTTON, pos, tray_hwnd);
39
+ }
40
+
41
+ static LRESULT CALLBACK
42
+ tray_wndproc (HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
43
+ {
44
+ if (Application_has_exception())
45
+ return DefWindowProcW(hwnd, msg, wp, lp);
46
+
47
+ return Application_guard([&]() -> LRESULT
48
+ {
49
+ switch (msg)
50
+ {
51
+ case WM_TRAY_ICON:
52
+ {
53
+ if (lp == WM_LBUTTONUP || lp == WM_RBUTTONUP)
54
+ popup_tray_menu();
55
+ return 0;
56
+ }
57
+
58
+ case WM_MENUCOMMAND:
59
+ {
60
+ Menu_call_command_event((HMENU) lp, (uint) wp);
61
+ return 0;
62
+ }
63
+
64
+ case WM_INITMENUPOPUP:
65
+ {
66
+ Menu_call_open_event((HMENU) wp);
67
+ break;
68
+ }
69
+
70
+ case WM_UNINITMENUPOPUP:
71
+ {
72
+ Menu_call_close_event((HMENU) wp);
73
+ break;
74
+ }
75
+ }
76
+ return DefWindowProcW(hwnd, msg, wp, lp);
77
+ }, (LRESULT) 0);
78
+ }
79
+
80
+ static HWND
81
+ create_tray_window ()
82
+ {
83
+ static const wchar_t* WINDOWCLASS = L"Reflex:TrayWindowClass";
84
+
85
+ WNDCLASSEXW wc = {sizeof(wc)};
86
+ wc.lpfnWndProc = tray_wndproc;
87
+ wc.hInstance = GetModuleHandle(NULL);
88
+ wc.lpszClassName = WINDOWCLASS;
89
+ if (!RegisterClassExW(&wc))
90
+ system_error(__FILE__, __LINE__);
91
+
92
+ HWND hwnd = CreateWindowExW(
93
+ WS_EX_TOOLWINDOW, WINDOWCLASS, L"", WS_POPUP,
94
+ 0, 0, 0, 0, NULL, NULL, wc.hInstance, NULL);
95
+ if (!hwnd)
96
+ system_error(__FILE__, __LINE__);
97
+
98
+ return hwnd;
99
+ }
100
+
101
+ static HICON
102
+ create_tray_icon (const Image& image)
103
+ {
104
+ HBITMAP color = Rays::Bitmap_get_hbitmap(image.bitmap());
105
+ if (!color) return NULL;
106
+
107
+ BITMAP bmp = {0};
108
+ GetObjectW(color, sizeof(bmp), &bmp);
109
+
110
+ // the mask is required but the alpha channel decides what shows,
111
+ // so it stays all zero
112
+ int stride = ((bmp.bmWidth + 15) / 16) * 2;
113
+ std::vector<BYTE> zero((size_t) stride * bmp.bmHeight, 0);
114
+ HBITMAP mask = CreateBitmap(bmp.bmWidth, bmp.bmHeight, 1, 1, zero.data());
115
+
116
+ ICONINFO info = {0};
117
+ info.fIcon = TRUE;
118
+ info.hbmColor = color;
119
+ info.hbmMask = mask;
120
+
121
+ HICON icon = CreateIconIndirect(&info);
122
+ DeleteObject(mask);
123
+ DeleteObject(color);
124
+ return icon;
125
+ }
126
+
127
+ void
128
+ Tray_update_icon (Application* app)
129
+ {
130
+ Menu* menu = app ? app->background_menu() : NULL;
131
+ if (!menu && app && app->background())
132
+ menu = app->menu();
133
+
134
+ if (!menu)
135
+ {
136
+ Tray_remove_icon();
137
+ Application_quit_if_should();
138
+ return;
139
+ }
140
+
141
+ if (!tray_hwnd)
142
+ tray_hwnd = create_tray_window();
143
+
144
+ if (tray_icon)
145
+ {
146
+ DestroyIcon(tray_icon);
147
+ tray_icon = NULL;
148
+ }
149
+ if (menu->image())
150
+ tray_icon = create_tray_icon(menu->image());
151
+
152
+ String tip = menu->label();
153
+ if (tip.empty()) tip = app->name();
154
+
155
+ NOTIFYICONDATAW nid = {sizeof(nid)};
156
+ nid.hWnd = tray_hwnd;
157
+ nid.uID = TRAY_ICON_ID;
158
+ nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
159
+ nid.uCallbackMessage = WM_TRAY_ICON;
160
+ nid.hIcon =
161
+ tray_icon ? tray_icon : LoadIconW(NULL, (LPCWSTR) IDI_APPLICATION);
162
+ lstrcpynW(nid.szTip, tip.to_wstr().c_str(), sizeof(nid.szTip) / sizeof(*nid.szTip));
163
+
164
+ Shell_NotifyIconW(tray_shown ? NIM_MODIFY : NIM_ADD, &nid);
165
+ tray_shown = true;
166
+ tray_menu = menu;
167
+ }
168
+
169
+ void
170
+ Tray_remove_icon ()
171
+ {
172
+ if (tray_shown)
173
+ {
174
+ NOTIFYICONDATAW nid = {sizeof(nid)};
175
+ nid.hWnd = tray_hwnd;
176
+ nid.uID = TRAY_ICON_ID;
177
+ Shell_NotifyIconW(NIM_DELETE, &nid);
178
+ tray_shown = false;
179
+ }
180
+
181
+ if (tray_icon)
182
+ {
183
+ DestroyIcon(tray_icon);
184
+ tray_icon = NULL;
185
+ }
186
+
187
+ tray_menu = NULL;
188
+ }
189
+
190
+
191
+ }// Reflex
data/src/win32/tray.h ADDED
@@ -0,0 +1,22 @@
1
+ // -*- c++ -*-
2
+ #pragma once
3
+ #ifndef __REFLEX_SRC_WIN32_TRAY_H__
4
+ #define __REFLEX_SRC_WIN32_TRAY_H__
5
+
6
+
7
+ #include "application.h"
8
+
9
+
10
+ namespace Reflex
11
+ {
12
+
13
+
14
+ void Tray_update_icon (Application* app);
15
+
16
+ void Tray_remove_icon ();
17
+
18
+
19
+ }// Reflex
20
+
21
+
22
+ #endif//EOH
data/src/win32/vk.cpp ADDED
@@ -0,0 +1,11 @@
1
+ // vk.h needs VK_NAVIGATION_*, but winuser.h defines them only when
2
+ // _WIN32_WINNT >= 0x0604, and RbConfig's CPPFLAGS sets it to 0x0600.
3
+ // so set a higher value here before vk.h includes windows.h.
4
+ #if _WIN32_WINNT >= 0x0604
5
+ #error _WIN32_WINNT is now high enough; delete this workaround
6
+ #endif
7
+
8
+ #undef _WIN32_WINNT
9
+ #define _WIN32_WINNT 0x0A00
10
+
11
+ #include "../vk.h"