]> git.sesse.net Git - vlc/blobdiff - modules/video_output/msw/events.c
Wav: No tabs in source code
[vlc] / modules / video_output / msw / events.c
index fbe539ed455be87b903bb18623b2027f88204c17..ada4d43090d58d3fd5c18822e18fe8120c87de99 100644 (file)
@@ -1,24 +1,24 @@
 /*****************************************************************************
  * events.c: Windows DirectX video output events handler
  *****************************************************************************
- * Copyright (C) 2001-2009 the VideoLAN team
+ * Copyright (C) 2001-2009 VLC authors and VideoLAN
  * $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
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 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.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser 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.
+ * You should have received a copy of the GNU Lesser 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.
  *****************************************************************************/
 
 
@@ -40,7 +40,7 @@
 
 #include <ctype.h>
 
-#ifdef MODULE_NAME_IS_directx
+#ifdef MODULE_NAME_IS_directdraw
 #include <ddraw.h>
 #endif
 #ifdef MODULE_NAME_IS_direct3d
 #ifdef MODULE_NAME_IS_glwin32
 #include "../opengl.h"
 #endif
+#ifdef MODULE_NAME_IS_direct2d
+#include <d2d1.h>
+#endif
 
 #include <vlc_keys.h>
 #include "common.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)
+#define WM_VLC_CHANGE_TEXT  (WM_APP + 1)
 
 struct event_thread_t
 {
@@ -89,9 +79,10 @@ 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;
+    unsigned button_pressed;
 
     /* Title */
     char *psz_title;
@@ -101,6 +92,8 @@ struct event_thread_t
 
     /* */
     vout_window_t *parent_window;
+    TCHAR class_main[256];
+    TCHAR class_video[256];
     HWND hparent;
     HWND hwnd;
     HWND hvideownd;
@@ -108,6 +101,8 @@ struct event_thread_t
     video_format_t       source;
     vout_display_place_t place;
 
+    HICON vlc_icon;
+
     bool has_moved;
 };
 
@@ -117,6 +112,80 @@ static long FAR PASCAL DirectXEventProc( HWND, UINT, WPARAM, LPARAM );
 
 static int DirectXConvertKey( int i_key );
 
+static inline bool isMouseEvent( WPARAM type )
+{
+    return type >= WM_MOUSEFIRST &&
+           type <= WM_MOUSELAST;
+}
+
+static inline bool isKeyEvent( WPARAM type )
+{
+    return type >= WM_KEYFIRST &&
+           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 )
+    {
+        if( b_show )
+            SetCursor( cursor );
+        else
+            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;
+}
+
+static void MousePressed( event_thread_t *p_event, HWND hwnd, unsigned button )
+{
+    if( !p_event->button_pressed )
+        SetCapture( hwnd );
+    p_event->button_pressed |= 1 << button;
+    vout_display_SendEventMousePressed( p_event->vd, button );
+}
+
+static void MouseReleased( event_thread_t *p_event, unsigned button )
+{
+    p_event->button_pressed &= ~(1 << button);
+    if( !p_event->button_pressed )
+        ReleaseCapture();
+    vout_display_SendEventMouseReleased( p_event->vd, button );
+}
 /*****************************************************************************
  * EventThread: Create video window & handle its messages
  *****************************************************************************
@@ -131,9 +200,11 @@ static void *EventThread( void *p_this )
     vout_display_t *vd = p_event->vd;
     MSG msg;
     POINT old_mouse_pos = {0,0}, mouse_pos;
-    HMODULE hkernel32;
     int canc = vlc_savecancel ();
 
+    bool b_mouse_support = var_InheritBool( p_event->vd, "mouse-events" );
+    bool b_key_support = var_InheritBool( p_event->vd, "keyboard-events" );
+
     vlc_mutex_lock( &p_event->lock );
     /* Create a window for the video */
     /* Creating a window under Windows also initializes the thread's event
@@ -153,22 +224,8 @@ static void *EventThread( void *p_this )
         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( vd, "no support for SetThreadExecutionState()" );
-    }
-#endif
+    /* Prevent monitor from powering off */
+    SetThreadExecutionState( ES_DISPLAY_REQUIRED | ES_SYSTEM_REQUIRED | ES_CONTINUOUS );
 
     /* Main loop */
     /* GetMessage will sleep if there's no message in the queue */
@@ -192,6 +249,34 @@ static void *EventThread( void *p_this )
         if( b_done )
             break;
 
+        if( !b_mouse_support && isMouseEvent( msg.message ) )
+            continue;
+
+        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 )
         {
@@ -215,62 +300,35 @@ 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:
-            vout_display_SendEventMousePressed(vd, MOUSE_BUTTON_LEFT);
+            MousePressed( p_event, msg.hwnd, MOUSE_BUTTON_LEFT );
             break;
         case WM_LBUTTONUP:
-            vout_display_SendEventMouseReleased(vd, MOUSE_BUTTON_LEFT);
+            MouseReleased( p_event, MOUSE_BUTTON_LEFT );
             break;
         case WM_LBUTTONDBLCLK:
             vout_display_SendEventMouseDoubleClick(vd);
             break;
 
         case WM_MBUTTONDOWN:
-            vout_display_SendEventMousePressed(vd, MOUSE_BUTTON_CENTER);
+            MousePressed( p_event, msg.hwnd, MOUSE_BUTTON_CENTER );
             break;
         case WM_MBUTTONUP:
-            vout_display_SendEventMouseReleased(vd, MOUSE_BUTTON_CENTER);
+            MouseReleased( p_event, MOUSE_BUTTON_CENTER );
             break;
 
         case WM_RBUTTONDOWN:
-            vout_display_SendEventMousePressed(vd, MOUSE_BUTTON_RIGHT);
+            MousePressed( p_event, msg.hwnd, MOUSE_BUTTON_RIGHT );
             break;
         case WM_RBUTTONUP:
-            vout_display_SendEventMouseReleased(vd, MOUSE_BUTTON_RIGHT);
+            MouseReleased( p_event, MOUSE_BUTTON_RIGHT );
             break;
 
         case WM_KEYDOWN:
@@ -283,7 +341,7 @@ static void *EventThread( void *p_this )
             if( !i_key )
             {
                 /* This appears to be a "normal" (ascii) key */
-                i_key = tolower( MapVirtualKey( msg.wParam, 2 ) );
+                i_key = tolower( (unsigned char)MapVirtualKey( msg.wParam, 2 ) );
             }
 
             if( i_key )
@@ -354,9 +412,9 @@ static void *EventThread( void *p_this )
 
             if( pwz_title )
             {
-                SetWindowTextW( p_event->hwnd, (LPCTSTR)pwz_title );
+                SetWindowTextW( p_event->hwnd, pwz_title );
                 if( p_event->hfswnd )
-                    SetWindowTextW( p_event->hfswnd, (LPCTSTR)pwz_title );
+                    SetWindowTextW( p_event->hfswnd, pwz_title );
                 free( pwz_title );
             }
             break;
@@ -387,7 +445,44 @@ static void *EventThread( void *p_this )
     return NULL;
 }
 
+#ifdef MODULE_NAME_IS_direct3d
+static int CALLBACK
+enumWindowsProc(HWND hwnd, LPARAM lParam)
+{
+    HWND *wnd = (HWND *)lParam;
 
+    char name[128];
+    name[0] = '\0';
+    GetClassNameA( hwnd, name, 128 );
+
+    if( !strcasecmp( name, "WorkerW" ) )
+    {
+        hwnd = FindWindowEx( hwnd, NULL, _T("SHELLDLL_DefView"), NULL );
+        if( hwnd ) hwnd = FindWindowEx( hwnd, NULL, _T("SysListView32"), NULL );
+        if( hwnd )
+        {
+            *wnd = hwnd;
+            return false;
+        }
+    }
+    return true;
+}
+
+static HWND GetDesktopHandle(vout_display_t *vd)
+{
+    /* 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 )
+        return hwnd;
+
+    msg_Dbg( vd, "Couldn't find desktop icon window,. Trying the hard way." );
+
+    EnumWindows( enumWindowsProc, (LPARAM)&hwnd );
+    return hwnd;
+}
+#endif
 /* following functions are local */
 
 /*****************************************************************************
@@ -404,8 +499,7 @@ static int DirectXCreateWindow( event_thread_t *p_event )
     HMENU      hMenu;
     RECT       rect_window;
     WNDCLASS   wc;                            /* window class components */
-    HICON      vlc_icon;
-    char       vlc_path[MAX_PATH+1];
+    TCHAR      vlc_path[MAX_PATH+1];
     int        i_style, i_stylex;
 
     msg_Dbg( vd, "DirectXCreateWindow" );
@@ -420,32 +514,26 @@ static int DirectXCreateWindow( event_thread_t *p_event )
         /* If an external window was specified, we'll draw in it. */
         p_event->parent_window = vout_display_NewWindow(vd, &p_event->wnd_cfg );
         if( p_event->parent_window )
-            p_event->hparent = p_event->parent_window->hwnd;
+            p_event->hparent = p_event->parent_window->handle.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( vd, "Couldn't find desktop icon window. Desktop mode can't be established." );
         p_event->parent_window = NULL;
-        p_event->hparent = hwnd;
+        p_event->hparent = GetDesktopHandle(vd);
     }
     #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;
-#ifndef UNDER_CE
+    p_event->vlc_icon = NULL;
     if( GetModuleFileName( NULL, vlc_path, MAX_PATH ) )
     {
-        vlc_icon = ExtractIcon( hInstance, vlc_path, 0 );
+        p_event->vlc_icon = ExtractIcon( hInstance, vlc_path, 0 );
     }
-#endif
 
     /* Fill in the window class structure */
     wc.style         = CS_OWNDC|CS_DBLCLKS;          /* style: dbl click */
@@ -453,50 +541,39 @@ static int DirectXCreateWindow( event_thread_t *p_event )
     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.hIcon         = p_event->vlc_icon;       /* load the vlc big icon */
+    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( p_event->vlc_icon )
+            DestroyIcon( p_event->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
      * 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.top    = 10;
     rect_window.right  = rect_window.left + p_event->wnd_cfg.width;
     rect_window.bottom = rect_window.top  + p_event->wnd_cfg.height;
 
@@ -520,6 +597,12 @@ static int DirectXCreateWindow( event_thread_t *p_event )
     {
         i_style = WS_VISIBLE|WS_CLIPCHILDREN|WS_CHILD;
         i_stylex = 0;
+
+        /* allow user to regain control over input events if requested */
+        bool b_mouse_support = var_InheritBool( vd, "mouse-events" );
+        bool b_key_support = var_InheritBool( vd, "keyboard-events" );
+        if( !b_mouse_support && !b_key_support )
+            i_style |= WS_DISABLED;
     }
 
     p_event->i_window_style = i_style;
@@ -527,12 +610,12 @@ 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 < 0) ? CW_USEDEFAULT :
+                    (!p_event->wnd_cfg.x) ? (UINT)CW_USEDEFAULT :
                         (UINT)p_event->wnd_cfg.x,   /* default X coordinate */
-                    (p_event->wnd_cfg.y < 0) ? CW_USEDEFAULT :
+                    (!p_event->wnd_cfg.y) ? (UINT)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 */
@@ -561,7 +644,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,
@@ -584,7 +667,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 */
@@ -624,9 +707,14 @@ 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 );
+
+    if( p_event->vlc_icon )
+        DestroyIcon( p_event->vlc_icon );
+
+    DestroyCursor( p_event->cursor_empty );
 }
 
 /*****************************************************************************
@@ -665,7 +753,6 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
     }
     vout_display_t *vd = p_event->vd;
 
-#ifndef UNDER_CE
     /* Catch the screensaver and the monitor turn-off */
     if( message == WM_SYSCOMMAND &&
         ( (wParam & 0xFFF0) == SC_SCREENSAVE || (wParam & 0xFFF0) == SC_MONITORPOWER ) )
@@ -673,11 +760,30 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
         //if( vd ) msg_Dbg( vd, "WinProc WM_SYSCOMMAND screensaver" );
         return 0; /* this stops them from happening */
     }
+#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( message == WM_CAPTURECHANGED )
+    {
+        for( int button = 0; p_event->button_pressed; button++ )
+        {
+            unsigned m = 1 << button;
+            if( p_event->button_pressed & m )
+                vout_display_SendEventMouseReleased( p_event->vd, button );
+            p_event->button_pressed &= ~m;
+        }
+        p_event->button_pressed = 0;
+        return 0;
+    }
 
     if( hwnd == p_event->hvideownd )
     {
-#ifdef MODULE_NAME_IS_directx
+#ifdef MODULE_NAME_IS_directdraw
         vlc_mutex_lock( &p_event->lock );
         const bool use_overlay = p_event->use_overlay;
         vlc_mutex_unlock( &p_event->lock );
@@ -685,7 +791,7 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
 
         switch( message )
         {
-#ifdef MODULE_NAME_IS_directx
+#ifdef MODULE_NAME_IS_directdraw
         case WM_ERASEBKGND:
         /* For overlay, we need to erase background */
             return !use_overlay ? 1 : DefWindowProc(hwnd, message, wParam, lParam);
@@ -764,47 +870,9 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
         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
-        /* FIXME vd->cfg is not lock[ed/able] */
-#warning "FIXME: race condition"
-        if( p_event->hparent &&
-            hwnd != p_event->hfswnd && vd->cfg->is_fullscreen )
-            vout_display_SendEventFullscreen(vd, false);
-
-        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:
@@ -882,33 +950,14 @@ 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" );
+    char *psz_title = var_InheritString( p_event->vd, "video-title" );
     if( !psz_title )
         psz_title = strdup( psz_fallback );
     if( !psz_title )
@@ -927,13 +976,14 @@ int EventThreadGetWindowStyle( event_thread_t *p_event )
     return p_event->i_window_style;
 }
 
-void EventThreadUpdateWindowPosition( event_thread_t *p_event, bool *pb_changed,
-                                      int x, int y, int w, int h )
+void EventThreadUpdateWindowPosition( event_thread_t *p_event,
+                                      bool *pb_moved, bool *pb_resized,
+                                      int x, int y, unsigned w, unsigned 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 ||
+    *pb_moved   = x != p_event->wnd_cfg.x ||
+                  y != p_event->wnd_cfg.y;
+    *pb_resized = w != p_event->wnd_cfg.width ||
                   h != p_event->wnd_cfg.height;
 
     p_event->wnd_cfg.x      = x;
@@ -987,14 +1037,16 @@ 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->button_pressed = 0;
     p_event->psz_title = NULL;
     p_event->source = vd->source;
-    vout_display_PlacePicture(&p_event->place, &vd->source, vd->cfg, true);
+    vout_display_PlacePicture(&p_event->place, &vd->source, vd->cfg, false);
 
+    _sntprintf( p_event->class_main, sizeof(p_event->class_main)/sizeof(*p_event->class_main),
+               _T("VLC MSW %p"), p_event );
+    _sntprintf( p_event->class_video, sizeof(p_event->class_video)/sizeof(*p_event->class_video),
+               _T("VLC MSW video %p"), p_event );
     return p_event;
 }