]> git.sesse.net Git - vlc/commitdiff
Fixed invalid mouse cursor state on win32 (close #3675).
authorLaurent Aimar <fenrir@videolan.org>
Thu, 10 Jun 2010 19:00:54 +0000 (21:00 +0200)
committerLaurent Aimar <fenrir@videolan.org>
Thu, 10 Jun 2010 22:20:33 +0000 (00:20 +0200)
As a side effect, window class names are now uniques (process wide)
allowing to unregister them and so to unload properly the msw vouts.

modules/video_output/msw/common.c
modules/video_output/msw/direct3d.c
modules/video_output/msw/directx.c
modules/video_output/msw/events.c
modules/video_output/msw/events.h
modules/video_output/msw/glwin32.c
modules/video_output/msw/wingdi.c

index 9d607c9000f01f1dfc445884d7c1e9b832ece5cc..58b9844cd97a1fd201106c517c847db99a2ac18e 100644 (file)
@@ -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;
index 66be688442d03bf1a36ccf6f5120d2671174e24a..c1c59568d39fe359f82aea423eab865c6e254372 100644 (file)
@@ -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;
 
index 041852342b1a4e73e95d373f3def803129066a35..020725a45265a9958133687eb4f2417c47100629 100644 (file)
@@ -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;
 
index e3e5457fe511d9f5eb2d109db12ca98ceb0ce842..8af17019f4844e4bbe7ea656b1138f6449348604 100644 (file)
@@ -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;
 }
 
index 43828f4bef9dba4a821f2b6389e6a46e829e08c1..2b21965f94d05a73eba74834e6ff540e97897ea5 100644 (file)
@@ -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,
index 10d52d471e61449dccf3a698a7c85b1701515f04..b5647cfe78283c5e8ac09909a03f7acac50c7634 100644 (file)
@@ -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;
 
index fe97eeb852ea05458a8d67eb3ddfd08930b2bec8..619e664fddec95255058c757c941b093fa3ed7bc 100644 (file)
@@ -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;
 
     /* */