Add Win32 gestures helper

This is a helper to take action on touchscreens on Windows 7 or later
It uses the braindead WM_GESTURE API and supports volume, seek (1 and 2
fingers), play/pause (2finger touch) and fullscreen (zoom gesture)

The API is simple so other UI element can use it, notably Qt and the
vouts

This has been edited by jb too

Signed-off-by: Jean-Baptiste Kempf <jb@videolan.org>
This commit is contained in:
Ludovic Fauvet 2014-02-14 20:00:48 +01:00 committed by Jean-Baptiste Kempf
parent 2581bd185d
commit 20c8e19ed3
2 changed files with 325 additions and 0 deletions

View File

@ -0,0 +1,242 @@
/*****************************************************************************
* win32touch.c: touch gestures recognition
*****************************************************************************
* Copyright © 2013-2014 VideoLAN
*
* Authors: Ludovic Fauvet <etix@videolan.org>
* Jean-Baptiste Kempf <jb@videolan.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include "win32touch.h"
#include <vlc_keys.h>
#include <assert.h>
LRESULT DecodeGesture( vlc_object_t *p_this, win32_gesture_sys_t *p_gesture,
HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
if( !p_gesture )
return DefWindowProc( hWnd, message, wParam, lParam );
GESTUREINFO gi;
ZeroMemory( &gi, sizeof( GESTUREINFO ) );
gi.cbSize = sizeof( GESTUREINFO );
BOOL bResult = p_gesture->OurGetGestureInfo((HGESTUREINFO)lParam, &gi);
BOOL bHandled = FALSE; /* Needed to release the handle */
if( bResult )
{
switch ( gi.dwID )
{
case GID_BEGIN:
/* Set the win32_gesture_sys_t values */
p_gesture->i_beginx = gi.ptsLocation.x;
p_gesture->i_beginy = gi.ptsLocation.y;
p_gesture->i_lasty = -1;
p_gesture->b_2fingers = false;
break;
case GID_END:
if( p_gesture->i_type != 0 &&
p_gesture->i_action == GESTURE_ACTION_JUMP )
{
int action_id;
if( p_gesture->i_beginx > gi.ptsLocation.x )
{
if( p_gesture->b_2fingers )
action_id = ACTIONID_JUMP_BACKWARD_MEDIUM;
else
action_id = ACTIONID_JUMP_BACKWARD_SHORT;
}
else
{
if( p_gesture->b_2fingers )
action_id = ACTIONID_JUMP_FORWARD_MEDIUM;
else
action_id = ACTIONID_JUMP_FORWARD_SHORT;
}
var_SetInteger( p_this->p_libvlc, "key-action", action_id );
}
/* Reset the values */
p_gesture->i_action = GESTURE_ACTION_UNDEFINED;
p_gesture->i_type = p_gesture->i_beginx = p_gesture->i_beginy = -1;
p_gesture->b_2fingers = false;
break;
case GID_PAN:
p_gesture->i_type = GID_PAN;
bHandled = TRUE;
if( (DWORD)gi.ullArguments > 0 )
p_gesture->b_2fingers = true;
if( p_gesture->i_action == GESTURE_ACTION_UNDEFINED )
{
if( abs( p_gesture->i_beginx - gi.ptsLocation.x ) +
abs( p_gesture->i_beginy - gi.ptsLocation.y ) > 50 )
{
if( abs( p_gesture->i_beginx - gi.ptsLocation.x ) >
abs( p_gesture->i_beginy - gi.ptsLocation.y ) )
p_gesture->i_action = GESTURE_ACTION_JUMP;
else if ( p_gesture->b_2fingers )
p_gesture->i_action = GESTURE_ACTION_BRIGHTNESS;
else
p_gesture->i_action = GESTURE_ACTION_VOLUME;
}
}
if( p_gesture->i_action == GESTURE_ACTION_VOLUME )
{
int offset = p_gesture->i_beginy - gi.ptsLocation.y;
if( offset > 0 )
var_SetInteger( p_this->p_libvlc, "key-action", ACTIONID_VOL_UP );
else
var_SetInteger( p_this->p_libvlc, "key-action", ACTIONID_VOL_DOWN );
}
else if ( p_gesture->i_action == GESTURE_ACTION_BRIGHTNESS )
{
/* Currently unimplemented
if( p_gesture->i_lasty == -1 )
p_gesture->i_lasty = p_gesture->i_beginy;
if( p_gesture->i_lasty - p_gesture->i_beginy > 80 )
{
var_SetInteger( p_this->p_libvlc, "key-action", ACTIONID_BRIGHTNESS_DOWN );
p_gesture->i_lasty = gi.ptsLocation.y;
}
else if ( p_gesture->i_lasty - p_gesture->i_beginy < 80 )
{
var_SetInteger( p_this->p_libvlc, "key-action", ACTIONID_BRIGHTNESS_UP );
p_gesture->i_lasty = gi.ptsLocation.y;
} */
}
break;
case GID_TWOFINGERTAP:
p_gesture->i_type = GID_TWOFINGERTAP;
var_SetInteger( p_this->p_libvlc, "key-action", ACTIONID_PLAY_PAUSE );
bHandled = TRUE;
break;
case GID_ZOOM:
p_gesture->i_type = GID_ZOOM;
switch( gi.dwFlags )
{
case GF_BEGIN:
p_gesture->i_ullArguments = gi.ullArguments;
break;
case GF_END:
{
double k = (double)(gi.ullArguments) /
(double)(p_gesture->i_ullArguments);
if( k > 1 )
var_SetInteger( p_this->p_libvlc, "key-action",
ACTIONID_TOGGLE_FULLSCREEN );
else
var_SetInteger( p_this->p_libvlc, "key-action",
ACTIONID_LEAVE_FULLSCREEN );
}
break;
default:
assert(0);
}
bHandled = TRUE;
break;
case WM_VSCROLL:
bHandled = TRUE;
break;
default:
break;
}
}
else
{
DWORD dwErr = GetLastError();
if( dwErr > 0 )
msg_Err( p_this, "Could not retrieve a valid GESTUREINFO structure" );
}
if( bHandled )
{
/* Close the Handle, if we handled the gesture, a contrario
* from the doc example */
p_gesture->OurCloseGestureInfoHandle((HGESTUREINFO)lParam);
return 0;
}
else
return DefWindowProc( hWnd, message, wParam, lParam );
}
BOOL InitGestures( HWND hwnd, win32_gesture_sys_t **pp_gesture )
{
BOOL result = FALSE;
GESTURECONFIG config = { 0, 0, 0 };
config.dwID = GID_PAN;
config.dwWant = GC_PAN |
GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY |
GC_PAN_WITH_SINGLE_FINGER_VERTICALLY;
config.dwBlock = GC_PAN_WITH_INERTIA;
win32_gesture_sys_t *p_gesture = malloc( sizeof(win32_gesture_sys_t) );
if( !p_gesture )
{
*pp_gesture = NULL;
return FALSE;
}
HINSTANCE h_user32_dll = LoadLibrary(TEXT("user32.dll"));
if( !h_user32_dll )
{
*pp_gesture = NULL;
free( p_gesture );
return FALSE;
}
BOOL (WINAPI *OurSetGestureConfig) (HWND, DWORD, UINT, PGESTURECONFIG, UINT);
OurSetGestureConfig = (void *)GetProcAddress(h_user32_dll, "SetGestureConfig");
p_gesture->OurCloseGestureInfoHandle =
(void *)GetProcAddress(h_user32_dll, "CloseGestureInfoHandle" );
p_gesture->OurGetGestureInfo =
(void *)GetProcAddress(h_user32_dll, "GetGestureInfo");
if( OurSetGestureConfig )
{
result = OurSetGestureConfig(
hwnd,
0,
1,
&config,
sizeof( GESTURECONFIG )
);
}
p_gesture->i_type = 0;
p_gesture->b_2fingers = false;
p_gesture->i_action = GESTURE_ACTION_UNDEFINED;
p_gesture->i_beginx = p_gesture->i_beginy = -1;
p_gesture->i_lasty = -1;
p_gesture->huser_dll = h_user32_dll;
*pp_gesture = p_gesture;
return result;
}
void CloseGestures( win32_gesture_sys_t *p_gesture )
{
if (p_gesture && p_gesture->huser_dll )
FreeLibrary( p_gesture->huser_dll );
free( p_gesture );
}

View File

@ -0,0 +1,83 @@
/*****************************************************************************
* win32touch.c: touch gestures recognition
*****************************************************************************
* Copyright © 2013-2014 VideoLAN
*
* Authors: Ludovic Fauvet <etix@videolan.org>
* Jean-Baptiste Kempf <jb@videolan.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef VLC_GESTURE_H_
#define VLC_GESTURE_H_
# ifdef _WIN32_WINNT
# undef _WIN32_WINNT
# endif
# define _WIN32_WINNT 0x0601
# include <windows.h>
# include <winuser.h>
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#ifndef WM_GESTURE
# define WM_GESTURE 0x0119
#endif
#ifdef __cplusplus
extern "C" {
#endif
enum {
GESTURE_ACTION_UNDEFINED = 0,
GESTURE_ACTION_VOLUME,
GESTURE_ACTION_JUMP,
GESTURE_ACTION_BRIGHTNESS
};
typedef struct {
DWORD i_type; /* Gesture ID */
int i_action; /* GESTURE_ACTION */
int i_beginx; /* Start X position */
int i_beginy; /* Start Y position */
int i_lasty; /* Last known Y position for PAN */
ULONGLONG i_ullArguments; /* Base values to compare between 2 zoom gestures */
bool b_2fingers; /* Did we detect 2 fingers? */
HINSTANCE huser_dll; /* user32.dll */
BOOL (WINAPI * OurCloseGestureInfoHandle)(HGESTUREINFO hGestureInfo);
BOOL (WINAPI * OurGetGestureInfo)(HGESTUREINFO hGestureInfo, PGESTUREINFO pGestureInfo);
} win32_gesture_sys_t;
BOOL InitGestures( HWND hwnd, win32_gesture_sys_t **p_gesture );
LRESULT DecodeGesture( vlc_object_t *p_intf, win32_gesture_sys_t *p_gesture,
HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );
void CloseGestures( win32_gesture_sys_t *p_gesture );
#ifdef __cplusplus
}
#endif
#endif