]> git.sesse.net Git - vlc/blobdiff - modules/video_output/directx/glwin32.c
Avoid \r\n problems between platforms
[vlc] / modules / video_output / directx / glwin32.c
index 1950d05bb38dd558a2f795a7cdd14d84873a2906..c3b83694c5ae749fe6d1aa2355834fe2557c2196 100644 (file)
-/*****************************************************************************\r
- * glwin32.c: Windows OpenGL provider\r
- *****************************************************************************\r
- * Copyright (C) 2001-2004 VideoLAN\r
- * $Id$\r
- *\r
- * Authors: Gildas Bazin <gbazin@videolan.org>\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.\r
- *****************************************************************************/\r
-\r
-#include <errno.h>                                                 /* ENOMEM */\r
-#include <stdlib.h>                                                /* free() */\r
-#include <string.h>                                            /* strerror() */\r
-\r
-#include <vlc/vlc.h>\r
-#include <vlc/intf.h>\r
-#include <vlc/vout.h>\r
-\r
-#include <windows.h>\r
-#include <ddraw.h>\r
-#include <commctrl.h>\r
-\r
-#include <multimon.h>\r
-#undef GetSystemMetrics\r
-\r
-#ifndef MONITOR_DEFAULTTONEAREST\r
-#   define MONITOR_DEFAULTTONEAREST 2\r
-#endif\r
-\r
-#include <GL/gl.h>\r
-\r
-#include "vout.h"\r
-\r
-/*****************************************************************************\r
- * Local prototypes.\r
- *****************************************************************************/\r
-static int  OpenVideo  ( vlc_object_t * );\r
-static void CloseVideo ( vlc_object_t * );\r
-\r
-static int  Init      ( vout_thread_t * );\r
-static void End       ( vout_thread_t * );\r
-static int  Manage    ( vout_thread_t * );\r
-static void GLSwapBuffers( vout_thread_t * );\r
-\r
-/*****************************************************************************\r
- * Module descriptor\r
- *****************************************************************************/\r
-vlc_module_begin();\r
-    set_category( CAT_VIDEO );\r
-    set_subcategory( SUBCAT_VIDEO_VOUT );\r
-    set_description( _("Win32 OpenGL provider") );\r
-    set_capability( "opengl provider", 100 );\r
-    add_shortcut( "glwin32" );\r
-    set_callbacks( OpenVideo, CloseVideo );\r
-\r
-    /* FIXME: Hack to avoid unregistering our window class */\r
-    linked_with_a_crap_library_which_uses_atexit( );\r
-vlc_module_end();\r
-\r
-#if 0 /* FIXME */\r
-    /* check if we registered a window class because we need to\r
-     * unregister it */\r
-    WNDCLASS wndclass;\r
-    if( GetClassInfo( GetModuleHandle(NULL), "VLC DirectX", &wndclass ) )\r
-        UnregisterClass( "VLC DirectX", GetModuleHandle(NULL) );\r
-#endif\r
-\r
-/*****************************************************************************\r
- * OpenVideo: allocate OpenGL provider\r
- *****************************************************************************\r
- * This function creates and initializes a video window.\r
- *****************************************************************************/\r
-static int OpenVideo( vlc_object_t *p_this )\r
-{\r
-    vout_thread_t * p_vout = (vout_thread_t *)p_this;\r
-    vlc_value_t val;\r
-\r
-    /* Allocate structure */\r
-    p_vout->p_sys = malloc( sizeof( vout_sys_t ) );\r
-    if( p_vout->p_sys == NULL )\r
-    {\r
-        msg_Err( p_vout, "out of memory" );\r
-        return VLC_ENOMEM;\r
-    }\r
-    memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) );\r
-\r
-    /* Initialisations */\r
-    p_vout->pf_init = Init;\r
-    p_vout->pf_end = End;\r
-    p_vout->pf_manage = Manage;\r
-    p_vout->pf_swap = GLSwapBuffers;\r
-\r
-    p_vout->p_sys->p_ddobject = NULL;\r
-    p_vout->p_sys->p_display = NULL;\r
-    p_vout->p_sys->p_current_surface = NULL;\r
-    p_vout->p_sys->p_clipper = NULL;\r
-    p_vout->p_sys->hwnd = p_vout->p_sys->hvideownd = NULL;\r
-    p_vout->p_sys->hparent = p_vout->p_sys->hfswnd = NULL;\r
-    p_vout->p_sys->i_changes = 0;\r
-    p_vout->p_sys->b_wallpaper = 0;\r
-    vlc_mutex_init( p_vout, &p_vout->p_sys->lock );\r
-    SetRectEmpty( &p_vout->p_sys->rect_display );\r
-    SetRectEmpty( &p_vout->p_sys->rect_parent );\r
-\r
-    var_Create( p_vout, "video-title", VLC_VAR_STRING | VLC_VAR_DOINHERIT );\r
-\r
-    p_vout->p_sys->b_cursor_hidden = 0;\r
-    p_vout->p_sys->i_lastmoved = mdate();\r
-\r
-    /* Set main window's size */\r
-    p_vout->p_sys->i_window_width = p_vout->i_window_width;\r
-    p_vout->p_sys->i_window_height = p_vout->i_window_height;\r
-\r
-    /* Create the DirectXEventThread, this thread is created by us to isolate\r
-     * the Win32 PeekMessage function calls. We want to do this because\r
-     * Windows can stay blocked inside this call for a long time, and when\r
-     * this happens it thus blocks vlc's video_output thread.\r
-     * DirectXEventThread will take care of the creation of the video\r
-     * window (because PeekMessage has to be called from the same thread which\r
-     * created the window). */\r
-    msg_Dbg( p_vout, "creating DirectXEventThread" );\r
-    p_vout->p_sys->p_event =\r
-        vlc_object_create( p_vout, sizeof(event_thread_t) );\r
-    p_vout->p_sys->p_event->p_vout = p_vout;\r
-    if( vlc_thread_create( p_vout->p_sys->p_event, "DirectX Events Thread",\r
-                           E_(DirectXEventThread), 0, 1 ) )\r
-    {\r
-        msg_Err( p_vout, "cannot create DirectXEventThread" );\r
-        vlc_object_destroy( p_vout->p_sys->p_event );\r
-        p_vout->p_sys->p_event = NULL;\r
-        goto error;\r
-    }\r
-\r
-    if( p_vout->p_sys->p_event->b_error )\r
-    {\r
-        msg_Err( p_vout, "DirectXEventThread failed" );\r
-        goto error;\r
-    }\r
-\r
-    vlc_object_attach( p_vout->p_sys->p_event, p_vout );\r
-\r
-    msg_Dbg( p_vout, "DirectXEventThread running" );\r
-\r
-    /* Variable to indicate if the window should be on top of others */\r
-    /* Trigger a callback right now */\r
-    var_Get( p_vout, "video-on-top", &val );\r
-    var_Set( p_vout, "video-on-top", val );\r
-\r
-    return VLC_SUCCESS;\r
-\r
- error:\r
-    CloseVideo( VLC_OBJECT(p_vout) );\r
-    return VLC_EGENERIC;\r
-}\r
-\r
-/*****************************************************************************\r
- * Init: initialize video thread output method\r
- *****************************************************************************/\r
-static int Init( vout_thread_t *p_vout )\r
-{\r
-    PIXELFORMATDESCRIPTOR pfd;\r
-    int iFormat;\r
-\r
-    /* Change the window title bar text */\r
-    PostMessage( p_vout->p_sys->hwnd, WM_VLC_CHANGE_TEXT, 0, 0 );\r
-\r
-    p_vout->p_sys->hGLDC = GetDC( p_vout->p_sys->hvideownd );\r
-\r
-    /* Set the pixel format for the DC */\r
-    memset( &pfd, 0, sizeof( pfd ) );\r
-    pfd.nSize = sizeof( pfd );\r
-    pfd.nVersion = 1;\r
-    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;\r
-    pfd.iPixelType = PFD_TYPE_RGBA;\r
-    pfd.cColorBits = 24;\r
-    pfd.cDepthBits = 16;\r
-    pfd.iLayerType = PFD_MAIN_PLANE;\r
-    iFormat = ChoosePixelFormat( p_vout->p_sys->hGLDC, &pfd );\r
-    SetPixelFormat( p_vout->p_sys->hGLDC, iFormat, &pfd );\r
-\r
-    /* Create and enable the render context */\r
-    p_vout->p_sys->hGLRC = wglCreateContext( p_vout->p_sys->hGLDC );\r
-    wglMakeCurrent( p_vout->p_sys->hGLDC, p_vout->p_sys->hGLRC );\r
-\r
-    return VLC_SUCCESS;\r
-}\r
-\r
-/*****************************************************************************\r
- * End: terminate Sys video thread output method\r
- *****************************************************************************\r
- * Terminate an output method created by Create.\r
- * It is called at the end of the thread.\r
- *****************************************************************************/\r
-static void End( vout_thread_t *p_vout )\r
-{\r
-    wglMakeCurrent( NULL, NULL );\r
-    wglDeleteContext( p_vout->p_sys->hGLRC );\r
-    ReleaseDC( p_vout->p_sys->hvideownd, p_vout->p_sys->hGLDC );\r
-    return;\r
-}\r
-\r
-/*****************************************************************************\r
- * CloseVideo: destroy Sys video thread output method\r
- *****************************************************************************\r
- * Terminate an output method created by Create\r
- *****************************************************************************/\r
-static void CloseVideo( vlc_object_t *p_this )\r
-{\r
-    vout_thread_t * p_vout = (vout_thread_t *)p_this;\r
-\r
-    msg_Dbg( p_vout, "CloseVideo" );\r
-\r
-    if( p_vout->p_sys->p_event )\r
-    {\r
-        vlc_object_detach( p_vout->p_sys->p_event );\r
-\r
-        /* Kill DirectXEventThread */\r
-        p_vout->p_sys->p_event->b_die = VLC_TRUE;\r
-\r
-        /* we need to be sure DirectXEventThread won't stay stuck in\r
-         * GetMessage, so we send a fake message */\r
-        if( p_vout->p_sys->hwnd )\r
-        {\r
-            PostMessage( p_vout->p_sys->hwnd, WM_NULL, 0, 0);\r
-        }\r
-\r
-        vlc_thread_join( p_vout->p_sys->p_event );\r
-        vlc_object_destroy( p_vout->p_sys->p_event );\r
-    }\r
-\r
-    vlc_mutex_destroy( &p_vout->p_sys->lock );\r
-\r
-    if( p_vout->p_sys )\r
-    {\r
-        free( p_vout->p_sys );\r
-        p_vout->p_sys = NULL;\r
-    }\r
-}\r
-\r
-/*****************************************************************************\r
- * Manage: handle Sys events\r
- *****************************************************************************\r
- * This function should be called regularly by the video output thread.\r
- * It returns a non null value if an error occurred.\r
- *****************************************************************************/\r
-static int Manage( vout_thread_t *p_vout )\r
-{\r
-    WINDOWPLACEMENT window_placement;\r
-\r
-    int i_width = p_vout->p_sys->rect_dest.right -\r
-        p_vout->p_sys->rect_dest.left;\r
-    int i_height = p_vout->p_sys->rect_dest.bottom -\r
-        p_vout->p_sys->rect_dest.top;\r
-    glViewport( 0, 0, i_width, i_height );\r
-\r
-    /* If we do not control our window, we check for geometry changes\r
-     * ourselves because the parent might not send us its events. */\r
-    vlc_mutex_lock( &p_vout->p_sys->lock );\r
-    if( p_vout->p_sys->hparent && !p_vout->b_fullscreen )\r
-    {\r
-        RECT rect_parent;\r
-        POINT point;\r
-\r
-        vlc_mutex_unlock( &p_vout->p_sys->lock );\r
-\r
-        GetClientRect( p_vout->p_sys->hparent, &rect_parent );\r
-        point.x = point.y = 0;\r
-        ClientToScreen( p_vout->p_sys->hparent, &point );\r
-        OffsetRect( &rect_parent, point.x, point.y );\r
-\r
-        if( !EqualRect( &rect_parent, &p_vout->p_sys->rect_parent ) )\r
-        {\r
-            p_vout->p_sys->rect_parent = rect_parent;\r
-\r
-            /* This one is to force the update even if only\r
-             * the position has changed */\r
-            SetWindowPos( p_vout->p_sys->hwnd, 0, 1, 1,\r
-                          rect_parent.right - rect_parent.left,\r
-                          rect_parent.bottom - rect_parent.top, 0 );\r
-\r
-            SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,\r
-                          rect_parent.right - rect_parent.left,\r
-                          rect_parent.bottom - rect_parent.top, 0 );\r
-        }\r
-    }\r
-    else\r
-    {\r
-        vlc_mutex_unlock( &p_vout->p_sys->lock );\r
-    }\r
-\r
-    /* We used to call the Win32 PeekMessage function here to read the window\r
-     * messages. But since window can stay blocked into this function for a\r
-     * long time (for example when you move your window on the screen), I\r
-     * decided to isolate PeekMessage in another thread. */\r
-\r
-    /*\r
-     * Fullscreen change\r
-     */\r
-    if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE\r
-        || p_vout->p_sys->i_changes & VOUT_FULLSCREEN_CHANGE )\r
-    {\r
-        vlc_value_t val;\r
-        HWND hwnd = (p_vout->p_sys->hparent && p_vout->p_sys->hfswnd) ?\r
-            p_vout->p_sys->hfswnd : p_vout->p_sys->hwnd;\r
-\r
-        p_vout->b_fullscreen = ! p_vout->b_fullscreen;\r
-\r
-        /* We need to switch between Maximized and Normal sized window */\r
-        window_placement.length = sizeof(WINDOWPLACEMENT);\r
-        GetWindowPlacement( hwnd, &window_placement );\r
-        if( p_vout->b_fullscreen )\r
-        {\r
-            /* Change window style, no borders and no title bar */\r
-            int i_style = WS_CLIPCHILDREN | WS_VISIBLE;\r
-            SetWindowLong( hwnd, GWL_STYLE, i_style );\r
-\r
-            if( p_vout->p_sys->hparent )\r
-            {\r
-                /* Retrieve current window position so fullscreen will happen\r
-                 * on the right screen */\r
-                POINT point = {0,0};\r
-                RECT rect;\r
-                ClientToScreen( p_vout->p_sys->hwnd, &point );\r
-                GetClientRect( p_vout->p_sys->hwnd, &rect );\r
-                SetWindowPos( hwnd, 0, point.x, point.y,\r
-                              rect.right, rect.bottom,\r
-                              SWP_NOZORDER|SWP_FRAMECHANGED );\r
-                GetWindowPlacement( hwnd, &window_placement );\r
-            }\r
-\r
-            /* Maximize window */\r
-            window_placement.showCmd = SW_SHOWMAXIMIZED;\r
-            SetWindowPlacement( hwnd, &window_placement );\r
-            SetWindowPos( hwnd, 0, 0, 0, 0, 0,\r
-                          SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED);\r
-\r
-            if( p_vout->p_sys->hparent )\r
-            {\r
-                RECT rect;\r
-                GetClientRect( hwnd, &rect );\r
-                SetParent( p_vout->p_sys->hwnd, hwnd );\r
-                SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,\r
-                              rect.right, rect.bottom,\r
-                              SWP_NOZORDER|SWP_FRAMECHANGED );\r
-            }\r
-\r
-            SetForegroundWindow( hwnd );\r
-        }\r
-        else\r
-        {\r
-            /* Change window style, no borders and no title bar */\r
-            SetWindowLong( hwnd, GWL_STYLE, p_vout->p_sys->i_window_style );\r
-\r
-            /* Normal window */\r
-            window_placement.showCmd = SW_SHOWNORMAL;\r
-            SetWindowPlacement( hwnd, &window_placement );\r
-            SetWindowPos( hwnd, 0, 0, 0, 0, 0,\r
-                          SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED);\r
-\r
-            if( p_vout->p_sys->hparent )\r
-            {\r
-                RECT rect;\r
-                GetClientRect( p_vout->p_sys->hparent, &rect );\r
-                SetParent( p_vout->p_sys->hwnd, p_vout->p_sys->hparent );\r
-                SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,\r
-                              rect.right, rect.bottom,\r
-                              SWP_NOZORDER|SWP_FRAMECHANGED );\r
-\r
-                ShowWindow( hwnd, SW_HIDE );\r
-                SetForegroundWindow( p_vout->p_sys->hparent );\r
-            }\r
-\r
-            /* Make sure the mouse cursor is displayed */\r
-            PostMessage( p_vout->p_sys->hwnd, WM_VLC_SHOW_MOUSE, 0, 0 );\r
-        }\r
-\r
-        /* Update the object variable and trigger callback */\r
-        val.b_bool = p_vout->b_fullscreen;\r
-        var_Set( p_vout, "fullscreen", val );\r
-\r
-        p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;\r
-        p_vout->p_sys->i_changes &= ~VOUT_FULLSCREEN_CHANGE;\r
-    }\r
-\r
-    /*\r
-     * Pointer change\r
-     */\r
-    if( p_vout->b_fullscreen && !p_vout->p_sys->b_cursor_hidden &&\r
-        (mdate() - p_vout->p_sys->i_lastmoved) > 5000000 )\r
-    {\r
-        POINT point;\r
-        HWND hwnd;\r
-\r
-        /* Hide the cursor only if it is inside our window */\r
-        GetCursorPos( &point );\r
-        hwnd = WindowFromPoint(point);\r
-        if( hwnd == p_vout->p_sys->hwnd || hwnd == p_vout->p_sys->hvideownd )\r
-        {\r
-            PostMessage( p_vout->p_sys->hwnd, WM_VLC_HIDE_MOUSE, 0, 0 );\r
-        }\r
-        else\r
-        {\r
-            p_vout->p_sys->i_lastmoved = mdate();\r
-        }\r
-    }\r
-\r
-    /*\r
-     * "Always on top" status change\r
-     */\r
-    if( p_vout->p_sys->b_on_top_change )\r
-    {\r
-        vlc_value_t val;\r
-        HMENU hMenu = GetSystemMenu( p_vout->p_sys->hwnd, FALSE );\r
-\r
-        var_Get( p_vout, "video-on-top", &val );\r
-\r
-        /* Set the window on top if necessary */\r
-        if( val.b_bool && !( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE )\r
-                           & WS_EX_TOPMOST ) )\r
-        {\r
-            CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP,\r
-                           MF_BYCOMMAND | MFS_CHECKED );\r
-            SetWindowPos( p_vout->p_sys->hwnd, HWND_TOPMOST, 0, 0, 0, 0,\r
-                          SWP_NOSIZE | SWP_NOMOVE );\r
-        }\r
-        else\r
-        /* The window shouldn't be on top */\r
-        if( !val.b_bool && ( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE )\r
-                           & WS_EX_TOPMOST ) )\r
-        {\r
-            CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP,\r
-                           MF_BYCOMMAND | MFS_UNCHECKED );\r
-            SetWindowPos( p_vout->p_sys->hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,\r
-                          SWP_NOSIZE | SWP_NOMOVE );\r
-        }\r
-\r
-        p_vout->p_sys->b_on_top_change = VLC_FALSE;\r
-    }\r
-\r
-    /* Check if the event thread is still running */\r
-    if( p_vout->p_sys->p_event->b_die )\r
-    {\r
-        return VLC_EGENERIC; /* exit */\r
-    }\r
-\r
-    return VLC_SUCCESS;\r
-}\r
-\r
-/*****************************************************************************\r
- * GLSwapBuffers: swap front/back buffers\r
- *****************************************************************************/\r
-static void GLSwapBuffers( vout_thread_t *p_vout )\r
-{\r
-    SwapBuffers( p_vout->p_sys->hGLDC );\r
-}\r
-\r
-int E_(DirectXUpdateOverlay)( vout_thread_t *p_vout )\r
-{\r
-    return 1;\r
-}\r
+/*****************************************************************************
+ * glwin32.c: Windows OpenGL provider
+ *****************************************************************************
+ * Copyright (C) 2001-2004 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
+ * (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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include <errno.h>                                                 /* ENOMEM */
+#include <stdlib.h>                                                /* free() */
+#include <string.h>                                            /* strerror() */
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+#include <vlc/vout.h>
+
+#include <windows.h>
+#include <ddraw.h>
+#include <commctrl.h>
+
+#include <multimon.h>
+#undef GetSystemMetrics
+
+#ifndef MONITOR_DEFAULTTONEAREST
+#   define MONITOR_DEFAULTTONEAREST 2
+#endif
+
+#include <GL/gl.h>
+
+#include "vout.h"
+
+/*****************************************************************************
+ * Local prototypes.
+ *****************************************************************************/
+static int  OpenVideo  ( vlc_object_t * );
+static void CloseVideo ( vlc_object_t * );
+
+static int  Init      ( vout_thread_t * );
+static void End       ( vout_thread_t * );
+static int  Manage    ( vout_thread_t * );
+static void GLSwapBuffers( vout_thread_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+    set_category( CAT_VIDEO );
+    set_subcategory( SUBCAT_VIDEO_VOUT );
+    set_description( _("Win32 OpenGL provider") );
+    set_capability( "opengl provider", 100 );
+    add_shortcut( "glwin32" );
+    set_callbacks( OpenVideo, CloseVideo );
+
+    /* FIXME: Hack to avoid unregistering our window class */
+    linked_with_a_crap_library_which_uses_atexit( );
+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
+
+/*****************************************************************************
+ * OpenVideo: allocate OpenGL provider
+ *****************************************************************************
+ * This function creates and initializes a video window.
+ *****************************************************************************/
+static int OpenVideo( vlc_object_t *p_this )
+{
+    vout_thread_t * p_vout = (vout_thread_t *)p_this;
+    vlc_value_t val;
+
+    /* Allocate structure */
+    p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
+    if( p_vout->p_sys == NULL )
+    {
+        msg_Err( p_vout, "out of memory" );
+        return VLC_ENOMEM;
+    }
+    memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) );
+
+    /* Initialisations */
+    p_vout->pf_init = Init;
+    p_vout->pf_end = End;
+    p_vout->pf_manage = Manage;
+    p_vout->pf_swap = GLSwapBuffers;
+
+    p_vout->p_sys->p_ddobject = NULL;
+    p_vout->p_sys->p_display = NULL;
+    p_vout->p_sys->p_current_surface = NULL;
+    p_vout->p_sys->p_clipper = NULL;
+    p_vout->p_sys->hwnd = p_vout->p_sys->hvideownd = NULL;
+    p_vout->p_sys->hparent = p_vout->p_sys->hfswnd = NULL;
+    p_vout->p_sys->i_changes = 0;
+    p_vout->p_sys->b_wallpaper = 0;
+    vlc_mutex_init( p_vout, &p_vout->p_sys->lock );
+    SetRectEmpty( &p_vout->p_sys->rect_display );
+    SetRectEmpty( &p_vout->p_sys->rect_parent );
+
+    var_Create( p_vout, "video-title", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
+
+    p_vout->p_sys->b_cursor_hidden = 0;
+    p_vout->p_sys->i_lastmoved = mdate();
+
+    /* Set main window's size */
+    p_vout->p_sys->i_window_width = p_vout->i_window_width;
+    p_vout->p_sys->i_window_height = p_vout->i_window_height;
+
+    /* Create the DirectXEventThread, 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.
+     * DirectXEventThread 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 DirectXEventThread" );
+    p_vout->p_sys->p_event =
+        vlc_object_create( p_vout, sizeof(event_thread_t) );
+    p_vout->p_sys->p_event->p_vout = p_vout;
+    if( vlc_thread_create( p_vout->p_sys->p_event, "DirectX Events Thread",
+                           E_(DirectXEventThread), 0, 1 ) )
+    {
+        msg_Err( p_vout, "cannot create DirectXEventThread" );
+        vlc_object_destroy( p_vout->p_sys->p_event );
+        p_vout->p_sys->p_event = NULL;
+        goto error;
+    }
+
+    if( p_vout->p_sys->p_event->b_error )
+    {
+        msg_Err( p_vout, "DirectXEventThread failed" );
+        goto error;
+    }
+
+    vlc_object_attach( p_vout->p_sys->p_event, p_vout );
+
+    msg_Dbg( p_vout, "DirectXEventThread running" );
+
+    /* Variable to indicate if the window should be on top of others */
+    /* Trigger a callback right now */
+    var_Get( p_vout, "video-on-top", &val );
+    var_Set( p_vout, "video-on-top", val );
+
+    return VLC_SUCCESS;
+
+ error:
+    CloseVideo( VLC_OBJECT(p_vout) );
+    return VLC_EGENERIC;
+}
+
+/*****************************************************************************
+ * Init: initialize video thread output method
+ *****************************************************************************/
+static int Init( vout_thread_t *p_vout )
+{
+    PIXELFORMATDESCRIPTOR pfd;
+    int iFormat;
+
+    /* Change the window title bar text */
+    PostMessage( p_vout->p_sys->hwnd, WM_VLC_CHANGE_TEXT, 0, 0 );
+
+    p_vout->p_sys->hGLDC = GetDC( p_vout->p_sys->hvideownd );
+
+    /* Set the pixel format for the DC */
+    memset( &pfd, 0, sizeof( pfd ) );
+    pfd.nSize = sizeof( pfd );
+    pfd.nVersion = 1;
+    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
+    pfd.iPixelType = PFD_TYPE_RGBA;
+    pfd.cColorBits = 24;
+    pfd.cDepthBits = 16;
+    pfd.iLayerType = PFD_MAIN_PLANE;
+    iFormat = ChoosePixelFormat( p_vout->p_sys->hGLDC, &pfd );
+    SetPixelFormat( p_vout->p_sys->hGLDC, iFormat, &pfd );
+
+    /* Create and enable the render context */
+    p_vout->p_sys->hGLRC = wglCreateContext( p_vout->p_sys->hGLDC );
+    wglMakeCurrent( p_vout->p_sys->hGLDC, p_vout->p_sys->hGLRC );
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * End: terminate Sys video thread output method
+ *****************************************************************************
+ * Terminate an output method created by Create.
+ * It is called at the end of the thread.
+ *****************************************************************************/
+static void End( vout_thread_t *p_vout )
+{
+    wglMakeCurrent( NULL, NULL );
+    wglDeleteContext( p_vout->p_sys->hGLRC );
+    ReleaseDC( p_vout->p_sys->hvideownd, p_vout->p_sys->hGLDC );
+    return;
+}
+
+/*****************************************************************************
+ * CloseVideo: destroy Sys video thread output method
+ *****************************************************************************
+ * Terminate an output method created by Create
+ *****************************************************************************/
+static void CloseVideo( vlc_object_t *p_this )
+{
+    vout_thread_t * p_vout = (vout_thread_t *)p_this;
+
+    msg_Dbg( p_vout, "CloseVideo" );
+
+    if( p_vout->p_sys->p_event )
+    {
+        vlc_object_detach( p_vout->p_sys->p_event );
+
+        /* Kill DirectXEventThread */
+        p_vout->p_sys->p_event->b_die = VLC_TRUE;
+
+        /* we need to be sure DirectXEventThread won't stay stuck in
+         * GetMessage, so we send a fake message */
+        if( p_vout->p_sys->hwnd )
+        {
+            PostMessage( p_vout->p_sys->hwnd, WM_NULL, 0, 0);
+        }
+
+        vlc_thread_join( p_vout->p_sys->p_event );
+        vlc_object_destroy( p_vout->p_sys->p_event );
+    }
+
+    vlc_mutex_destroy( &p_vout->p_sys->lock );
+
+    if( p_vout->p_sys )
+    {
+        free( p_vout->p_sys );
+        p_vout->p_sys = NULL;
+    }
+}
+
+/*****************************************************************************
+ * Manage: handle Sys events
+ *****************************************************************************
+ * This function should be called regularly by the video output thread.
+ * It returns a non null value if an error occurred.
+ *****************************************************************************/
+static int Manage( vout_thread_t *p_vout )
+{
+    WINDOWPLACEMENT window_placement;
+
+    int i_width = p_vout->p_sys->rect_dest.right -
+        p_vout->p_sys->rect_dest.left;
+    int i_height = p_vout->p_sys->rect_dest.bottom -
+        p_vout->p_sys->rect_dest.top;
+    glViewport( 0, 0, i_width, i_height );
+
+    /* If we do not control our window, we check for geometry changes
+     * ourselves because the parent might not send us its events. */
+    vlc_mutex_lock( &p_vout->p_sys->lock );
+    if( p_vout->p_sys->hparent && !p_vout->b_fullscreen )
+    {
+        RECT rect_parent;
+        POINT point;
+
+        vlc_mutex_unlock( &p_vout->p_sys->lock );
+
+        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;
+
+            /* 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 );
+        }
+    }
+    else
+    {
+        vlc_mutex_unlock( &p_vout->p_sys->lock );
+    }
+
+    /* 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 )
+    {
+        vlc_value_t val;
+        HWND hwnd = (p_vout->p_sys->hparent && p_vout->p_sys->hfswnd) ?
+            p_vout->p_sys->hfswnd : p_vout->p_sys->hwnd;
+
+        p_vout->b_fullscreen = ! p_vout->b_fullscreen;
+
+        /* We need to switch between Maximized and Normal sized window */
+        window_placement.length = sizeof(WINDOWPLACEMENT);
+        GetWindowPlacement( hwnd, &window_placement );
+        if( p_vout->b_fullscreen )
+        {
+            /* 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 )
+            {
+                /* Retrieve current window position so fullscreen will happen
+                 * on the right screen */
+                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 );
+                GetWindowPlacement( hwnd, &window_placement );
+            }
+
+            /* Maximize window */
+            window_placement.showCmd = SW_SHOWMAXIMIZED;
+            SetWindowPlacement( hwnd, &window_placement );
+            SetWindowPos( hwnd, 0, 0, 0, 0, 0,
+                          SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED);
+
+            if( p_vout->p_sys->hparent )
+            {
+                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 );
+            }
+
+            SetForegroundWindow( hwnd );
+        }
+        else
+        {
+            /* Change window style, no borders and no title bar */
+            SetWindowLong( hwnd, GWL_STYLE, p_vout->p_sys->i_window_style );
+
+            /* Normal window */
+            window_placement.showCmd = SW_SHOWNORMAL;
+            SetWindowPlacement( hwnd, &window_placement );
+            SetWindowPos( hwnd, 0, 0, 0, 0, 0,
+                          SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED);
+
+            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 );
+
+                ShowWindow( hwnd, SW_HIDE );
+                SetForegroundWindow( p_vout->p_sys->hparent );
+            }
+
+            /* Make sure the mouse cursor is displayed */
+            PostMessage( p_vout->p_sys->hwnd, WM_VLC_SHOW_MOUSE, 0, 0 );
+        }
+
+        /* Update the object variable and trigger callback */
+        val.b_bool = p_vout->b_fullscreen;
+        var_Set( p_vout, "fullscreen", val );
+
+        p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
+        p_vout->p_sys->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
+    }
+
+    /*
+     * Pointer change
+     */
+    if( p_vout->b_fullscreen && !p_vout->p_sys->b_cursor_hidden &&
+        (mdate() - p_vout->p_sys->i_lastmoved) > 5000000 )
+    {
+        POINT point;
+        HWND hwnd;
+
+        /* Hide the cursor only if it is inside our window */
+        GetCursorPos( &point );
+        hwnd = WindowFromPoint(point);
+        if( hwnd == p_vout->p_sys->hwnd || hwnd == p_vout->p_sys->hvideownd )
+        {
+            PostMessage( p_vout->p_sys->hwnd, WM_VLC_HIDE_MOUSE, 0, 0 );
+        }
+        else
+        {
+            p_vout->p_sys->i_lastmoved = mdate();
+        }
+    }
+
+    /*
+     * "Always on top" status change
+     */
+    if( p_vout->p_sys->b_on_top_change )
+    {
+        vlc_value_t val;
+        HMENU hMenu = GetSystemMenu( p_vout->p_sys->hwnd, FALSE );
+
+        var_Get( p_vout, "video-on-top", &val );
+
+        /* Set the window on top if necessary */
+        if( val.b_bool && !( 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( !val.b_bool && ( 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 = VLC_FALSE;
+    }
+
+    /* Check if the event thread is still running */
+    if( p_vout->p_sys->p_event->b_die )
+    {
+        return VLC_EGENERIC; /* exit */
+    }
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * GLSwapBuffers: swap front/back buffers
+ *****************************************************************************/
+static void GLSwapBuffers( vout_thread_t *p_vout )
+{
+    SwapBuffers( p_vout->p_sys->hGLDC );
+}
+
+int E_(DirectXUpdateOverlay)( vout_thread_t *p_vout )
+{
+    return 1;
+}