Commit 4bd67b7a authored by Laurent Aimar's avatar Laurent Aimar

Revert "Revert "Removed old msw files.""

This reverts commit d98e43b1.

Sorry for the mess, missed it in the git rebase.
parent b78fa593
/*****************************************************************************
* 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
/*****************************************************************************
* 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;
}
/*****************************************************************************
* 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 );
/*****************************************************************************
* 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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment