Commit 6034b5c5 authored by Laurent Aimar's avatar Laurent Aimar

Fixed invalid mouse cursor state on win32 (close #3675).

As a side effect, window class names are now uniques (process wide)
allowing to unregister them and so to unload properly the msw vouts.
parent 5422c4fa
......@@ -84,9 +84,6 @@ int CommonInit(vout_display_t *vd)
var_Create(vd, "video-title", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
var_Create(vd, "video-deco", VLC_VAR_BOOL | VLC_VAR_DOINHERIT);
/* FIXME remove mouse hide from msw */
var_Create(vd, "mouse-hide-timeout", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
/* */
sys->event = EventThreadCreate(vd);
if (!sys->event)
......@@ -191,9 +188,6 @@ void CommonManage(vout_display_t *vd)
/* HasMoved means here resize or move */
if (EventThreadGetAndResetHasMoved(sys->event))
UpdateRects(vd, NULL, NULL, false);
/* Pointer change */
EventThreadMouseAutoHide(sys->event);
}
/**
......@@ -551,9 +545,6 @@ static int CommonControlSetFullscreen(vout_display_t *vd, bool is_fullscreen)
SetWindowPlacement(hwnd, &window_placement);
ShowWindow(hwnd, SW_SHOWNORMAL);
}
/* Make sure the mouse cursor is displayed */
EventThreadMouseShow(sys->event);
}
return VLC_SUCCESS;
}
......@@ -630,8 +621,10 @@ int CommonControl(vout_display_t *vd, int query, va_list args)
return CommonControlSetFullscreen(vd, cfg->is_fullscreen);
}
case VOUT_DISPLAY_RESET_PICTURES:
case VOUT_DISPLAY_HIDE_MOUSE:
EventThreadMouseHide(sys->event);
return VLC_SUCCESS;
case VOUT_DISPLAY_RESET_PICTURES:
assert(0);
default:
return VLC_EGENERIC;
......
......@@ -73,9 +73,6 @@ vlc_module_begin ()
add_shortcut("direct3d")
set_callbacks(OpenVideoVista, Close)
/* FIXME: Hack to avoid unregistering our window class */
cannot_unload_broken_library()
add_submodule()
set_description(N_("Direct3D video output (XP)"))
set_capability("vout display", 70)
......@@ -84,14 +81,6 @@ vlc_module_begin ()
vlc_module_end ()
#if 0 /* FIXME */
/* check if we registered a window class because we need to
* unregister it */
WNDCLASS wndclass;
if (GetClassInfo(GetModuleHandle(NULL), "VLC DirectX", &wndclass))
UnregisterClass("VLC DirectX", GetModuleHandle(NULL));
#endif
/*****************************************************************************
* Local prototypes.
*****************************************************************************/
......@@ -165,7 +154,7 @@ static int Open(vlc_object_t *object)
vout_display_info_t info = vd->info;
info.is_slow = true;
info.has_double_click = true;
info.has_hide_mouse = true;
info.has_hide_mouse = false;
info.has_pictures_invalid = true;
info.has_event_thread = true;
......
......@@ -118,19 +118,8 @@ vlc_module_begin()
set_capability("vout display", 100)
add_shortcut("directx")
set_callbacks(Open, Close)
/* FIXME: Hack to avoid unregistering our window class */
cannot_unload_broken_library()
vlc_module_end()
#if 0 /* FIXME */
/* check if we registered a window class because we need to
* unregister it */
WNDCLASS wndclass;
if (GetClassInfo(GetModuleHandle(NULL), "VLC DirectX", &wndclass))
UnregisterClass("VLC DirectX", GetModuleHandle(NULL));
#endif
/*****************************************************************************
* Local prototypes.
*****************************************************************************/
......@@ -220,7 +209,7 @@ static int Open(vlc_object_t *object)
vout_display_info_t info = vd->info;
info.is_slow = true;
info.has_double_click = true;
info.has_hide_mouse = true;
info.has_hide_mouse = false;
info.has_pictures_invalid = true;
info.has_event_thread = true;
......
......@@ -81,8 +81,7 @@ UINT GetMenuState(HMENU hMenu, UINT id, UINT flags)
* 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)
#define WM_VLC_CHANGE_TEXT (WM_APP + 1)
struct event_thread_t
{
......@@ -101,9 +100,9 @@ struct event_thread_t
bool use_overlay;
/* Mouse */
volatile bool b_cursor_hidden;
volatile mtime_t i_lastmoved;
mtime_t i_mouse_hide_timeout;
bool is_cursor_hidden;
HCURSOR cursor_arrow;
HCURSOR cursor_empty;
/* Title */
char *psz_title;
......@@ -113,6 +112,8 @@ struct event_thread_t
/* */
vout_window_t *parent_window;
TCHAR class_main[256];
TCHAR class_video[256];
HWND hparent;
HWND hwnd;
HWND hvideownd;
......@@ -141,6 +142,48 @@ static inline bool isKeyEvent( WPARAM type )
type <= WM_KEYLAST;
}
static void UpdateCursor( event_thread_t *p_event, bool b_show )
{
if( p_event->is_cursor_hidden == !b_show )
return;
p_event->is_cursor_hidden = !b_show;
#if 1
HCURSOR cursor = b_show ? p_event->cursor_arrow : p_event->cursor_empty;
if( p_event->hvideownd )
SetClassLongPtr( p_event->hvideownd, GCLP_HCURSOR, (LONG_PTR)cursor );
if( p_event->hwnd )
SetClassLongPtr( p_event->hwnd, GCLP_HCURSOR, (LONG_PTR)cursor );
#endif
/* FIXME I failed to find a cleaner way to force a redraw of the cursor */
POINT p;
GetCursorPos(&p);
HWND hwnd = WindowFromPoint(p);
if( hwnd == p_event->hvideownd || hwnd == p_event->hwnd )
SetCursorPos(p.x, p.y);
}
static HCURSOR EmptyCursor( HINSTANCE instance )
{
const int cw = GetSystemMetrics(SM_CXCURSOR);
const int ch = GetSystemMetrics(SM_CYCURSOR);
HCURSOR cursor = NULL;
uint8_t *and = malloc(cw * ch);
uint8_t *xor = malloc(cw * ch);
if( and && xor )
{
memset(and, 0xff, cw * ch );
memset(xor, 0x00, cw * ch );
cursor = CreateCursor( instance, 0, 0, cw, ch, and, xor);
}
free( and );
free( xor );
return cursor;
}
/*****************************************************************************
* EventThread: Create video window & handle its messages
*****************************************************************************
......@@ -225,6 +268,28 @@ static void *EventThread( void *p_this )
if( !b_key_support && isKeyEvent( msg.message ) )
continue;
/* Handle mouse state */
if( msg.message == WM_MOUSEMOVE ||
msg.message == WM_NCMOUSEMOVE )
{
GetCursorPos( &mouse_pos );
/* FIXME, why this >2 limits ? */
if( (abs(mouse_pos.x - old_mouse_pos.x) > 2 ||
(abs(mouse_pos.y - old_mouse_pos.y)) > 2 ) )
{
old_mouse_pos = mouse_pos;
UpdateCursor( p_event, true );
}
}
else if( isMouseEvent( msg.message ) )
{
UpdateCursor( p_event, true );
}
else if( msg.message == WM_VLC_HIDE_MOUSE )
{
UpdateCursor( p_event, false );
}
/* */
switch( msg.message )
{
......@@ -248,38 +313,11 @@ static void *EventThread( void *p_this )
(int64_t)(GET_Y_LPARAM(msg.lParam) - place.y) * source.i_height / place.height;
vout_display_SendEventMouseMoved(vd, x, y);
}
/* Fall through */
break;
case WM_NCMOUSEMOVE:
GetCursorPos( &mouse_pos );
/* FIXME, why this >2 limits ? */
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 = false;
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:
......@@ -470,6 +508,8 @@ static int DirectXCreateWindow( event_thread_t *p_event )
p_event->hparent = hwnd;
}
#endif
p_event->cursor_arrow = LoadCursor(NULL, IDC_ARROW);
p_event->cursor_empty = EmptyCursor(hInstance);
/* Get the Icon from the main app */
vlc_icon = NULL;
......@@ -487,41 +527,30 @@ static int DirectXCreateWindow( event_thread_t *p_event )
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.hCursor = p_event->is_cursor_hidden ? p_event->cursor_empty :
p_event->cursor_arrow;
wc.hbrBackground = GetStockObject(BLACK_BRUSH); /* background color */
wc.lpszMenuName = NULL; /* no menu */
wc.lpszClassName = _T("VLC DirectX"); /* use a special class */
wc.lpszClassName = p_event->class_main; /* use a special class */
/* Register the window class */
if( !RegisterClass(&wc) )
{
WNDCLASS wndclass;
if( vlc_icon )
DestroyIcon( vlc_icon );
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( vd, "DirectXCreateWindow RegisterClass FAILED (err=%lu)", GetLastError() );
return VLC_EGENERIC;
}
msg_Err( vd, "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.lpszClassName = p_event->class_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( vd, "DirectXCreateWindow RegisterClass FAILED (err=%lu)", GetLastError() );
return VLC_EGENERIC;
}
msg_Err( vd, "DirectXCreateWindow RegisterClass FAILED (err=%lu)", GetLastError() );
return VLC_EGENERIC;
}
/* When you create a window you give the dimensions you wish it to
......@@ -560,7 +589,7 @@ static int DirectXCreateWindow( event_thread_t *p_event )
/* Create the window */
p_event->hwnd =
CreateWindowEx( WS_EX_NOPARENTNOTIFY | i_stylex,
_T("VLC DirectX"), /* name of window class */
p_event->class_main, /* name of window class */
_T(VOUT_TITLE) _T(" (DirectX Output)"), /* window title */
i_style, /* window style */
(!p_event->wnd_cfg.x) ? CW_USEDEFAULT :
......@@ -594,7 +623,7 @@ static int DirectXCreateWindow( event_thread_t *p_event )
/* Create our fullscreen window */
p_event->hfswnd =
CreateWindowEx( WS_EX_APPWINDOW, _T("VLC DirectX"),
CreateWindowEx( WS_EX_APPWINDOW, p_event->class_main,
_T(VOUT_TITLE) _T(" (DirectX Output)"),
WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN|WS_SIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT,
......@@ -617,7 +646,7 @@ static int DirectXCreateWindow( event_thread_t *p_event )
* without having them shown outside of the video area. */
/* FIXME vd->source.i_width/i_height seems wrong */
p_event->hvideownd =
CreateWindow( _T("VLC DirectX video"), _T(""), /* window class */
CreateWindow( p_event->class_video, _T(""), /* window class */
WS_CHILD, /* window style, not visible initially */
0, 0,
vd->source.i_width, /* default width */
......@@ -657,9 +686,11 @@ static void DirectXCloseWindow( event_thread_t *p_event )
vout_display_DeleteWindow( vd, 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 */
HINSTANCE hInstance = GetModuleHandle(NULL);
UnregisterClass( p_event->class_video, hInstance );
UnregisterClass( p_event->class_main, hInstance );
DestroyCursor( p_event->cursor_empty );
}
/*****************************************************************************
......@@ -707,7 +738,14 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
return 0; /* this stops them from happening */
}
#endif
#if 0
if( message == WM_SETCURSOR )
{
msg_Err(vd, "WM_SETCURSOR: %d (t2)", p_event->is_cursor_hidden);
SetCursor( p_event->is_cursor_hidden ? p_event->cursor_empty : p_event->cursor_arrow );
return 1;
}
#endif
if( hwnd == p_event->hvideownd )
{
#ifdef MODULE_NAME_IS_directx
......@@ -915,30 +953,11 @@ static int DirectXConvertKey( int i_key )
return 0;
}
void EventThreadMouseAutoHide( event_thread_t *p_event )
{
if (!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 )
void EventThreadMouseHide( event_thread_t *p_event )
{
PostMessage( p_event->hwnd, WM_VLC_SHOW_MOUSE, 0, 0 );
PostMessage( p_event->hwnd, WM_VLC_HIDE_MOUSE, 0, 0 );
}
void EventThreadUpdateTitle( event_thread_t *p_event, const char *psz_fallback )
{
char *psz_title = var_GetNonEmptyString( p_event->vd, "video-title" );
......@@ -1021,14 +1040,15 @@ event_thread_t *EventThreadCreate( vout_display_t *vd)
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(vd, "mouse-hide-timeout") * 1000;
p_event->is_cursor_hidden = false;
p_event->psz_title = NULL;
p_event->source = vd->source;
vout_display_PlacePicture(&p_event->place, &vd->source, vd->cfg, false);
_snprintf( p_event->class_main, sizeof(p_event->class_main)/sizeof(*p_event->class_main),
_T("VLC MSW %p"), p_event );
_snprintf( p_event->class_video, sizeof(p_event->class_video)/sizeof(*p_event->class_video),
_T("VLC MSW video %p"), p_event );
return p_event;
}
......
......@@ -49,8 +49,7 @@ 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 EventThreadMouseHide( event_thread_t * );
void EventThreadUpdateTitle( event_thread_t *, const char *psz_fallback );
int EventThreadGetWindowStyle( event_thread_t * );
void EventThreadUpdateWindowPosition( event_thread_t *, bool *pb_moved, bool *pb_resized,
......
......@@ -57,20 +57,8 @@ vlc_module_begin()
add_shortcut("glwin32")
add_shortcut("opengl")
set_callbacks(Open, Close)
/* FIXME: Hack to avoid unregistering our window class */
cannot_unload_broken_library ()
vlc_module_end()
#if 0 /* FIXME */
/* check if we registered a window class because we need to
* unregister it */
WNDCLASS wndclass;
if(GetClassInfo(GetModuleHandle(NULL), "VLC DirectX", &wndclass))
UnregisterClass("VLC DirectX", GetModuleHandle(NULL));
#endif
/*****************************************************************************
* Local prototypes.
*****************************************************************************/
......@@ -133,7 +121,7 @@ static int Open(vlc_object_t *object)
vout_display_info_t info = vd->info;
info.has_double_click = true;
info.has_hide_mouse = true;
info.has_hide_mouse = false;
info.has_pictures_invalid = true;
info.has_event_thread = true;
......
......@@ -134,7 +134,7 @@ static int Open(vlc_object_t *object)
vout_display_info_t info = vd->info;
info.is_slow = false;
info.has_double_click = true;
info.has_hide_mouse = true;
info.has_hide_mouse = false;
info.has_pictures_invalid = true;
/* */
......
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