From 20c8e19ed360854cbc77b6b55285e04d651c1b50 Mon Sep 17 00:00:00 2001 From: Ludovic Fauvet Date: Fri, 14 Feb 2014 20:00:48 +0100 Subject: [PATCH] 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 --- modules/control/win32touch.c | 242 +++++++++++++++++++++++++++++++++++ modules/control/win32touch.h | 83 ++++++++++++ 2 files changed, 325 insertions(+) create mode 100644 modules/control/win32touch.c create mode 100644 modules/control/win32touch.h diff --git a/modules/control/win32touch.c b/modules/control/win32touch.c new file mode 100644 index 0000000000..03d795381e --- /dev/null +++ b/modules/control/win32touch.c @@ -0,0 +1,242 @@ +/***************************************************************************** + * win32touch.c: touch gestures recognition + ***************************************************************************** + * Copyright © 2013-2014 VideoLAN + * + * Authors: Ludovic Fauvet + * Jean-Baptiste Kempf + * + * 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 + +#include + +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 ); +} diff --git a/modules/control/win32touch.h b/modules/control/win32touch.h new file mode 100644 index 0000000000..d3f912895a --- /dev/null +++ b/modules/control/win32touch.h @@ -0,0 +1,83 @@ +/***************************************************************************** + * win32touch.c: touch gestures recognition + ***************************************************************************** + * Copyright © 2013-2014 VideoLAN + * + * Authors: Ludovic Fauvet + * Jean-Baptiste Kempf + * + * 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 +# include + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#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