44#include <fcntl.h>
55#include <io.h>
66#include "chuniio.h"
7+ #include "leapio/leapio.h"
78#include "log.h"
89#define CHUNI_WINPROC CallWindowProc(chuni_wndproc, hwnd, msg, w_param, l_param)
910#define MAXFINGERS 10
1011#define CONFIG L".\\chunitouch.ini"
1112
13+ #define CSRC_TOUCH 0
14+ #define CSRC_LEAP 1
15+
16+ #define LEAP_X 0
17+ #define LEAP_Y 1
18+ #define LEAP_Z 2
19+
1220static LONG chuni_ir_trigger_threshold = 7000 ;
1321static LONG chuni_ir_height = 5000 ;
22+ static UINT chuni_ir_leap_trigger = 500 ;
23+ static UINT chuni_ir_leap_step = 300 ;
24+ static uint8_t leap_orientation = LEAP_Y ;
25+
1426static LONG chuni_key_start = 31800 ;
1527static LONG chuni_key_width = 4000 ;
1628
1729static LONG chuni_key_end = 0 ; //chuni_key_start + 32 * chuni_key_width;
1830
1931static bool raw_input = false;
32+ static uint8_t ir_control_source = CSRC_TOUCH ;
2033static bool ir_keep_slider = false;
2134
2235static unsigned int __stdcall chuni_io_slider_thread_proc (void * ctx );
@@ -37,7 +50,9 @@ static int get_slider_from_pos(LONG x, LONG y) {
3750 return 31 - ((x - chuni_key_start ) / chuni_key_width );
3851}
3952
40- static void chuni_io_ir (uint8_t * bitmap , uint8_t sensor_id , bool set ) {
53+ static void chuni_io_ir (uint8_t * bitmap , int8_t sensor_id , bool set ) {
54+ if (sensor_id > 5 ) sensor_id = 5 ;
55+ if (sensor_id < 0 ) sensor_id = 0 ;
4156 if (sensor_id % 2 == 0 ) sensor_id ++ ;
4257 else sensor_id -- ;
4358 if (set ) * bitmap |= 1 << sensor_id ;
@@ -47,7 +62,7 @@ static void chuni_io_ir(uint8_t *bitmap, uint8_t sensor_id, bool set) {
4762static int get_finger_index (DWORD id ) {
4863 int avail_indx = -1 ;
4964 for (int i = 0 ; i < MAXFINGERS ; i ++ ) {
50- if (finger_ids [i ] == id ) return i ;
65+ if (finger_ids [i ] > 0 && ( DWORD ) finger_ids [ i ] == id ) return i ;
5166 if (avail_indx == -1 && finger_ids [i ] == -1 ) avail_indx = i ;
5267 }
5368
@@ -86,13 +101,11 @@ LRESULT CALLBACK chuni_winproc_hook(HWND hwnd, UINT msg, WPARAM w_param, LPARAM
86101 if (!raw_input ) ScreenToClient (hwnd , & local_point );
87102 if (p .dwFlags & TOUCHEVENTF_DOWN ) start_locations [fid ] = local_point .y ;
88103 LONG x_diff = start_locations [fid ] - local_point .y ;
89- if (x_diff > chuni_ir_trigger_threshold ) {
90- int ir_id = (x_diff / chuni_ir_height ) - 1 ;
91- if (ir_id > 5 ) ir_id = 5 ;
92- if (ir_id < 0 ) ir_id = 0 ;
104+ if (ir_control_source == CSRC_TOUCH && x_diff > chuni_ir_trigger_threshold ) {
105+ int8_t ir_id = (x_diff / chuni_ir_height ) - 1 ;
93106 chuni_io_ir (& chuni_ir_map_local , ir_id , true);
94107 }
95- if (x_diff <= chuni_ir_trigger_threshold || ir_keep_slider ) {
108+ if (ir_control_source == CSRC_LEAP || x_diff <= chuni_ir_trigger_threshold || ir_keep_slider ) {
96109 int slider_id = get_slider_from_pos (local_point .x , local_point .y );
97110 if (slider_id >= 0 && slider_id < 32 ) clicked_sliders [slider_id ] = 128 ;
98111 }
@@ -106,6 +119,27 @@ LRESULT CALLBACK chuni_winproc_hook(HWND hwnd, UINT msg, WPARAM w_param, LPARAM
106119 return CHUNI_WINPROC ;
107120}
108121
122+ void leap_handler (const LEAP_TRACKING_EVENT * ev ) {
123+ uint8_t chuni_ir_map_local = 0 ;
124+
125+ for (uint32_t h = 0 ; h < ev -> nHands ; h ++ ) {
126+ const LEAP_HAND * hand = & (ev -> pHands [h ]);
127+ float pos = 0 ;
128+ if (leap_orientation == LEAP_X ) pos = hand -> palm .position .x ;
129+ if (leap_orientation == LEAP_Y ) pos = hand -> palm .position .y ;
130+ if (leap_orientation == LEAP_Z ) pos = hand -> palm .position .z ;
131+
132+ if (pos > chuni_ir_leap_trigger ) {
133+ int8_t ir_id = (pos - chuni_ir_leap_trigger ) / chuni_ir_leap_step - 1 ;
134+ if (ir_id > 5 ) ir_id = 5 ;
135+ if (ir_id < 0 ) ir_id = 0 ;
136+ chuni_io_ir (& chuni_ir_map_local , ir_id , true);
137+ }
138+ }
139+
140+ chuni_ir_sensor_map = chuni_ir_map_local ;
141+ }
142+
109143HRESULT chuni_io_jvs_init (void ) {
110144 // hook winproc
111145 HWND hwnd = FindWindowA (NULL , "teaGfx DirectX Release" );
@@ -121,25 +155,58 @@ HRESULT chuni_io_jvs_init(void) {
121155 else {
122156 ULONG flags ;
123157 if (!IsTouchWindow (hwnd , & flags )) log_warn ("IsTouchWindow() returned false, touch might not work.\n" );
158+ #ifdef _WIN64
159+ chuni_wndproc = (WNDPROC )SetWindowLongPtr (hwnd , GWLP_WNDPROC , (LONG_PTR )& chuni_winproc_hook );
160+ #else
124161 chuni_wndproc = (WNDPROC )SetWindowLongPtr (hwnd , GWL_WNDPROC , (LONG_PTR )& chuni_winproc_hook );
162+ #endif
163+
125164 log_info ("hooked WNDPROC.\n" );
126165 }
127- chuni_ir_height = GetPrivateProfileIntW (L"ir" , L"height" , 50 , CONFIG ) * 100 ;
128- chuni_ir_trigger_threshold = GetPrivateProfileIntW (L"ir" , L"trigger" , 70 , CONFIG ) * 100 ;
166+ WCHAR str_control_src [16 ];
167+ WCHAR str_leap_orientation [16 ];
168+
169+ chuni_ir_height = GetPrivateProfileIntW (L"ir" , L"touch_height" , 50 , CONFIG ) * 100 ;
170+ chuni_ir_trigger_threshold = GetPrivateProfileIntW (L"ir" , L"touch_trigger" , 70 , CONFIG ) * 100 ;
171+ chuni_ir_leap_trigger = GetPrivateProfileIntW (L"ir" , L"leap_trigger" , 500 , CONFIG );
172+ chuni_ir_leap_step = GetPrivateProfileIntW (L"ir" , L"leap_step" , 300 , CONFIG );
129173 chuni_key_start = GetPrivateProfileIntW (L"slider" , L"offset" , 318 , CONFIG ) * 100 ;
130174 chuni_key_width = GetPrivateProfileIntW (L"slider" , L"width" , 40 , CONFIG ) * 100 ;
131175 raw_input = GetPrivateProfileIntW (L"io" , L"raw_input" , 0 , CONFIG );
132176 ir_keep_slider = GetPrivateProfileIntW (L"misc" , L"ir_keep_slider" , 0 , CONFIG );
133177
178+ GetPrivateProfileStringW (L"ir" , L"control_source" , L"touch" , str_control_src , 16 , CONFIG );
179+ GetPrivateProfileStringW (L"ir" , L"leap_orientation" , L"y" , str_leap_orientation , 16 , CONFIG );
180+
134181 chuni_key_end = chuni_key_start + 32 * chuni_key_width ;
182+ ir_control_source = (wcscmp (str_control_src , L"leap" ) == 0 ) ? CSRC_LEAP : CSRC_TOUCH ;
183+ /**/ if (wcscmp (str_leap_orientation , L"x" ) == 0 ) leap_orientation = LEAP_X ;
184+ else if (wcscmp (str_leap_orientation , L"y" ) == 0 ) leap_orientation = LEAP_Y ;
185+ else if (wcscmp (str_leap_orientation , L"z" ) == 0 ) leap_orientation = LEAP_Z ;
135186
136187 for (int i = 0 ; i < MAXFINGERS ; i ++ ) finger_ids [i ] = -1 ;
137188
189+ if (ir_control_source == CSRC_LEAP ) {
190+ log_info ("connecting to leap service...\n" );
191+ leap_connect (NULL );
192+ leap_set_tracking_handler (leap_handler );
193+ while (!leap_is_connected ()) {
194+ Sleep (10 );
195+ }
196+ log_info ("connected to leap service.\n" );
197+ }
198+
199+
138200 log_info ("raw_input: %s\n" , raw_input ? "enabled" : "disabled" );
139201 log_info ("ir_keep_slider: %s\n" , ir_keep_slider ? "enabled" : "disabled" );
140- log_info ("ir: trigger_threshold: %ld, height: %ld\n" , chuni_ir_trigger_threshold /100 , chuni_ir_height /100 );
141202 log_info ("key: start: %ld, width: %ld, end: %ld\n" , chuni_key_start /100 , chuni_key_width /100 , chuni_key_end /100 );
142203
204+ if (ir_control_source == CSRC_TOUCH ) {
205+ log_info ("ir: touch mode, trigger_threshold: %ld, height: %ld\n" , chuni_ir_trigger_threshold /100 , chuni_ir_height /100 );
206+ } else {
207+ log_info ("ir: leap mode, axis: %u, trigger_threshold: %u, step: %u\n" , leap_orientation , chuni_ir_leap_trigger , chuni_ir_leap_step );
208+ }
209+
143210 return S_OK ;
144211}
145212
0 commit comments