00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <errno.h>
00030 #include <stdlib.h>
00031 #include <ctype.h>
00032 #include <string.h>
00033
00034 #ifndef _WIN32_WINNT
00035 # define _WIN32_WINNT 0x0400
00036 #endif
00037
00038 #include <vlc/vlc.h>
00039 #include <vlc/intf.h>
00040 #include <vlc/input.h>
00041 #include <vlc/vout.h>
00042
00043 #include <windows.h>
00044 #include <windowsx.h>
00045 #include <shellapi.h>
00046
00047 #include <ddraw.h>
00048
00049 #include "vlc_keys.h"
00050 #include "vout.h"
00051
00052
00053
00054
00055 static int DirectXCreateWindow( vout_thread_t *p_vout );
00056 static void DirectXCloseWindow ( vout_thread_t *p_vout );
00057 static long FAR PASCAL DirectXEventProc( HWND, UINT, WPARAM, LPARAM );
00058
00059 static int Control( vout_thread_t *p_vout, int i_query, va_list args );
00060
00061 static void DirectXPopupMenu( event_thread_t *p_event, vlc_bool_t b_open )
00062 {
00063 playlist_t *p_playlist =
00064 vlc_object_find( p_event, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
00065 if( p_playlist != NULL )
00066 {
00067 vlc_value_t val;
00068 val.b_bool = b_open;
00069 var_Set( p_playlist, "intf-popupmenu", val );
00070 vlc_object_release( p_playlist );
00071 }
00072 }
00073
00074 static int DirectXConvertKey( int i_key );
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 void E_(DirectXEventThread)( event_thread_t *p_event )
00085 {
00086 MSG msg;
00087 POINT old_mouse_pos = {0,0}, mouse_pos;
00088 vlc_value_t val;
00089 int i_width, i_height, i_x, i_y;
00090 HMODULE hkernel32;
00091
00092
00093 p_event->p_vout->pf_control = Control;
00094
00095
00096
00097
00098 if( DirectXCreateWindow( p_event->p_vout ) )
00099 {
00100 msg_Err( p_event, "out of memory" );
00101 p_event->b_dead = VLC_TRUE;
00102 }
00103
00104
00105 vlc_thread_ready( p_event );
00106
00107
00108 if( (hkernel32 = GetModuleHandle( _T("KERNEL32") ) ) )
00109 {
00110 ULONG (WINAPI* OurSetThreadExecutionState)( ULONG );
00111
00112 OurSetThreadExecutionState = (ULONG (WINAPI*)( ULONG ))
00113 GetProcAddress( hkernel32, _T("SetThreadExecutionState") );
00114
00115 if( OurSetThreadExecutionState )
00116
00117 OurSetThreadExecutionState( ES_DISPLAY_REQUIRED | ES_CONTINUOUS );
00118 else
00119 msg_Dbg( p_event, "no support for SetThreadExecutionState()" );
00120 }
00121
00122
00123
00124 while( !p_event->b_die && GetMessage( &msg, 0, 0, 0 ) )
00125 {
00126
00127 if( p_event->b_die )
00128 break;
00129
00130 switch( msg.message )
00131 {
00132
00133 case WM_MOUSEMOVE:
00134 vout_PlacePicture( p_event->p_vout,
00135 p_event->p_vout->p_sys->i_window_width,
00136 p_event->p_vout->p_sys->i_window_height,
00137 &i_x, &i_y, &i_width, &i_height );
00138
00139 if( msg.hwnd == p_event->p_vout->p_sys->hvideownd )
00140 {
00141
00142 i_x = i_y = 0;
00143 }
00144
00145 if( i_width && i_height )
00146 {
00147 val.i_int = ( GET_X_LPARAM(msg.lParam) - i_x ) *
00148 p_event->p_vout->fmt_in.i_visible_width / i_width +
00149 p_event->p_vout->fmt_in.i_x_offset;
00150 var_Set( p_event->p_vout, "mouse-x", val );
00151 val.i_int = ( GET_Y_LPARAM(msg.lParam) - i_y ) *
00152 p_event->p_vout->fmt_in.i_visible_height / i_height +
00153 p_event->p_vout->fmt_in.i_y_offset;
00154 var_Set( p_event->p_vout, "mouse-y", val );
00155
00156 val.b_bool = VLC_TRUE;
00157 var_Set( p_event->p_vout, "mouse-moved", val );
00158 }
00159
00160 case WM_NCMOUSEMOVE:
00161 GetCursorPos( &mouse_pos );
00162 if( (abs(mouse_pos.x - old_mouse_pos.x) > 2 ||
00163 (abs(mouse_pos.y - old_mouse_pos.y)) > 2 ) )
00164 {
00165 GetCursorPos( &old_mouse_pos );
00166 p_event->p_vout->p_sys->i_lastmoved = mdate();
00167
00168 if( p_event->p_vout->p_sys->b_cursor_hidden )
00169 {
00170 p_event->p_vout->p_sys->b_cursor_hidden = 0;
00171 ShowCursor( TRUE );
00172 }
00173 }
00174 break;
00175
00176 case WM_VLC_HIDE_MOUSE:
00177 if( p_event->p_vout->p_sys->b_cursor_hidden ) break;
00178 p_event->p_vout->p_sys->b_cursor_hidden = VLC_TRUE;
00179 GetCursorPos( &old_mouse_pos );
00180 ShowCursor( FALSE );
00181 break;
00182
00183 case WM_VLC_SHOW_MOUSE:
00184 if( !p_event->p_vout->p_sys->b_cursor_hidden ) break;
00185 p_event->p_vout->p_sys->b_cursor_hidden = VLC_FALSE;
00186 GetCursorPos( &old_mouse_pos );
00187 ShowCursor( TRUE );
00188 break;
00189
00190 case WM_LBUTTONDOWN:
00191 var_Get( p_event->p_vout, "mouse-button-down", &val );
00192 val.i_int |= 1;
00193 var_Set( p_event->p_vout, "mouse-button-down", val );
00194 DirectXPopupMenu( p_event, VLC_FALSE );
00195 break;
00196
00197 case WM_LBUTTONUP:
00198 var_Get( p_event->p_vout, "mouse-button-down", &val );
00199 val.i_int &= ~1;
00200 var_Set( p_event->p_vout, "mouse-button-down", val );
00201
00202 val.b_bool = VLC_TRUE;
00203 var_Set( p_event->p_vout, "mouse-clicked", val );
00204 break;
00205
00206 case WM_LBUTTONDBLCLK:
00207 p_event->p_vout->p_sys->i_changes |= VOUT_FULLSCREEN_CHANGE;
00208 break;
00209
00210 case WM_MBUTTONDOWN:
00211 var_Get( p_event->p_vout, "mouse-button-down", &val );
00212 val.i_int |= 2;
00213 var_Set( p_event->p_vout, "mouse-button-down", val );
00214 DirectXPopupMenu( p_event, VLC_FALSE );
00215 break;
00216
00217 case WM_MBUTTONUP:
00218 var_Get( p_event->p_vout, "mouse-button-down", &val );
00219 val.i_int &= ~2;
00220 var_Set( p_event->p_vout, "mouse-button-down", val );
00221 break;
00222
00223 case WM_RBUTTONDOWN:
00224 var_Get( p_event->p_vout, "mouse-button-down", &val );
00225 val.i_int |= 4;
00226 var_Set( p_event->p_vout, "mouse-button-down", val );
00227 DirectXPopupMenu( p_event, VLC_FALSE );
00228 break;
00229
00230 case WM_RBUTTONUP:
00231 var_Get( p_event->p_vout, "mouse-button-down", &val );
00232 val.i_int &= ~4;
00233 var_Set( p_event->p_vout, "mouse-button-down", val );
00234 DirectXPopupMenu( p_event, VLC_TRUE );
00235 break;
00236
00237 case WM_KEYDOWN:
00238 case WM_SYSKEYDOWN:
00239
00240
00241
00242 val.i_int = DirectXConvertKey( msg.wParam );
00243 if( !val.i_int )
00244 {
00245
00246 val.i_int = tolower( MapVirtualKey( msg.wParam, 2 ) );
00247 }
00248
00249 if( val.i_int )
00250 {
00251 if( GetKeyState(VK_CONTROL) & 0x8000 )
00252 {
00253 val.i_int |= KEY_MODIFIER_CTRL;
00254 }
00255 if( GetKeyState(VK_SHIFT) & 0x8000 )
00256 {
00257 val.i_int |= KEY_MODIFIER_SHIFT;
00258 }
00259 if( GetKeyState(VK_MENU) & 0x8000 )
00260 {
00261 val.i_int |= KEY_MODIFIER_ALT;
00262 }
00263
00264 var_Set( p_event->p_vlc, "key-pressed", val );
00265 }
00266 break;
00267
00268 case WM_MOUSEWHEEL:
00269 if( GET_WHEEL_DELTA_WPARAM( msg.wParam ) > 0 )
00270 {
00271 val.i_int = KEY_MOUSEWHEELUP;
00272 }
00273 else
00274 {
00275 val.i_int = KEY_MOUSEWHEELDOWN;
00276 }
00277 if( val.i_int )
00278 {
00279 if( GetKeyState(VK_CONTROL) & 0x8000 )
00280 {
00281 val.i_int |= KEY_MODIFIER_CTRL;
00282 }
00283 if( GetKeyState(VK_SHIFT) & 0x8000 )
00284 {
00285 val.i_int |= KEY_MODIFIER_SHIFT;
00286 }
00287 if( GetKeyState(VK_MENU) & 0x8000 )
00288 {
00289 val.i_int |= KEY_MODIFIER_ALT;
00290 }
00291
00292 var_Set( p_event->p_vlc, "key-pressed", val );
00293 }
00294 break;
00295
00296 case WM_VLC_CHANGE_TEXT:
00297 var_Get( p_event->p_vout, "video-title", &val );
00298 if( !val.psz_string || !*val.psz_string )
00299 {
00300 if( val.psz_string ) free( val.psz_string );
00301
00302 #ifdef MODULE_NAME_IS_glwin32
00303 val.psz_string = strdup( VOUT_TITLE " (OpenGL output)" );
00304 #else
00305 if( p_event->p_vout->p_sys->b_using_overlay ) val.psz_string =
00306 strdup( VOUT_TITLE " (hardware YUV overlay DirectX output)" );
00307 else if( p_event->p_vout->p_sys->b_hw_yuv ) val.psz_string =
00308 strdup( VOUT_TITLE " (hardware YUV DirectX output)" );
00309 else val.psz_string =
00310 strdup( VOUT_TITLE " (software RGB DirectX output)" );
00311 #endif
00312 }
00313
00314 #ifdef UNICODE
00315 {
00316 wchar_t *psz_title = malloc( strlen(val.psz_string) * 2 + 2 );
00317 mbstowcs( psz_title, val.psz_string, strlen(val.psz_string)*2);
00318 psz_title[strlen(val.psz_string)] = 0;
00319 free( val.psz_string ); val.psz_string = (char *)psz_title;
00320 }
00321 #endif
00322
00323 SetWindowText( p_event->p_vout->p_sys->hwnd,
00324 (LPCTSTR)val.psz_string );
00325 if( p_event->p_vout->p_sys->hfswnd )
00326 SetWindowText( p_event->p_vout->p_sys->hfswnd,
00327 (LPCTSTR)val.psz_string );
00328 free( val.psz_string );
00329 break;
00330
00331 default:
00332
00333
00334 TranslateMessage(&msg);
00335 DispatchMessage(&msg);
00336 break;
00337
00338 }
00339
00340 }
00341
00342
00343 if( !p_event->p_vout->p_sys->hparent && msg.message == WM_QUIT )
00344 {
00345 msg_Warn( p_event, "WM_QUIT... should not happen!!" );
00346 p_event->p_vout->p_sys->hwnd = NULL;
00347 }
00348
00349 msg_Dbg( p_event, "DirectXEventThread terminating" );
00350
00351
00352 p_event->p_vout->p_sys->i_changes = 0;
00353
00354 DirectXCloseWindow( p_event->p_vout );
00355 }
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367 static int DirectXCreateWindow( vout_thread_t *p_vout )
00368 {
00369 HINSTANCE hInstance;
00370 HMENU hMenu;
00371 RECT rect_window;
00372 WNDCLASS wc;
00373 HICON vlc_icon = NULL;
00374 char vlc_path[MAX_PATH+1];
00375 int i_style, i_stylex;
00376
00377 msg_Dbg( p_vout, "DirectXCreateWindow" );
00378
00379
00380 hInstance = GetModuleHandle(NULL);
00381
00382
00383 p_vout->p_sys->hparent =
00384 vout_RequestWindow( p_vout, &p_vout->p_sys->i_window_x,
00385 &p_vout->p_sys->i_window_y,
00386 &p_vout->p_sys->i_window_width,
00387 &p_vout->p_sys->i_window_height );
00388
00389
00390 p_vout->p_sys->pf_wndproc = NULL;
00391
00392
00393 vlc_icon = NULL;
00394 #ifndef UNDER_CE
00395 if( GetModuleFileName( NULL, vlc_path, MAX_PATH ) )
00396 {
00397 vlc_icon = ExtractIcon( hInstance, vlc_path, 0 );
00398 }
00399 #endif
00400
00401
00402 wc.style = CS_OWNDC|CS_DBLCLKS;
00403 wc.lpfnWndProc = (WNDPROC)DirectXEventProc;
00404 wc.cbClsExtra = 0;
00405 wc.cbWndExtra = 0;
00406 wc.hInstance = hInstance;
00407 wc.hIcon = vlc_icon;
00408 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
00409 wc.hbrBackground = GetStockObject(BLACK_BRUSH);
00410 wc.lpszMenuName = NULL;
00411 wc.lpszClassName = _T("VLC DirectX");
00412
00413
00414 if( !RegisterClass(&wc) )
00415 {
00416 WNDCLASS wndclass;
00417
00418 if( vlc_icon ) DestroyIcon( vlc_icon );
00419
00420
00421
00422 if( !GetClassInfo( hInstance, _T("VLC DirectX"), &wndclass ) )
00423 {
00424 msg_Err( p_vout, "DirectXCreateWindow RegisterClass FAILED" );
00425 return VLC_EGENERIC;
00426 }
00427 }
00428
00429
00430 wc.lpszClassName = _T("VLC DirectX video"); wc.hIcon = 0;
00431 if( !RegisterClass(&wc) )
00432 {
00433 WNDCLASS wndclass;
00434
00435
00436
00437 if( !GetClassInfo( hInstance, _T("VLC DirectX video"), &wndclass ) )
00438 {
00439 msg_Err( p_vout, "DirectXCreateWindow RegisterClass FAILED" );
00440 return VLC_EGENERIC;
00441 }
00442 }
00443
00444
00445
00446
00447
00448 rect_window.top = 10;
00449 rect_window.left = 10;
00450 rect_window.right = rect_window.left + p_vout->p_sys->i_window_width;
00451 rect_window.bottom = rect_window.top + p_vout->p_sys->i_window_height;
00452
00453 if( var_GetBool( p_vout, "video-deco" ) )
00454 {
00455
00456 AdjustWindowRect( &rect_window, WS_OVERLAPPEDWINDOW|WS_SIZEBOX, 0 );
00457 i_style = WS_OVERLAPPEDWINDOW|WS_SIZEBOX|WS_VISIBLE|WS_CLIPCHILDREN;
00458 i_stylex = 0;
00459 }
00460 else
00461 {
00462
00463 AdjustWindowRect( &rect_window, WS_POPUP, 0 );
00464 i_style = WS_POPUP|WS_VISIBLE|WS_CLIPCHILDREN;
00465 i_stylex = 0;
00466
00467 }
00468
00469 if( p_vout->p_sys->hparent )
00470 {
00471 i_style = WS_VISIBLE|WS_CLIPCHILDREN|WS_CHILD;
00472 i_stylex = 0;
00473 }
00474
00475 p_vout->p_sys->i_window_style = i_style;
00476
00477
00478 p_vout->p_sys->hwnd =
00479 CreateWindowEx( WS_EX_NOPARENTNOTIFY | i_stylex,
00480 _T("VLC DirectX"),
00481 _T(VOUT_TITLE) _T(" (DirectX Output)"),
00482 i_style,
00483 (p_vout->p_sys->i_window_x < 0) ? CW_USEDEFAULT :
00484 p_vout->p_sys->i_window_x,
00485 (p_vout->p_sys->i_window_y < 0) ? CW_USEDEFAULT :
00486 p_vout->p_sys->i_window_y,
00487 rect_window.right - rect_window.left,
00488 rect_window.bottom - rect_window.top,
00489 p_vout->p_sys->hparent,
00490 NULL,
00491 hInstance,
00492 (LPVOID)p_vout );
00493
00494 if( !p_vout->p_sys->hwnd )
00495 {
00496 msg_Warn( p_vout, "DirectXCreateWindow create window FAILED" );
00497 return VLC_EGENERIC;
00498 }
00499
00500 if( p_vout->p_sys->hparent )
00501 {
00502 LONG i_style;
00503
00504
00505 i_style = GetWindowLong( p_vout->p_sys->hparent, GWL_STYLE );
00506
00507 if( !(i_style & WS_CLIPCHILDREN) )
00508
00509 SetWindowLong( p_vout->p_sys->hparent, GWL_STYLE,
00510 i_style | WS_CLIPCHILDREN );
00511
00512
00513 p_vout->p_sys->hfswnd =
00514 CreateWindowEx( WS_EX_APPWINDOW, _T("VLC DirectX"),
00515 _T(VOUT_TITLE) _T(" (DirectX Output)"),
00516 WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN|WS_SIZEBOX,
00517 CW_USEDEFAULT, CW_USEDEFAULT,
00518 CW_USEDEFAULT, CW_USEDEFAULT,
00519 NULL, NULL, hInstance, NULL );
00520 }
00521
00522
00523 ShowWindow( p_vout->p_sys->hwnd, SW_SHOW );
00524
00525
00526
00527
00528 SendMessage( p_vout->p_sys->hwnd, WM_VLC_CREATE_VIDEO_WIN, 0, 0 );
00529
00530
00531 hMenu = GetSystemMenu( p_vout->p_sys->hwnd, FALSE );
00532 AppendMenu( hMenu, MF_SEPARATOR, 0, _T("") );
00533 AppendMenu( hMenu, MF_STRING | MF_UNCHECKED,
00534 IDM_TOGGLE_ON_TOP, _T("Always on &Top") );
00535
00536 return VLC_SUCCESS;
00537 }
00538
00539
00540
00541
00542
00543
00544 static void DirectXCloseWindow( vout_thread_t *p_vout )
00545 {
00546 msg_Dbg( p_vout, "DirectXCloseWindow" );
00547
00548 DestroyWindow( p_vout->p_sys->hwnd );
00549 if( p_vout->p_sys->hfswnd ) DestroyWindow( p_vout->p_sys->hfswnd );
00550
00551 if( p_vout->p_sys->hparent )
00552 vout_ReleaseWindow( p_vout, (void *)p_vout->p_sys->hparent );
00553
00554 p_vout->p_sys->hwnd = NULL;
00555
00556
00557
00558
00559 }
00560
00561
00562
00563
00564
00565
00566
00567
00568 void E_(DirectXUpdateRects)( vout_thread_t *p_vout, vlc_bool_t b_force )
00569 {
00570 #define rect_src p_vout->p_sys->rect_src
00571 #define rect_src_clipped p_vout->p_sys->rect_src_clipped
00572 #define rect_dest p_vout->p_sys->rect_dest
00573 #define rect_dest_clipped p_vout->p_sys->rect_dest_clipped
00574
00575 int i_width, i_height, i_x, i_y;
00576
00577 RECT rect;
00578 POINT point;
00579
00580
00581 GetClientRect( p_vout->p_sys->hwnd, &rect );
00582
00583
00584 point.x = point.y = 0;
00585 ClientToScreen( p_vout->p_sys->hwnd, &point );
00586
00587
00588 if( !b_force
00589 && p_vout->p_sys->i_window_width == rect.right
00590 && p_vout->p_sys->i_window_height == rect.bottom
00591 && p_vout->p_sys->i_window_x == point.x
00592 && p_vout->p_sys->i_window_y == point.y )
00593 {
00594 return;
00595 }
00596
00597
00598 p_vout->p_sys->i_window_x = point.x;
00599 p_vout->p_sys->i_window_y = point.y;
00600 p_vout->p_sys->i_window_width = rect.right;
00601 p_vout->p_sys->i_window_height = rect.bottom;
00602
00603 vout_PlacePicture( p_vout, rect.right, rect.bottom,
00604 &i_x, &i_y, &i_width, &i_height );
00605
00606 if( p_vout->p_sys->hvideownd )
00607 SetWindowPos( p_vout->p_sys->hvideownd, HWND_TOP,
00608 i_x, i_y, i_width, i_height, 0 );
00609
00610
00611 rect_dest.left = point.x + i_x;
00612 rect_dest.right = rect_dest.left + i_width;
00613 rect_dest.top = point.y + i_y;
00614 rect_dest.bottom = rect_dest.top + i_height;
00615
00616
00617 if( p_vout->p_sys->b_using_overlay )
00618 {
00619 if( p_vout->p_sys->i_align_dest_boundary )
00620 rect_dest.left = ( rect_dest.left +
00621 p_vout->p_sys->i_align_dest_boundary / 2 ) &
00622 ~p_vout->p_sys->i_align_dest_boundary;
00623
00624 if( p_vout->p_sys->i_align_dest_size )
00625 rect_dest.right = (( rect_dest.right - rect_dest.left +
00626 p_vout->p_sys->i_align_dest_size / 2 ) &
00627 ~p_vout->p_sys->i_align_dest_size) + rect_dest.left;
00628 }
00629
00630
00631
00632
00633
00634 if( !IntersectRect( &rect_dest_clipped, &rect_dest,
00635 &p_vout->p_sys->rect_display ) )
00636 {
00637 SetRectEmpty( &rect_src_clipped );
00638 return;
00639 }
00640
00641 #if 0
00642 msg_Dbg( p_vout, "DirectXUpdateRects image_dst_clipped coords:"
00643 " %i,%i,%i,%i",
00644 rect_dest_clipped.left, rect_dest_clipped.top,
00645 rect_dest_clipped.right, rect_dest_clipped.bottom );
00646 #endif
00647
00648
00649 if( (rect_dest_clipped.right - rect_dest_clipped.left)==0 ||
00650 (rect_dest_clipped.bottom - rect_dest_clipped.top)==0 )
00651 {
00652 SetRectEmpty( &rect_src_clipped );
00653 return;
00654 }
00655
00656
00657 rect_src.left = 0;
00658 rect_src.top = 0;
00659 rect_src.right = p_vout->render.i_width;
00660 rect_src.bottom = p_vout->render.i_height;
00661
00662
00663 rect_src_clipped.left = p_vout->fmt_out.i_x_offset +
00664 (rect_dest_clipped.left - rect_dest.left) *
00665 p_vout->fmt_out.i_visible_width / (rect_dest.right - rect_dest.left);
00666 rect_src_clipped.right = p_vout->fmt_out.i_x_offset +
00667 p_vout->fmt_out.i_visible_width -
00668 (rect_dest.right - rect_dest_clipped.right) *
00669 p_vout->fmt_out.i_visible_width / (rect_dest.right - rect_dest.left);
00670 rect_src_clipped.top = p_vout->fmt_out.i_y_offset +
00671 (rect_dest_clipped.top - rect_dest.top) *
00672 p_vout->fmt_out.i_visible_height / (rect_dest.bottom - rect_dest.top);
00673 rect_src_clipped.bottom = p_vout->fmt_out.i_y_offset +
00674 p_vout->fmt_out.i_visible_height -
00675 (rect_dest.bottom - rect_dest_clipped.bottom) *
00676 p_vout->fmt_out.i_visible_height / (rect_dest.bottom - rect_dest.top);
00677
00678
00679 if( p_vout->p_sys->b_using_overlay )
00680 {
00681 if( p_vout->p_sys->i_align_src_boundary )
00682 rect_src_clipped.left = ( rect_src_clipped.left +
00683 p_vout->p_sys->i_align_src_boundary / 2 ) &
00684 ~p_vout->p_sys->i_align_src_boundary;
00685
00686 if( p_vout->p_sys->i_align_src_size )
00687 rect_src_clipped.right = (( rect_src_clipped.right -
00688 rect_src_clipped.left +
00689 p_vout->p_sys->i_align_src_size / 2 ) &
00690 ~p_vout->p_sys->i_align_src_size) + rect_src_clipped.left;
00691 }
00692
00693 #if 0
00694 msg_Dbg( p_vout, "DirectXUpdateRects image_src_clipped"
00695 " coords: %i,%i,%i,%i",
00696 rect_src_clipped.left, rect_src_clipped.top,
00697 rect_src_clipped.right, rect_src_clipped.bottom );
00698 #endif
00699
00700
00701
00702 rect_dest_clipped.left -= p_vout->p_sys->rect_display.left;
00703 rect_dest_clipped.right -= p_vout->p_sys->rect_display.left;
00704 rect_dest_clipped.top -= p_vout->p_sys->rect_display.top;
00705 rect_dest_clipped.bottom -= p_vout->p_sys->rect_display.top;
00706
00707 if( p_vout->p_sys->b_using_overlay )
00708 E_(DirectXUpdateOverlay)( p_vout );
00709
00710
00711 p_vout->p_sys->i_changes |= DX_POSITION_CHANGE;
00712
00713 #undef rect_src
00714 #undef rect_src_clipped
00715 #undef rect_dest
00716 #undef rect_dest_clipped
00717 }
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730 static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
00731 WPARAM wParam, LPARAM lParam )
00732 {
00733 vout_thread_t *p_vout;
00734
00735 if( message == WM_CREATE )
00736 {
00737
00738 p_vout = (vout_thread_t *)((CREATESTRUCT *)lParam)->lpCreateParams;
00739 SetWindowLongPtr( hwnd, GWLP_USERDATA, (LONG_PTR)p_vout );
00740 }
00741 else
00742 {
00743 p_vout = (vout_thread_t *)GetWindowLongPtr( hwnd, GWLP_USERDATA );
00744 }
00745
00746
00747 if( message == WM_SYSCOMMAND &&
00748 ( (wParam & 0xFFF0) == SC_SCREENSAVE || (wParam & 0xFFF0) == SC_MONITORPOWER ) )
00749 {
00750
00751 return 0;
00752 }
00753
00754 if( !p_vout )
00755 {
00756
00757
00758 return DefWindowProc(hwnd, message, wParam, lParam);
00759 }
00760
00761 if( hwnd == p_vout->p_sys->hvideownd )
00762 return DefWindowProc(hwnd, message, wParam, lParam);
00763
00764 switch( message )
00765 {
00766
00767 case WM_WINDOWPOSCHANGED:
00768 E_(DirectXUpdateRects)( p_vout, VLC_TRUE );
00769 return 0;
00770
00771
00772 case WM_CLOSE:
00773 {
00774 playlist_t * p_playlist =
00775 (playlist_t *)vlc_object_find( p_vout, VLC_OBJECT_PLAYLIST,
00776 FIND_ANYWHERE );
00777 if( p_playlist == NULL )
00778 {
00779 return 0;
00780 }
00781
00782 playlist_Stop( p_playlist );
00783 vlc_object_release( p_playlist );
00784 return 0;
00785 }
00786
00787
00788 case WM_DESTROY:
00789 msg_Dbg( p_vout, "WinProc WM_DESTROY" );
00790
00791 PostQuitMessage( 0 );
00792 return 0;
00793
00794 case WM_SYSCOMMAND:
00795 switch (wParam)
00796 {
00797 case IDM_TOGGLE_ON_TOP:
00798 {
00799 vlc_value_t val;
00800 msg_Dbg( p_vout, "WinProc WM_SYSCOMMAND: IDM_TOGGLE_ON_TOP");
00801
00802
00803 var_Get( p_vout, "video-on-top", &val );
00804 val.b_bool = !val.b_bool;
00805 var_Set( p_vout, "video-on-top", val );
00806 return 0;
00807 }
00808 }
00809 break;
00810
00811 case WM_VLC_CREATE_VIDEO_WIN:
00812
00813 p_vout->p_sys->hvideownd =
00814 CreateWindow( _T("VLC DirectX video"), _T(""),
00815 WS_CHILD | WS_VISIBLE,
00816 CW_USEDEFAULT, CW_USEDEFAULT,
00817 CW_USEDEFAULT, CW_USEDEFAULT,
00818 hwnd,
00819 NULL, GetModuleHandle(NULL),
00820 (LPVOID)p_vout );
00821
00822 if( !p_vout->p_sys->hvideownd )
00823 msg_Warn( p_vout, "Can't create video sub-window" );
00824 else
00825 msg_Dbg( p_vout, "Created video sub-window" );
00826 break;
00827
00828 case WM_PAINT:
00829 case WM_NCPAINT:
00830 case WM_ERASEBKGND:
00831
00832
00833 return DefWindowProc(hwnd, message, wParam, lParam);
00834 break;
00835
00836 default:
00837
00838 break;
00839 }
00840
00841
00842 return DefWindowProc(hwnd, message, wParam, lParam);
00843 }
00844
00845 static struct
00846 {
00847 int i_dxkey;
00848 int i_vlckey;
00849
00850 } dxkeys_to_vlckeys[] =
00851 {
00852 { VK_F1, KEY_F1 }, { VK_F2, KEY_F2 }, { VK_F3, KEY_F3 }, { VK_F4, KEY_F4 },
00853 { VK_F5, KEY_F5 }, { VK_F6, KEY_F6 }, { VK_F7, KEY_F7 }, { VK_F8, KEY_F8 },
00854 { VK_F9, KEY_F9 }, { VK_F10, KEY_F10 }, { VK_F11, KEY_F11 },
00855 { VK_F12, KEY_F12 },
00856
00857 { VK_RETURN, KEY_ENTER },
00858 { VK_SPACE, KEY_SPACE },
00859 { VK_ESCAPE, KEY_ESC },
00860
00861 { VK_LEFT, KEY_LEFT },
00862 { VK_RIGHT, KEY_RIGHT },
00863 { VK_UP, KEY_UP },
00864 { VK_DOWN, KEY_DOWN },
00865
00866 { VK_HOME, KEY_HOME },
00867 { VK_END, KEY_END },
00868 { VK_PRIOR, KEY_PAGEUP },
00869 { VK_NEXT, KEY_PAGEDOWN },
00870
00871 { VK_INSERT, KEY_INSERT },
00872 { VK_DELETE, KEY_DELETE },
00873
00874 { VK_CONTROL, 0 },
00875 { VK_SHIFT, 0 },
00876 { VK_MENU, 0 },
00877
00878 { 0, 0 }
00879 };
00880
00881 static int DirectXConvertKey( int i_key )
00882 {
00883 int i;
00884
00885 for( i = 0; dxkeys_to_vlckeys[i].i_dxkey != 0; i++ )
00886 {
00887 if( dxkeys_to_vlckeys[i].i_dxkey == i_key )
00888 {
00889 return dxkeys_to_vlckeys[i].i_vlckey;
00890 }
00891 }
00892
00893 return 0;
00894 }
00895
00896
00897
00898
00899 static int Control( vout_thread_t *p_vout, int i_query, va_list args )
00900 {
00901 double f_arg;
00902 RECT rect_window;
00903 POINT point;
00904
00905 switch( i_query )
00906 {
00907 case VOUT_SET_ZOOM:
00908 if( p_vout->p_sys->hparent )
00909 return vout_ControlWindow( p_vout,
00910 (void *)p_vout->p_sys->hparent, i_query, args );
00911
00912
00913 rect_window.top = rect_window.left = 0;
00914 rect_window.right = p_vout->i_window_width;
00915 rect_window.bottom = p_vout->i_window_height;
00916 AdjustWindowRect( &rect_window, p_vout->p_sys->i_window_style, 0 );
00917
00918 SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
00919 rect_window.right - rect_window.left,
00920 rect_window.bottom - rect_window.top, SWP_NOMOVE );
00921
00922 return VLC_SUCCESS;
00923
00924 case VOUT_CLOSE:
00925 ShowWindow( p_vout->p_sys->hwnd, SW_HIDE );
00926 case VOUT_REPARENT:
00927
00928 vlc_mutex_lock( &p_vout->p_sys->lock );
00929 p_vout->p_sys->hparent = 0;
00930 vlc_mutex_unlock( &p_vout->p_sys->lock );
00931
00932
00933 point.x = point.y = 0;
00934 ClientToScreen( p_vout->p_sys->hwnd, &point );
00935
00936 SetParent( p_vout->p_sys->hwnd, 0 );
00937 p_vout->p_sys->i_window_style =
00938 WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW | WS_SIZEBOX;
00939 SetWindowLong( p_vout->p_sys->hwnd, GWL_STYLE,
00940 p_vout->p_sys->i_window_style |
00941 (i_query == VOUT_CLOSE ? 0 : WS_VISIBLE) );
00942 SetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW );
00943 SetWindowPos( p_vout->p_sys->hwnd, 0, point.x, point.y, 0, 0,
00944 SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED );
00945
00946 return vout_vaControlDefault( p_vout, i_query, args );
00947
00948 case VOUT_SET_STAY_ON_TOP:
00949 if( p_vout->p_sys->hparent )
00950 return vout_ControlWindow( p_vout,
00951 (void *)p_vout->p_sys->hparent, i_query, args );
00952
00953 p_vout->p_sys->b_on_top_change = VLC_TRUE;
00954 return VLC_SUCCESS;
00955
00956 default:
00957 return vout_vaControlDefault( p_vout, i_query, args );
00958 }
00959 }