/*****************************************************************************
* events.c: Windows DirectX video output events handler
*****************************************************************************
- * Copyright (C) 2001-2004 the VideoLAN team
+ * Copyright (C) 2001-2009 the VideoLAN team
* $Id$
*
* Authors: Gildas Bazin <gbazin@videolan.org>
* Preamble: This file contains the functions related to the creation of
* a window and the handling of its messages (events).
*****************************************************************************/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
#include <errno.h> /* ENOMEM */
#include <ctype.h> /* tolower() */
# define _WIN32_WINNT 0x0500
#endif
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <vlc/vlc.h>
+#include <vlc_common.h>
#include <vlc_interface.h>
#include <vlc_playlist.h>
#include <vlc_vout.h>
+#include <vlc_window.h>
#include <windows.h>
+#include <tchar.h>
#include <windowsx.h>
#include <shellapi.h>
#include "vlc_keys.h"
#include "vout.h"
-#if defined(UNDER_CE) && !defined(__PLUGIN__) /*FIXME*/
-# define SHFS_SHOWSIPBUTTON 0x0004
+#ifdef UNDER_CE
+#include <aygshell.h>
+ //WINSHELLAPI BOOL WINAPI SHFullScreen(HWND hwndRequester, DWORD dwState);
+#endif
+
+/*#if defined(UNDER_CE) && !defined(__PLUGIN__) --FIXME*/
+/*# define SHFS_SHOWSIPBUTTON 0x0004
# define SHFS_HIDESIPBUTTON 0x0008
# define MENU_HEIGHT 26
BOOL SHFullScreen(HWND hwndRequester, DWORD dwState);
-#endif
+#endif*/
+
/*****************************************************************************
* Local prototypes.
static long FAR PASCAL DirectXEventProc( HWND, UINT, WPARAM, LPARAM );
static int Control( vout_thread_t *p_vout, int i_query, va_list args );
+static int vaControlParentWindow( vout_thread_t *, int, va_list );
-static void DirectXPopupMenu( event_thread_t *p_event, vlc_bool_t b_open )
+static void DirectXPopupMenu( event_thread_t *p_event, bool b_open )
{
- playlist_t *p_playlist =
- vlc_object_find( p_event, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
- if( p_playlist != NULL )
- {
- vlc_value_t val;
- val.b_bool = b_open;
- var_Set( p_playlist, "intf-popupmenu", val );
- vlc_object_release( p_playlist );
- }
+ vlc_value_t val;
+ val.b_bool = b_open;
+ var_Set( p_event->p_libvlc, "intf-popupmenu", val );
}
static int DirectXConvertKey( int i_key );
* The main goal of this thread is to isolate the Win32 PeekMessage function
* because this one can block for a long time.
*****************************************************************************/
-void E_(EventThread)( event_thread_t *p_event )
+void* EventThread( vlc_object_t *p_this )
{
+ event_thread_t *p_event = (event_thread_t *)p_this;
MSG msg;
POINT old_mouse_pos = {0,0}, mouse_pos;
vlc_value_t val;
- int i_width, i_height, i_x, i_y;
+ unsigned int i_width, i_height, i_x, i_y;
HMODULE hkernel32;
+ int canc = vlc_savecancel ();
/* Initialisation */
p_event->p_vout->pf_control = Control;
* message queue */
if( DirectXCreateWindow( p_event->p_vout ) )
{
- msg_Err( p_event, "out of memory" );
- p_event->b_dead = VLC_TRUE;
+ vlc_restorecancel (canc);
+ return NULL;
}
/* Signal the creation of the window */
- vlc_thread_ready( p_event );
+ SetEvent( p_event->window_ready );
#ifndef UNDER_CE
/* Set power management stuff */
/* Main loop */
/* GetMessage will sleep if there's no message in the queue */
- while( !p_event->b_die && GetMessage( &msg, 0, 0, 0 ) )
+ while( vlc_object_alive (p_event) && GetMessage( &msg, 0, 0, 0 ) )
{
/* Check if we are asked to exit */
- if( p_event->b_die )
+ if( !vlc_object_alive (p_event) )
break;
switch( msg.message )
p_event->p_vout->fmt_in.i_y_offset;
var_Set( p_event->p_vout, "mouse-y", val );
- val.b_bool = VLC_TRUE;
- var_Set( p_event->p_vout, "mouse-moved", val );
+ var_SetBool( p_event->p_vout, "mouse-moved", true );
}
case WM_NCMOUSEMOVE:
case WM_VLC_HIDE_MOUSE:
if( p_event->p_vout->p_sys->b_cursor_hidden ) break;
- p_event->p_vout->p_sys->b_cursor_hidden = VLC_TRUE;
+ p_event->p_vout->p_sys->b_cursor_hidden = true;
GetCursorPos( &old_mouse_pos );
ShowCursor( FALSE );
break;
case WM_VLC_SHOW_MOUSE:
if( !p_event->p_vout->p_sys->b_cursor_hidden ) break;
- p_event->p_vout->p_sys->b_cursor_hidden = VLC_FALSE;
+ p_event->p_vout->p_sys->b_cursor_hidden = false;
GetCursorPos( &old_mouse_pos );
ShowCursor( TRUE );
break;
var_Get( p_event->p_vout, "mouse-button-down", &val );
val.i_int |= 1;
var_Set( p_event->p_vout, "mouse-button-down", val );
- DirectXPopupMenu( p_event, VLC_FALSE );
+ DirectXPopupMenu( p_event, false );
break;
case WM_LBUTTONUP:
val.i_int &= ~1;
var_Set( p_event->p_vout, "mouse-button-down", val );
- val.b_bool = VLC_TRUE;
- var_Set( p_event->p_vout, "mouse-clicked", val );
+ var_SetBool( p_event->p_vout, "mouse-clicked", true );
break;
case WM_LBUTTONDBLCLK:
var_Get( p_event->p_vout, "mouse-button-down", &val );
val.i_int |= 2;
var_Set( p_event->p_vout, "mouse-button-down", val );
- DirectXPopupMenu( p_event, VLC_FALSE );
+ DirectXPopupMenu( p_event, false );
break;
case WM_MBUTTONUP:
var_Get( p_event->p_vout, "mouse-button-down", &val );
val.i_int |= 4;
var_Set( p_event->p_vout, "mouse-button-down", val );
- DirectXPopupMenu( p_event, VLC_FALSE );
+ DirectXPopupMenu( p_event, false );
break;
case WM_RBUTTONUP:
var_Get( p_event->p_vout, "mouse-button-down", &val );
val.i_int &= ~4;
var_Set( p_event->p_vout, "mouse-button-down", val );
- DirectXPopupMenu( p_event, VLC_TRUE );
+ DirectXPopupMenu( p_event, true );
break;
case WM_KEYDOWN:
#ifdef UNICODE
{
wchar_t *psz_title = malloc( strlen(val.psz_string) * 2 + 2 );
- mbstowcs( psz_title, val.psz_string, strlen(val.psz_string)*2);
- psz_title[strlen(val.psz_string)] = 0;
- free( val.psz_string ); val.psz_string = (char *)psz_title;
+ if( psz_title )
+ {
+ mbstowcs( psz_title, val.psz_string, strlen(val.psz_string)*2);
+ psz_title[strlen(val.psz_string)] = 0;
+ free( val.psz_string ); val.psz_string = (char *)psz_title;
+ }
}
#endif
p_event->p_vout->p_sys->i_changes = 0;
DirectXCloseWindow( p_event->p_vout );
+ vlc_restorecancel (canc);
+ return NULL;
}
hInstance = GetModuleHandle(NULL);
/* If an external window was specified, we'll draw in it. */
- p_vout->p_sys->hparent =
- vout_RequestWindow( p_vout, &p_vout->p_sys->i_window_x,
+ p_vout->p_sys->parent_window =
+ vout_RequestHWND( p_vout, &p_vout->p_sys->i_window_x,
&p_vout->p_sys->i_window_y,
&p_vout->p_sys->i_window_width,
&p_vout->p_sys->i_window_height );
+ if( p_vout->p_sys->parent_window )
+ p_vout->p_sys->hparent = p_vout->p_sys->parent_window->handle.hwnd;
/* We create the window ourself, there is no previous window proc. */
p_vout->p_sys->pf_wndproc = NULL;
DestroyWindow( p_vout->p_sys->hwnd );
if( p_vout->p_sys->hfswnd ) DestroyWindow( p_vout->p_sys->hfswnd );
- if( p_vout->p_sys->hparent )
- vout_ReleaseWindow( p_vout, (void *)p_vout->p_sys->hparent );
-
+ vout_ReleaseWindow( p_vout->p_sys->parent_window );
p_vout->p_sys->hwnd = NULL;
/* We don't unregister the Window Class because it could lead to race
* its job is to update the source and destination RECTs used to display the
* picture.
*****************************************************************************/
-void E_(UpdateRects)( vout_thread_t *p_vout, vlc_bool_t b_force )
+void UpdateRects( vout_thread_t *p_vout, bool b_force )
{
#define rect_src p_vout->p_sys->rect_src
#define rect_src_clipped p_vout->p_sys->rect_src_clipped
{
case WM_WINDOWPOSCHANGED:
- E_(UpdateRects)( p_vout, VLC_TRUE );
+ UpdateRects( p_vout, true );
return 0;
/* the user wants to close the window */
case WM_CLOSE:
{
- playlist_t * p_playlist =
- (playlist_t *)vlc_object_find( p_vout, VLC_OBJECT_PLAYLIST,
- FIND_ANYWHERE );
- if( p_playlist == NULL )
+ playlist_t * p_playlist = pl_Hold( p_vout );
+ if( p_playlist )
{
- return 0;
+ playlist_Stop( p_playlist );
+ pl_Release( p_vout );
}
-
- playlist_Stop( p_playlist );
- vlc_object_release( p_playlist );
return 0;
}
case WM_KILLFOCUS:
#ifdef MODULE_NAME_IS_wingapi
- p_vout->p_sys->b_focus = VLC_FALSE;
+ p_vout->p_sys->b_focus = false;
if( !p_vout->p_sys->b_parent_focus ) GXSuspend();
#endif
#ifdef UNDER_CE
- if( hWnd == p_vout->p_sys->hfswnd )
+ if( hwnd == p_vout->p_sys->hfswnd )
{
HWND htbar = FindWindow( _T("HHTaskbar"), NULL );
ShowWindow( htbar, SW_SHOW );
}
if( !p_vout->p_sys->hparent ||
- hWnd == p_vout->p_sys->hfswnd )
+ hwnd == p_vout->p_sys->hfswnd )
{
- SHFullScreen( hWnd, SHFS_SHOWSIPBUTTON );
+ SHFullScreen( hwnd, SHFS_SHOWSIPBUTTON );
}
#endif
return 0;
case WM_SETFOCUS:
#ifdef MODULE_NAME_IS_wingapi
- p_vout->p_sys->b_focus = VLC_TRUE;
+ p_vout->p_sys->b_focus = true;
GXResume();
#endif
#ifdef UNDER_CE
if( p_vout->p_sys->hparent &&
- hWnd != p_vout->p_sys->hfswnd && p_vout->b_fullscreen )
+ hwnd != p_vout->p_sys->hfswnd && p_vout->b_fullscreen )
p_vout->p_sys->i_changes |= VOUT_FULLSCREEN_CHANGE;
- if( hWnd == p_vout->p_sys->hfswnd )
+ if( hwnd == p_vout->p_sys->hfswnd )
{
HWND htbar = FindWindow( _T("HHTaskbar"), NULL );
ShowWindow( htbar, SW_HIDE );
}
if( !p_vout->p_sys->hparent ||
- hWnd == p_vout->p_sys->hfswnd )
+ hwnd == p_vout->p_sys->hfswnd )
{
- SHFullScreen( hWnd, SHFS_HIDESIPBUTTON );
+ SHFullScreen( hwnd, SHFS_HIDESIPBUTTON );
}
#endif
return 0;
static int Control( vout_thread_t *p_vout, int i_query, va_list args )
{
unsigned int *pi_width, *pi_height;
+ bool b_bool;
RECT rect_window;
POINT point;
switch( i_query )
{
- case VOUT_GET_SIZE:
- if( p_vout->p_sys->hparent )
- return vout_ControlWindow( p_vout,
- (void *)p_vout->p_sys->hparent, i_query, args );
-
- pi_width = va_arg( args, unsigned int * );
- pi_height = va_arg( args, unsigned int * );
-
- GetClientRect( p_vout->p_sys->hwnd, &rect_window );
-
- *pi_width = rect_window.right - rect_window.left;
- *pi_height = rect_window.bottom - rect_window.top;
- return VLC_SUCCESS;
-
case VOUT_SET_SIZE:
- if( p_vout->p_sys->hparent )
- return vout_ControlWindow( p_vout,
- (void *)p_vout->p_sys->hparent, i_query, args );
+ if( p_vout->p_sys->parent_window )
+ return vaControlParentWindow( p_vout, i_query, args );
/* Update dimensions */
rect_window.top = rect_window.left = 0;
return VLC_SUCCESS;
- case VOUT_CLOSE:
- ShowWindow( p_vout->p_sys->hwnd, SW_HIDE );
- case VOUT_REPARENT:
- /* Retrieve the window position */
- point.x = point.y = 0;
- ClientToScreen( p_vout->p_sys->hwnd, &point );
-
- HWND d = 0;
-
- if( i_query == VOUT_REPARENT ) d = (HWND)va_arg( args, int );
- if( !d )
- {
- vlc_mutex_lock( &p_vout->p_sys->lock );
- p_vout->p_sys->hparent = 0;
- vlc_mutex_unlock( &p_vout->p_sys->lock );
- SetParent( p_vout->p_sys->hwnd, 0 );
- p_vout->p_sys->i_window_style =
- WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW | WS_SIZEBOX;
- SetWindowLong( p_vout->p_sys->hwnd, GWL_STYLE,
- p_vout->p_sys->i_window_style |
- (i_query == VOUT_CLOSE ? 0 : WS_VISIBLE) );
- SetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW );
- SetWindowPos( p_vout->p_sys->hwnd, 0, point.x, point.y, 0, 0,
- SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED );
- }
- else
- {
- vlc_mutex_lock( &p_vout->p_sys->lock );
- p_vout->p_sys->hparent = d;
- vlc_mutex_unlock( &p_vout->p_sys->lock );
-
- SetParent( p_vout->p_sys->hwnd, d );
- p_vout->p_sys->i_window_style = WS_CLIPCHILDREN;
- SetWindowLong( p_vout->p_sys->hwnd, GWL_STYLE,
- p_vout->p_sys->i_window_style |
- (i_query == VOUT_CLOSE ? 0 : WS_VISIBLE) );
- SetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW );
-
- /* Retrieve the parent size */
- RECT rect;
- GetClientRect( d, &rect );
- SetWindowPos( p_vout->p_sys->hwnd, d, point.x, point.y, rect.right, rect.bottom,
- SWP_FRAMECHANGED );
- }
-
- return vout_vaControlDefault( p_vout, i_query, args );
-
case VOUT_SET_STAY_ON_TOP:
if( p_vout->p_sys->hparent && !var_GetBool( p_vout, "fullscreen" ) )
- return vout_ControlWindow( p_vout,
- (void *)p_vout->p_sys->hparent, i_query, args );
+ return vaControlParentWindow( p_vout, i_query, args );
- p_vout->p_sys->b_on_top_change = VLC_TRUE;
+ p_vout->p_sys->b_on_top_change = true;
return VLC_SUCCESS;
-#ifdef MODULE_NAME_IS_wingapi
- case VOUT_SET_FOCUS:
- b_bool = va_arg( args, vlc_bool_t );
- p_vout->p_sys->b_parent_focus = b_bool;
- if( b_bool ) GXResume();
- else if( !p_vout->p_sys->b_focus ) GXSuspend();
- return VLC_SUCCESS;
-#endif
-
default:
- return vout_vaControlDefault( p_vout, i_query, args );
+ return VLC_EGENERIC;
}
}
-/* Internal wrapper over GetWindowPlacement / SetWindowPlacement */
-static void SetWindowState(HWND hwnd, int nShowCmd)
+/* Internal wrapper over GetWindowPlacement */
+static WINDOWPLACEMENT getWindowState(HWND hwnd)
{
WINDOWPLACEMENT window_placement;
window_placement.length = sizeof(WINDOWPLACEMENT);
GetWindowPlacement( hwnd, &window_placement );
- window_placement.showCmd = nShowCmd;
- SetWindowPlacement( hwnd, &window_placement );
- SetWindowPos( hwnd, 0, 0, 0, 0, 0,
- SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED);
+ return window_placement;
}
/* Internal wrapper to call vout_ControlWindow for hparent */
-static void ControlParentWindow( vout_thread_t *p_vout, int i_query, ... )
+static int vaControlParentWindow( vout_thread_t *p_vout, int i_query,
+ va_list args )
+{
+ return vout_ControlWindow( p_vout->p_sys->parent_window, i_query, args );
+}
+
+static int ControlParentWindow( vout_thread_t *p_vout, int i_query, ... )
{
va_list args;
+ int ret;
+
va_start( args, i_query );
- vout_ControlWindow( p_vout,
- (void *)p_vout->p_sys->hparent, i_query, args );
+ ret = vaControlParentWindow( p_vout, i_query, args );
va_end( args );
+ return ret;
}
void Win32ToggleFullscreen( vout_thread_t *p_vout )
HWND hwnd = (p_vout->p_sys->hparent && p_vout->p_sys->hfswnd) ?
p_vout->p_sys->hfswnd : p_vout->p_sys->hwnd;
+ /* Save the current windows placement/placement to restore
+ when fullscreen is over */
+ WINDOWPLACEMENT window_placement = getWindowState( hwnd );
+
p_vout->b_fullscreen = ! p_vout->b_fullscreen;
+ /* We want to go to Fullscreen */
if( p_vout->b_fullscreen )
{
msg_Dbg( p_vout, "entering fullscreen mode" );
+
/* Change window style, no borders and no title bar */
int i_style = WS_CLIPCHILDREN | WS_VISIBLE;
SetWindowLong( hwnd, GWL_STYLE, i_style );
if( p_vout->p_sys->hparent )
{
- /* Retrieve current window position so fullscreen will happen
- * on the right screen */
+#ifdef UNDER_CE
POINT point = {0,0};
RECT rect;
ClientToScreen( p_vout->p_sys->hwnd, &point );
SetWindowPos( hwnd, 0, point.x, point.y,
rect.right, rect.bottom,
SWP_NOZORDER|SWP_FRAMECHANGED );
+#else
+ /* Retrieve current window position so fullscreen will happen
+ *on the right screen */
+ HMONITOR hmon = MonitorFromWindow(p_vout->p_sys->hparent,
+ MONITOR_DEFAULTTONEAREST);
+ MONITORINFO mi = {sizeof(mi)};
+ if (GetMonitorInfo(hmon, &mi))
+ SetWindowPos( hwnd, 0,
+ mi.rcMonitor.left,
+ mi.rcMonitor.top,
+ mi.rcMonitor.right - mi.rcMonitor.left,
+ mi.rcMonitor.bottom - mi.rcMonitor.top,
+ SWP_NOZORDER|SWP_FRAMECHANGED );
+#endif
+ }
+ else
+ {
+ /* Maximize non embedded window */
+ ShowWindow( hwnd, SW_SHOWMAXIMIZED );
}
-
- /* Maximize window */
- SetWindowState( hwnd, SW_SHOWMAXIMIZED );
if( p_vout->p_sys->hparent )
{
+ /* Hide the previous window */
RECT rect;
GetClientRect( hwnd, &rect );
SetParent( p_vout->p_sys->hwnd, hwnd );
rect.right, rect.bottom,
SWP_NOZORDER|SWP_FRAMECHANGED );
+#ifdef UNDER_CE
+ HWND topLevelParent = GetParent( p_vout->p_sys->hparent );
+#else
HWND topLevelParent = GetAncestor( p_vout->p_sys->hparent, GA_ROOT );
+#endif
ShowWindow( topLevelParent, SW_HIDE );
}
/* Change window style, no borders and no title bar */
SetWindowLong( hwnd, GWL_STYLE, p_vout->p_sys->i_window_style );
- /* Normal window */
- SetWindowState( hwnd, SW_SHOWNORMAL );
-
if( p_vout->p_sys->hparent )
{
RECT rect;
rect.right, rect.bottom,
SWP_NOZORDER|SWP_FRAMECHANGED );
+#ifdef UNDER_CE
+ HWND topLevelParent = GetParent( p_vout->p_sys->hparent );
+#else
HWND topLevelParent = GetAncestor( p_vout->p_sys->hparent, GA_ROOT );
+#endif
ShowWindow( topLevelParent, SW_SHOW );
SetForegroundWindow( p_vout->p_sys->hparent );
ShowWindow( hwnd, SW_HIDE );
-
- /* Update "video-on-top" status for main interface window, it
- needs to be updated as we were hiding VOUT_SET_STAY_ON_TOP
- queries from it while we were in fullscreen mode */
- int b_ontop = var_GetBool( p_vout, "video-on-top" );
- ControlParentWindow( p_vout, VOUT_SET_STAY_ON_TOP, b_ontop );
+ }
+ else
+ {
+ /* return to normal window for non embedded vout */
+ SetWindowPlacement( hwnd, &window_placement );
+ ShowWindow( hwnd, SW_SHOWNORMAL );
}
/* Make sure the mouse cursor is displayed */
PostMessage( p_vout->p_sys->hwnd, WM_VLC_SHOW_MOUSE, 0, 0 );
}
- {
- vlc_value_t val;
- /* Update the object variable and trigger callback */
- val.b_bool = p_vout->b_fullscreen;
- var_Set( p_vout, "fullscreen", val );
- }
+ /* Update the object variable and trigger callback */
+ var_SetBool( p_vout, "fullscreen", p_vout->b_fullscreen );
}