X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fvideo_output%2Fdirectx%2Fevents.c;h=19ea96376b59ebcd4f6a54bfc6ed3decc324e852;hb=1e9ecb9029e00ada8ceced3d60c54570bd7c1a84;hp=44207162a5e3370317177ae2d22c89c2370c5b92;hpb=6640e3127e593f9bba8948df41b278b9a515b21f;p=vlc diff --git a/modules/video_output/directx/events.c b/modules/video_output/directx/events.c index 44207162a5..19ea96376b 100644 --- a/modules/video_output/directx/events.c +++ b/modules/video_output/directx/events.c @@ -1,10 +1,10 @@ /***************************************************************************** * events.c: Windows DirectX video output events handler ***************************************************************************** - * Copyright (C) 2001 VideoLAN - * $Id: events.c,v 1.33 2003/12/16 22:10:56 gbazin Exp $ + * Copyright (C) 2001-2004 VideoLAN + * $Id$ * - * Authors: Gildas Bazin + * Authors: Gildas Bazin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,6 +31,10 @@ #include /* tolower() */ #include /* strerror() */ +#ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0400 +#endif + #include #include #include @@ -53,6 +57,8 @@ static void DirectXCloseWindow ( vout_thread_t *p_vout ); static long FAR PASCAL DirectXEventProc( HWND, UINT, WPARAM, LPARAM ); static long FAR PASCAL DirectXVideoEventProc( HWND, UINT, WPARAM, LPARAM ); +static int Control( vout_thread_t *p_vout, int i_query, va_list args ); + static void DirectXPopupMenu( event_thread_t *p_event, vlc_bool_t b_open ) { playlist_t *p_playlist = @@ -79,11 +85,13 @@ static int DirectXConvertKey( int i_key ); void DirectXEventThread( event_thread_t *p_event ) { MSG msg; - POINT old_mouse_pos = {0,0}; + POINT old_mouse_pos = {0,0}, mouse_pos; vlc_value_t val; int i_width, i_height, i_x, i_y; + HMODULE hkernel32; /* Initialisation */ + p_event->p_vout->pf_control = Control; /* Create a window for the video */ /* Creating a window under Windows also initializes the thread's event @@ -94,48 +102,65 @@ void DirectXEventThread( event_thread_t *p_event ) p_event->b_dead = VLC_TRUE; } - /* signal the creation of the window */ + /* Signal the creation of the window */ vlc_thread_ready( p_event ); + /* Set power management stuff */ + if( (hkernel32 = GetModuleHandle( "KERNEL32" ) ) ) + { + ULONG (WINAPI* OurSetThreadExecutionState)( ULONG ); + + OurSetThreadExecutionState = + GetProcAddress( hkernel32, "SetThreadExecutionState" ); + + if( OurSetThreadExecutionState ) + /* Prevent monitor from powering off */ + OurSetThreadExecutionState( ES_DISPLAY_REQUIRED | ES_CONTINUOUS ); + else + msg_Dbg( p_event, "no support for SetThreadExecutionState()" ); + } + /* Main loop */ /* GetMessage will sleep if there's no message in the queue */ - while( !p_event->b_die && ( p_event->p_vout->p_sys->hparent || - GetMessage( &msg, p_event->p_vout->p_sys->hwnd, 0, 0 ) ) ) + while( !p_event->b_die && + GetMessage( &msg, p_event->p_vout->p_sys->hwnd, 0, 0 ) ) { /* Check if we are asked to exit */ if( p_event->b_die ) break; - if( p_event->p_vout->p_sys->hparent ) - { - /* Parent window was created in another thread so we can't - * access the window messages. */ - msleep( INTF_IDLE_SLEEP ); - continue; - } - switch( msg.message ) { - case WM_NCMOUSEMOVE: case WM_MOUSEMOVE: vout_PlacePicture( p_event->p_vout, p_event->p_vout->p_sys->i_window_width, p_event->p_vout->p_sys->i_window_height, &i_x, &i_y, &i_width, &i_height ); - val.i_int = ( GET_X_LPARAM(msg.lParam) - i_x ) - * p_event->p_vout->render.i_width / i_width; - var_Set( p_event->p_vout, "mouse-x", val ); - val.i_int = ( GET_Y_LPARAM(msg.lParam) - i_y ) - * p_event->p_vout->render.i_height / i_height; - var_Set( p_event->p_vout, "mouse-y", val ); + if( msg.hwnd != p_event->p_vout->p_sys->hwnd ) + { + /* Child window */ + i_x = i_y = 0; + } - val.b_bool = VLC_TRUE; - var_Set( p_event->p_vout, "mouse-moved", val ); + if( i_width && i_height ) + { + val.i_int = ( GET_X_LPARAM(msg.lParam) - i_x ) + * p_event->p_vout->render.i_width / i_width; + var_Set( p_event->p_vout, "mouse-x", val ); + val.i_int = ( GET_Y_LPARAM(msg.lParam) - i_y ) + * p_event->p_vout->render.i_height / i_height; + var_Set( p_event->p_vout, "mouse-y", val ); + + val.b_bool = VLC_TRUE; + var_Set( p_event->p_vout, "mouse-moved", val ); + } - if( (abs(GET_X_LPARAM(msg.lParam) - old_mouse_pos.x) > 2 || - (abs(GET_Y_LPARAM(msg.lParam) - old_mouse_pos.y)) > 2 ) ) + case WM_NCMOUSEMOVE: + GetCursorPos( &mouse_pos ); + if( (abs(mouse_pos.x - old_mouse_pos.x) > 2 || + (abs(mouse_pos.y - old_mouse_pos.y)) > 2 ) ) { GetCursorPos( &old_mouse_pos ); p_event->p_vout->p_sys->i_lastmoved = mdate(); @@ -149,10 +174,19 @@ void DirectXEventThread( event_thread_t *p_event ) break; 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; 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; + GetCursorPos( &old_mouse_pos ); + ShowCursor( TRUE ); + break; + case WM_LBUTTONDOWN: var_Get( p_event->p_vout, "mouse-button-down", &val ); val.i_int |= 1; @@ -231,6 +265,54 @@ void DirectXEventThread( event_thread_t *p_event ) } break; + case WM_MOUSEWHEEL: + if( GET_WHEEL_DELTA_WPARAM( msg.wParam ) > 0 ) + { + val.i_int = KEY_MOUSEWHEELUP; + } + else + { + val.i_int = KEY_MOUSEWHEELDOWN; + } + if( val.i_int ) + { + if( GetKeyState(VK_CONTROL) & 0x8000 ) + { + val.i_int |= KEY_MODIFIER_CTRL; + } + if( GetKeyState(VK_SHIFT) & 0x8000 ) + { + val.i_int |= KEY_MODIFIER_SHIFT; + } + if( GetKeyState(VK_MENU) & 0x8000 ) + { + val.i_int |= KEY_MODIFIER_ALT; + } + + var_Set( p_event->p_vlc, "key-pressed", val ); + } + break; + + case WM_VLC_CHANGE_TEXT: + var_Get( p_event->p_vout, "video-title", &val ); + + if( !val.psz_string || !*val.psz_string ) /* Default video title */ + { + if( p_event->p_vout->p_sys->b_using_overlay ) + SetWindowText( p_event->p_vout->p_sys->hwnd, + VOUT_TITLE " (hardware YUV overlay DirectX output)" ); + else if( p_event->p_vout->p_sys->b_hw_yuv ) + SetWindowText( p_event->p_vout->p_sys->hwnd, + VOUT_TITLE " (hardware YUV DirectX output)" ); + else SetWindowText( p_event->p_vout->p_sys->hwnd, + VOUT_TITLE " (software RGB DirectX output)" ); + } + else + { + SetWindowText( p_event->p_vout->p_sys->hwnd, val.psz_string ); + } + break; + default: /* Messages we don't handle directly are dispatched to the * window procedure */ @@ -242,7 +324,8 @@ void DirectXEventThread( event_thread_t *p_event ) } /* End Main loop */ - if( msg.message == WM_QUIT ) + /* Check for WM_QUIT if we created the window */ + if( !p_event->p_vout->p_sys->hparent && msg.message == WM_QUIT ) { msg_Warn( p_event, "WM_QUIT... should not happen!!" ); p_event->p_vout->p_sys->hwnd = NULL; /* Window already destroyed */ @@ -271,8 +354,10 @@ static int DirectXCreateWindow( vout_thread_t *p_vout ) HINSTANCE hInstance; HMENU hMenu; RECT rect_window; - - vlc_value_t val; + WNDCLASSEX wc; /* window class components */ + HICON vlc_icon = NULL; + char vlc_path[MAX_PATH+1]; + int i_style; msg_Dbg( p_vout, "DirectXCreateWindow" ); @@ -280,109 +365,99 @@ static int DirectXCreateWindow( vout_thread_t *p_vout ) hInstance = GetModuleHandle(NULL); /* If an external window was specified, we'll draw in it. */ - var_Get( p_vout->p_vlc, "drawable", &val ); - p_vout->p_sys->hparent = p_vout->p_sys->hwnd = - val.i_int ? (void*)(ptrdiff_t) val.i_int : NULL; - - if( p_vout->p_sys->hparent ) + p_vout->p_sys->hparent = + vout_RequestWindow( 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 ); + + /* We create the window ourself, there is no previous window proc. */ + p_vout->p_sys->pf_wndproc = NULL; + + /* Get the Icon from the main app */ + vlc_icon = NULL; + if( GetModuleFileName( NULL, vlc_path, MAX_PATH ) ) { - msg_Dbg( p_vout, "using external window %p\n", p_vout->p_sys->hwnd ); - - /* Set stuff in the window that we can not put directly in - * a class (see below). */ - SetClassLong( p_vout->p_sys->hwnd, - GCL_STYLE, CS_DBLCLKS ); - SetClassLong( p_vout->p_sys->hwnd, - GCL_HBRBACKGROUND, (LONG)GetStockObject(BLACK_BRUSH) ); - SetClassLong( p_vout->p_sys->hwnd, - GCL_HCURSOR, (LONG)LoadCursor(NULL, IDC_ARROW) ); - /* Store a p_vout pointer into the window local storage (for later - * use in DirectXEventProc). */ - SetWindowLong( p_vout->p_sys->hwnd, GWL_USERDATA, (LONG)p_vout ); - - p_vout->p_sys->pf_wndproc = - (WNDPROC)SetWindowLong( p_vout->p_sys->hwnd, - GWL_WNDPROC, (LONG)DirectXEventProc ); - - /* Blam! Erase everything that might have been there. */ - InvalidateRect( p_vout->p_sys->hwnd, NULL, TRUE ); + vlc_icon = ExtractIcon( hInstance, vlc_path, 0 ); } - else + + /* Fill in the window class structure */ + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_DBLCLKS; /* style: dbl click */ + wc.lpfnWndProc = (WNDPROC)DirectXEventProc; /* event handler */ + wc.cbClsExtra = 0; /* no extra class data */ + wc.cbWndExtra = 0; /* no extra window data */ + wc.hInstance = hInstance; /* instance */ + wc.hIcon = vlc_icon; /* load the vlc big icon */ + wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* default cursor */ + wc.hbrBackground = GetStockObject(BLACK_BRUSH); /* background color */ + wc.lpszMenuName = NULL; /* no menu */ + wc.lpszClassName = "VLC DirectX"; /* use a special class */ + wc.hIconSm = vlc_icon; /* load the vlc small icon */ + + /* Register the window class */ + if( !RegisterClassEx(&wc) ) { - WNDCLASSEX wc; /* window class components */ - HICON vlc_icon = NULL; - char vlc_path[MAX_PATH+1]; + WNDCLASS wndclass; - /* Get the Icon from the main app */ - vlc_icon = NULL; - if( GetModuleFileName( NULL, vlc_path, MAX_PATH ) ) - { - vlc_icon = ExtractIcon( hInstance, vlc_path, 0 ); - } + if( vlc_icon ) DestroyIcon( vlc_icon ); - /* Fill in the window class structure */ - wc.cbSize = sizeof(WNDCLASSEX); - wc.style = CS_DBLCLKS; /* style: dbl click */ - wc.lpfnWndProc = (WNDPROC)DirectXEventProc; /* event handler */ - wc.cbClsExtra = 0; /* no extra class data */ - wc.cbWndExtra = 0; /* no extra window data */ - wc.hInstance = hInstance; /* instance */ - wc.hIcon = vlc_icon; /* load the vlc big icon */ - wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* default cursor */ - wc.hbrBackground = GetStockObject(BLACK_BRUSH); /* background color */ - wc.lpszMenuName = NULL; /* no menu */ - wc.lpszClassName = "VLC DirectX"; /* use a special class */ - wc.hIconSm = vlc_icon; /* load the vlc small icon */ - - /* Register the window class */ - if( !RegisterClassEx(&wc) ) + /* Check why it failed. If it's because one already exists + * then fine, otherwise return with an error. */ + if( !GetClassInfo( hInstance, "VLC DirectX", &wndclass ) ) { - WNDCLASS wndclass; - - if( vlc_icon ) - { - DestroyIcon( vlc_icon ); - } - - /* Check why it failed. If it's because one already exists - * then fine, otherwise return with an error. */ - if( !GetClassInfo( hInstance, "VLC DirectX", &wndclass ) ) - { - msg_Err( p_vout, "DirectXCreateWindow RegisterClass FAILED" ); - return VLC_EGENERIC; - } + msg_Err( p_vout, "DirectXCreateWindow RegisterClass FAILED" ); + return VLC_EGENERIC; } + } - /* When you create a window you give the dimensions you wish it to - * have. Unfortunatly these dimensions will include the borders and - * titlebar. We use the following function to find out the size of - * the window corresponding to the useable surface we want */ - rect_window.top = 10; - rect_window.left = 10; - rect_window.right = rect_window.left + p_vout->p_sys->i_window_width; - rect_window.bottom = rect_window.top + p_vout->p_sys->i_window_height; - AdjustWindowRect( &rect_window, WS_OVERLAPPEDWINDOW|WS_SIZEBOX, 0 ); + /* When you create a window you give the dimensions you wish it to + * have. Unfortunatly these dimensions will include the borders and + * titlebar. We use the following function to find out the size of + * the window corresponding to the useable surface we want */ + rect_window.top = 10; + rect_window.left = 10; + rect_window.right = rect_window.left + p_vout->p_sys->i_window_width; + rect_window.bottom = rect_window.top + p_vout->p_sys->i_window_height; + AdjustWindowRect( &rect_window, WS_OVERLAPPEDWINDOW|WS_SIZEBOX, 0 ); - /* Create the window */ - p_vout->p_sys->hwnd = - CreateWindow( "VLC DirectX", /* name of window class */ + if( p_vout->p_sys->hparent ) + i_style = WS_VISIBLE|WS_CLIPCHILDREN|WS_CHILD; + else + i_style = WS_OVERLAPPEDWINDOW|WS_SIZEBOX|WS_VISIBLE|WS_CLIPCHILDREN; + + /* Create the window */ + p_vout->p_sys->hwnd = + CreateWindowEx( WS_EX_NOPARENTNOTIFY, + "VLC DirectX", /* name of window class */ VOUT_TITLE " (DirectX Output)", /* window title bar text */ - WS_OVERLAPPEDWINDOW | WS_SIZEBOX | WS_VISIBLE | - WS_CLIPCHILDREN, /* window style */ - CW_USEDEFAULT, /* default X coordinate */ - 0, /* default Y coordinate */ + i_style, /* window style */ + (p_vout->p_sys->i_window_x < 0) ? CW_USEDEFAULT : + p_vout->p_sys->i_window_x, /* default X coordinate */ + (p_vout->p_sys->i_window_y < 0) ? CW_USEDEFAULT : + p_vout->p_sys->i_window_y, /* default Y coordinate */ rect_window.right - rect_window.left, /* window width */ rect_window.bottom - rect_window.top, /* window height */ - NULL, /* no parent window */ + p_vout->p_sys->hparent, /* parent window */ NULL, /* no menu in this window */ hInstance, /* handle of this program instance */ (LPVOID)p_vout ); /* send p_vout to WM_CREATE */ - if( !p_vout->p_sys->hwnd ) - { - msg_Warn( p_vout, "DirectXCreateWindow create window FAILED" ); - return VLC_EGENERIC; - } + if( !p_vout->p_sys->hwnd ) + { + msg_Warn( p_vout, "DirectXCreateWindow create window FAILED" ); + return VLC_EGENERIC; + } + + if( p_vout->p_sys->hparent ) + { + LONG i_style; + + /* We don't want the window owner to overwrite our client area */ + i_style = GetWindowLong( p_vout->p_sys->hparent, GWL_STYLE ); + SetWindowLong( p_vout->p_sys->hparent, GWL_STYLE, + i_style | WS_CLIPCHILDREN ); + } /* Now display the window */ @@ -411,23 +486,10 @@ static void DirectXCloseWindow( vout_thread_t *p_vout ) { msg_Dbg( p_vout, "DirectXCloseWindow" ); - if( p_vout->p_sys->hwnd && !p_vout->p_sys->hparent ) - { - DestroyWindow( p_vout->p_sys->hwnd ); - } - else if( p_vout->p_sys->hparent ) - { - /* Get rid of the video sub-window */ - PostMessage( p_vout->p_sys->hvideownd, WM_VLC_DESTROY_VIDEO_WIN, 0, 0); + DestroyWindow( p_vout->p_sys->hwnd ); - /* We don't want our windowproc to be called anymore */ - SetWindowLong( p_vout->p_sys->hwnd, - GWL_WNDPROC, (LONG)p_vout->p_sys->pf_wndproc ); - SetWindowLong( p_vout->p_sys->hwnd, GWL_USERDATA, (LONG)NULL ); - - /* Blam! Erase everything that might have been there. */ - InvalidateRect( p_vout->p_sys->hwnd, NULL, TRUE ); - } + if( p_vout->p_sys->hparent ) + vout_ReleaseWindow( p_vout, (void *)p_vout->p_sys->hparent ); p_vout->p_sys->hwnd = NULL; @@ -481,8 +543,9 @@ void DirectXUpdateRects( vout_thread_t *p_vout, vlc_bool_t b_force ) vout_PlacePicture( p_vout, rect.right, rect.bottom, &i_x, &i_y, &i_width, &i_height ); - SetWindowPos( p_vout->p_sys->hvideownd, HWND_TOP, - i_x, i_y, i_width, i_height, 0 ); + if( p_vout->p_sys->hvideownd ) + SetWindowPos( p_vout->p_sys->hvideownd, HWND_TOP, + i_x, i_y, i_width, i_height, 0 ); /* Destination image position and dimensions */ rect_dest.left = point.x + i_x; @@ -490,6 +553,20 @@ void DirectXUpdateRects( vout_thread_t *p_vout, vlc_bool_t b_force ) rect_dest.top = point.y + i_y; rect_dest.bottom = rect_dest.top + i_height; + /* Apply overlay hardware constraints */ + if( p_vout->p_sys->b_using_overlay ) + { + if( p_vout->p_sys->i_align_dest_boundary ) + rect_dest.left = ( rect_dest.left + + p_vout->p_sys->i_align_dest_boundary / 2 ) & + ~p_vout->p_sys->i_align_dest_boundary; + + if( p_vout->p_sys->i_align_dest_size ) + rect_dest.right = (( rect_dest.right - rect_dest.left + + p_vout->p_sys->i_align_dest_size / 2 ) & + ~p_vout->p_sys->i_align_dest_size) + rect_dest.left; + } + /* UpdateOverlay directdraw function doesn't automatically clip to the * display size so we need to do it otherwise it will fail */ @@ -534,12 +611,20 @@ void DirectXUpdateRects( vout_thread_t *p_vout, vlc_bool_t b_force ) (rect_dest.bottom - rect_dest_clipped.bottom) * p_vout->render.i_height / (rect_dest.bottom - rect_dest.top); - /* The destination coordinates need to be relative to the current - * directdraw primary surface (display) */ - rect_dest_clipped.left -= p_vout->p_sys->rect_display.left; - rect_dest_clipped.right -= p_vout->p_sys->rect_display.left; - rect_dest_clipped.top -= p_vout->p_sys->rect_display.top; - rect_dest_clipped.bottom -= p_vout->p_sys->rect_display.top; + /* Apply overlay hardware constraints */ + if( p_vout->p_sys->b_using_overlay ) + { + if( p_vout->p_sys->i_align_src_boundary ) + rect_src_clipped.left = ( rect_src_clipped.left + + p_vout->p_sys->i_align_src_boundary / 2 ) & + ~p_vout->p_sys->i_align_src_boundary; + + if( p_vout->p_sys->i_align_src_size ) + rect_src_clipped.right = (( rect_src_clipped.right - + rect_src_clipped.left + + p_vout->p_sys->i_align_src_size / 2 ) & + ~p_vout->p_sys->i_align_src_size) + rect_src_clipped.left; + } #if 0 msg_Dbg( p_vout, "DirectXUpdateRects image_src_clipped" @@ -548,6 +633,16 @@ void DirectXUpdateRects( vout_thread_t *p_vout, vlc_bool_t b_force ) rect_src_clipped.right, rect_src_clipped.bottom ); #endif + /* The destination coordinates need to be relative to the current + * directdraw primary surface (display) */ + rect_dest_clipped.left -= p_vout->p_sys->rect_display.left; + rect_dest_clipped.right -= p_vout->p_sys->rect_display.left; + rect_dest_clipped.top -= p_vout->p_sys->rect_display.top; + rect_dest_clipped.bottom -= p_vout->p_sys->rect_display.top; + + if( p_vout->p_sys->b_using_overlay ) + DirectXUpdateOverlay( p_vout ); + /* Signal the change in size/position */ p_vout->p_sys->i_changes |= DX_POSITION_CHANGE; @@ -577,11 +672,11 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message, { /* Store p_vout for future use */ p_vout = (vout_thread_t *)((CREATESTRUCT *)lParam)->lpCreateParams; - SetWindowLong( hwnd, GWL_USERDATA, (LONG)p_vout ); + SetWindowLongPtr( hwnd, GWLP_USERDATA, (LONG_PTR)p_vout ); } else { - p_vout = (vout_thread_t *)GetWindowLong( hwnd, GWL_USERDATA ); + p_vout = (vout_thread_t *)GetWindowLongPtr( hwnd, GWLP_USERDATA ); } if( !p_vout ) @@ -661,26 +756,82 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message, } else { - SetWindowLong( p_vout->p_sys->hvideownd, - GWL_WNDPROC, (LONG)DirectXVideoEventProc ); + msg_Dbg( p_vout, "Created video sub-window" ); + SetWindowLongPtr( p_vout->p_sys->hvideownd, + GWLP_WNDPROC, (LONG_PTR)DirectXVideoEventProc ); + /* Store the previous window proc of _this_ window with the video + * window so we can use it in DirectXVideoEventProc to pass + * messages to the creator of _this_ window */ + SetWindowLongPtr( p_vout->p_sys->hvideownd, GWLP_USERDATA, + (LONG_PTR)p_vout->p_sys->pf_wndproc ); } break; + case WM_PAINT: + case WM_NCPAINT: + case WM_ERASEBKGND: + /* We do not want to relay these messages to the parent window + * because we rely on the background color for the overlay. */ + return DefWindowProc(hwnd, message, wParam, lParam); + break; + default: //msg_Dbg( p_vout, "WinProc WM Default %i", message ); break; } + /* Let windows handle the message */ return DefWindowProc(hwnd, message, wParam, lParam); } + static long FAR PASCAL DirectXVideoEventProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) { + WNDPROC pf_parentwndproc; + POINT pt; + switch( message ) { - case WM_VLC_DESTROY_VIDEO_WIN: - /* Destroy video sub-window */ - DestroyWindow( hwnd ); + case WM_MOUSEMOVE: + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_LBUTTONDBLCLK: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + /* Translate mouse cursor position to parent window coordinates. */ + pt.x = LOWORD( lParam ); + pt.y = HIWORD( lParam ); + MapWindowPoints( hwnd, GetParent( hwnd ), &pt, 1 ); + lParam = MAKELPARAM( pt.x, pt.y ); + /* Fall through. */ + case WM_KEYDOWN: + case WM_KEYUP: + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + /* Foward these to the original window proc of the parent so the + * creator of the window gets a chance to process them. If we created + * the parent window ourself DirectXEventThread will process these + * and they will never make it here. + * Note that we fake the hwnd to be our parent in order to prevent + * confusion in the creator's window proc. */ + pf_parentwndproc = (WNDPROC)GetWindowLongPtr( hwnd, GWLP_USERDATA ); + + if( pf_parentwndproc ) + { + LRESULT i_ret; + LONG_PTR p_backup; + + pf_parentwndproc = (WNDPROC)GetWindowLongPtr( hwnd, GWLP_USERDATA); + + p_backup = SetWindowLongPtr( GetParent( hwnd ), GWLP_USERDATA, 0 ); + i_ret = CallWindowProc( pf_parentwndproc, GetParent( hwnd ), + message, wParam, lParam ); + SetWindowLongPtr( GetParent( hwnd ), GWLP_USERDATA, p_backup ); + + return i_ret; + } break; } @@ -734,3 +885,64 @@ static int DirectXConvertKey( int i_key ) return 0; } + +/***************************************************************************** + * Control: control facility for the vout + *****************************************************************************/ +static int Control( vout_thread_t *p_vout, int i_query, va_list args ) +{ + double f_arg; + RECT rect_window; + + switch( i_query ) + { + case VOUT_SET_ZOOM: + if( p_vout->p_sys->hparent ) + return vout_ControlWindow( p_vout, + (void *)p_vout->p_sys->hparent, i_query, args ); + + f_arg = va_arg( args, double ); + + /* Update dimensions */ + rect_window.top = rect_window.left = 0; + rect_window.right = p_vout->i_window_width * f_arg; + rect_window.bottom = p_vout->i_window_height * f_arg; + AdjustWindowRect( &rect_window, WS_OVERLAPPEDWINDOW|WS_SIZEBOX, 0 ); + + SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0, + rect_window.right - rect_window.left, + rect_window.bottom - rect_window.top, SWP_NOMOVE ); + + return VLC_SUCCESS; + + case VOUT_REPARENT: + /* Change window style, borders and title bar */ + 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, GetDesktopWindow() ); + SetWindowLong( p_vout->p_sys->hwnd, GWL_STYLE, + WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW | + WS_SIZEBOX | WS_VISIBLE ); + SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0, 0, 0, + SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED ); + + return VLC_SUCCESS; + + case VOUT_CLOSE: + return VLC_SUCCESS; + + case VOUT_SET_STAY_ON_TOP: + if( p_vout->p_sys->hparent ) + return vout_ControlWindow( p_vout, + (void *)p_vout->p_sys->hparent, i_query, args ); + + p_vout->p_sys->b_on_top_change = VLC_TRUE; + return VLC_SUCCESS; + + default: + msg_Dbg( p_vout, "control query not supported" ); + return VLC_EGENERIC; + } +}