From: Laurent Aimar Date: Thu, 10 Jun 2010 19:00:54 +0000 (+0200) Subject: Fixed invalid mouse cursor state on win32 (close #3675). X-Git-Tag: 1.2.0-pre1~6243 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=6034b5c50ffda54704f8e053a7b0b2a55bddb73d;p=vlc 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. --- diff --git a/modules/video_output/msw/common.c b/modules/video_output/msw/common.c index 9d607c9000..58b9844cd9 100644 --- a/modules/video_output/msw/common.c +++ b/modules/video_output/msw/common.c @@ -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; diff --git a/modules/video_output/msw/direct3d.c b/modules/video_output/msw/direct3d.c index 66be688442..c1c59568d3 100644 --- a/modules/video_output/msw/direct3d.c +++ b/modules/video_output/msw/direct3d.c @@ -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; diff --git a/modules/video_output/msw/directx.c b/modules/video_output/msw/directx.c index 041852342b..020725a452 100644 --- a/modules/video_output/msw/directx.c +++ b/modules/video_output/msw/directx.c @@ -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; diff --git a/modules/video_output/msw/events.c b/modules/video_output/msw/events.c index e3e5457fe5..8af17019f4 100644 --- a/modules/video_output/msw/events.c +++ b/modules/video_output/msw/events.c @@ -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; } diff --git a/modules/video_output/msw/events.h b/modules/video_output/msw/events.h index 43828f4bef..2b21965f94 100644 --- a/modules/video_output/msw/events.h +++ b/modules/video_output/msw/events.h @@ -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, diff --git a/modules/video_output/msw/glwin32.c b/modules/video_output/msw/glwin32.c index 10d52d471e..b5647cfe78 100644 --- a/modules/video_output/msw/glwin32.c +++ b/modules/video_output/msw/glwin32.c @@ -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; diff --git a/modules/video_output/msw/wingdi.c b/modules/video_output/msw/wingdi.c index fe97eeb852..619e664fdd 100644 --- a/modules/video_output/msw/wingdi.c +++ b/modules/video_output/msw/wingdi.c @@ -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; /* */