Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc
Commits
d98e43b1
Commit
d98e43b1
authored
Jan 05, 2010
by
Laurent Aimar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert "Removed old msw files."
This reverts commit e145f5a5bb6d61d67a8b9a6d1a4f1b33976c8ff6.
parent
e36b4e6a
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
2217 additions
and
0 deletions
+2217
-0
modules/video_output/msw/common_vo.c
modules/video_output/msw/common_vo.c
+761
-0
modules/video_output/msw/events_vo.c
modules/video_output/msw/events_vo.c
+1093
-0
modules/video_output/msw/events_vo.h
modules/video_output/msw/events_vo.h
+57
-0
modules/video_output/msw/vout.h
modules/video_output/msw/vout.h
+306
-0
No files found.
modules/video_output/msw/common_vo.c
0 → 100644
View file @
d98e43b1
/*****************************************************************************
* common.c:
*****************************************************************************
* Copyright (C) 2001-2009 the VideoLAN team
* $Id$
*
* Authors: Gildas Bazin <gbazin@videolan.org>
*
* 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
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*****************************************************************************/
/*****************************************************************************
* 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 <vlc_common.h>
#include <vlc_vout.h>
#include <vlc_vout_window.h>
#include <windows.h>
#include <windowsx.h>
#include <shellapi.h>
#ifdef MODULE_NAME_IS_directx
#include <ddraw.h>
#endif
#ifdef MODULE_NAME_IS_direct3d
#include <d3d9.h>
#endif
#ifdef MODULE_NAME_IS_glwin32
#include <GL/gl.h>
#endif
#include "vout.h"
#ifndef UNDER_CE
#include <vlc_windows_interfaces.h>
#endif
#ifdef UNDER_CE
#include <aygshell.h>
//WINSHELLAPI BOOL WINAPI SHFullScreen(HWND hwndRequester, DWORD dwState);
#endif
static
int
vaControlParentWindow
(
vout_thread_t
*
,
int
,
va_list
);
/* */
int
CommonInit
(
vout_thread_t
*
p_vout
)
{
vout_sys_t
*
p_sys
=
p_vout
->
p_sys
;
p_sys
->
hwnd
=
NULL
;
p_sys
->
hvideownd
=
NULL
;
p_sys
->
hparent
=
NULL
;
p_sys
->
hfswnd
=
NULL
;
p_sys
->
i_changes
=
0
;
SetRectEmpty
(
&
p_sys
->
rect_display
);
SetRectEmpty
(
&
p_sys
->
rect_parent
);
var_Create
(
p_vout
,
"video-title"
,
VLC_VAR_STRING
|
VLC_VAR_DOINHERIT
);
/* Set main window's size */
vout_window_cfg_t
wnd_cfg
;
memset
(
&
wnd_cfg
,
0
,
sizeof
(
wnd_cfg
)
);
wnd_cfg
.
type
=
VOUT_WINDOW_TYPE_HWND
;
wnd_cfg
.
x
=
0
;
wnd_cfg
.
y
=
0
;
wnd_cfg
.
width
=
p_vout
->
i_window_width
;
wnd_cfg
.
height
=
p_vout
->
i_window_height
;
p_sys
->
p_event
=
EventThreadCreate
(
p_vout
,
&
wnd_cfg
);
if
(
!
p_sys
->
p_event
)
return
VLC_EGENERIC
;
event_cfg_t
cfg
;
memset
(
&
cfg
,
0
,
sizeof
(
cfg
));
#ifdef MODULE_NAME_IS_direct3d
cfg
.
use_desktop
=
p_vout
->
p_sys
->
b_desktop
;
#endif
#ifdef MODULE_NAME_IS_directx
cfg
.
use_overlay
=
p_vout
->
p_sys
->
b_using_overlay
;
#endif
event_hwnd_t
hwnd
;
if
(
EventThreadStart
(
p_sys
->
p_event
,
&
hwnd
,
&
cfg
)
)
return
VLC_EGENERIC
;
p_sys
->
parent_window
=
hwnd
.
parent_window
;
p_sys
->
hparent
=
hwnd
.
hparent
;
p_sys
->
hwnd
=
hwnd
.
hwnd
;
p_sys
->
hvideownd
=
hwnd
.
hvideownd
;
p_sys
->
hfswnd
=
hwnd
.
hfswnd
;
/* Variable to indicate if the window should be on top of others */
/* Trigger a callback right now */
var_TriggerCallback
(
p_vout
,
"video-on-top"
);
/* Why not with glwin32 */
#if !defined(UNDER_CE) && !defined(MODULE_NAME_IS_glwin32)
var_Create
(
p_vout
,
"disable-screensaver"
,
VLC_VAR_BOOL
|
VLC_VAR_DOINHERIT
);
DisableScreensaver
(
p_vout
);
#endif
return
VLC_SUCCESS
;
}
/* */
void
CommonClean
(
vout_thread_t
*
p_vout
)
{
vout_sys_t
*
p_sys
=
p_vout
->
p_sys
;
ExitFullscreen
(
p_vout
);
if
(
p_sys
->
p_event
)
{
EventThreadStop
(
p_sys
->
p_event
);
EventThreadDestroy
(
p_sys
->
p_event
);
}
#if !defined(UNDER_CE) && !defined(MODULE_NAME_IS_glwin32)
RestoreScreensaver
(
p_vout
);
#endif
}
void
CommonManage
(
vout_thread_t
*
p_vout
)
{
/* If we do not control our window, we check for geometry changes
* ourselves because the parent might not send us its events. */
if
(
p_vout
->
p_sys
->
hparent
)
{
RECT
rect_parent
;
POINT
point
;
GetClientRect
(
p_vout
->
p_sys
->
hparent
,
&
rect_parent
);
point
.
x
=
point
.
y
=
0
;
ClientToScreen
(
p_vout
->
p_sys
->
hparent
,
&
point
);
OffsetRect
(
&
rect_parent
,
point
.
x
,
point
.
y
);
if
(
!
EqualRect
(
&
rect_parent
,
&
p_vout
->
p_sys
->
rect_parent
)
)
{
p_vout
->
p_sys
->
rect_parent
=
rect_parent
;
/* FIXME I find such #ifdef quite weirds. Are they really needed ? */
#if defined(MODULE_NAME_IS_direct3d)
SetWindowPos
(
p_vout
->
p_sys
->
hwnd
,
0
,
0
,
0
,
rect_parent
.
right
-
rect_parent
.
left
,
rect_parent
.
bottom
-
rect_parent
.
top
,
SWP_NOZORDER
);
UpdateRects
(
p_vout
,
true
);
#else
/* This one is to force the update even if only
* the position has changed */
SetWindowPos
(
p_vout
->
p_sys
->
hwnd
,
0
,
1
,
1
,
rect_parent
.
right
-
rect_parent
.
left
,
rect_parent
.
bottom
-
rect_parent
.
top
,
0
);
SetWindowPos
(
p_vout
->
p_sys
->
hwnd
,
0
,
0
,
0
,
rect_parent
.
right
-
rect_parent
.
left
,
rect_parent
.
bottom
-
rect_parent
.
top
,
0
);
#if defined(MODULE_NAME_IS_wingdi) || defined(MODULE_NAME_IS_wingapi)
unsigned
int
i_x
,
i_y
,
i_width
,
i_height
;
vout_PlacePicture
(
p_vout
,
rect_parent
.
right
-
rect_parent
.
left
,
rect_parent
.
bottom
-
rect_parent
.
top
,
&
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
);
#endif
#endif
}
}
/* */
p_vout
->
p_sys
->
i_changes
|=
EventThreadRetreiveChanges
(
p_vout
->
p_sys
->
p_event
);
/* autoscale toggle */
if
(
p_vout
->
i_changes
&
VOUT_SCALE_CHANGE
)
{
p_vout
->
i_changes
&=
~
VOUT_SCALE_CHANGE
;
p_vout
->
b_autoscale
=
var_GetBool
(
p_vout
,
"autoscale"
);
p_vout
->
i_zoom
=
(
int
)
ZOOM_FP_FACTOR
;
UpdateRects
(
p_vout
,
true
);
}
/* scaling factor */
if
(
p_vout
->
i_changes
&
VOUT_ZOOM_CHANGE
)
{
p_vout
->
i_changes
&=
~
VOUT_ZOOM_CHANGE
;
p_vout
->
b_autoscale
=
false
;
p_vout
->
i_zoom
=
(
int
)(
ZOOM_FP_FACTOR
*
var_GetFloat
(
p_vout
,
"scale"
)
);
UpdateRects
(
p_vout
,
true
);
}
/* Check for cropping / aspect changes */
if
(
p_vout
->
i_changes
&
VOUT_CROP_CHANGE
||
p_vout
->
i_changes
&
VOUT_ASPECT_CHANGE
)
{
p_vout
->
i_changes
&=
~
VOUT_CROP_CHANGE
;
p_vout
->
i_changes
&=
~
VOUT_ASPECT_CHANGE
;
p_vout
->
fmt_out
.
i_x_offset
=
p_vout
->
fmt_in
.
i_x_offset
;
p_vout
->
fmt_out
.
i_y_offset
=
p_vout
->
fmt_in
.
i_y_offset
;
p_vout
->
fmt_out
.
i_visible_width
=
p_vout
->
fmt_in
.
i_visible_width
;
p_vout
->
fmt_out
.
i_visible_height
=
p_vout
->
fmt_in
.
i_visible_height
;
p_vout
->
fmt_out
.
i_sar_num
=
p_vout
->
fmt_in
.
i_sar_num
;
p_vout
->
fmt_out
.
i_sar_den
=
p_vout
->
fmt_in
.
i_sar_den
;
p_vout
->
output
.
i_aspect
=
(
int64_t
)
VOUT_ASPECT_FACTOR
*
p_vout
->
fmt_in
.
i_sar_num
*
p_vout
->
fmt_in
.
i_width
/
(
p_vout
->
fmt_in
.
i_sar_den
*
p_vout
->
fmt_in
.
i_height
);
UpdateRects
(
p_vout
,
true
);
}
/* We used to call the Win32 PeekMessage function here to read the window
* messages. But since window can stay blocked into this function for a
* long time (for example when you move your window on the screen), I
* decided to isolate PeekMessage in another thread. */
/*
* Fullscreen change
*/
if
(
p_vout
->
i_changes
&
VOUT_FULLSCREEN_CHANGE
||
p_vout
->
p_sys
->
i_changes
&
VOUT_FULLSCREEN_CHANGE
)
{
Win32ToggleFullscreen
(
p_vout
);
p_vout
->
i_changes
&=
~
VOUT_FULLSCREEN_CHANGE
;
p_vout
->
p_sys
->
i_changes
&=
~
VOUT_FULLSCREEN_CHANGE
;
}
/*
* Pointer change
*/
EventThreadMouseAutoHide
(
p_vout
->
p_sys
->
p_event
);
/*
* "Always on top" status change
*/
if
(
p_vout
->
p_sys
->
b_on_top_change
)
{
HMENU
hMenu
=
GetSystemMenu
(
p_vout
->
p_sys
->
hwnd
,
FALSE
);
bool
b
=
var_GetBool
(
p_vout
,
"video-on-top"
);
/* Set the window on top if necessary */
if
(
b
&&
!
(
GetWindowLong
(
p_vout
->
p_sys
->
hwnd
,
GWL_EXSTYLE
)
&
WS_EX_TOPMOST
)
)
{
CheckMenuItem
(
hMenu
,
IDM_TOGGLE_ON_TOP
,
MF_BYCOMMAND
|
MFS_CHECKED
);
SetWindowPos
(
p_vout
->
p_sys
->
hwnd
,
HWND_TOPMOST
,
0
,
0
,
0
,
0
,
SWP_NOSIZE
|
SWP_NOMOVE
);
}
else
/* The window shouldn't be on top */
if
(
!
b
&&
(
GetWindowLong
(
p_vout
->
p_sys
->
hwnd
,
GWL_EXSTYLE
)
&
WS_EX_TOPMOST
)
)
{
CheckMenuItem
(
hMenu
,
IDM_TOGGLE_ON_TOP
,
MF_BYCOMMAND
|
MFS_UNCHECKED
);
SetWindowPos
(
p_vout
->
p_sys
->
hwnd
,
HWND_NOTOPMOST
,
0
,
0
,
0
,
0
,
SWP_NOSIZE
|
SWP_NOMOVE
);
}
p_vout
->
p_sys
->
b_on_top_change
=
false
;
}
}
/*****************************************************************************
* UpdateRects: update clipping rectangles
*****************************************************************************
* This function is called when the window position or size are changed, and
* its job is to update the source and destination RECTs used to display the
* picture.
*****************************************************************************/
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
#define rect_dest p_vout->p_sys->rect_dest
#define rect_dest_clipped p_vout->p_sys->rect_dest_clipped
unsigned
int
i_width
,
i_height
,
i_x
,
i_y
;
RECT
rect
;
POINT
point
;
/* Retrieve the window size */
GetClientRect
(
p_vout
->
p_sys
->
hwnd
,
&
rect
);
/* Retrieve the window position */
point
.
x
=
point
.
y
=
0
;
ClientToScreen
(
p_vout
->
p_sys
->
hwnd
,
&
point
);
/* If nothing changed, we can return */
bool
b_changed
;
EventThreadUpdateWindowPosition
(
p_vout
->
p_sys
->
p_event
,
&
b_changed
,
point
.
x
,
point
.
y
,
rect
.
right
,
rect
.
bottom
);
if
(
!
b_force
&&
!
b_changed
)
return
;
/* Update the window position and size */
vout_PlacePicture
(
p_vout
,
rect
.
right
,
rect
.
bottom
,
&
i_x
,
&
i_y
,
&
i_width
,
&
i_height
);
if
(
p_vout
->
p_sys
->
hvideownd
)
SetWindowPos
(
p_vout
->
p_sys
->
hvideownd
,
0
,
i_x
,
i_y
,
i_width
,
i_height
,
SWP_NOCOPYBITS
|
SWP_NOZORDER
|
SWP_ASYNCWINDOWPOS
);
/* Destination image position and dimensions */
#if defined(MODULE_NAME_IS_direct3d)
rect_dest
.
left
=
0
;
rect_dest
.
right
=
i_width
;
rect_dest
.
top
=
0
;
rect_dest
.
bottom
=
i_height
;
#else
rect_dest
.
left
=
point
.
x
+
i_x
;
rect_dest
.
right
=
rect_dest
.
left
+
i_width
;
rect_dest
.
top
=
point
.
y
+
i_y
;
rect_dest
.
bottom
=
rect_dest
.
top
+
i_height
;
#ifdef MODULE_NAME_IS_directx
/* 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
;
}
#endif
#endif
#if defined(MODULE_NAME_IS_directx) || defined(MODULE_NAME_IS_direct3d)
/* UpdateOverlay directdraw function doesn't automatically clip to the
* display size so we need to do it otherwise it will fail
* It is also needed for d3d to avoid exceding our surface size */
/* Clip the destination window */
if
(
!
IntersectRect
(
&
rect_dest_clipped
,
&
rect_dest
,
&
p_vout
->
p_sys
->
rect_display
)
)
{
SetRectEmpty
(
&
rect_src_clipped
);
return
;
}
#ifndef NDEBUG
msg_Dbg
(
p_vout
,
"DirectXUpdateRects image_dst_clipped coords:"
" %li,%li,%li,%li"
,
rect_dest_clipped
.
left
,
rect_dest_clipped
.
top
,
rect_dest_clipped
.
right
,
rect_dest_clipped
.
bottom
);
#endif
#else
/* AFAIK, there are no clipping constraints in Direct3D, OpenGL and GDI */
rect_dest_clipped
=
rect_dest
;
#endif
/* the 2 following lines are to fix a bug when clicking on the desktop */
if
(
(
rect_dest_clipped
.
right
-
rect_dest_clipped
.
left
)
==
0
||
(
rect_dest_clipped
.
bottom
-
rect_dest_clipped
.
top
)
==
0
)
{
SetRectEmpty
(
&
rect_src_clipped
);
return
;
}
/* src image dimensions */
rect_src
.
left
=
0
;
rect_src
.
top
=
0
;
rect_src
.
right
=
p_vout
->
render
.
i_width
;
rect_src
.
bottom
=
p_vout
->
render
.
i_height
;
/* Clip the source image */
rect_src_clipped
.
left
=
p_vout
->
fmt_out
.
i_x_offset
+
(
rect_dest_clipped
.
left
-
rect_dest
.
left
)
*
p_vout
->
fmt_out
.
i_visible_width
/
(
rect_dest
.
right
-
rect_dest
.
left
);
rect_src_clipped
.
right
=
p_vout
->
fmt_out
.
i_x_offset
+
p_vout
->
fmt_out
.
i_visible_width
-
(
rect_dest
.
right
-
rect_dest_clipped
.
right
)
*
p_vout
->
fmt_out
.
i_visible_width
/
(
rect_dest
.
right
-
rect_dest
.
left
);
rect_src_clipped
.
top
=
p_vout
->
fmt_out
.
i_y_offset
+
(
rect_dest_clipped
.
top
-
rect_dest
.
top
)
*
p_vout
->
fmt_out
.
i_visible_height
/
(
rect_dest
.
bottom
-
rect_dest
.
top
);
rect_src_clipped
.
bottom
=
p_vout
->
fmt_out
.
i_y_offset
+
p_vout
->
fmt_out
.
i_visible_height
-
(
rect_dest
.
bottom
-
rect_dest_clipped
.
bottom
)
*
p_vout
->
fmt_out
.
i_visible_height
/
(
rect_dest
.
bottom
-
rect_dest
.
top
);
#ifdef MODULE_NAME_IS_directx
/* 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
;
}
#elif defined(MODULE_NAME_IS_direct3d)
/* Needed at least with YUV content */
rect_src_clipped
.
left
&=
~
1
;
rect_src_clipped
.
right
&=
~
1
;
rect_src_clipped
.
top
&=
~
1
;
rect_src_clipped
.
bottom
&=
~
1
;
#endif
#ifndef NDEBUG
msg_Dbg
(
p_vout
,
"DirectXUpdateRects image_src_clipped"
" coords: %li,%li,%li,%li"
,
rect_src_clipped
.
left
,
rect_src_clipped
.
top
,
rect_src_clipped
.
right
,
rect_src_clipped
.
bottom
);
#endif
#ifdef MODULE_NAME_IS_directx
/* 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
)
DirectDrawUpdateOverlay
(
p_vout
);
#endif
#ifndef UNDER_CE
/* Windows 7 taskbar thumbnail code */
LPTASKBARLIST3
p_taskbl
;
OSVERSIONINFO
winVer
;
winVer
.
dwOSVersionInfoSize
=
sizeof
(
OSVERSIONINFO
);
if
(
GetVersionEx
(
&
winVer
)
&&
winVer
.
dwMajorVersion
>
5
)
{
CoInitialize
(
0
);
if
(
S_OK
==
CoCreateInstance
(
&
clsid_ITaskbarList
,
NULL
,
CLSCTX_INPROC_SERVER
,
&
IID_ITaskbarList3
,
&
p_taskbl
)
)
{
RECT
rect_video
,
rect_parent
,
rect_relative
;
HWND
hroot
=
GetAncestor
(
p_vout
->
p_sys
->
hwnd
,
GA_ROOT
);
p_taskbl
->
vt
->
HrInit
(
p_taskbl
);
GetWindowRect
(
p_vout
->
p_sys
->
hvideownd
,
&
rect_video
);
GetWindowRect
(
hroot
,
&
rect_parent
);
rect_relative
.
left
=
rect_video
.
left
-
rect_parent
.
left
-
8
;
rect_relative
.
right
=
rect_video
.
right
-
rect_video
.
left
+
rect_relative
.
left
;
rect_relative
.
top
=
rect_video
.
top
-
rect_parent
.
top
-
10
;
rect_relative
.
bottom
=
rect_video
.
bottom
-
rect_video
.
top
+
rect_relative
.
top
-
25
;
if
(
S_OK
!=
p_taskbl
->
vt
->
SetThumbnailClip
(
p_taskbl
,
hroot
,
&
rect_relative
))
msg_Err
(
p_vout
,
"SetThumbNailClip failed"
);
p_taskbl
->
vt
->
Release
(
p_taskbl
);
}
CoUninitialize
();
}
#endif
/* Signal the change in size/position */
p_vout
->
p_sys
->
i_changes
|=
DX_POSITION_CHANGE
;
#undef rect_src
#undef rect_src_clipped
#undef rect_dest
#undef rect_dest_clipped
}
/*****************************************************************************
* Control: control facility for the vout
*****************************************************************************/
int
Control
(
vout_thread_t
*
p_vout
,
int
i_query
,
va_list
args
)
{
RECT
rect_window
;
switch
(
i_query
)
{
case
VOUT_SET_SIZE
:
if
(
p_vout
->
p_sys
->
parent_window
)
return
vaControlParentWindow
(
p_vout
,
i_query
,
args
);
/* Update dimensions */
rect_window
.
top
=
rect_window
.
left
=
0
;
rect_window
.
right
=
va_arg
(
args
,
unsigned
int
);
rect_window
.
bottom
=
va_arg
(
args
,
unsigned
int
);
if
(
!
rect_window
.
right
)
rect_window
.
right
=
p_vout
->
i_window_width
;
if
(
!
rect_window
.
bottom
)
rect_window
.
bottom
=
p_vout
->
i_window_height
;
AdjustWindowRect
(
&
rect_window
,
EventThreadGetWindowStyle
(
p_vout
->
p_sys
->
p_event
),
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_SET_STAY_ON_TOP
:
if
(
p_vout
->
p_sys
->
hparent
&&
!
var_GetBool
(
p_vout
,
"fullscreen"
)
)
return
vaControlParentWindow
(
p_vout
,
i_query
,
args
);
p_vout
->
p_sys
->
b_on_top_change
=
true
;
return
VLC_SUCCESS
;
default:
return
VLC_EGENERIC
;
}
}
/* Internal wrapper over GetWindowPlacement */
static
WINDOWPLACEMENT
getWindowState
(
HWND
hwnd
)
{
WINDOWPLACEMENT
window_placement
;
window_placement
.
length
=
sizeof
(
WINDOWPLACEMENT
);
GetWindowPlacement
(
hwnd
,
&
window_placement
);
return
window_placement
;
}
/* Internal wrapper to call vout_ControlWindow for hparent */
static
int
vaControlParentWindow
(
vout_thread_t
*
p_vout
,
int
i_query
,
va_list
args
)
{
switch
(
i_query
)
{
case
VOUT_SET_SIZE
:
{
const
unsigned
i_width
=
va_arg
(
args
,
unsigned
);
const
unsigned
i_height
=
va_arg
(
args
,
unsigned
);
return
vout_window_SetSize
(
p_vout
->
p_sys
->
parent_window
,
i_width
,
i_height
);
}
case
VOUT_SET_STAY_ON_TOP
:
{
const
bool
is_on_top
=
va_arg
(
args
,
int
);
return
vout_window_SetState
(
p_vout
->
p_sys
->
parent_window
,
is_on_top
);
}
default:
return
VLC_EGENERIC
;
}
}
#if 0
static int ControlParentWindow( vout_thread_t *p_vout, int i_query, ... )
{
va_list args;
int ret;
va_start( args, i_query );
ret = vaControlParentWindow( p_vout, i_query, args );
va_end( args );
return ret;
}
#endif
void
ExitFullscreen
(
vout_thread_t
*
p_vout
)
{
if
(
p_vout
->
b_fullscreen
)
{
msg_Dbg
(
p_vout
,
"Quitting fullscreen"
);
Win32ToggleFullscreen
(
p_vout
);
/* Force fullscreen in the core for the next video */
var_SetBool
(
p_vout
,
"fullscreen"
,
true
);
}
}
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
;
if
(
p_vout
->
p_sys
->
parent_window
)
{
vout_window_SetFullScreen
(
p_vout
->
p_sys
->
parent_window
,
p_vout
->
b_fullscreen
);
return
;
}
/* 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
)
{
#ifdef UNDER_CE
POINT
point
=
{
0
,
0
};
RECT
rect
;
ClientToScreen
(
p_vout
->
p_sys
->
hwnd
,
&
point
);
GetClientRect
(
p_vout
->
p_sys
->
hwnd
,
&
rect
);
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
;
mi
.
cbSize
=
sizeof
(
MONITORINFO
);
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
);
}
if
(
p_vout
->
p_sys
->
hparent
)
{
/* Hide the previous window */
RECT
rect
;
GetClientRect
(
hwnd
,
&
rect
);
SetParent
(
p_vout
->
p_sys
->
hwnd
,
hwnd
);
SetWindowPos
(
p_vout
->
p_sys
->
hwnd
,
0
,
0
,
0
,
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
);
}
SetForegroundWindow
(
hwnd
);
}
else
{
msg_Dbg
(
p_vout
,
"leaving fullscreen mode"
);
/* Change window style, no borders and no title bar */
SetWindowLong
(
hwnd
,
GWL_STYLE
,
EventThreadGetWindowStyle
(
p_vout
->
p_sys
->
p_event
)
);
if
(
p_vout
->
p_sys
->
hparent
)
{
RECT
rect
;
GetClientRect
(
p_vout
->
p_sys
->
hparent
,
&
rect
);
SetParent
(
p_vout
->
p_sys
->
hwnd
,
p_vout
->
p_sys
->
hparent
);
SetWindowPos
(
p_vout
->
p_sys
->
hwnd
,
0
,
0
,
0
,
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
);
}
else
{
/* return to normal window for non embedded vout */
SetWindowPlacement
(
hwnd
,
&
window_placement
);
ShowWindow
(
hwnd
,
SW_SHOWNORMAL
);
}
/* Make sure the mouse cursor is displayed */
EventThreadMouseShow
(
p_vout
->
p_sys
->
p_event
);
}
/* Update the object variable and trigger callback */
var_SetBool
(
p_vout
,
"fullscreen"
,
p_vout
->
b_fullscreen
);
}
#ifndef UNDER_CE
void
DisableScreensaver
(
vout_thread_t
*
p_vout
)
{
/* disable screensaver by temporarily changing system settings */
p_vout
->
p_sys
->
i_spi_lowpowertimeout
=
0
;
p_vout
->
p_sys
->
i_spi_powerofftimeout
=
0
;
p_vout
->
p_sys
->
i_spi_screensavetimeout
=
0
;
if
(
var_GetBool
(
p_vout
,
"disable-screensaver"
)
)
{
msg_Dbg
(
p_vout
,
"disabling screen saver"
);
SystemParametersInfo
(
SPI_GETLOWPOWERTIMEOUT
,
0
,
&
(
p_vout
->
p_sys
->
i_spi_lowpowertimeout
),
0
);
if
(
0
!=
p_vout
->
p_sys
->
i_spi_lowpowertimeout
)
{
SystemParametersInfo
(
SPI_SETLOWPOWERTIMEOUT
,
0
,
NULL
,
0
);
}
SystemParametersInfo
(
SPI_GETPOWEROFFTIMEOUT
,
0
,
&
(
p_vout
->
p_sys
->
i_spi_powerofftimeout
),
0
);
if
(
0
!=
p_vout
->
p_sys
->
i_spi_powerofftimeout
)
{
SystemParametersInfo
(
SPI_SETPOWEROFFTIMEOUT
,
0
,
NULL
,
0
);
}
SystemParametersInfo
(
SPI_GETSCREENSAVETIMEOUT
,
0
,
&
(
p_vout
->
p_sys
->
i_spi_screensavetimeout
),
0
);
if
(
0
!=
p_vout
->
p_sys
->
i_spi_screensavetimeout
)
{
SystemParametersInfo
(
SPI_SETSCREENSAVETIMEOUT
,
0
,
NULL
,
0
);
}
}
}
void
RestoreScreensaver
(
vout_thread_t
*
p_vout
)
{
/* restore screensaver system settings */
if
(
0
!=
p_vout
->
p_sys
->
i_spi_lowpowertimeout
)
{
SystemParametersInfo
(
SPI_SETLOWPOWERTIMEOUT
,
p_vout
->
p_sys
->
i_spi_lowpowertimeout
,
NULL
,
0
);
}
if
(
0
!=
p_vout
->
p_sys
->
i_spi_powerofftimeout
)
{
SystemParametersInfo
(
SPI_SETPOWEROFFTIMEOUT
,
p_vout
->
p_sys
->
i_spi_powerofftimeout
,
NULL
,
0
);
}
if
(
0
!=
p_vout
->
p_sys
->
i_spi_screensavetimeout
)
{
SystemParametersInfo
(
SPI_SETSCREENSAVETIMEOUT
,
p_vout
->
p_sys
->
i_spi_screensavetimeout
,
NULL
,
0
);
}
}
#endif
modules/video_output/msw/events_vo.c
0 → 100644
View file @
d98e43b1
/*****************************************************************************
* events.c: Windows DirectX video output events handler
*****************************************************************************
* Copyright (C) 2001-2009 the VideoLAN team
* $Id$
*
* Authors: Gildas Bazin <gbazin@videolan.org>
*
* 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
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*****************************************************************************/
/*****************************************************************************
* 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 <vlc_common.h>
#include <vlc_playlist.h>
#include <vlc_vout.h>
#include <vlc_vout_window.h>
#include <windows.h>
#include <windowsx.h>
#include <shellapi.h>
#include <ctype.h>
#ifdef MODULE_NAME_IS_directx
#include <ddraw.h>
#endif
#ifdef MODULE_NAME_IS_direct3d
#include <d3d9.h>
#endif
#ifdef MODULE_NAME_IS_glwin32
#include <GL/gl.h>
#endif
#include <vlc_keys.h>
#include "vout.h"
#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*/
/*****************************************************************************
* Local prototypes.
*****************************************************************************/
#define WM_VLC_HIDE_MOUSE (WM_APP + 0)
#define WM_VLC_SHOW_MOUSE (WM_APP + 1)
#define WM_VLC_CHANGE_TEXT (WM_APP + 2)
struct
event_thread_t
{
vout_thread_t
*
p_vout
;
/* */
vlc_thread_t
thread
;
vlc_mutex_t
lock
;
vlc_cond_t
wait
;
bool
b_ready
;
bool
b_done
;
bool
b_error
;
/* */
bool
use_desktop
;
bool
use_overlay
;
/* Mouse */
volatile
bool
b_cursor_hidden
;
volatile
mtime_t
i_lastmoved
;
mtime_t
i_mouse_hide_timeout
;
/* Title */
char
*
psz_title
;
int
i_window_style
;
vout_window_cfg_t
wnd_cfg
;
/* */
unsigned
i_changes
;
/* */
vout_window_t
*
parent_window
;
HWND
hparent
;
HWND
hwnd
;
HWND
hvideownd
;
HWND
hfswnd
;
};
static
int
DirectXCreateWindow
(
event_thread_t
*
);
static
void
DirectXCloseWindow
(
event_thread_t
*
);
static
long
FAR
PASCAL
DirectXEventProc
(
HWND
,
UINT
,
WPARAM
,
LPARAM
);
static
void
DirectXPopupMenu
(
event_thread_t
*
p_event
,
bool
b_open
)
{
var_SetBool
(
p_event
->
p_vout
->
p_libvlc
,
"intf-popupmenu"
,
b_open
);
}
static
int
DirectXConvertKey
(
int
i_key
);
/*****************************************************************************
* EventThread: Create video window & handle its messages
*****************************************************************************
* This function creates a video window and then enters an infinite loop
* that handles the messages sent to that window.
* The main goal of this thread is to isolate the Win32 PeekMessage function
* because this one can block for a long time.
*****************************************************************************/
static
void
*
EventThread
(
void
*
p_this
)
{
event_thread_t
*
p_event
=
(
event_thread_t
*
)
p_this
;
vout_thread_t
*
p_vout
=
p_event
->
p_vout
;
MSG
msg
;
POINT
old_mouse_pos
=
{
0
,
0
},
mouse_pos
;
vlc_value_t
val
;
unsigned
int
i_width
,
i_height
,
i_x
,
i_y
;
HMODULE
hkernel32
;
int
canc
=
vlc_savecancel
();
vlc_mutex_lock
(
&
p_event
->
lock
);
/* Create a window for the video */
/* Creating a window under Windows also initializes the thread's event
* message queue */
if
(
DirectXCreateWindow
(
p_event
)
)
p_event
->
b_error
=
true
;
p_event
->
b_ready
=
true
;
vlc_cond_signal
(
&
p_event
->
wait
);
const
bool
b_error
=
p_event
->
b_error
;
vlc_mutex_unlock
(
&
p_event
->
lock
);
if
(
b_error
)
{
vlc_restorecancel
(
canc
);
return
NULL
;
}
#ifndef UNDER_CE
/* Set power management stuff */
if
(
(
hkernel32
=
GetModuleHandle
(
_T
(
"KERNEL32"
)
)
)
)
{
ULONG
(
WINAPI
*
OurSetThreadExecutionState
)(
ULONG
);
OurSetThreadExecutionState
=
(
ULONG
(
WINAPI
*
)(
ULONG
))
GetProcAddress
(
hkernel32
,
_T
(
"SetThreadExecutionState"
)
);
if
(
OurSetThreadExecutionState
)
/* Prevent monitor from powering off */
OurSetThreadExecutionState
(
ES_DISPLAY_REQUIRED
|
ES_CONTINUOUS
);
else
msg_Dbg
(
p_vout
,
"no support for SetThreadExecutionState()"
);
}
#endif
/* Main loop */
/* GetMessage will sleep if there's no message in the queue */
for
(
;;
)
{
if
(
!
GetMessage
(
&
msg
,
0
,
0
,
0
)
)
{
vlc_mutex_lock
(
&
p_event
->
lock
);
p_event
->
b_done
=
true
;
vlc_mutex_unlock
(
&
p_event
->
lock
);
break
;
}
/* Check if we are asked to exit */
vlc_mutex_lock
(
&
p_event
->
lock
);
const
bool
b_done
=
p_event
->
b_done
;
vlc_mutex_unlock
(
&
p_event
->
lock
);
if
(
b_done
)
break
;
/* */
switch
(
msg
.
message
)
{
case
WM_MOUSEMOVE
:
vlc_mutex_lock
(
&
p_event
->
lock
);
vout_PlacePicture
(
p_event
->
p_vout
,
p_event
->
wnd_cfg
.
width
,
p_event
->
wnd_cfg
.
height
,
&
i_x
,
&
i_y
,
&
i_width
,
&
i_height
);
vlc_mutex_unlock
(
&
p_event
->
lock
);
if
(
msg
.
hwnd
==
p_event
->
hvideownd
)
{
/* Child window */
i_x
=
i_y
=
0
;
}
if
(
i_width
&&
i_height
)
{
val
.
i_int
=
(
GET_X_LPARAM
(
msg
.
lParam
)
-
i_x
)
*
p_event
->
p_vout
->
fmt_in
.
i_visible_width
/
i_width
+
p_event
->
p_vout
->
fmt_in
.
i_x_offset
;
var_Set
(
p_event
->
p_vout
,
"mouse-x"
,
val
);
val
.
i_int
=
(
GET_Y_LPARAM
(
msg
.
lParam
)
-
i_y
)
*
p_event
->
p_vout
->
fmt_in
.
i_visible_height
/
i_height
+
p_event
->
p_vout
->
fmt_in
.
i_y_offset
;
var_Set
(
p_event
->
p_vout
,
"mouse-y"
,
val
);
var_SetBool
(
p_event
->
p_vout
,
"mouse-moved"
,
true
);
}
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
->
i_lastmoved
=
mdate
();
if
(
p_event
->
b_cursor_hidden
)
{
p_event
->
b_cursor_hidden
=
0
;
ShowCursor
(
TRUE
);
}
}
break
;
case
WM_VLC_HIDE_MOUSE
:
if
(
p_event
->
b_cursor_hidden
)
break
;
p_event
->
b_cursor_hidden
=
true
;
GetCursorPos
(
&
old_mouse_pos
);
ShowCursor
(
FALSE
);
break
;
case
WM_VLC_SHOW_MOUSE
:
if
(
!
p_event
->
b_cursor_hidden
)
break
;
p_event
->
b_cursor_hidden
=
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
;
var_Set
(
p_event
->
p_vout
,
"mouse-button-down"
,
val
);
DirectXPopupMenu
(
p_event
,
false
);
break
;
case
WM_LBUTTONUP
:
var_Get
(
p_event
->
p_vout
,
"mouse-button-down"
,
&
val
);
val
.
i_int
&=
~
1
;
var_Set
(
p_event
->
p_vout
,
"mouse-button-down"
,
val
);
var_SetBool
(
p_event
->
p_vout
,
"mouse-clicked"
,
true
);
break
;
case
WM_LBUTTONDBLCLK
:
vlc_mutex_lock
(
&
p_event
->
lock
);
p_event
->
i_changes
|=
VOUT_FULLSCREEN_CHANGE
;
vlc_mutex_unlock
(
&
p_event
->
lock
);
break
;
case
WM_MBUTTONDOWN
:
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
,
false
);
var_ToggleBool
(
p_event
->
p_vout
->
p_libvlc
,
"intf-show"
);
break
;
case
WM_MBUTTONUP
:
var_Get
(
p_event
->
p_vout
,
"mouse-button-down"
,
&
val
);
val
.
i_int
&=
~
2
;
var_Set
(
p_event
->
p_vout
,
"mouse-button-down"
,
val
);
break
;
case
WM_RBUTTONDOWN
:
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
,
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
,
true
);
break
;
case
WM_KEYDOWN
:
case
WM_SYSKEYDOWN
:
/* The key events are first processed here and not translated
* into WM_CHAR events because we need to know the status of the
* modifier keys. */
val
.
i_int
=
DirectXConvertKey
(
msg
.
wParam
);
if
(
!
val
.
i_int
)
{
/* This appears to be a "normal" (ascii) key */
val
.
i_int
=
tolower
(
MapVirtualKey
(
msg
.
wParam
,
2
)
);
}
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_vout
->
p_libvlc
,
"key-pressed"
,
val
);
}
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_vout
->
p_libvlc
,
"key-pressed"
,
val
);
}
break
;
case
WM_VLC_CHANGE_TEXT
:
{
vlc_mutex_lock
(
&
p_event
->
lock
);
wchar_t
*
pwz_title
=
NULL
;
if
(
p_event
->
psz_title
)
{
const
size_t
i_length
=
strlen
(
p_event
->
psz_title
);
pwz_title
=
malloc
(
2
*
(
i_length
+
1
)
);
if
(
pwz_title
)
{
mbstowcs
(
pwz_title
,
p_event
->
psz_title
,
2
*
i_length
);
pwz_title
[
i_length
]
=
0
;
}
}
vlc_mutex_unlock
(
&
p_event
->
lock
);
if
(
pwz_title
)
{
SetWindowText
(
p_event
->
hwnd
,
(
LPCTSTR
)
pwz_title
);
if
(
p_event
->
hfswnd
)
SetWindowText
(
p_event
->
hfswnd
,
(
LPCTSTR
)
pwz_title
);
free
(
pwz_title
);
}
break
;
}
default:
/* Messages we don't handle directly are dispatched to the
* window procedure */
TranslateMessage
(
&
msg
);
DispatchMessage
(
&
msg
);
break
;
}
/* End Switch */
}
/* End Main loop */
/* Check for WM_QUIT if we created the window */
if
(
!
p_event
->
hparent
&&
msg
.
message
==
WM_QUIT
)
{
msg_Warn
(
p_vout
,
"WM_QUIT... should not happen!!"
);
p_event
->
hwnd
=
NULL
;
/* Window already destroyed */
}
msg_Dbg
(
p_vout
,
"DirectXEventThread terminating"
);
DirectXCloseWindow
(
p_event
);
vlc_restorecancel
(
canc
);
return
NULL
;
}
/* following functions are local */
/*****************************************************************************
* DirectXCreateWindow: create a window for the video.
*****************************************************************************
* Before creating a direct draw surface, we need to create a window in which
* the video will be displayed. This window will also allow us to capture the
* events.
*****************************************************************************/
static
int
DirectXCreateWindow
(
event_thread_t
*
p_event
)
{
vout_thread_t
*
p_vout
=
p_event
->
p_vout
;
HINSTANCE
hInstance
;
HMENU
hMenu
;
RECT
rect_window
;
WNDCLASS
wc
;
/* window class components */
HICON
vlc_icon
;
char
vlc_path
[
MAX_PATH
+
1
];
int
i_style
,
i_stylex
;
msg_Dbg
(
p_vout
,
"DirectXCreateWindow"
);
/* Get this module's instance */
hInstance
=
GetModuleHandle
(
NULL
);
#ifdef MODULE_NAME_IS_direct3d
if
(
!
p_event
->
use_desktop
)
{
#endif
/* If an external window was specified, we'll draw in it. */
p_event
->
parent_window
=
vout_window_New
(
VLC_OBJECT
(
p_vout
),
NULL
,
&
p_event
->
wnd_cfg
);
if
(
p_event
->
parent_window
)
p_event
->
hparent
=
p_event
->
parent_window
->
hwnd
;
else
p_event
->
hparent
=
NULL
;
#ifdef MODULE_NAME_IS_direct3d
}
else
{
/* Find Program Manager */
HWND
hwnd
=
FindWindow
(
_T
(
"Progman"
),
NULL
);
if
(
hwnd
)
hwnd
=
FindWindowEx
(
hwnd
,
NULL
,
_T
(
"SHELLDLL_DefView"
),
NULL
);
if
(
hwnd
)
hwnd
=
FindWindowEx
(
hwnd
,
NULL
,
_T
(
"SysListView32"
),
NULL
);
if
(
!
hwnd
)
msg_Err
(
p_vout
,
"Couldn't find desktop icon window. Desktop mode can't be established."
);
p_event
->
hparent
=
hwnd
;
}
#endif
/* Get the Icon from the main app */
vlc_icon
=
NULL
;
#ifndef UNDER_CE
if
(
GetModuleFileName
(
NULL
,
vlc_path
,
MAX_PATH
)
)
{
vlc_icon
=
ExtractIcon
(
hInstance
,
vlc_path
,
0
);
}
#endif
/* Fill in the window class structure */
wc
.
style
=
CS_OWNDC
|
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
=
_T
(
"VLC DirectX"
);
/* use a special class */
/* Register the window class */
if
(
!
RegisterClass
(
&
wc
)
)
{
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
,
_T
(
"VLC DirectX"
),
&
wndclass
)
)
{
msg_Err
(
p_vout
,
"DirectXCreateWindow RegisterClass FAILED (err=%lu)"
,
GetLastError
()
);
return
VLC_EGENERIC
;
}
}
/* Register the video sub-window class */
wc
.
lpszClassName
=
_T
(
"VLC DirectX video"
);
wc
.
hIcon
=
0
;
wc
.
hbrBackground
=
NULL
;
/* no background color */
if
(
!
RegisterClass
(
&
wc
)
)
{
WNDCLASS
wndclass
;
/* Check why it failed. If it's because one already exists
* then fine, otherwise return with an error. */
if
(
!
GetClassInfo
(
hInstance
,
_T
(
"VLC DirectX video"
),
&
wndclass
)
)
{
msg_Err
(
p_vout
,
"DirectXCreateWindow RegisterClass FAILED (err=%lu)"
,
GetLastError
()
);
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_event
->
wnd_cfg
.
width
;
rect_window
.
bottom
=
rect_window
.
top
+
p_event
->
wnd_cfg
.
height
;
if
(
var_GetBool
(
p_vout
,
"video-deco"
)
)
{
/* Open with window decoration */
AdjustWindowRect
(
&
rect_window
,
WS_OVERLAPPEDWINDOW
|
WS_SIZEBOX
,
0
);
i_style
=
WS_OVERLAPPEDWINDOW
|
WS_SIZEBOX
|
WS_VISIBLE
|
WS_CLIPCHILDREN
;
i_stylex
=
0
;
}
else
{
/* No window decoration */
AdjustWindowRect
(
&
rect_window
,
WS_POPUP
,
0
);
i_style
=
WS_POPUP
|
WS_VISIBLE
|
WS_CLIPCHILDREN
;
i_stylex
=
0
;
// WS_EX_TOOLWINDOW; Is TOOLWINDOW really needed ?
// It messes up the fullscreen window.
}
if
(
p_event
->
hparent
)
{
i_style
=
WS_VISIBLE
|
WS_CLIPCHILDREN
|
WS_CHILD
;
i_stylex
=
0
;
}
p_event
->
i_window_style
=
i_style
;
/* Create the window */
p_event
->
hwnd
=
CreateWindowEx
(
WS_EX_NOPARENTNOTIFY
|
i_stylex
,
_T
(
"VLC DirectX"
),
/* name of window class */
_T
(
VOUT_TITLE
)
_T
(
" (DirectX Output)"
),
/* window title */
i_style
,
/* window style */
(
p_event
->
wnd_cfg
.
x
<
0
)
?
CW_USEDEFAULT
:
(
UINT
)
p_event
->
wnd_cfg
.
x
,
/* default X coordinate */
(
p_event
->
wnd_cfg
.
y
<
0
)
?
CW_USEDEFAULT
:
(
UINT
)
p_event
->
wnd_cfg
.
y
,
/* default Y coordinate */
rect_window
.
right
-
rect_window
.
left
,
/* window width */
rect_window
.
bottom
-
rect_window
.
top
,
/* window height */
p_event
->
hparent
,
/* parent window */
NULL
,
/* no menu in this window */
hInstance
,
/* handle of this program instance */
(
LPVOID
)
p_event
);
/* send p_vout to WM_CREATE */
if
(
!
p_event
->
hwnd
)
{
msg_Warn
(
p_vout
,
"DirectXCreateWindow create window FAILED (err=%lu)"
,
GetLastError
()
);
return
VLC_EGENERIC
;
}
if
(
p_event
->
hparent
)
{
LONG
i_style
;
/* We don't want the window owner to overwrite our client area */
i_style
=
GetWindowLong
(
p_event
->
hparent
,
GWL_STYLE
);
if
(
!
(
i_style
&
WS_CLIPCHILDREN
)
)
/* Hmmm, apparently this is a blocking call... */
SetWindowLong
(
p_event
->
hparent
,
GWL_STYLE
,
i_style
|
WS_CLIPCHILDREN
);
/* Create our fullscreen window */
p_event
->
hfswnd
=
CreateWindowEx
(
WS_EX_APPWINDOW
,
_T
(
"VLC DirectX"
),
_T
(
VOUT_TITLE
)
_T
(
" (DirectX Output)"
),
WS_OVERLAPPEDWINDOW
|
WS_CLIPCHILDREN
|
WS_SIZEBOX
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
NULL
,
NULL
,
hInstance
,
NULL
);
}
else
{
p_event
->
hfswnd
=
NULL
;
}
/* Append a "Always On Top" entry in the system menu */
hMenu
=
GetSystemMenu
(
p_event
->
hwnd
,
FALSE
);
AppendMenu
(
hMenu
,
MF_SEPARATOR
,
0
,
_T
(
""
)
);
AppendMenu
(
hMenu
,
MF_STRING
|
MF_UNCHECKED
,
IDM_TOGGLE_ON_TOP
,
_T
(
"Always on &Top"
)
);
/* Create video sub-window. This sub window will always exactly match
* the size of the video, which allows us to use crazy overlay colorkeys
* without having them shown outside of the video area. */
p_event
->
hvideownd
=
CreateWindow
(
_T
(
"VLC DirectX video"
),
_T
(
""
),
/* window class */
WS_CHILD
,
/* window style, not visible initially */
0
,
0
,
p_vout
->
render
.
i_width
,
/* default width */
p_vout
->
render
.
i_height
,
/* default height */
p_event
->
hwnd
,
/* parent window */
NULL
,
hInstance
,
(
LPVOID
)
p_event
);
/* send p_vout to WM_CREATE */
if
(
!
p_event
->
hvideownd
)
msg_Warn
(
p_vout
,
"can't create video sub-window"
);
else
msg_Dbg
(
p_vout
,
"created video sub-window"
);
/* Now display the window */
ShowWindow
(
p_event
->
hwnd
,
SW_SHOW
);
return
VLC_SUCCESS
;
}
/*****************************************************************************
* DirectXCloseWindow: close the window created by DirectXCreateWindow
*****************************************************************************
* This function returns all resources allocated by DirectXCreateWindow.
*****************************************************************************/
static
void
DirectXCloseWindow
(
event_thread_t
*
p_event
)
{
vout_thread_t
*
p_vout
=
p_event
->
p_vout
;
msg_Dbg
(
p_vout
,
"DirectXCloseWindow"
);
DestroyWindow
(
p_event
->
hwnd
);
if
(
p_event
->
hfswnd
)
DestroyWindow
(
p_event
->
hfswnd
);
#ifdef MODULE_NAME_IS_direct3d
if
(
!
p_event
->
use_desktop
)
#endif
vout_window_Delete
(
p_event
->
parent_window
);
p_event
->
hwnd
=
NULL
;
/* We don't unregister the Window Class because it could lead to race
* conditions and it will be done anyway by the system when the app will
* exit */
}
/*****************************************************************************
* DirectXEventProc: This is the window event processing function.
*****************************************************************************
* On Windows, when you create a window you have to attach an event processing
* function to it. The aim of this function is to manage "Queued Messages" and
* "Nonqueued Messages".
* Queued Messages are those picked up and retransmitted by vout_Manage
* (using the GetMessage and DispatchMessage functions).
* Nonqueued Messages are those that Windows will send directly to this
* procedure (like WM_DESTROY, WM_WINDOWPOSCHANGED...)
*****************************************************************************/
static
long
FAR
PASCAL
DirectXEventProc
(
HWND
hwnd
,
UINT
message
,
WPARAM
wParam
,
LPARAM
lParam
)
{
event_thread_t
*
p_event
;
if
(
message
==
WM_CREATE
)
{
/* Store p_vout for future use */
p_event
=
(
event_thread_t
*
)((
CREATESTRUCT
*
)
lParam
)
->
lpCreateParams
;
SetWindowLongPtr
(
hwnd
,
GWLP_USERDATA
,
(
LONG_PTR
)
p_event
);
return
TRUE
;
}
else
{
LONG_PTR
p_user_data
=
GetWindowLongPtr
(
hwnd
,
GWLP_USERDATA
);
p_event
=
(
event_thread_t
*
)
p_user_data
;
if
(
!
p_event
)
{
/* Hmmm mozilla does manage somehow to save the pointer to our
* windowproc and still calls it after the vout has been closed. */
return
DefWindowProc
(
hwnd
,
message
,
wParam
,
lParam
);
}
}
vout_thread_t
*
p_vout
=
p_event
->
p_vout
;
#ifndef UNDER_CE
/* Catch the screensaver and the monitor turn-off */
if
(
message
==
WM_SYSCOMMAND
&&
(
(
wParam
&
0xFFF0
)
==
SC_SCREENSAVE
||
(
wParam
&
0xFFF0
)
==
SC_MONITORPOWER
)
)
{
//if( p_vout ) msg_Dbg( p_vout, "WinProc WM_SYSCOMMAND screensaver" );
return
0
;
/* this stops them from happening */
}
#endif
if
(
hwnd
==
p_event
->
hvideownd
)
{
#ifdef MODULE_NAME_IS_directx
vlc_mutex_lock
(
&
p_event
->
lock
);
const
bool
use_overlay
=
p_event
->
use_overlay
;
vlc_mutex_unlock
(
&
p_event
->
lock
);
#endif
switch
(
message
)
{
#ifdef MODULE_NAME_IS_directx
case
WM_ERASEBKGND
:
/* For overlay, we need to erase background */
return
!
use_overlay
?
1
:
DefWindowProc
(
hwnd
,
message
,
wParam
,
lParam
);
case
WM_PAINT
:
/*
** For overlay, DefWindowProc() will erase dirty regions
** with colorkey.
** For non-overlay, vout will paint the whole window at
** regular interval, therefore dirty regions can be ignored
** to minimize repaint.
*/
if
(
!
use_overlay
)
{
ValidateRect
(
hwnd
,
NULL
);
}
// fall through to default
#else
/*
** For OpenGL and Direct3D, vout will update the whole
** window at regular interval, therefore dirty region
** can be ignored to minimize repaint.
*/
case
WM_ERASEBKGND
:
/* nothing to erase */
return
1
;
case
WM_PAINT
:
/* nothing to repaint */
ValidateRect
(
hwnd
,
NULL
);
// fall through
#endif
default:
return
DefWindowProc
(
hwnd
,
message
,
wParam
,
lParam
);
}
}
switch
(
message
)
{
case
WM_WINDOWPOSCHANGED
:
UpdateRects
(
p_vout
,
true
);
return
0
;
/* the user wants to close the window */
case
WM_CLOSE
:
{
playlist_t
*
p_playlist
=
pl_Hold
(
p_vout
);
if
(
p_playlist
)
{
playlist_Stop
(
p_playlist
);
pl_Release
(
p_vout
);
}
return
0
;
}
/* the window has been closed so shut down everything now */
case
WM_DESTROY
:
msg_Dbg
(
p_vout
,
"WinProc WM_DESTROY"
);
/* just destroy the window */
PostQuitMessage
(
0
);
return
0
;
case
WM_SYSCOMMAND
:
switch
(
wParam
)
{
case
IDM_TOGGLE_ON_TOP
:
/* toggle the "on top" status */
{
msg_Dbg
(
p_vout
,
"WinProc WM_SYSCOMMAND: IDM_TOGGLE_ON_TOP"
);
/* Change the current value */
var_ToggleBool
(
p_vout
,
"video-on-top"
);
return
0
;
}
}
break
;
case
WM_PAINT
:
case
WM_NCPAINT
:
case
WM_ERASEBKGND
:
return
DefWindowProc
(
hwnd
,
message
,
wParam
,
lParam
);
case
WM_KILLFOCUS
:
#ifdef MODULE_NAME_IS_wingapi
GXSuspend
();
#endif
#ifdef UNDER_CE
if
(
hwnd
==
p_event
->
hfswnd
)
{
HWND
htbar
=
FindWindow
(
_T
(
"HHTaskbar"
),
NULL
);
ShowWindow
(
htbar
,
SW_SHOW
);
}
if
(
!
p_event
->
hparent
||
hwnd
==
p_event
->
hfswnd
)
{
SHFullScreen
(
hwnd
,
SHFS_SHOWSIPBUTTON
);
}
#endif
return
0
;
case
WM_SETFOCUS
:
#ifdef MODULE_NAME_IS_wingapi
GXResume
();
#endif
#ifdef UNDER_CE
if
(
p_event
->
hparent
&&
hwnd
!=
p_event
->
hfswnd
&&
p_vout
->
b_fullscreen
)
{
vlc_mutex_lock
(
&
p_event
->
lock
);
p_event
->
i_changes
|=
VOUT_FULLSCREEN_CHANGE
;
vlc_mutex_unlock
(
&
p_event
->
lock
);
}
if
(
hwnd
==
p_event
->
hfswnd
)
{
HWND
htbar
=
FindWindow
(
_T
(
"HHTaskbar"
),
NULL
);
ShowWindow
(
htbar
,
SW_HIDE
);
}
if
(
!
p_event
->
hparent
||
hwnd
==
p_event
->
hfswnd
)
{
SHFullScreen
(
hwnd
,
SHFS_HIDESIPBUTTON
);
}
#endif
return
0
;
default:
//msg_Dbg( p_vout, "WinProc WM Default %i", message );
break
;
}
/* Let windows handle the message */
return
DefWindowProc
(
hwnd
,
message
,
wParam
,
lParam
);
}
static
struct
{
int
i_dxkey
;
int
i_vlckey
;
}
dxkeys_to_vlckeys
[]
=
{
{
VK_F1
,
KEY_F1
},
{
VK_F2
,
KEY_F2
},
{
VK_F3
,
KEY_F3
},
{
VK_F4
,
KEY_F4
},
{
VK_F5
,
KEY_F5
},
{
VK_F6
,
KEY_F6
},
{
VK_F7
,
KEY_F7
},
{
VK_F8
,
KEY_F8
},
{
VK_F9
,
KEY_F9
},
{
VK_F10
,
KEY_F10
},
{
VK_F11
,
KEY_F11
},
{
VK_F12
,
KEY_F12
},
{
VK_RETURN
,
KEY_ENTER
},
{
VK_SPACE
,
' '
},
{
VK_ESCAPE
,
KEY_ESC
},
{
VK_LEFT
,
KEY_LEFT
},
{
VK_RIGHT
,
KEY_RIGHT
},
{
VK_UP
,
KEY_UP
},
{
VK_DOWN
,
KEY_DOWN
},
{
VK_HOME
,
KEY_HOME
},
{
VK_END
,
KEY_END
},
{
VK_PRIOR
,
KEY_PAGEUP
},
{
VK_NEXT
,
KEY_PAGEDOWN
},
{
VK_INSERT
,
KEY_INSERT
},
{
VK_DELETE
,
KEY_DELETE
},
{
VK_CONTROL
,
0
},
{
VK_SHIFT
,
0
},
{
VK_MENU
,
0
},
{
VK_BROWSER_BACK
,
KEY_BROWSER_BACK
},
{
VK_BROWSER_FORWARD
,
KEY_BROWSER_FORWARD
},
{
VK_BROWSER_REFRESH
,
KEY_BROWSER_REFRESH
},
{
VK_BROWSER_STOP
,
KEY_BROWSER_STOP
},
{
VK_BROWSER_SEARCH
,
KEY_BROWSER_SEARCH
},
{
VK_BROWSER_FAVORITES
,
KEY_BROWSER_FAVORITES
},
{
VK_BROWSER_HOME
,
KEY_BROWSER_HOME
},
{
VK_VOLUME_MUTE
,
KEY_VOLUME_MUTE
},
{
VK_VOLUME_DOWN
,
KEY_VOLUME_DOWN
},
{
VK_VOLUME_UP
,
KEY_VOLUME_UP
},
{
VK_MEDIA_NEXT_TRACK
,
KEY_MEDIA_NEXT_TRACK
},
{
VK_MEDIA_PREV_TRACK
,
KEY_MEDIA_PREV_TRACK
},
{
VK_MEDIA_STOP
,
KEY_MEDIA_STOP
},
{
VK_MEDIA_PLAY_PAUSE
,
KEY_MEDIA_PLAY_PAUSE
},
{
0
,
0
}
};
static
int
DirectXConvertKey
(
int
i_key
)
{
int
i
;
for
(
i
=
0
;
dxkeys_to_vlckeys
[
i
].
i_dxkey
!=
0
;
i
++
)
{
if
(
dxkeys_to_vlckeys
[
i
].
i_dxkey
==
i_key
)
{
return
dxkeys_to_vlckeys
[
i
].
i_vlckey
;
}
}
return
0
;
}
void
EventThreadMouseAutoHide
(
event_thread_t
*
p_event
)
{
vout_thread_t
*
p_vout
=
p_event
->
p_vout
;
if
(
p_vout
->
b_fullscreen
&&
!
p_event
->
b_cursor_hidden
&&
(
mdate
()
-
p_event
->
i_lastmoved
)
>
p_event
->
i_mouse_hide_timeout
)
{
/* Hide the cursor only if it is inside our window */
POINT
point
;
GetCursorPos
(
&
point
);
HWND
hwnd
=
WindowFromPoint
(
point
);
if
(
hwnd
==
p_event
->
hwnd
||
hwnd
==
p_event
->
hvideownd
)
{
PostMessage
(
p_event
->
hwnd
,
WM_VLC_HIDE_MOUSE
,
0
,
0
);
}
else
{
p_event
->
i_lastmoved
=
mdate
();
}
}
}
void
EventThreadMouseShow
(
event_thread_t
*
p_event
)
{
PostMessage
(
p_event
->
hwnd
,
WM_VLC_SHOW_MOUSE
,
0
,
0
);
}
void
EventThreadUpdateTitle
(
event_thread_t
*
p_event
,
const
char
*
psz_fallback
)
{
char
*
psz_title
=
var_GetNonEmptyString
(
p_event
->
p_vout
,
"video-title"
);
if
(
!
psz_title
)
psz_title
=
strdup
(
psz_fallback
);
if
(
!
psz_title
)
return
;
vlc_mutex_lock
(
&
p_event
->
lock
);
free
(
p_event
->
psz_title
);
p_event
->
psz_title
=
psz_title
;
vlc_mutex_unlock
(
&
p_event
->
lock
);
PostMessage
(
p_event
->
hwnd
,
WM_VLC_CHANGE_TEXT
,
0
,
0
);
}
unsigned
EventThreadRetreiveChanges
(
event_thread_t
*
p_event
)
{
vlc_mutex_lock
(
&
p_event
->
lock
);
unsigned
i_changes
=
p_event
->
i_changes
;
p_event
->
i_changes
=
0
;
vlc_mutex_unlock
(
&
p_event
->
lock
);
return
i_changes
;
}
int
EventThreadGetWindowStyle
(
event_thread_t
*
p_event
)
{
/* No need to lock, it is serialized by EventThreadStart */
return
p_event
->
i_window_style
;
}
void
EventThreadUpdateWindowPosition
(
event_thread_t
*
p_event
,
bool
*
pb_changed
,
int
x
,
int
y
,
int
w
,
int
h
)
{
vlc_mutex_lock
(
&
p_event
->
lock
);
*
pb_changed
=
x
!=
p_event
->
wnd_cfg
.
x
||
y
!=
p_event
->
wnd_cfg
.
y
||
w
!=
p_event
->
wnd_cfg
.
width
||
h
!=
p_event
->
wnd_cfg
.
height
;
p_event
->
wnd_cfg
.
x
=
x
;
p_event
->
wnd_cfg
.
y
=
y
;
p_event
->
wnd_cfg
.
width
=
w
;
p_event
->
wnd_cfg
.
height
=
h
;
vlc_mutex_unlock
(
&
p_event
->
lock
);
}
void
EventThreadUseOverlay
(
event_thread_t
*
p_event
,
bool
b_used
)
{
vlc_mutex_lock
(
&
p_event
->
lock
);
p_event
->
use_overlay
=
b_used
;
vlc_mutex_unlock
(
&
p_event
->
lock
);
}
event_thread_t
*
EventThreadCreate
(
vout_thread_t
*
p_vout
,
const
vout_window_cfg_t
*
p_wnd_cfg
)
{
/* Create the Vout EventThread, this thread is created by us to isolate
* the Win32 PeekMessage function calls. We want to do this because
* Windows can stay blocked inside this call for a long time, and when
* this happens it thus blocks vlc's video_output thread.
* Vout EventThread will take care of the creation of the video
* window (because PeekMessage has to be called from the same thread which
* created the window). */
msg_Dbg
(
p_vout
,
"creating Vout EventThread"
);
event_thread_t
*
p_event
=
malloc
(
sizeof
(
*
p_event
)
);
if
(
!
p_event
)
return
NULL
;
p_event
->
p_vout
=
p_vout
;
vlc_mutex_init
(
&
p_event
->
lock
);
vlc_cond_init
(
&
p_event
->
wait
);
p_event
->
b_cursor_hidden
=
false
;
p_event
->
i_lastmoved
=
mdate
();
p_event
->
i_mouse_hide_timeout
=
var_GetInteger
(
p_vout
,
"mouse-hide-timeout"
)
*
1000
;
p_event
->
psz_title
=
NULL
;
p_event
->
wnd_cfg
=
*
p_wnd_cfg
;
return
p_event
;
}
void
EventThreadDestroy
(
event_thread_t
*
p_event
)
{
free
(
p_event
->
psz_title
);
vlc_cond_destroy
(
&
p_event
->
wait
);
vlc_mutex_destroy
(
&
p_event
->
lock
);
free
(
p_event
);
}
int
EventThreadStart
(
event_thread_t
*
p_event
,
event_hwnd_t
*
p_hwnd
,
const
event_cfg_t
*
p_cfg
)
{
p_event
->
use_desktop
=
p_cfg
->
use_desktop
;
p_event
->
use_overlay
=
p_cfg
->
use_overlay
;
p_event
->
i_changes
=
0
;
p_event
->
b_ready
=
false
;
p_event
->
b_done
=
false
;
p_event
->
b_error
=
false
;
if
(
vlc_clone
(
&
p_event
->
thread
,
EventThread
,
p_event
,
VLC_THREAD_PRIORITY_LOW
)
)
{
msg_Err
(
p_event
->
p_vout
,
"cannot create Vout EventThread"
);
return
VLC_EGENERIC
;
}
vlc_mutex_lock
(
&
p_event
->
lock
);
while
(
!
p_event
->
b_ready
)
vlc_cond_wait
(
&
p_event
->
wait
,
&
p_event
->
lock
);
const
bool
b_error
=
p_event
->
b_error
;
vlc_mutex_unlock
(
&
p_event
->
lock
);
if
(
b_error
)
{
vlc_join
(
p_event
->
thread
,
NULL
);
p_event
->
b_ready
=
false
;
return
VLC_EGENERIC
;
}
msg_Dbg
(
p_event
->
p_vout
,
"Vout EventThread running"
);
if
(
!
p_event
->
use_desktop
)
p_hwnd
->
parent_window
=
p_event
->
parent_window
;
else
p_hwnd
->
parent_window
=
NULL
;
p_hwnd
->
hparent
=
p_event
->
hparent
;
p_hwnd
->
hwnd
=
p_event
->
hwnd
;
p_hwnd
->
hvideownd
=
p_event
->
hvideownd
;
p_hwnd
->
hfswnd
=
p_event
->
hfswnd
;
return
VLC_SUCCESS
;
}
void
EventThreadStop
(
event_thread_t
*
p_event
)
{
if
(
!
p_event
->
b_ready
)
return
;
vlc_mutex_lock
(
&
p_event
->
lock
);
p_event
->
b_done
=
true
;
vlc_mutex_unlock
(
&
p_event
->
lock
);
/* we need to be sure Vout EventThread won't stay stuck in
* GetMessage, so we send a fake message */
if
(
p_event
->
hwnd
)
PostMessage
(
p_event
->
hwnd
,
WM_NULL
,
0
,
0
);
vlc_join
(
p_event
->
thread
,
NULL
);
p_event
->
b_ready
=
false
;
}
modules/video_output/msw/events_vo.h
0 → 100644
View file @
d98e43b1
/*****************************************************************************
* event.h: Windows video output header file
*****************************************************************************
* Copyright (C) 2001-2009 the VideoLAN team
* $Id$
*
* Authors: Gildas Bazin <gbazin@videolan.org>
* Damien Fouilleul <damienf@videolan.org>
*
* 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
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 <vlc_vout_window.h>
/**
* HWNDs manager.
*/
typedef
struct
event_thread_t
event_thread_t
;
typedef
struct
{
bool
use_desktop
;
/* direct3d */
bool
use_overlay
;
/* directx */
}
event_cfg_t
;
typedef
struct
{
vout_window_t
*
parent_window
;
HWND
hparent
;
HWND
hwnd
;
HWND
hvideownd
;
HWND
hfswnd
;
}
event_hwnd_t
;
event_thread_t
*
EventThreadCreate
(
vout_thread_t
*
,
const
vout_window_cfg_t
*
);
void
EventThreadDestroy
(
event_thread_t
*
);
int
EventThreadStart
(
event_thread_t
*
,
event_hwnd_t
*
,
const
event_cfg_t
*
);
void
EventThreadStop
(
event_thread_t
*
);
void
EventThreadMouseAutoHide
(
event_thread_t
*
);
void
EventThreadMouseShow
(
event_thread_t
*
);
void
EventThreadUpdateTitle
(
event_thread_t
*
,
const
char
*
psz_fallback
);
unsigned
EventThreadRetreiveChanges
(
event_thread_t
*
);
int
EventThreadGetWindowStyle
(
event_thread_t
*
);
void
EventThreadUpdateWindowPosition
(
event_thread_t
*
,
bool
*
pb_changed
,
int
x
,
int
y
,
int
w
,
int
h
);
void
EventThreadUseOverlay
(
event_thread_t
*
,
bool
b_used
);
modules/video_output/msw/vout.h
0 → 100644
View file @
d98e43b1
/*****************************************************************************
* vout.h: Windows video output header file
*****************************************************************************
* Copyright (C) 2001-2009 the VideoLAN team
* $Id$
*
* Authors: Gildas Bazin <gbazin@videolan.org>
* Damien Fouilleul <damienf@videolan.org>
*
* 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
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.
*****************************************************************************/
/*****************************************************************************
* event_thread_t: event thread
*****************************************************************************/
#include "events_vo.h"
#ifdef MODULE_NAME_IS_wingapi
typedef
struct
GXDisplayProperties
{
DWORD
cxWidth
;
DWORD
cyHeight
;
long
cbxPitch
;
long
cbyPitch
;
long
cBPP
;
DWORD
ffFormat
;
}
GXDisplayProperties
;
typedef
struct
GXScreenRect
{
DWORD
dwTop
;
DWORD
dwLeft
;
DWORD
dwWidth
;
DWORD
dwHeight
;
}
GXScreenRect
;
# define GX_FULLSCREEN 0x01
# define GX_NORMALKEYS 0x02
# define GX_LANDSCAPEKEYS 0x03
# ifndef kfLandscape
# define kfLandscape 0x8
# define kfPalette 0x10
# define kfDirect 0x20
# define kfDirect555 0x40
# define kfDirect565 0x80
# define kfDirect888 0x100
# define kfDirect444 0x200
# define kfDirectInverted 0x400
# endif
#endif
struct
vout_window_t
;
/*****************************************************************************
* vout_sys_t: video output method descriptor
*****************************************************************************
* This structure is part of the video output thread descriptor.
* It describes the module specific properties of an output thread.
*****************************************************************************/
struct
vout_sys_t
{
HWND
hwnd
;
/* Handle of the main window */
HWND
hvideownd
;
/* Handle of the video sub-window */
struct
vout_window_t
*
parent_window
;
/* Parent window VLC object */
HWND
hparent
;
/* Handle of the parent window */
HWND
hfswnd
;
/* Handle of the fullscreen window */
/* Multi-monitor support */
HMONITOR
hmonitor
;
/* handle of the current monitor */
GUID
*
p_display_driver
;
HMONITOR
(
WINAPI
*
MonitorFromWindow
)(
HWND
,
DWORD
);
BOOL
(
WINAPI
*
GetMonitorInfo
)(
HMONITOR
,
LPMONITORINFO
);
/* size of the display */
RECT
rect_display
;
int
i_display_depth
;
/* size of the overall window (including black bands) */
RECT
rect_parent
;
volatile
uint16_t
i_changes
;
/* changes made to the video display */
/* Misc */
bool
b_on_top_change
;
#ifndef UNDER_CE
/* screensaver system settings to be restored when vout is closed */
UINT
i_spi_lowpowertimeout
;
UINT
i_spi_powerofftimeout
;
UINT
i_spi_screensavetimeout
;
#endif
/* Coordinates of src and dest images (used when blitting to display) */
RECT
rect_src
;
RECT
rect_src_clipped
;
RECT
rect_dest
;
RECT
rect_dest_clipped
;
bool
b_hw_yuv
;
/* Should we use hardware YUV->RGB conversions */
#ifdef MODULE_NAME_IS_directx
/* Overlay alignment restrictions */
int
i_align_src_boundary
;
int
i_align_src_size
;
int
i_align_dest_boundary
;
int
i_align_dest_size
;
bool
b_wallpaper
;
/* show as desktop wallpaper ? */
bool
b_using_overlay
;
/* Are we using an overlay surface */
bool
b_use_sysmem
;
/* Should we use system memory for surfaces */
bool
b_3buf_overlay
;
/* Should we use triple buffered overlays */
/* DDraw capabilities */
int
b_caps_overlay_clipping
;
unsigned
int
i_rgb_colorkey
;
/* colorkey in RGB used by the overlay */
unsigned
int
i_colorkey
;
/* colorkey used by the overlay */
COLORREF
color_bkg
;
COLORREF
color_bkgtxt
;
LPDIRECTDRAW2
p_ddobject
;
/* DirectDraw object */
LPDIRECTDRAWSURFACE2
p_display
;
/* Display device */
LPDIRECTDRAWSURFACE2
p_current_surface
;
/* surface currently displayed */
LPDIRECTDRAWCLIPPER
p_clipper
;
/* clipper used for blitting */
HINSTANCE
hddraw_dll
;
/* handle of the opened ddraw dll */
vlc_mutex_t
lock
;
#endif
#ifdef MODULE_NAME_IS_glwin32
HDC
hGLDC
;
HGLRC
hGLRC
;
#endif
#ifdef MODULE_NAME_IS_direct3d
/* show video on desktop window ? */
bool
b_desktop
;
// core objects
HINSTANCE
hd3d9_dll
;
/* handle of the opened d3d9 dll */
LPDIRECT3D9
p_d3dobj
;
LPDIRECT3DDEVICE9
p_d3ddev
;
D3DPRESENT_PARAMETERS
d3dpp
;
// scene objects
LPDIRECT3DTEXTURE9
p_d3dtex
;
LPDIRECT3DVERTEXBUFFER9
p_d3dvtc
;
#endif
#ifdef MODULE_NAME_IS_wingdi
int
i_depth
;
/* Our offscreen bitmap and its framebuffer */
HDC
off_dc
;
HBITMAP
off_bitmap
;
uint8_t
*
p_pic_buffer
;
int
i_pic_pitch
;
int
i_pic_pixel_pitch
;
BITMAPINFO
bitmapinfo
;
RGBQUAD
red
;
RGBQUAD
green
;
RGBQUAD
blue
;
#endif
#ifdef MODULE_NAME_IS_wingapi
int
i_depth
;
int
render_width
;
int
render_height
;
/* Our offscreen bitmap and its framebuffer */
HDC
off_dc
;
HBITMAP
off_bitmap
;
uint8_t
*
p_pic_buffer
;
int
i_pic_pitch
;
int
i_pic_pixel_pitch
;
BITMAPINFO
bitmapinfo
;
RGBQUAD
red
;
RGBQUAD
green
;
RGBQUAD
blue
;
HINSTANCE
gapi_dll
;
/* handle of the opened gapi dll */
/* GAPI functions */
int
(
*
GXOpenDisplay
)(
HWND
hWnd
,
DWORD
dwFlags
);
int
(
*
GXCloseDisplay
)();
void
*
(
*
GXBeginDraw
)();
int
(
*
GXEndDraw
)();
GXDisplayProperties
(
*
GXGetDisplayProperties
)();
int
(
*
GXSuspend
)();
int
(
*
GXResume
)();
#endif
event_thread_t
*
p_event
;
};
#ifdef MODULE_NAME_IS_wingapi
# define GXOpenDisplay p_vout->p_sys->GXOpenDisplay
# define GXCloseDisplay p_vout->p_sys->GXCloseDisplay
# define GXBeginDraw p_vout->p_sys->GXBeginDraw
# define GXEndDraw p_vout->p_sys->GXEndDraw
# define GXGetDisplayProperties p_vout->p_sys->GXGetDisplayProperties
# define GXSuspend p_vout->p_sys->GXSuspend
# define GXResume p_vout->p_sys->GXResume
#endif
/*****************************************************************************
* Prototypes from directx.c
*****************************************************************************/
int
DirectDrawUpdateOverlay
(
vout_thread_t
*
p_vout
);
/*****************************************************************************
* Prototypes from common.c
*****************************************************************************/
int
CommonInit
(
vout_thread_t
*
);
void
CommonClean
(
vout_thread_t
*
);
void
CommonManage
(
vout_thread_t
*
);
int
Control
(
vout_thread_t
*
p_vout
,
int
i_query
,
va_list
args
);
void
UpdateRects
(
vout_thread_t
*
p_vout
,
bool
b_force
);
void
Win32ToggleFullscreen
(
vout_thread_t
*
p_vout
);
void
ExitFullscreen
(
vout_thread_t
*
p_vout
);
#ifndef UNDER_CE
void
DisableScreensaver
(
vout_thread_t
*
p_vout
);
void
RestoreScreensaver
(
vout_thread_t
*
p_vout
);
#endif
/*****************************************************************************
* Constants
*****************************************************************************/
#define IDM_TOGGLE_ON_TOP WM_USER + 1
#define DX_POSITION_CHANGE 0x1000
#define DX_WALLPAPER_CHANGE 0x2000
#define DX_DESKTOP_CHANGE 0x4000
/*****************************************************************************
* WinCE helpers
*****************************************************************************/
#ifdef UNDER_CE
#define AdjustWindowRect(a,b,c) AdjustWindowRectEx(a,b,c,0)
#ifndef GCL_HBRBACKGROUND
# define GCL_HBRBACKGROUND (-10)
#endif
//#define FindWindowEx(a,b,c,d) 0
#define GetWindowPlacement(a,b)
#define SetWindowPlacement(a,b)
/*typedef struct _WINDOWPLACEMENT {
UINT length;
UINT flags;
UINT showCmd;
POINT ptMinPosition;
POINT ptMaxPosition;
RECT rcNormalPosition;
} WINDOWPLACEMENT;*/
#ifndef WM_NCMOUSEMOVE
# define WM_NCMOUSEMOVE 160
#endif
#ifndef CS_OWNDC
# define CS_OWNDC 32
#endif
#ifndef SC_SCREENSAVE
# define SC_SCREENSAVE 0xF140
#endif
#ifndef SC_MONITORPOWER
# define SC_MONITORPOWER 0xF170
#endif
#ifndef WM_NCPAINT
# define WM_NCPAINT 133
#endif
#ifndef WS_OVERLAPPEDWINDOW
# define WS_OVERLAPPEDWINDOW 0xcf0000
#endif
#ifndef WS_EX_NOPARENTNOTIFY
# define WS_EX_NOPARENTNOTIFY 4
#endif
#ifndef WS_EX_APPWINDOW
#define WS_EX_APPWINDOW 0x40000
#endif
//#define SetWindowLongPtr SetWindowLong
//#define GetWindowLongPtr GetWindowLong
//#define GWLP_USERDATA GWL_USERDATA
#endif //UNDER_CE
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment