]> git.sesse.net Git - vlc/blobdiff - modules/video_output/wingdi.c
backport [13049] and [13059]
[vlc] / modules / video_output / wingdi.c
index a4f1ad0c21fd1565e7f4784bcb14074f278c368c..34723464a4b29d513565c8d9defb325738d6efb3 100644 (file)
@@ -1,11 +1,11 @@
 /*****************************************************************************
  * wingdi.c : Win32 / WinCE GDI video output plugin for vlc
  *****************************************************************************
- * Copyright (C) 2002 VideoLAN
+ * Copyright (C) 2002 the VideoLAN team
  * $Id$
  *
- * Authors: Samuel Hocevar <sam@zoy.org>
- *          Gildas Bazin <gbazin@videolan.org>
+ * Authors: Gildas Bazin <gbazin@videolan.org>
+ *          Samuel Hocevar <sam@zoy.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
 #include <string.h>
 
 #include <vlc/vlc.h>
+#include <vlc/intf.h>
 #include <vlc/vout.h>
 
 #include <commctrl.h>
 
-#ifdef UNDER_CE
-#   define SHFS_HIDESIPBUTTON   0x0008
+#define SHFS_SHOWSIPBUTTON 0x0004
+#define SHFS_HIDESIPBUTTON 0x0008
+
+#if defined(UNDER_CE) && !defined(__PLUGIN__) /*FIXME*/
 #   define MENU_HEIGHT 26
+    BOOL SHFullScreen(HWND hwndRequester, DWORD dwState);
 #else
-#   define SHFS_HIDESIPBUTTON 0
 #   define MENU_HEIGHT 0
+#   define SHFullScreen(a,b)
 #endif
 
-#undef MODULE_NAME_IS_gapi
-#ifdef MODULE_NAME_IS_gapi
+#ifdef MODULE_NAME_IS_wingapi
     typedef struct GXDisplayProperties {
         DWORD cxWidth;
         DWORD cyHeight;
@@ -73,7 +76,7 @@
 #       define kfDirect444      0x200
 #       define kfDirectInverted 0x400
 #   endif
-#endif /* MODULE_NAME_IS_gapi */
+#endif /* MODULE_NAME_IS_wingapi */
 
 #define MAX_DIRECTBUFFERS 10
 
@@ -90,6 +93,7 @@
 #define SetWindowLongPtr SetWindowLong
 #define GetWindowLongPtr GetWindowLong
 #define GWLP_USERDATA GWL_USERDATA
+#define AdjustWindowRect(a,b,c)
 #endif //UNDER_CE
 
 #ifndef WS_NONAVDONEBUTTON
@@ -105,8 +109,10 @@ static int  Init      ( vout_thread_t * );
 static void End       ( vout_thread_t * );
 static int  Manage    ( vout_thread_t * );
 static void Render    ( vout_thread_t *, picture_t * );
-#ifdef MODULE_NAME_IS_gapi
+#ifdef MODULE_NAME_IS_wingapi
 static void DisplayGAPI( vout_thread_t *, picture_t * );
+static int GAPILockSurface( vout_thread_t *, picture_t * );
+static int GAPIUnlockSurface( vout_thread_t *, picture_t * );
 #else
 static void DisplayGDI( vout_thread_t *, picture_t * );
 #endif
@@ -117,6 +123,8 @@ static long FAR PASCAL WndProc ( HWND, UINT, WPARAM, LPARAM );
 static void InitBuffers        ( vout_thread_t * );
 static void UpdateRects        ( vout_thread_t *, vlc_bool_t );
 
+static int Control( vout_thread_t *p_vout, int i_query, va_list args );
+
 /*****************************************************************************
  * Private structure
  *****************************************************************************/
@@ -140,6 +148,7 @@ struct vout_sys_t
     int          i_window_y;
     int          i_window_width;
     int          i_window_height;
+    int          i_window_style;
     int          render_width;
     int          render_height;
 
@@ -154,7 +163,9 @@ struct vout_sys_t
     /* Our offscreen bitmap and its framebuffer */
     HDC        off_dc;
     HBITMAP    off_bitmap;
-    uint8_t *  p_buffer;
+    uint8_t *  p_pic_buffer;
+    int        i_pic_pitch;
+    int        i_pic_pixel_pitch;
 
     BITMAPINFO bitmapinfo;
     RGBQUAD    red;
@@ -162,11 +173,13 @@ struct vout_sys_t
     RGBQUAD    blue;
 
     /* WINCE stuff */
-    HWND hMenu;
-    HWND hTaskBar;
     vlc_bool_t   b_video_display;
 
-#ifdef MODULE_NAME_IS_gapi
+    /* Window focus states */
+    vlc_bool_t b_focus;
+    vlc_bool_t b_parent_focus;
+
+#ifdef MODULE_NAME_IS_wingapi
     HINSTANCE  gapi_dll;                    /* handle of the opened gapi dll */
 
     /* GAPI functions */
@@ -185,8 +198,14 @@ struct vout_sys_t
 #define GXBeginDraw p_vout->p_sys->GXBeginDraw
 #define GXEndDraw p_vout->p_sys->GXEndDraw
 #define GXGetDisplayProperties p_vout->p_sys->GXGetDisplayProperties
-#define GXSuspend p_vout->p_sys->GXSuspend
-#define GXResume p_vout->p_sys->GXResume
+
+#ifdef MODULE_NAME_IS_wingapi
+#   define GXSuspend p_vout->p_sys->GXSuspend
+#   define GXResume p_vout->p_sys->GXResume
+#else
+#   define GXSuspend()
+#   define GXResume()
+#endif
 
 #define DX_POSITION_CHANGE 0x1000
 
@@ -194,10 +213,14 @@ struct vout_sys_t
  * Module descriptor
  *****************************************************************************/
 vlc_module_begin();
-#ifdef MODULE_NAME_IS_gapi
+    set_category( CAT_VIDEO );
+    set_subcategory( SUBCAT_VIDEO_VOUT );
+#ifdef MODULE_NAME_IS_wingapi
+    set_shortname( _("Windows GAPI") );
     set_description( _("Windows GAPI video output") );
     set_capability( "video output", 20 );
 #else
+    set_shortname( _("Windows GDI") );
     set_description( _("Windows GDI video output") );
     set_capability( "video output", 10 );
 #endif
@@ -215,7 +238,7 @@ static int OpenVideo ( vlc_object_t *p_this )
     p_vout->p_sys = (vout_sys_t *)malloc( sizeof(vout_sys_t) );
     if( !p_vout->p_sys ) return VLC_ENOMEM;
 
-#ifdef MODULE_NAME_IS_gapi
+#ifdef MODULE_NAME_IS_wingapi
     /* Load GAPI */
     p_vout->p_sys->gapi_dll = LoadLibrary( _T("GX.DLL") );
     if( p_vout->p_sys->gapi_dll == NULL )
@@ -280,13 +303,16 @@ static int OpenVideo ( vlc_object_t *p_this )
     p_vout->pf_end = End;
     p_vout->pf_manage = Manage;
     p_vout->pf_render = Render;
-#ifdef MODULE_NAME_IS_gapi
+#ifdef MODULE_NAME_IS_wingapi
     p_vout->pf_display = DisplayGAPI;
 #else
     p_vout->pf_display = DisplayGDI;
 #endif
     p_vout->p_sys->i_changes = 0;
 
+    p_vout->p_sys->b_focus = 0;
+    p_vout->p_sys->b_parent_focus = 0;
+
     return VLC_SUCCESS;
 }
 
@@ -297,15 +323,14 @@ static void CloseVideo ( vlc_object_t *p_this )
 {
     vout_thread_t * p_vout = (vout_thread_t *)p_this;
 
-#ifdef MODULE_NAME_IS_gapi
-    GXCloseDisplay();
-    FreeLibrary( p_vout->p_sys->gapi_dll );
-#endif
-
     p_vout->p_sys->p_event->b_die = VLC_TRUE;
     PostMessage( p_vout->p_sys->hwnd, WM_NULL, 0, 0 );
     vlc_thread_join( p_vout->p_sys->p_event );
 
+#ifdef MODULE_NAME_IS_wingapi
+    FreeLibrary( p_vout->p_sys->gapi_dll );
+#endif
+
     var_Destroy( p_vout->p_sys->p_event, "p_vout" );
     vlc_object_destroy( p_vout->p_sys->p_event );
     free( p_vout->p_sys );
@@ -316,7 +341,6 @@ static void CloseVideo ( vlc_object_t *p_this )
  *****************************************************************************/
 static int Init( vout_thread_t *p_vout )
 {
-    int i_index;
     picture_t *p_pic;
 
     p_vout->p_sys->rect_display.left = 0;
@@ -367,47 +391,41 @@ static int Init( vout_thread_t *p_vout )
         break;
     }
 
-#ifdef MODULE_NAME_IS_gapi
+    p_pic = &p_vout->p_picture[0];
+
+#ifdef MODULE_NAME_IS_wingapi
+    p_vout->output.i_width  = 0;
+    p_vout->output.i_height = 0;
+    p_pic->pf_lock  = GAPILockSurface;
+    p_pic->pf_unlock = GAPIUnlockSurface;
+    Manage( p_vout );
+    GAPILockSurface( p_vout, p_pic );
+    p_vout->i_changes = 0;
     p_vout->output.i_width  = p_vout->p_sys->render_width;
     p_vout->output.i_height = p_vout->p_sys->render_height;
+
 #else
     p_vout->output.i_width  = p_vout->render.i_width;
     p_vout->output.i_height = p_vout->render.i_height;
-#endif
-    p_vout->output.i_aspect = p_vout->render.i_aspect;
-
-    /* Try to initialize MAX_DIRECTBUFFERS direct buffers */
-    while( I_OUTPUTPICTURES < MAX_DIRECTBUFFERS )
-    {
-        p_pic = NULL;
 
-        /* Find an empty picture slot */
-        for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
-        {
-            if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
-            {
-                p_pic = p_vout->p_picture + i_index;
-                break;
-            }
-        }
-
-        /* Allocate the picture */
-        if( p_pic == NULL ) break;
-
-        vout_AllocatePicture( VLC_OBJECT(p_vout), p_pic,
-                              p_vout->output.i_chroma,
-                              p_vout->output.i_width, p_vout->output.i_height,
-                              p_vout->output.i_aspect );
-
-        if( p_pic->i_planes == 0 ) break;
+    p_vout->fmt_out = p_vout->fmt_in;
+    p_vout->fmt_out.i_chroma = p_vout->output.i_chroma;
+#endif
 
-        p_pic->i_status = DESTROYED_PICTURE;
-        p_pic->i_type   = DIRECT_PICTURE;
+    p_vout->output.i_aspect = p_vout->render.i_aspect;
 
-        PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
+    p_pic->p->p_pixels = p_vout->p_sys->p_pic_buffer;
+    p_pic->p->i_lines = p_vout->output.i_height;
+    p_pic->p->i_visible_lines = p_vout->output.i_height;
+    p_pic->p->i_pitch = p_vout->p_sys->i_pic_pitch;
+    p_pic->p->i_pixel_pitch = p_vout->p_sys->i_pic_pixel_pitch;
+    p_pic->p->i_visible_pitch = p_vout->output.i_width *
+        p_pic->p->i_pixel_pitch;
+    p_pic->i_planes = 1;
+    p_pic->i_status = DESTROYED_PICTURE;
+    p_pic->i_type   = DIRECT_PICTURE;
 
-        I_OUTPUTPICTURES++;
-    }
+    PP_OUTPUTPICTURE[ I_OUTPUTPICTURES++ ] = p_pic;
 
     return VLC_SUCCESS;
 }
@@ -417,14 +435,6 @@ static int Init( vout_thread_t *p_vout )
  *****************************************************************************/
 static void End( vout_thread_t *p_vout )
 {
-    int i_index;
-
-    /* Free the fake output buffers we allocated */
-    for( i_index = I_OUTPUTPICTURES ; i_index ; )
-    {
-        i_index--;
-        free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
-    }
 }
 
 /*****************************************************************************
@@ -570,18 +580,10 @@ static int Manage( vout_thread_t *p_vout )
             //PostMessage( p_vout->p_sys->hwnd, WM_VLC_SHOW_MOUSE, 0, 0 );
         }
 
-#ifdef MODULE_NAME_IS_gapi
-        GXCloseDisplay();
-#endif
-
         /* Change window style, borders and title bar */
         ShowWindow( p_vout->p_sys->hwnd, SW_SHOW );
         UpdateWindow( p_vout->p_sys->hwnd );
 
-#ifdef MODULE_NAME_IS_gapi
-        GXOpenDisplay( p_vout->p_sys->hvideownd, GX_FULLSCREEN );
-#endif
-
         /* Update the object variable and trigger callback */
         val.b_bool = p_vout->b_fullscreen;
         var_Set( p_vout, "fullscreen", val );
@@ -609,34 +611,16 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic )
 #define rect_dest p_vout->p_sys->rect_dest
 #define rect_dest_clipped p_vout->p_sys->rect_dest_clipped
 
-#ifndef MODULE_NAME_IS_gapi
+#ifndef MODULE_NAME_IS_wingapi
 static void DisplayGDI( vout_thread_t *p_vout, picture_t *p_pic )
 {
     vout_sys_t *p_sys = p_vout->p_sys;
-    int i_src_bytes, i_dest_bytes;
     RECT rect_dst = rect_dest_clipped;
     HDC hdc = GetDC( p_sys->hvideownd );
 
     OffsetRect( &rect_dst, -rect_dest.left, -rect_dest.top );
     SelectObject( p_sys->off_dc, p_sys->off_bitmap );
 
-#if 1
-    /* Stupid GDI is upside-down */
-    i_src_bytes = p_pic->p->i_lines * p_pic->p->i_pitch;
-    i_dest_bytes = 0;
-
-    while( i_src_bytes )
-    {
-        i_src_bytes -= p_pic->p->i_pitch;
-
-        p_vout->p_vlc->pf_memcpy( p_sys->p_buffer + i_dest_bytes,
-                                  p_pic->p->p_pixels + i_src_bytes,
-                                  p_pic->p->i_visible_pitch );
-
-        i_dest_bytes += p_pic->p->i_pitch;
-    }
-#endif
-
     if( rect_dest_clipped.right - rect_dest_clipped.left !=
         rect_src_clipped.right - rect_src_clipped.left ||
         rect_dest_clipped.bottom - rect_dest_clipped.top !=
@@ -659,7 +643,7 @@ static void DisplayGDI( vout_thread_t *p_vout, picture_t *p_pic )
 }
 #else
 
-static void DisplayGAPI( vout_thread_t *p_vout, picture_t *p_pic )
+static int GAPILockSurface( vout_thread_t *p_vout, picture_t *p_pic )
 {
     vout_sys_t *p_sys = p_vout->p_sys;
     int i_x, i_y, i_width, i_height;
@@ -670,7 +654,7 @@ static void DisplayGAPI( vout_thread_t *p_vout, picture_t *p_pic )
     if( ( GetForegroundWindow() != GetParent(p_sys->hwnd) ) ||
         ( p_sys->b_video_display == VLC_FALSE ) )
     {
-        return;
+        //return VLC_EGENERIC;
     }
 
     GetClientRect( p_sys->hwnd, &video_rect);
@@ -685,9 +669,19 @@ static void DisplayGAPI( vout_thread_t *p_vout, picture_t *p_pic )
     if( i_width != p_vout->output.i_width ||
         i_height != p_vout->output.i_height )
     {
+        GXDisplayProperties gxdisplayprop = GXGetDisplayProperties();
+
         p_sys->render_width = i_width;
         p_sys->render_height = i_height;
         p_vout->i_changes |= VOUT_SIZE_CHANGE;
+
+        msg_Dbg( p_vout, "vout size change (%ix%i -> %ix%i)",
+                 i_width, i_height, p_vout->output.i_width,
+                 p_vout->output.i_height );
+
+        p_vout->p_sys->i_pic_pixel_pitch = gxdisplayprop.cbxPitch;
+        p_vout->p_sys->i_pic_pitch = gxdisplayprop.cbyPitch;
+        return VLC_EGENERIC;
     }
     else
     {
@@ -706,7 +700,7 @@ static void DisplayGAPI( vout_thread_t *p_vout, picture_t *p_pic )
 
         if( !IntersectRect( &dest_rect, &video_rect, &display_rect ) )
         {
-            return;
+            return VLC_EGENERIC;
         }
 
 #if 0
@@ -722,8 +716,10 @@ static void DisplayGAPI( vout_thread_t *p_vout, picture_t *p_pic )
 
         if( !(p_dest = GXBeginDraw()) )
         {
+#if 0
             msg_Err( p_vout, "GXBeginDraw error %d ", GetLastError() );
-            return;
+#endif
+            return VLC_EGENERIC;
         }
 
         p_src += (dest_rect.left - video_rect.left) * gxdisplayprop.cbxPitch +
@@ -733,16 +729,20 @@ static void DisplayGAPI( vout_thread_t *p_vout, picture_t *p_pic )
         i_width = dest_rect.right - dest_rect.left;
         i_height = dest_rect.bottom - dest_rect.top;
 
-        while( i_height-- )
-        {
-            p_vout->p_vlc->pf_memcpy( p_dest, p_src,
-                                      i_width * gxdisplayprop.cbxPitch );
-            p_src += p_pic->p->i_pitch;
-            p_dest += gxdisplayprop.cbyPitch;
-        }
+        p_pic->p->p_pixels = p_dest;
     }
 
+    return VLC_SUCCESS;
+}
+
+static int GAPIUnlockSurface( vout_thread_t *p_vout, picture_t *p_pic )
+{
     GXEndDraw();
+    return VLC_SUCCESS;
+}
+
+static void DisplayGAPI( vout_thread_t *p_vout, picture_t *p_pic )
+{
 }
 #endif
 
@@ -771,6 +771,7 @@ static void EventThread ( vlc_object_t *p_event )
     WNDCLASS   wc;
     MSG        msg;
 
+    /* Initialisations */
     var_Get( p_event, "p_vout", &val );
     p_vout = (vout_thread_t *)val.p_address;
 
@@ -793,19 +794,22 @@ static void EventThread ( vlc_object_t *p_event )
     RegisterClass(&wc);
 
     /* Create output window */
-    p_vout->p_sys->hparent = p_vout->p_sys->hwnd = (HWND)
+    p_vout->p_sys->hparent = (HWND)
         vout_RequestWindow( p_vout, &p_vout->p_sys->i_window_x,
                             &p_vout->p_sys->i_window_y,
                             (unsigned int *)&p_vout->p_sys->i_window_width,
                             (unsigned int *)&p_vout->p_sys->i_window_height );
 
-    ShowWindow( p_vout->p_sys->hparent, SW_SHOW );
+    if( p_vout->p_sys->hparent )
+        ShowWindow( p_vout->p_sys->hparent, SW_SHOW );
 
     if( p_vout->p_sys->hparent )
         i_style = WS_VISIBLE|WS_CLIPCHILDREN|WS_CHILD;
     else
         i_style = WS_OVERLAPPEDWINDOW|WS_SIZEBOX|WS_VISIBLE|WS_CLIPCHILDREN;
 
+    p_vout->p_sys->i_window_style = i_style;
+
     p_vout->p_sys->hwnd =
         CreateWindow( _T("VLC WinGDI"), _T(VOUT_TITLE), i_style,
                       (p_vout->p_sys->i_window_x < 0) ? CW_USEDEFAULT :
@@ -843,7 +847,7 @@ static void EventThread ( vlc_object_t *p_event )
                             WS_NONAVDONEBUTTON|WS_CLIPCHILDREN,
                             CW_USEDEFAULT, CW_USEDEFAULT,
                             CW_USEDEFAULT, CW_USEDEFAULT,
-                            NULL, NULL, GetModuleHandle(NULL), NULL );
+                            NULL, NULL, GetModuleHandle(NULL), (LPVOID)p_vout);
     }
 
     /* Display our window */
@@ -860,11 +864,11 @@ static void EventThread ( vlc_object_t *p_event )
                     NULL, GetModuleHandle(NULL),
                     (LPVOID)p_vout );            /* send p_vout to WM_CREATE */
 
-    ShowWindow( p_vout->p_sys->hvideownd, SW_SHOW );
-
     /* Initialize offscreen buffer */
     InitBuffers( p_vout );
 
+    p_vout->pf_control = Control;
+
     /* Tell the video output we're ready to receive data */
     vlc_thread_ready( p_event );
 
@@ -895,16 +899,6 @@ static void EventThread ( vlc_object_t *p_event )
             }
             break;
 
-#ifdef MODULE_NAME_IS_gapi
-        case WM_KILLFOCUS:
-            GXSuspend();
-            break;
-
-        case WM_SETFOCUS:
-            GXResume();
-            break;
-#endif
-
         default:
             TranslateMessage( &msg );
             DispatchMessage( &msg );
@@ -914,14 +908,18 @@ static void EventThread ( vlc_object_t *p_event )
 
     msg_Dbg( p_vout, "CloseWindow" );
 
+#ifdef MODULE_NAME_IS_wingapi
+    GXCloseDisplay();
+#else
+    DeleteDC( p_vout->p_sys->off_dc );
+    DeleteObject( p_vout->p_sys->off_bitmap );
+#endif
+
     DestroyWindow( p_vout->p_sys->hwnd );
     if( p_vout->p_sys->hfswnd ) DestroyWindow( p_vout->p_sys->hfswnd );
 
     if( p_vout->p_sys->hparent )
         vout_ReleaseWindow( p_vout, (void *)p_vout->p_sys->hparent );
-
-    DeleteDC( p_vout->p_sys->off_dc );
-    DeleteObject( p_vout->p_sys->off_bitmap );
 }
 
 /*****************************************************************************
@@ -1044,8 +1042,8 @@ static void UpdateRects( vout_thread_t *p_vout, vlc_bool_t b_force )
 /*****************************************************************************
  * Message handler for the main window
  *****************************************************************************/
-static long FAR PASCAL WndProc ( HWND hWnd, UINT message,
-                                 WPARAM wParam, LPARAM lParam )
+static long FAR PASCAL WndProc( HWND hWnd, UINT message,
+                                WPARAM wParam, LPARAM lParam )
 {
     vout_thread_t *p_vout;
 
@@ -1078,14 +1076,70 @@ static long FAR PASCAL WndProc ( HWND hWnd, UINT message,
         return DefWindowProc(hWnd, message, wParam, lParam);
     }
 
-    if( hWnd != p_vout->p_sys->hwnd )
+    if( hWnd != p_vout->p_sys->hwnd &&
+        hWnd != p_vout->p_sys->hfswnd &&
+        hWnd != p_vout->p_sys->hvideownd )
         return DefWindowProc(hWnd, message, wParam, lParam);
 
     switch( message )
     {
     case WM_WINDOWPOSCHANGED:
-        UpdateRects( p_vout, VLC_TRUE );
+        if( hWnd == p_vout->p_sys->hwnd )
+            UpdateRects( p_vout, VLC_TRUE );
+        break;
+
+#if 0
+    case WM_ACTIVATE:
+        msg_Err( p_vout, "WM_ACTIVATE: %i", wParam );
+        if( wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE )
+            GXResume();
+        else if( wParam == WA_INACTIVE )
+            GXSuspend();
+        break;
+#endif
+
+    case WM_KILLFOCUS:
+        p_vout->p_sys->b_focus = VLC_FALSE;
+        if( !p_vout->p_sys->b_parent_focus ) GXSuspend();
+
+        if( hWnd == p_vout->p_sys->hfswnd )
+        {
+#ifdef UNDER_CE
+            HWND htbar = FindWindow( _T("HHTaskbar"), NULL );
+            ShowWindow( htbar, SW_SHOW );
+#endif
+        }
+
+        if( !p_vout->p_sys->hparent ||
+            hWnd == p_vout->p_sys->hfswnd )
+        {
+            SHFullScreen( hWnd, SHFS_SHOWSIPBUTTON );
+        }
         break;
+
+    case WM_SETFOCUS:
+        p_vout->p_sys->b_focus = VLC_TRUE;
+        GXResume();
+
+        if( p_vout->p_sys->hparent &&
+            hWnd != p_vout->p_sys->hfswnd && p_vout->b_fullscreen )
+            p_vout->p_sys->i_changes |= VOUT_FULLSCREEN_CHANGE;
+
+        if( hWnd == p_vout->p_sys->hfswnd )
+        {
+#ifdef UNDER_CE
+            HWND htbar = FindWindow( _T("HHTaskbar"), NULL );
+            ShowWindow( htbar, SW_HIDE );
+#endif
+        }
+
+        if( !p_vout->p_sys->hparent ||
+            hWnd == p_vout->p_sys->hfswnd )
+        {
+            SHFullScreen( hWnd, SHFS_HIDESIPBUTTON );
+        }
+        break;
+
     case WM_LBUTTONDOWN:
         p_vout->p_sys->i_changes |= VOUT_FULLSCREEN_CHANGE;
         break;
@@ -1094,9 +1148,6 @@ static long FAR PASCAL WndProc ( HWND hWnd, UINT message,
     case WM_LBUTTONUP:
         break;
 
-    case WM_CREATE:
-        break;
-
     case WM_INITMENUPOPUP:
         p_vout->p_sys->b_video_display = VLC_FALSE;
         break;
@@ -1108,6 +1159,19 @@ static long FAR PASCAL WndProc ( HWND hWnd, UINT message,
             p_vout->p_sys->b_video_display = VLC_TRUE;
         break;
 
+    /* the user wants to close the window */
+    case WM_CLOSE:
+    {
+        playlist_t * p_playlist =
+            (playlist_t *)vlc_object_find( p_vout, VLC_OBJECT_PLAYLIST,
+                                           FIND_ANYWHERE );
+        if( p_playlist == NULL ) return 0;
+
+        playlist_Stop( p_playlist );
+        vlc_object_release( p_playlist );
+        return 0;
+    }
+
     case WM_DESTROY:
         msg_Dbg( p_vout, "WinProc WM_DESTROY" );
         PostQuitMessage( 0 );
@@ -1128,60 +1192,21 @@ static void InitBuffers( vout_thread_t *p_vout )
     BITMAPINFOHEADER *p_header = &p_vout->p_sys->bitmapinfo.bmiHeader;
     BITMAPINFO *p_info = &p_vout->p_sys->bitmapinfo;
     int i_pixels = p_vout->render.i_height * p_vout->render.i_width;
-    HDC window_dc;
-
-    window_dc = GetDC( p_vout->p_sys->hvideownd );
+    HDC window_dc = GetDC( p_vout->p_sys->hvideownd );
 
     /* Get screen properties */
-#ifdef MODULE_NAME_IS_gapi
-    {
+#ifdef MODULE_NAME_IS_wingapi
     GXDisplayProperties gx_displayprop = GXGetDisplayProperties();
     p_vout->p_sys->i_depth = gx_displayprop.cBPP;
-    }
 #else
     p_vout->p_sys->i_depth = GetDeviceCaps( window_dc, PLANES ) *
         GetDeviceCaps( window_dc, BITSPIXEL );
 #endif
     msg_Dbg( p_vout, "GDI depth is %i", p_vout->p_sys->i_depth );
 
-#ifdef MODULE_NAME_IS_gapi
-    if( p_vout->b_fullscreen )
-    {
-        /* We need to restore Maximized sized window */
-        GetWindowRect( p_vout->p_sys->hwnd,
-                       &p_vout->p_sys->window_placement );
-
-        /* Maximized window */
-        if( p_vout->p_sys->hparent )
-        {
-            SetWindowPos( GetParent( p_vout->p_sys->hwnd ), HWND_TOP,
-                          0, 0, GetSystemMetrics(SM_CXSCREEN),
-                          GetSystemMetrics(SM_CYSCREEN), SWP_SHOWWINDOW );
-            SetWindowPos( p_vout->p_sys->hwnd, HWND_TOP,
-                          0, 0, GetSystemMetrics(SM_CXSCREEN),
-                          GetSystemMetrics(SM_CYSCREEN), SWP_SHOWWINDOW );
-
-#ifdef UNDER_CE
-            /* Hide SIP button, taskbar and menubar */
-            SHFullScreen( GetParent(p_vout->p_sys->hwnd),
-                          SHFS_HIDESIPBUTTON );
-            p_vout->p_sys->hTaskBar = FindWindow(_T("HHTaskbar"),NULL);
-            ShowWindow( p_vout->p_sys->hTaskBar, SW_HIDE);
-            p_vout->p_sys->hMenu =
-              SHFindMenuBar( GetParent( p_vout->p_sys->hwnd ) );
-            ShowWindow( p_vout->p_sys->hMenu,SW_HIDE );
-#endif
-        }
-        else
-        {
-            SetWindowPos( p_vout->p_sys->hwnd, HWND_TOP,
-                          0, 0, CW_USEDEFAULT, CW_USEDEFAULT, SWP_SHOWWINDOW );
-        }
-
-        GXCloseDisplay();
-    }
-
+#ifdef MODULE_NAME_IS_wingapi
     GXOpenDisplay( p_vout->p_sys->hvideownd, GX_FULLSCREEN );
+
 #else
 
     /* Initialize offscreen bitmap */
@@ -1232,15 +1257,18 @@ static void InitBuffers( vout_thread_t *p_vout )
         break;
     }
     p_header->biWidth = p_vout->render.i_width;
-    p_header->biHeight = p_vout->render.i_height;
+    p_header->biHeight = -p_vout->render.i_height;
     p_header->biClrImportant = 0;
     p_header->biClrUsed = 0;
     p_header->biXPelsPerMeter = 0;
     p_header->biYPelsPerMeter = 0;
 
+    p_vout->p_sys->i_pic_pixel_pitch = p_header->biBitCount / 8;
+    p_vout->p_sys->i_pic_pitch = p_header->biBitCount * p_header->biWidth / 8;
+
     p_vout->p_sys->off_bitmap =
         CreateDIBSection( window_dc, (BITMAPINFO *)p_header, DIB_RGB_COLORS,
-                          (void**)&p_vout->p_sys->p_buffer, NULL, 0 );
+                          (void**)&p_vout->p_sys->p_pic_buffer, NULL, 0 );
 
     p_vout->p_sys->off_dc = CreateCompatibleDC( window_dc );
 
@@ -1248,3 +1276,70 @@ static void InitBuffers( vout_thread_t *p_vout )
     ReleaseDC( 0, window_dc );
 #endif
 }
+
+/*****************************************************************************
+ * Control: control facility for the vout
+ *****************************************************************************/
+static int Control( vout_thread_t *p_vout, int i_query, va_list args )
+{
+    vlc_bool_t b_bool;
+    double f_arg;
+    RECT rect_window;
+    POINT point;
+
+    switch( i_query )
+    {
+    case VOUT_SET_ZOOM:
+        if( p_vout->p_sys->hparent )
+            return vout_ControlWindow( p_vout,
+                    (void *)p_vout->p_sys->hparent, i_query, args );
+
+        /* Update dimensions */
+        rect_window.top = rect_window.left = 0;
+        rect_window.right  = p_vout->i_window_width;
+        rect_window.bottom = p_vout->i_window_height;
+        AdjustWindowRect( &rect_window, p_vout->p_sys->i_window_style, 0 );
+
+        SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
+                      rect_window.right - rect_window.left,
+                      rect_window.bottom - rect_window.top, SWP_NOMOVE );
+
+        return VLC_SUCCESS;
+
+    case VOUT_CLOSE:
+        ShowWindow( p_vout->p_sys->hwnd, SW_HIDE );
+    case VOUT_REPARENT:
+        /* Change window style, borders and title bar */
+        //vlc_mutex_lock( &p_vout->p_sys->lock );
+        p_vout->p_sys->hparent = 0;
+        //vlc_mutex_unlock( &p_vout->p_sys->lock );
+
+        /* Retrieve the window position */
+        point.x = point.y = 0;
+        ClientToScreen( p_vout->p_sys->hwnd, &point );
+
+        SetParent( p_vout->p_sys->hwnd, 0 );
+        p_vout->p_sys->i_window_style =
+            WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW | WS_SIZEBOX;
+        SetWindowLong( p_vout->p_sys->hwnd, GWL_STYLE,
+                       p_vout->p_sys->i_window_style |
+                       (i_query == VOUT_CLOSE ? 0 : WS_VISIBLE) );
+        SetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW );
+        SetWindowPos( p_vout->p_sys->hwnd, 0, point.x, point.y, 0, 0,
+                      SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED );
+
+        return vout_vaControlDefault( p_vout, i_query, args );
+
+    case VOUT_SET_FOCUS:
+        b_bool = va_arg( args, vlc_bool_t );
+
+        p_vout->p_sys->b_parent_focus = b_bool;
+        if( b_bool ) GXResume();
+        else if( !p_vout->p_sys->b_focus ) GXSuspend();
+
+        return VLC_SUCCESS;
+
+    default:
+        return vout_vaControlDefault( p_vout, i_query, args );
+    }
+}