1 /*****************************************************************************
2 * win32touch.c: touch gestures recognition
3 *****************************************************************************
4 * Copyright © 2013-2014 VideoLAN
6 * Authors: Ludovic Fauvet <etix@videolan.org>
7 * Jean-Baptiste Kempf <jb@videolan.org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
28 #include "win32touch.h"
30 #include <vlc_actions.h>
34 static BOOL
DecodeGestureAction( vlc_object_t
*p_this
, win32_gesture_sys_t
*p_gesture
, const GESTUREINFO
* p_gi
);
35 static BOOL
DecodeGestureProjection( vlc_object_t
*p_this
, win32_gesture_sys_t
*p_gesture
, const GESTUREINFO
* p_gi
);
37 LRESULT
DecodeGesture( vlc_object_t
*p_this
, win32_gesture_sys_t
*p_gesture
,
38 HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
41 return DefWindowProc( hWnd
, message
, wParam
, lParam
);
44 ZeroMemory( &gi
, sizeof( GESTUREINFO
) );
45 gi
.cbSize
= sizeof( GESTUREINFO
);
47 BOOL bResult
= p_gesture
->OurGetGestureInfo((HGESTUREINFO
)lParam
, &gi
);
48 BOOL bHandled
= FALSE
; /* Needed to release the handle */
51 bHandled
= p_gesture
->DecodeGestureImpl(p_this
, p_gesture
, &gi
);
54 DWORD dwErr
= GetLastError();
56 msg_Err( p_this
, "Could not retrieve a valid GESTUREINFO structure" );
61 /* Close the Handle, if we handled the gesture, a contrario
62 * from the doc example */
63 p_gesture
->OurCloseGestureInfoHandle((HGESTUREINFO
)lParam
);
67 return DefWindowProc( hWnd
, message
, wParam
, lParam
);
70 static BOOL
DecodeGestureAction( vlc_object_t
*p_this
, win32_gesture_sys_t
*p_gesture
, const GESTUREINFO
* p_gi
)
72 BOOL bHandled
= FALSE
; /* Needed to release the handle */
76 /* Set the win32_gesture_sys_t values */
77 p_gesture
->i_beginx
= p_gi
->ptsLocation
.x
;
78 p_gesture
->i_beginy
= p_gi
->ptsLocation
.y
;
79 p_gesture
->i_lasty
= p_gesture
->i_beginy
;
80 p_gesture
->b_2fingers
= false;
83 if( p_gesture
->i_type
!= 0 &&
84 p_gesture
->i_action
== GESTURE_ACTION_JUMP
)
87 if( p_gesture
->i_beginx
> p_gi
->ptsLocation
.x
)
89 if( p_gesture
->b_2fingers
)
90 action_id
= ACTIONID_JUMP_BACKWARD_MEDIUM
;
92 action_id
= ACTIONID_JUMP_BACKWARD_SHORT
;
96 if( p_gesture
->b_2fingers
)
97 action_id
= ACTIONID_JUMP_FORWARD_MEDIUM
;
99 action_id
= ACTIONID_JUMP_FORWARD_SHORT
;
101 var_SetInteger( p_this
->obj
.libvlc
, "key-action", action_id
);
103 /* Reset the values */
104 p_gesture
->i_action
= GESTURE_ACTION_UNDEFINED
;
105 p_gesture
->i_type
= p_gesture
->i_beginx
= p_gesture
->i_beginy
= -1;
106 p_gesture
->b_2fingers
= false;
109 p_gesture
->i_type
= GID_PAN
;
112 if (p_gi
->dwFlags
& GF_BEGIN
) {
113 p_gesture
->i_beginx
= p_gi
->ptsLocation
.x
;
114 p_gesture
->i_beginy
= p_gi
->ptsLocation
.y
;
117 if( (DWORD
)p_gi
->ullArguments
> 0 )
118 p_gesture
->b_2fingers
= true;
120 if( p_gesture
->i_action
== GESTURE_ACTION_UNDEFINED
)
122 if( abs( p_gesture
->i_beginx
- p_gi
->ptsLocation
.x
) +
123 abs( p_gesture
->i_beginy
- p_gi
->ptsLocation
.y
) > 50 )
125 if( abs( p_gesture
->i_beginx
- p_gi
->ptsLocation
.x
) >
126 abs( p_gesture
->i_beginy
- p_gi
->ptsLocation
.y
) )
127 p_gesture
->i_action
= GESTURE_ACTION_JUMP
;
128 else if ( p_gesture
->b_2fingers
)
129 p_gesture
->i_action
= GESTURE_ACTION_BRIGHTNESS
;
131 p_gesture
->i_action
= GESTURE_ACTION_VOLUME
;
135 if( p_gesture
->i_action
== GESTURE_ACTION_VOLUME
)
137 int offset
= p_gesture
->i_lasty
- p_gi
->ptsLocation
.y
;
140 var_SetInteger( p_this
->obj
.libvlc
, "key-action", ACTIONID_VOL_UP
);
141 else if( offset
< -100)
142 var_SetInteger( p_this
->obj
.libvlc
, "key-action", ACTIONID_VOL_DOWN
);
146 p_gesture
->i_lasty
= p_gi
->ptsLocation
.y
;
148 else if ( p_gesture
->i_action
== GESTURE_ACTION_BRIGHTNESS
)
150 /* Currently unimplemented
151 if( p_gesture->i_lasty == -1 )
152 p_gesture->i_lasty = p_gesture->i_beginy;
154 if( p_gesture->i_lasty - p_gesture->i_beginy > 80 )
156 var_SetInteger( p_this->obj.libvlc, "key-action", ACTIONID_BRIGHTNESS_DOWN );
157 p_gesture->i_lasty = p_gi->ptsLocation.y;
159 else if ( p_gesture->i_lasty - p_gesture->i_beginy < 80 )
161 var_SetInteger( p_this->obj.libvlc, "key-action", ACTIONID_BRIGHTNESS_UP );
162 p_gesture->i_lasty = p_gi->ptsLocation.y;
166 case GID_TWOFINGERTAP
:
167 p_gesture
->i_type
= GID_TWOFINGERTAP
;
168 var_SetInteger( p_this
->obj
.libvlc
, "key-action", ACTIONID_PLAY_PAUSE
);
172 p_gesture
->i_type
= GID_ZOOM
;
173 switch( p_gi
->dwFlags
)
176 p_gesture
->i_ullArguments
= p_gi
->ullArguments
;
180 double k
= (double)(p_gi
->ullArguments
) /
181 (double)(p_gesture
->i_ullArguments
);
183 var_SetInteger( p_this
->obj
.libvlc
, "key-action",
184 ACTIONID_TOGGLE_FULLSCREEN
);
186 var_SetInteger( p_this
->obj
.libvlc
, "key-action",
187 ACTIONID_LEAVE_FULLSCREEN
);
191 msg_Err( p_this
, "Unmanaged dwFlag: %lx", p_gi
->dwFlags
);
205 static BOOL
DecodeGestureProjection( vlc_object_t
*p_this
, win32_gesture_sys_t
*p_gesture
, const GESTUREINFO
* p_gi
)
207 //vout_display_t *vd = (vout_display_t *)p_this;
209 BOOL bHandled
= FALSE
; /* Needed to release the handle */
210 switch ( p_gi
->dwID
)
213 /* Set the win32_gesture_sys_t values */
214 p_gesture
->i_beginx
= p_gi
->ptsLocation
.x
;
215 p_gesture
->i_beginy
= p_gi
->ptsLocation
.y
;
216 p_gesture
->i_lasty
= p_gesture
->i_beginy
;
217 p_gesture
->b_2fingers
= false;
220 if( p_gesture
->i_type
!= 0 &&
221 p_gesture
->i_action
== GESTURE_ACTION_JUMP
)
224 if( p_gesture
->b_2fingers
)
226 if( p_gesture
->i_beginx
> p_gi
->ptsLocation
.x
)
227 action_id
= ACTIONID_JUMP_BACKWARD_SHORT
;
229 action_id
= ACTIONID_JUMP_FORWARD_SHORT
;
230 var_SetInteger( p_this
->obj
.libvlc
, "key-action", action_id
);
233 /* Reset the values */
234 p_gesture
->i_action
= GESTURE_ACTION_UNDEFINED
;
235 p_gesture
->i_type
= p_gesture
->i_beginx
= p_gesture
->i_beginy
= -1;
236 p_gesture
->b_2fingers
= false;
239 //vd->cfg->display.width;
240 p_gesture
->i_type
= GID_PAN
;
242 if (p_gi
->dwFlags
& GF_BEGIN
) {
243 p_gesture
->i_beginx
= p_gi
->ptsLocation
.x
;
244 p_gesture
->i_beginy
= p_gi
->ptsLocation
.y
;
247 if( (DWORD
)p_gi
->ullArguments
> 0 )
248 p_gesture
->b_2fingers
= true;
250 if( p_gesture
->b_2fingers
&& p_gesture
->i_action
== GESTURE_ACTION_UNDEFINED
)
252 if( abs( p_gesture
->i_beginx
- p_gi
->ptsLocation
.x
) +
253 abs( p_gesture
->i_beginy
- p_gi
->ptsLocation
.y
) > 50 )
255 if( abs( p_gesture
->i_beginx
- p_gi
->ptsLocation
.x
) >
256 abs( p_gesture
->i_beginy
- p_gi
->ptsLocation
.y
) )
257 p_gesture
->i_action
= GESTURE_ACTION_JUMP
;
259 p_gesture
->i_action
= GESTURE_ACTION_VOLUME
;
263 if( p_gesture
->i_action
== GESTURE_ACTION_VOLUME
)
265 int offset
= p_gesture
->i_lasty
- p_gi
->ptsLocation
.y
;
268 var_SetInteger( p_this
->obj
.libvlc
, "key-action", ACTIONID_VOL_UP
);
269 else if( offset
< -100)
270 var_SetInteger( p_this
->obj
.libvlc
, "key-action", ACTIONID_VOL_DOWN
);
274 p_gesture
->i_lasty
= p_gi
->ptsLocation
.y
;
277 case GID_TWOFINGERTAP
:
278 p_gesture
->i_type
= GID_TWOFINGERTAP
;
279 var_SetInteger( p_this
->obj
.libvlc
, "key-action", ACTIONID_PLAY_PAUSE
);
283 p_gesture
->i_type
= GID_ZOOM
;
285 switch( p_gi
->dwFlags
)
288 p_gesture
->i_ullArguments
= p_gi
->ullArguments
;
289 p_gesture
->f_lastzoom
= 1.0;
293 double k
= (double)(p_gi
->ullArguments
) /
294 (double)(p_gesture
->i_ullArguments
);
296 if (k
> p_gesture
->f_lastzoom
* 1.01)
298 var_SetInteger( p_this
->obj
.libvlc
, "key-action", ACTIONID_VIEWPOINT_FOV_IN
);
299 p_gesture
->f_lastzoom
= k
;
301 else if (k
< p_gesture
->f_lastzoom
* 0.99)
303 var_SetInteger( p_this
->obj
.libvlc
, "key-action", ACTIONID_VIEWPOINT_FOV_OUT
);
304 p_gesture
->f_lastzoom
= k
;
319 BOOL
InitGestures( HWND hwnd
, win32_gesture_sys_t
**pp_gesture
, bool b_isProjected
)
322 GESTURECONFIG config
= { 0, 0, 0 };
325 //don't handle single finger pan in projected mode, it will be interpreted
327 config
.dwID
= GID_PAN
;
328 config
.dwWant
= GC_PAN
;
329 config
.dwBlock
= GC_PAN_WITH_INERTIA
;
333 config
.dwID
= GID_PAN
;
334 config
.dwWant
= GC_PAN
|
335 GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY
|
336 GC_PAN_WITH_SINGLE_FINGER_VERTICALLY
;
337 config
.dwBlock
= GC_PAN_WITH_INERTIA
;
340 win32_gesture_sys_t
*p_gesture
= malloc( sizeof(win32_gesture_sys_t
) );
347 HINSTANCE h_user32_dll
= LoadLibrary(TEXT("user32.dll"));
355 BOOL (WINAPI
*OurSetGestureConfig
) (HWND
, DWORD
, UINT
, PGESTURECONFIG
, UINT
);
356 OurSetGestureConfig
= (void *)GetProcAddress(h_user32_dll
, "SetGestureConfig");
358 p_gesture
->OurCloseGestureInfoHandle
=
359 (void *)GetProcAddress(h_user32_dll
, "CloseGestureInfoHandle" );
360 p_gesture
->OurGetGestureInfo
=
361 (void *)GetProcAddress(h_user32_dll
, "GetGestureInfo");
362 if( OurSetGestureConfig
)
364 result
= OurSetGestureConfig(
369 sizeof( GESTURECONFIG
)
373 p_gesture
->DecodeGestureImpl
= DecodeGestureProjection
;
375 p_gesture
->DecodeGestureImpl
= DecodeGestureAction
;
377 p_gesture
->i_type
= 0;
378 p_gesture
->b_2fingers
= false;
379 p_gesture
->i_action
= GESTURE_ACTION_UNDEFINED
;
380 p_gesture
->i_beginx
= p_gesture
->i_beginy
= -1;
381 p_gesture
->i_lasty
= -1;
382 p_gesture
->huser_dll
= h_user32_dll
;
384 *pp_gesture
= p_gesture
;
388 void CloseGestures( win32_gesture_sys_t
*p_gesture
)
390 if (p_gesture
&& p_gesture
->huser_dll
)
391 FreeLibrary( p_gesture
->huser_dll
);