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.
- checksums.yaml +4 -4
- data/.doc/ext/reflex/application.cpp +37 -6
- data/.doc/ext/reflex/capture_event.cpp +1 -1
- data/.doc/ext/reflex/chase_constraint.cpp +1 -1
- data/.doc/ext/reflex/clipboard.cpp +1 -1
- data/.doc/ext/reflex/color_event.cpp +76 -0
- data/.doc/ext/reflex/color_picker.cpp +113 -0
- data/.doc/ext/reflex/constraint.cpp +1 -1
- data/.doc/ext/reflex/contact_event.cpp +1 -1
- data/.doc/ext/reflex/control_change_event.cpp +1 -1
- data/.doc/ext/reflex/device.cpp +1 -1
- data/.doc/ext/reflex/device_event.cpp +1 -1
- data/.doc/ext/reflex/draw_event.cpp +1 -1
- data/.doc/ext/reflex/ellipse_shape.cpp +1 -1
- data/.doc/ext/reflex/event.cpp +1 -1
- data/.doc/ext/reflex/file_dialog.cpp +181 -0
- data/.doc/ext/reflex/file_event.cpp +103 -0
- data/.doc/ext/reflex/filter.cpp +1 -1
- data/.doc/ext/reflex/focus_event.cpp +1 -1
- data/.doc/ext/reflex/frame_event.cpp +1 -1
- data/.doc/ext/reflex/gamepad.cpp +48 -0
- data/.doc/ext/reflex/image_view.cpp +1 -1
- data/.doc/ext/reflex/key_event.cpp +1 -274
- data/.doc/ext/reflex/line_shape.cpp +1 -1
- data/.doc/ext/reflex/link_constraint.cpp +1 -1
- data/.doc/ext/reflex/menu.cpp +6 -5
- data/.doc/ext/reflex/midi.cpp +9 -2
- data/.doc/ext/reflex/midi_event.cpp +1 -1
- data/.doc/ext/reflex/motion_event.cpp +1 -1
- data/.doc/ext/reflex/native.cpp +18 -6
- data/.doc/ext/reflex/note_event.cpp +1 -1
- data/.doc/ext/reflex/pin.cpp +1 -1
- data/.doc/ext/reflex/pointer.cpp +1 -1
- data/.doc/ext/reflex/pointer_event.cpp +2 -2
- data/.doc/ext/reflex/polygon_shape.cpp +1 -1
- data/.doc/ext/reflex/rect_shape.cpp +1 -1
- data/.doc/ext/reflex/reflex.cpp +566 -232
- data/.doc/ext/reflex/screen.cpp +27 -1
- data/.doc/ext/reflex/scroll_event.cpp +1 -1
- data/.doc/ext/reflex/selector.cpp +1 -1
- data/.doc/ext/reflex/shape.cpp +1 -1
- data/.doc/ext/reflex/snap_constraint.cpp +1 -1
- data/.doc/ext/reflex/style.cpp +1 -1
- data/.doc/ext/reflex/style_length.cpp +1 -1
- data/.doc/ext/reflex/text_event.cpp +104 -0
- data/.doc/ext/reflex/timer.cpp +1 -1
- data/.doc/ext/reflex/timer_event.cpp +1 -1
- data/.doc/ext/reflex/update_event.cpp +1 -1
- data/.doc/ext/reflex/view.cpp +110 -56
- data/.doc/ext/reflex/wheel_constraint.cpp +1 -1
- data/.doc/ext/reflex/wheel_event.cpp +1 -1
- data/.doc/ext/reflex/window.cpp +226 -17
- data/.github/workflows/release-gem.yml +2 -49
- data/.github/workflows/tag.yml +5 -28
- data/.github/workflows/test.yml +1 -37
- data/ChangeLog.md +54 -0
- data/Gemfile.lock +13 -8
- data/Rakefile +13 -2
- data/Reflex.podspec +2 -2
- data/VERSION +1 -1
- data/ext/reflex/application.cpp +41 -6
- data/ext/reflex/capture_event.cpp +1 -1
- data/ext/reflex/chase_constraint.cpp +1 -1
- data/ext/reflex/clipboard.cpp +1 -1
- data/ext/reflex/color_event.cpp +80 -0
- data/ext/reflex/color_picker.cpp +121 -0
- data/ext/reflex/constraint.cpp +1 -1
- data/ext/reflex/contact_event.cpp +1 -1
- data/ext/reflex/control_change_event.cpp +1 -1
- data/ext/reflex/device.cpp +1 -1
- data/ext/reflex/device_event.cpp +1 -1
- data/ext/reflex/draw_event.cpp +1 -1
- data/ext/reflex/ellipse_shape.cpp +1 -1
- data/ext/reflex/event.cpp +1 -1
- data/ext/reflex/extconf.rb +4 -2
- data/ext/reflex/file_dialog.cpp +194 -0
- data/ext/reflex/file_event.cpp +108 -0
- data/ext/reflex/filter.cpp +1 -1
- data/ext/reflex/focus_event.cpp +1 -1
- data/ext/reflex/frame_event.cpp +1 -1
- data/ext/reflex/gamepad.cpp +50 -0
- data/ext/reflex/image_view.cpp +1 -1
- data/ext/reflex/key_event.cpp +1 -275
- data/ext/reflex/line_shape.cpp +1 -1
- data/ext/reflex/link_constraint.cpp +1 -1
- data/ext/reflex/menu.cpp +8 -7
- data/ext/reflex/midi.cpp +11 -3
- data/ext/reflex/midi_event.cpp +1 -1
- data/ext/reflex/motion_event.cpp +1 -1
- data/ext/reflex/native.cpp +18 -6
- data/ext/reflex/note_event.cpp +1 -1
- data/ext/reflex/pin.cpp +1 -1
- data/ext/reflex/pointer.cpp +1 -1
- data/ext/reflex/pointer_event.cpp +2 -2
- data/ext/reflex/polygon_shape.cpp +1 -1
- data/ext/reflex/rect_shape.cpp +1 -1
- data/ext/reflex/reflex.cpp +568 -232
- data/ext/reflex/screen.cpp +31 -2
- data/ext/reflex/scroll_event.cpp +1 -1
- data/ext/reflex/selector.cpp +1 -1
- data/ext/reflex/selector.h +9 -9
- data/ext/reflex/shape.cpp +1 -1
- data/ext/reflex/snap_constraint.cpp +1 -1
- data/ext/reflex/style.cpp +1 -1
- data/ext/reflex/style_length.cpp +1 -1
- data/ext/reflex/text_event.cpp +111 -0
- data/ext/reflex/timer.cpp +1 -1
- data/ext/reflex/timer_event.cpp +1 -1
- data/ext/reflex/update_event.cpp +1 -1
- data/ext/reflex/view.cpp +121 -61
- data/ext/reflex/wheel_constraint.cpp +1 -1
- data/ext/reflex/wheel_event.cpp +1 -1
- data/ext/reflex/window.cpp +256 -25
- data/include/reflex/application.h +10 -0
- data/include/reflex/color_picker.h +65 -0
- data/include/reflex/event.h +178 -88
- data/include/reflex/file_dialog.h +73 -0
- data/include/reflex/gamepad.h +3 -0
- data/include/reflex/menu.h +3 -3
- data/include/reflex/midi.h +3 -0
- data/include/reflex/reflex.h +2 -0
- data/include/reflex/ruby/application.h +6 -1
- data/include/reflex/ruby/color_picker.h +89 -0
- data/include/reflex/ruby/event.h +62 -29
- data/include/reflex/ruby/file_dialog.h +89 -0
- data/include/reflex/ruby/gamepad.h +46 -0
- data/include/reflex/ruby/reflex.h +3 -0
- data/include/reflex/ruby/view.h +92 -44
- data/include/reflex/ruby/window.h +60 -1
- data/include/reflex/ruby.h +3 -0
- data/include/reflex/screen.h +11 -2
- data/include/reflex/view.h +28 -16
- data/include/reflex/window.h +40 -8
- data/include/reflex.h +3 -0
- data/lib/reflex/application.rb +5 -5
- data/lib/reflex/autoinit.rb +3 -1
- data/lib/reflex/button.rb +3 -3
- data/lib/reflex/color_event.rb +16 -0
- data/lib/reflex/color_picker.rb +45 -0
- data/lib/reflex/control_change_event.rb +17 -0
- data/lib/reflex/file_dialog.rb +70 -0
- data/lib/reflex/file_event.rb +37 -0
- data/lib/reflex/helper.rb +58 -7
- data/lib/reflex/key_event.rb +9 -4
- data/lib/reflex/menu.rb +17 -1
- data/lib/reflex/model.rb +19 -19
- data/lib/reflex/note_event.rb +1 -1
- data/lib/reflex/pointer.rb +14 -3
- data/lib/reflex/pointer_event.rb +12 -1
- data/lib/reflex/reflex.rb +5 -0
- data/lib/reflex/shape.rb +14 -14
- data/lib/reflex/style.rb +16 -16
- data/lib/reflex/text_event.rb +40 -0
- data/lib/reflex/timer.rb +3 -3
- data/lib/reflex/view.rb +29 -14
- data/lib/reflex/wheel_event.rb +12 -3
- data/lib/reflex/window.rb +25 -13
- data/lib/reflex.rb +8 -2
- data/reflex.gemspec +4 -4
- data/samples/ime.rb +100 -0
- data/samples/ios/hello/hello.xcodeproj/project.pbxproj +236 -224
- data/samples/menu.rb +4 -1
- data/samples/model.rb +3 -3
- data/samples/test/alert.rb +93 -0
- data/samples/test/always_on.rb +76 -0
- data/samples/test/app_background.rb +51 -0
- data/samples/test/boundary.rb +75 -0
- data/samples/test/callback_exception.rb +101 -0
- data/samples/test/cancel.rb +53 -0
- data/samples/test/color_picker.rb +63 -0
- data/samples/test/file_dialog.rb +102 -0
- data/samples/window_style.rb +156 -0
- data/src/application.cpp +159 -18
- data/src/application.h +92 -7
- data/src/color_picker.cpp +113 -0
- data/src/color_picker.h +36 -0
- data/src/event.cpp +410 -252
- data/src/event.h +12 -0
- data/src/file_dialog.cpp +163 -0
- data/src/file_dialog.h +52 -0
- data/src/gamepad.cpp +42 -5
- data/src/gamepad.h +4 -0
- data/src/ios/app_delegate.mm +5 -3
- data/src/ios/application.mm +24 -0
- data/src/ios/color_picker.mm +19 -0
- data/src/ios/file_dialog.mm +21 -0
- data/src/ios/gamepad.mm +4 -4
- data/src/ios/menu.mm +5 -0
- data/src/ios/reflex.mm +8 -0
- data/src/ios/screen.mm +26 -0
- data/src/ios/view_controller.mm +2 -30
- data/src/ios/window.mm +38 -9
- data/src/menu.cpp +66 -4
- data/src/menu.h +17 -1
- data/src/midi.cpp +61 -31
- data/src/osx/app_delegate.h +4 -0
- data/src/osx/app_delegate.mm +102 -22
- data/src/osx/application.mm +88 -6
- data/src/osx/color_picker.mm +112 -0
- data/src/osx/event.h +10 -0
- data/src/osx/event.mm +84 -30
- data/src/osx/file_dialog.mm +168 -0
- data/src/osx/gamepad.mm +2 -2
- data/src/osx/gamepad_hid.mm +1 -1
- data/src/osx/menu.mm +177 -33
- data/src/osx/native_window.h +16 -2
- data/src/osx/native_window.mm +114 -57
- data/src/osx/opengl_view.h +2 -1
- data/src/osx/opengl_view.mm +184 -43
- data/src/osx/reflex.mm +38 -0
- data/src/osx/screen.mm +36 -0
- data/src/osx/window.mm +106 -24
- data/src/pointer.cpp +13 -4
- data/src/pointer.h +4 -0
- data/src/rays.h +46 -0
- data/src/sdl/application.cpp +68 -8
- data/src/sdl/color_picker.cpp +18 -0
- data/src/sdl/event.cpp +24 -3
- data/src/sdl/event.h +12 -0
- data/src/sdl/file_dialog.cpp +20 -0
- data/src/sdl/gamepad.cpp +3 -7
- data/src/sdl/menu.cpp +5 -0
- data/src/sdl/reflex.cpp +20 -0
- data/src/sdl/screen.cpp +36 -0
- data/src/sdl/window.cpp +142 -29
- data/src/shape.cpp +15 -10
- data/src/view.cpp +287 -198
- data/src/view.h +4 -2
- data/src/vk.h +416 -0
- data/src/win32/application.cpp +162 -12
- data/src/win32/application.h +20 -0
- data/src/win32/color_picker.cpp +82 -0
- data/src/win32/event.cpp +114 -12
- data/src/win32/event.h +21 -4
- data/src/win32/file_dialog.cpp +226 -0
- data/src/win32/gamepad.cpp +9 -2
- data/src/win32/menu.cpp +191 -53
- data/src/win32/menu.h +9 -1
- data/src/win32/opengl.cpp +2 -9
- data/src/win32/reflex.cpp +44 -3
- data/src/win32/screen.cpp +164 -3
- data/src/win32/screen.h +8 -0
- data/src/win32/tray.cpp +191 -0
- data/src/win32/tray.h +22 -0
- data/src/win32/vk.cpp +11 -0
- data/src/win32/window.cpp +809 -148
- data/src/win32/window.h +6 -0
- data/src/window.cpp +718 -185
- data/src/window.h +66 -33
- data/src/world.cpp +9 -1
- data/test/helper.rb +17 -0
- data/test/test_application.rb +90 -1
- data/test/test_chase_constraint.rb +1 -3
- data/test/test_color_event.rb +36 -0
- data/test/test_color_picker.rb +62 -0
- data/test/test_constraint.rb +2 -4
- data/test/test_event.rb +1 -1
- data/test/test_file_dialog.rb +48 -0
- data/test/test_file_event.rb +43 -0
- data/test/test_has_text_preedit.rb +54 -0
- data/test/test_key_event.rb +20 -5
- data/test/test_link_constraint.rb +1 -3
- data/test/test_menu.rb +40 -10
- data/test/test_pointer.rb +33 -23
- data/test/test_pointer_event.rb +24 -9
- data/test/test_reflex.rb +36 -0
- data/test/test_screen.rb +24 -2
- data/test/test_snap_constraint.rb +1 -3
- data/test/test_text_event.rb +54 -0
- data/test/test_view.rb +41 -4
- data/test/test_wheel_constraint.rb +1 -3
- data/test/test_wheel_event.rb +13 -5
- data/test/test_window.rb +196 -44
- metadata +80 -10
- data/.github/workflows/utils.rb +0 -127
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#include "../color_picker.h"
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
#include <xot/windows.h>
|
|
5
|
+
#include <commdlg.h>
|
|
6
|
+
#include "reflex/exception.h"
|
|
7
|
+
#include "window.h"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
namespace Reflex
|
|
11
|
+
{
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
// the custom color slots of the dialog live as long as the process
|
|
15
|
+
static COLORREF custom_colors[16] =
|
|
16
|
+
{
|
|
17
|
+
RGB(255, 255, 255), RGB(255, 255, 255), RGB(255, 255, 255), RGB(255, 255, 255),
|
|
18
|
+
RGB(255, 255, 255), RGB(255, 255, 255), RGB(255, 255, 255), RGB(255, 255, 255),
|
|
19
|
+
RGB(255, 255, 255), RGB(255, 255, 255), RGB(255, 255, 255), RGB(255, 255, 255),
|
|
20
|
+
RGB(255, 255, 255), RGB(255, 255, 255), RGB(255, 255, 255), RGB(255, 255, 255)
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
static BYTE
|
|
25
|
+
to_byte (float value)
|
|
26
|
+
{
|
|
27
|
+
if (value < 0) value = 0;
|
|
28
|
+
if (value > 1) value = 1;
|
|
29
|
+
return (BYTE) (value * 255 + 0.5f);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static COLORREF
|
|
33
|
+
to_colorref (const Color& color)
|
|
34
|
+
{
|
|
35
|
+
return RGB(to_byte(color.red), to_byte(color.green), to_byte(color.blue));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
static Color
|
|
39
|
+
to_color (COLORREF colorref)
|
|
40
|
+
{
|
|
41
|
+
return Color(
|
|
42
|
+
GetRValue(colorref) / 255.f,
|
|
43
|
+
GetGValue(colorref) / 255.f,
|
|
44
|
+
GetBValue(colorref) / 255.f);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
void
|
|
48
|
+
ColorPicker_show (ColorPicker* ppicker, const Color* initial)
|
|
49
|
+
{
|
|
50
|
+
if (!ppicker)
|
|
51
|
+
argument_error(__FILE__, __LINE__);
|
|
52
|
+
|
|
53
|
+
ColorPicker::Ref picker = ppicker;
|
|
54
|
+
|
|
55
|
+
Window* owner = picker->owner();
|
|
56
|
+
CHOOSECOLORW cc = {0};
|
|
57
|
+
cc.lStructSize = sizeof(cc);
|
|
58
|
+
cc.hwndOwner = owner ? Window_get_hwnd(owner) : NULL;
|
|
59
|
+
cc.lpCustColors = custom_colors;
|
|
60
|
+
cc.Flags = CC_FULLOPEN | CC_ANYCOLOR;
|
|
61
|
+
if (initial)
|
|
62
|
+
{
|
|
63
|
+
cc.rgbResult = to_colorref(*initial);
|
|
64
|
+
cc.Flags |= CC_RGBINIT;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// the dialog has no alpha, so the picked color always has alpha 1
|
|
68
|
+
BOOL picked = ChooseColorW(&cc);// runs a modal loop
|
|
69
|
+
if (picked)
|
|
70
|
+
{
|
|
71
|
+
ColorEvent e(to_color(cc.rgbResult));
|
|
72
|
+
ColorPicker_call_color_event(picker, &e);
|
|
73
|
+
}
|
|
74
|
+
else if (CommDlgExtendedError() != 0)
|
|
75
|
+
system_error(__FILE__, __LINE__);
|
|
76
|
+
|
|
77
|
+
Event e;
|
|
78
|
+
ColorPicker_call_close_event(picker, &e);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
}// Reflex
|
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
|
{
|
|
@@ -131,19 +217,20 @@ namespace Reflex
|
|
|
131
217
|
}
|
|
132
218
|
}
|
|
133
219
|
|
|
134
|
-
NativePointerEvent::NativePointerEvent (
|
|
135
|
-
|
|
220
|
+
NativePointerEvent::NativePointerEvent (
|
|
221
|
+
const Window& window, UINT msg, WPARAM wp, LPARAM lp)
|
|
222
|
+
: NativePointerEvent(window, msg, wp, lp, get_mouse_action(msg))
|
|
136
223
|
{
|
|
137
224
|
}
|
|
138
225
|
|
|
139
226
|
NativePointerEvent::NativePointerEvent (
|
|
140
|
-
UINT msg, WPARAM wp, LPARAM lp, Pointer::Action action)
|
|
227
|
+
const Window& window, UINT msg, WPARAM wp, LPARAM lp, Pointer::Action action)
|
|
141
228
|
{
|
|
142
229
|
PointerEvent_add_pointer(this, Pointer(
|
|
143
230
|
0,
|
|
144
231
|
get_mouse_type(msg, wp),
|
|
145
232
|
action,
|
|
146
|
-
|
|
233
|
+
Window_from_native_coord(window, GET_X_LPARAM(lp), GET_Y_LPARAM(lp)),
|
|
147
234
|
KeyEvent_get_modifiers(),
|
|
148
235
|
get_mouse_click_count(msg),
|
|
149
236
|
is_mouse_dragging(msg, wp),
|
|
@@ -168,19 +255,19 @@ namespace Reflex
|
|
|
168
255
|
}
|
|
169
256
|
|
|
170
257
|
static Point
|
|
171
|
-
get_touch_position (
|
|
258
|
+
get_touch_position (const Window& window, const TOUCHINPUT& touch)
|
|
172
259
|
{
|
|
173
260
|
coord x = (coord) touch.x / 100;
|
|
174
261
|
coord y = (coord) touch.y / 100;
|
|
175
262
|
|
|
176
263
|
POINT point = {0, 0};
|
|
177
|
-
if (ClientToScreen(
|
|
264
|
+
if (ClientToScreen(Window_get_hwnd(&window), &point))
|
|
178
265
|
{
|
|
179
266
|
x -= point.x;
|
|
180
267
|
y -= point.y;
|
|
181
268
|
}
|
|
182
269
|
|
|
183
|
-
return
|
|
270
|
+
return Window_from_native_coord(window, x, y);
|
|
184
271
|
}
|
|
185
272
|
|
|
186
273
|
static double
|
|
@@ -193,7 +280,7 @@ namespace Reflex
|
|
|
193
280
|
}
|
|
194
281
|
|
|
195
282
|
NativePointerEvent::NativePointerEvent (
|
|
196
|
-
|
|
283
|
+
const Window& window, const TOUCHINPUT* touches, size_t size)
|
|
197
284
|
{
|
|
198
285
|
for (size_t i = 0; i < size; ++i)
|
|
199
286
|
{
|
|
@@ -204,7 +291,7 @@ namespace Reflex
|
|
|
204
291
|
0,
|
|
205
292
|
get_touch_type(touch),
|
|
206
293
|
action,
|
|
207
|
-
get_touch_position(
|
|
294
|
+
get_touch_position(window, touch),
|
|
208
295
|
KeyEvent_get_modifiers(),
|
|
209
296
|
action == Pointer::DOWN ? 1 : 0,
|
|
210
297
|
action == Pointer::MOVE,
|
|
@@ -217,10 +304,25 @@ namespace Reflex
|
|
|
217
304
|
}
|
|
218
305
|
|
|
219
306
|
|
|
220
|
-
|
|
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)
|
|
221
323
|
: WheelEvent(
|
|
222
|
-
|
|
223
|
-
|
|
324
|
+
get_pointer_position(window, lp),
|
|
325
|
+
Point(to_wheel_pixels(wp_x), -to_wheel_pixels(wp_y), 0),
|
|
224
326
|
KeyEvent_get_modifiers())
|
|
225
327
|
{
|
|
226
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,16 +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);
|
|
31
46
|
|
|
32
|
-
NativePointerEvent (
|
|
47
|
+
NativePointerEvent (
|
|
48
|
+
const Window& window, UINT msg, WPARAM wp, LPARAM lp, Pointer::Action action);
|
|
33
49
|
|
|
34
|
-
NativePointerEvent (
|
|
50
|
+
NativePointerEvent (
|
|
51
|
+
const Window& window, const TOUCHINPUT* touches, size_t size);
|
|
35
52
|
|
|
36
53
|
};// NativePointerEvent
|
|
37
54
|
|
|
@@ -41,7 +58,7 @@ namespace Reflex
|
|
|
41
58
|
|
|
42
59
|
public:
|
|
43
60
|
|
|
44
|
-
NativeWheelEvent (WPARAM wp_x, WPARAM wp_y, LPARAM lp);
|
|
61
|
+
NativeWheelEvent (const Window& window, WPARAM wp_x, WPARAM wp_y, LPARAM lp);
|
|
45
62
|
|
|
46
63
|
};// NativeWheelEvent
|
|
47
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
|
data/src/win32/gamepad.cpp
CHANGED
|
@@ -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
|
-
|
|
78
|
+
Gamepad_init_native (Application* app)
|
|
77
79
|
{
|
|
80
|
+
polling = true;
|
|
78
81
|
}
|
|
79
82
|
|
|
80
83
|
void
|
|
81
|
-
|
|
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
|
|