]> git.sesse.net Git - vlc/blobdiff - modules/gui/beos/VideoOutput.cpp
Removes trailing spaces. Removes tabs.
[vlc] / modules / gui / beos / VideoOutput.cpp
index 92748917c265fc3722ee90a42e7b10184e2a5bde..24a30010345e48f2d550c031d9a83c428b6f3a8e 100644 (file)
@@ -1,19 +1,20 @@
 /*****************************************************************************
- * vout.cpp: beos video output display method
+ * vout_beos.cpp: beos video output display method
  *****************************************************************************
- * Copyright (C) 2000, 2001 VideoLAN
- * $Id: VideoOutput.cpp,v 1.1 2002/08/04 17:23:43 sam Exp $
+ * Copyright (C) 2000, 2001 the VideoLAN team
+ * $Id$
  *
  * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
  *          Samuel Hocevar <sam@zoy.org>
  *          Tony Castley <tcastley@mail.powerup.com.au>
  *          Richard Shepherd <richard@rshepherd.demon.co.uk>
+ *          Stephan Aßmus <stippi@yellowbites.com>
  *
  * 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
  *
  * 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.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 /*****************************************************************************
  * Preamble
  *****************************************************************************/
 #include <errno.h>                                                 /* ENOMEM */
-#include <stdlib.h>                                                /* free() */
-#include <stdio.h>
-#include <string.h>                                            /* strerror() */
-#include <InterfaceKit.h>
-#include <DirectWindow.h>
+
 #include <Application.h>
+#include <BitmapStream.h>
 #include <Bitmap.h>
+#include <Directory.h>
+#include <DirectWindow.h>
+#include <File.h>
+#include <InterfaceKit.h>
+#include <NodeInfo.h>
+#include <String.h>
+#include <TranslatorRoster.h>
+#include <WindowScreen.h>
 
+/* VLC headers */
 #include <vlc/vlc.h>
-#include <vlc/intf.h>
-#include <vlc/vout.h>
+#include <vlc_interface.h>
+#include <vlc_vout.h>
+#include <vlc_keys.h>
 
-#include "VideoWindow.h"
+#include "InterfaceWindow.h"    // for load/save_settings()
 #include "DrawingTidbits.h"
 #include "MsgVals.h"
 
+#include "VideoWindow.h"
 
 /*****************************************************************************
  * vout_sys_t: BeOS video output method descriptor
@@ -55,21 +64,27 @@ struct vout_sys_t
 {
     VideoWindow *  p_window;
 
-    s32 i_width;
-    s32 i_height;
+    int32_t i_width;
+    int32_t i_height;
 
-    u32 source_chroma;
+//    uint8_t *pp_buffer[3];
+    uint32_t source_chroma;
     int i_index;
+
 };
 
+#define MOUSE_IDLE_TIMEOUT 2000000    // two seconds
+#define MIN_AUTO_VSYNC_REFRESH 61    // Hz
+
 /*****************************************************************************
  * beos_GetAppWindow : retrieve a BWindow pointer from the window name
  *****************************************************************************/
-BWindow *beos_GetAppWindow(char *name)
+BWindow*
+beos_GetAppWindow(char *name)
 {
-    int32       index;
+    int32_t     index;
     BWindow     *window;
-    
+
     for (index = 0 ; ; index++)
     {
         window = be_app->WindowAt(index);
@@ -85,294 +100,886 @@ BWindow *beos_GetAppWindow(char *name)
             window->Unlock();
         }
     }
-    return window; 
+    return window;
+}
+
+static const int beos_keys[][2] =
+{
+    { B_LEFT_ARROW,  KEY_LEFT },
+    { B_RIGHT_ARROW, KEY_RIGHT },
+    { B_UP_ARROW,    KEY_UP },
+    { B_DOWN_ARROW,  KEY_DOWN },
+    { B_SPACE,       KEY_SPACE },
+    { B_ENTER,       KEY_ENTER },
+    { B_F1_KEY,      KEY_F1 },
+    { B_F2_KEY,      KEY_F2 },
+    { B_F3_KEY,      KEY_F3 },
+    { B_F4_KEY,      KEY_F4 },
+    { B_F5_KEY,      KEY_F5 },
+    { B_F6_KEY,      KEY_F6 },
+    { B_F7_KEY,      KEY_F7 },
+    { B_F8_KEY,      KEY_F8 },
+    { B_F9_KEY,      KEY_F9 },
+    { B_F10_KEY,     KEY_F10 },
+    { B_F11_KEY,     KEY_F11 },
+    { B_F12_KEY,     KEY_F12 },
+    { B_HOME,        KEY_HOME },
+    { B_END,         KEY_END },
+    { B_ESCAPE,      KEY_ESC },
+    { B_PAGE_UP,     KEY_PAGEUP },
+    { B_PAGE_DOWN,   KEY_PAGEDOWN },
+    { B_TAB,         KEY_TAB },
+    { B_BACKSPACE,   KEY_BACKSPACE }
+};
+
+static int ConvertKeyFromVLC( int key )
+{
+    for( unsigned i = 0; i < sizeof( beos_keys ) / sizeof( int ) / 2; i++ )
+    {
+        if( beos_keys[i][1] == key )
+        {
+            return beos_keys[i][0];
+        }
+    }
+    return key;
+}
+
+static int ConvertKeyToVLC( int key )
+{
+    for( unsigned i = 0; i < sizeof( beos_keys ) / sizeof( int ) / 2; i++ )
+    {
+        if( beos_keys[i][0] == key )
+        {
+            return beos_keys[i][1];
+        }
+    }
+    return key;
+}
+
+/*****************************************************************************
+ * get_interface_window
+ *****************************************************************************/
+BWindow*
+get_interface_window()
+{
+    return beos_GetAppWindow( "VLC " PACKAGE_VERSION );
+}
+
+class BackgroundView : public BView
+{
+ public:
+                            BackgroundView(BRect frame, VLCView* view)
+                            : BView(frame, "background",
+                                    B_FOLLOW_ALL, B_FULL_UPDATE_ON_RESIZE),
+                              fVideoView(view)
+                            {
+                                SetViewColor(kBlack);
+                            }
+    virtual                    ~BackgroundView() {}
+
+    virtual    void            MouseDown(BPoint where)
+                            {
+                                // convert coordinates
+                                where = fVideoView->ConvertFromParent(where);
+                                // let him handle it
+                                fVideoView->MouseDown(where);
+                            }
+    virtual    void            MouseMoved(BPoint where, uint32_t transit,
+                                       const BMessage* dragMessage)
+                            {
+                                // convert coordinates
+                                where = fVideoView->ConvertFromParent(where);
+                                // let him handle it
+                                fVideoView->MouseMoved(where, transit, dragMessage);
+                                // notice: It might look like transit should be
+                                // B_OUTSIDE_VIEW regardless, but leave it like this,
+                                // otherwise, unwanted things will happen!
+                            }
+
+ private:
+    VLCView*                fVideoView;
+};
+
+
+/*****************************************************************************
+ * VideoSettings constructor and destructor
+ *****************************************************************************/
+VideoSettings::VideoSettings()
+    : fVideoSize( SIZE_100 ),
+      fFlags( FLAG_CORRECT_RATIO ),
+      fSettings( new BMessage( 'sett' ) )
+{
+    // read settings from disk
+    status_t ret = load_settings( fSettings, "video_settings", "VideoLAN Client" );
+    if ( ret == B_OK )
+    {
+        uint32_t flags;
+        if ( fSettings->FindInt32( "flags", (int32*)&flags ) == B_OK )
+            SetFlags( flags );
+        uint32_t size;
+        if ( fSettings->FindInt32( "video size", (int32*)&size ) == B_OK )
+            SetVideoSize( size );
+    }
+    else
+    {
+        // figure out if we should use vertical sync by default
+        BScreen screen(B_MAIN_SCREEN_ID);
+        if (screen.IsValid())
+        {
+            display_mode mode;
+            screen.GetMode(&mode);
+            float refresh = (mode.timing.pixel_clock * 1000)
+                            / ((mode.timing.h_total)* (mode.timing.v_total));
+            if (refresh < MIN_AUTO_VSYNC_REFRESH)
+                AddFlags(FLAG_SYNC_RETRACE);
+        }
+    }
+}
+
+VideoSettings::VideoSettings( const VideoSettings& clone )
+    : fVideoSize( clone.VideoSize() ),
+      fFlags( clone.Flags() ),
+      fSettings( NULL )
+{
+}
+
+
+VideoSettings::~VideoSettings()
+{
+    if ( fSettings )
+    {
+        // we are the default settings
+        // and write our settings to disk
+        if (fSettings->ReplaceInt32( "video size", VideoSize() ) != B_OK)
+            fSettings->AddInt32( "video size", VideoSize() );
+        if (fSettings->ReplaceInt32( "flags", Flags() ) != B_OK)
+            fSettings->AddInt32( "flags", Flags() );
+
+        save_settings( fSettings, "video_settings", "VideoLAN Client" );
+        delete fSettings;
+    }
+    else
+    {
+        // we are just a clone of the default settings
+        fDefaultSettings.SetVideoSize( VideoSize() );
+        fDefaultSettings.SetFlags( Flags() );
+    }
+}
+
+/*****************************************************************************
+ * VideoSettings::DefaultSettings
+ *****************************************************************************/
+VideoSettings*
+VideoSettings::DefaultSettings()
+{
+    return &fDefaultSettings;
 }
 
+/*****************************************************************************
+ * VideoSettings::SetVideoSize
+ *****************************************************************************/
+void
+VideoSettings::SetVideoSize( uint32_t mode )
+{
+    fVideoSize = mode;
+}
+
+// static variable initialization
+VideoSettings
+VideoSettings::fDefaultSettings;
+
+
 /*****************************************************************************
  * VideoWindow constructor and destructor
  *****************************************************************************/
-VideoWindow::VideoWindow( int v_width, int v_height, 
-                          BRect frame )
-            : BWindow( frame, NULL, B_TITLED_WINDOW, 
-                    B_NOT_CLOSABLE | B_NOT_MINIMIZABLE )
+VideoWindow::VideoWindow(int v_width, int v_height, BRect frame,
+                         vout_thread_t *p_videoout)
+    : BWindow(frame, NULL, B_TITLED_WINDOW, B_NOT_CLOSABLE | B_NOT_MINIMIZABLE),
+      i_width(frame.IntegerWidth()),
+      i_height(frame.IntegerHeight()),
+      winSize(frame),
+      i_buffer(0),
+      teardownwindow(false),
+      fTrueWidth(v_width),
+      fTrueHeight(v_height),
+      fCachedFeel(B_NORMAL_WINDOW_FEEL),
+      fInterfaceShowing(false),
+      fInitStatus(B_ERROR),
+      fSettings(new VideoSettings(*VideoSettings::DefaultSettings()))
 {
-    BView *mainView =  new BView( Bounds(), "mainView", 
-                                  B_FOLLOW_ALL, B_FULL_UPDATE_ON_RESIZE);
+    p_vout = p_videoout;
+
+    // create the view to do the display
+    view = new VLCView( Bounds(), p_vout );
+
+    // create background view
+    BView *mainView =  new BackgroundView( Bounds(), view );
     AddChild(mainView);
-    mainView->SetViewColor(kBlack);
-                                  
-    /* create the view to do the display */
-    view = new VLCView( Bounds() );
     mainView->AddChild(view);
 
-    /* set the VideoWindow variables */
-    teardownwindow = false;
-    is_zoomed = false;
-    vsync = false;
-    i_buffer = 0;
-
-    /* call ScreenChanged to set vsync correctly */
-    BScreen *screen;
-    display_mode disp_mode; 
-    float refresh;
-
-    screen = new BScreen(this);
-    
-    screen-> GetMode(&disp_mode); 
-    refresh = 
-         (disp_mode.timing.pixel_clock * 1000)/((disp_mode.timing.h_total)* 
-         (disp_mode.timing.v_total)); 
-    if (refresh  < 61) 
-    { 
-        vsync = true; 
-    } 
-    delete screen;
-    
-    mode = SelectDrawingMode(v_width, v_height);
-
-    // remember current settings
-    i_width = v_width;
-    i_height = v_height;
-    FrameResized(v_width, v_height);
-
-    if (mode == OVERLAY)
+    // allocate bitmap buffers
+    for (int32_t i = 0; i < 3; i++)
+        bitmap[i] = NULL;
+    fInitStatus = _AllocateBuffers(v_width, v_height, &mode);
+
+    // make sure we layout the view correctly
+    FrameResized(i_width, i_height);
+
+    if (fInitStatus >= B_OK && mode == OVERLAY)
     {
        overlay_restrictions r;
 
-       bitmap[1]->GetOverlayRestrictions(&r);
-       SetSizeLimits((i_width * r.min_width_scale) + 1, i_width * r.max_width_scale,
-                     (i_height * r.min_height_scale) + 1, i_height * r.max_height_scale);
+       bitmap[0]->GetOverlayRestrictions(&r);
+       SetSizeLimits((i_width * r.min_width_scale), i_width * r.max_width_scale,
+                     (i_height * r.min_height_scale), i_height * r.max_height_scale);
     }
-    Show();
+
+    // vlc settings override settings from disk
+    if (config_GetInt(p_vout, "fullscreen"))
+        fSettings->AddFlags(VideoSettings::FLAG_FULL_SCREEN);
+
+    _SetToSettings();
 }
 
 VideoWindow::~VideoWindow()
 {
+    int32 result;
+
     teardownwindow = true;
-    delete bitmap[0];
-    delete bitmap[1];
-    delete bitmap[2];
+    wait_for_thread(fDrawThreadID, &result);
+    _FreeBuffers();
+    delete fSettings;
 }
 
-void VideoWindow::MessageReceived( BMessage *p_message )
+/*****************************************************************************
+ * VideoWindow::MessageReceived
+ *****************************************************************************/
+void
+VideoWindow::MessageReceived( BMessage *p_message )
 {
     switch( p_message->what )
     {
-    case TOGGLE_FULL_SCREEN:
-        ((BWindow *)this)->Zoom();
-        break;
-    case RESIZE_100:
-        if (is_zoomed)
-        {
-           ((BWindow *)this)->Zoom();
-        }
-        ResizeTo(i_width, i_height);
-        break;
-    case RESIZE_200:
-        if (is_zoomed)
-        {
-           ((BWindow *)this)->Zoom();
-        }
-        ResizeTo(i_width * 2, i_height * 2);
-        break;
-    case VERT_SYNC:
-        vsync = !vsync;
-        break;
-    case WINDOW_FEEL:
+        case SHOW_INTERFACE:
+            SetInterfaceShowing( true );
+            break;
+        case TOGGLE_FULL_SCREEN:
+            BWindow::Zoom();
+            break;
+        case RESIZE_50:
+        case RESIZE_100:
+        case RESIZE_200:
+            if (IsFullScreen())
+                BWindow::Zoom();
+            _SetVideoSize(p_message->what);
+            break;
+        case VERT_SYNC:
+            SetSyncToRetrace(!IsSyncedToRetrace());
+            break;
+        case WINDOW_FEEL:
+            {
+                window_feel winFeel;
+                if (p_message->FindInt32("WinFeel", (int32*)&winFeel) == B_OK)
+                {
+                    SetFeel(winFeel);
+                    fCachedFeel = winFeel;
+                    if (winFeel == B_FLOATING_ALL_WINDOW_FEEL)
+                        fSettings->AddFlags(VideoSettings::FLAG_ON_TOP_ALL);
+                    else
+                        fSettings->ClearFlags(VideoSettings::FLAG_ON_TOP_ALL);
+                }
+            }
+            break;
+        case ASPECT_CORRECT:
+            SetCorrectAspectRatio(!CorrectAspectRatio());
+            break;
+
+        case B_KEY_DOWN:
+        case B_UNMAPPED_KEY_DOWN:
+        case B_KEY_UP:
+        case B_UNMAPPED_KEY_UP:
         {
-            int16 winFeel;
-            if (p_message->FindInt16("WinFeel", &winFeel) == B_OK)
+            key_map * keys;
+            char    * chars;
+            int32     key, modifiers;
+
+            if( p_message->FindInt32( "key", &key ) != B_OK ||
+                p_message->FindInt32( "modifiers", &modifiers ) != B_OK )
+            {
+                /* Shouldn't happen */
+                break;
+            }
+
+            if( ( p_message->what == B_KEY_UP ||
+                  p_message->what == B_UNMAPPED_KEY_UP ) &&
+                !( modifiers & B_COMMAND_KEY ) )
+            {
+                /* We only use the KEY_UP messages to detect Alt+X
+                   shortcuts (because the KEY_DOWN messages aren't
+                   sent when Alt is pressed) */
+                break;
+            }
+
+            /* Special case for Alt+1, Alt+2 and Alt+3 shortcuts: since
+               the character depends on the keymap, we use the key codes
+               directly (18, 19, 20) */
+            if( ( modifiers & B_COMMAND_KEY ) &&
+                key >= 18 && key <= 20 )
+            {
+                if( key == 18 )
+                    PostMessage( RESIZE_50 );
+                else if( key == 19 )
+                    PostMessage( RESIZE_100 );
+                else
+                    PostMessage( RESIZE_200 );
+
+                break;
+            }
+
+            /* Get the current keymap */
+            get_key_map( &keys, &chars );
+
+            if( key >= 128 || chars[keys->normal_map[key]] != 1 )
             {
-                SetFeel((window_feel)winFeel);
+                /* Weird key or Unicode character */
+                free( keys );
+                free( chars );
+                break;
+            }
+
+            vlc_value_t val;
+            val.i_int = ConvertKeyToVLC( chars[keys->normal_map[key]+1] );
+
+            if( modifiers & B_COMMAND_KEY )
+            {
+                val.i_int |= KEY_MODIFIER_ALT;
             }
+            if( modifiers & B_SHIFT_KEY )
+            {
+                val.i_int |= KEY_MODIFIER_SHIFT;
+            }
+            if( modifiers & B_CONTROL_KEY )
+            {
+                val.i_int |= KEY_MODIFIER_CTRL;
+            }
+            var_Set( p_vout->p_libvlc, "key-pressed", val );
+
+            free( keys );
+            free( chars );
+            break;
         }
-        break;
-    default:
-        BWindow::MessageReceived( p_message );
-        break;
+
+        default:
+            BWindow::MessageReceived( p_message );
+            break;
+    }
+}
+
+/*****************************************************************************
+ * VideoWindow::Zoom
+ *****************************************************************************/
+void
+VideoWindow::Zoom(BPoint origin, float width, float height )
+{
+    ToggleFullScreen();
+}
+
+/*****************************************************************************
+ * VideoWindow::FrameMoved
+ *****************************************************************************/
+void
+VideoWindow::FrameMoved(BPoint origin)
+{
+    if (IsFullScreen())
+        return ;
+    winSize = Frame();
+}
+
+/*****************************************************************************
+ * VideoWindow::FrameResized
+ *****************************************************************************/
+void
+VideoWindow::FrameResized( float width, float height )
+{
+    int32_t useWidth = CorrectAspectRatio() ? i_width : fTrueWidth;
+    int32_t useHeight = CorrectAspectRatio() ? i_height : fTrueHeight;
+    float out_width, out_height;
+    float out_left, out_top;
+    float width_scale = width / useWidth;
+    float height_scale = height / useHeight;
+
+    if (width_scale <= height_scale)
+    {
+        out_width = (useWidth * width_scale);
+        out_height = (useHeight * width_scale);
+        out_left = 0;
+        out_top = (height - out_height) / 2;
     }
+    else   /* if the height is proportionally smaller */
+    {
+        out_width = (useWidth * height_scale);
+        out_height = (useHeight * height_scale);
+        out_top = 0;
+        out_left = (width - out_width) / 2;
+    }
+    view->MoveTo(out_left,out_top);
+    view->ResizeTo(out_width, out_height);
+
+    if (!IsFullScreen())
+        winSize = Frame();
 }
 
-void VideoWindow::drawBuffer(int bufferIndex)
+/*****************************************************************************
+ * VideoWindow::ScreenChanged
+ *****************************************************************************/
+void
+VideoWindow::ScreenChanged(BRect frame, color_space format)
+{
+    BScreen screen(this);
+    display_mode mode;
+    screen.GetMode(&mode);
+    float refresh = (mode.timing.pixel_clock * 1000)
+                    / ((mode.timing.h_total) * (mode.timing.v_total));
+    SetSyncToRetrace(refresh < MIN_AUTO_VSYNC_REFRESH);
+}
+
+/*****************************************************************************
+ * VideoWindow::Activate
+ *****************************************************************************/
+void
+VideoWindow::WindowActivated(bool active)
+{
+}
+
+/*****************************************************************************
+ * VideoWindow::drawBuffer
+ *****************************************************************************/
+void
+VideoWindow::drawBuffer(int bufferIndex)
 {
     i_buffer = bufferIndex;
 
     // sync to the screen if required
-    if (vsync)
+    if (IsSyncedToRetrace())
     {
-        BScreen *screen;
-        screen = new BScreen(this);
-        screen-> WaitForRetrace(22000);
-        delete screen;
+        BScreen screen(this);
+        screen.WaitForRetrace(22000);
     }
-    if (LockLooper())
+    if (fInitStatus >= B_OK && LockLooper())
     {
        // switch the overlay bitmap
        if (mode == OVERLAY)
        {
           rgb_color key;
-          view->SetViewOverlay(bitmap[i_buffer], 
+          view->SetViewOverlay(bitmap[i_buffer],
                             bitmap[i_buffer]->Bounds() ,
                             view->Bounds(),
                             &key, B_FOLLOW_ALL,
-                                   B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL|
-                                   B_OVERLAY_TRANSFER_CHANNEL);
-                  view->SetViewColor(key);
-          }
+                            B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL|
+                            B_OVERLAY_TRANSFER_CHANNEL);
+           view->SetViewColor(key);
+       }
        else
        {
          // switch the bitmap
-         view-> DrawBitmap(bitmap[i_buffer], view->Bounds() );
+         view->DrawBitmap(bitmap[i_buffer], view->Bounds() );
        }
        UnlockLooper();
     }
 }
 
-void VideoWindow::Zoom(BPoint origin, float width, float height )
+/*****************************************************************************
+ * VideoWindow::SetInterfaceShowing
+ *****************************************************************************/
+void
+VideoWindow::ToggleInterfaceShowing()
 {
-    if(is_zoomed)
+    SetInterfaceShowing(!fInterfaceShowing);
+}
+
+/*****************************************************************************
+ * VideoWindow::SetInterfaceShowing
+ *****************************************************************************/
+void
+VideoWindow::SetInterfaceShowing(bool showIt)
+{
+    BWindow* window = get_interface_window();
+    if (window)
     {
-        is_zoomed = !is_zoomed;
-        MoveTo(winSize.left, winSize.top);
-        ResizeTo(winSize.IntegerWidth(), winSize.IntegerHeight());
-        be_app->ShowCursor();
+        if (showIt)
+        {
+            if (fCachedFeel != B_NORMAL_WINDOW_FEEL)
+                SetFeel(B_NORMAL_WINDOW_FEEL);
+            window->Activate(true);
+            SendBehind(window);
+        }
+        else
+        {
+            SetFeel(fCachedFeel);
+            Activate(true);
+            window->SendBehind(this);
+        }
+        fInterfaceShowing = showIt;
     }
-    else
+}
+
+/*****************************************************************************
+ * VideoWindow::SetCorrectAspectRatio
+ *****************************************************************************/
+void
+VideoWindow::SetCorrectAspectRatio(bool doIt)
+{
+    if (CorrectAspectRatio() != doIt)
     {
-        is_zoomed = !is_zoomed;
-        BScreen *screen;
-        screen = new BScreen(this);
-        BRect rect = screen->Frame();
-        delete screen;
-        MoveTo(0,0);
-        ResizeTo(rect.IntegerWidth(), rect.IntegerHeight());
-        be_app->ObscureCursor();
+        if (doIt)
+            fSettings->AddFlags(VideoSettings::FLAG_CORRECT_RATIO);
+        else
+            fSettings->ClearFlags(VideoSettings::FLAG_CORRECT_RATIO);
+        FrameResized(Bounds().Width(), Bounds().Height());
     }
 }
 
-void VideoWindow::FrameMoved(BPoint origin) 
+/*****************************************************************************
+ * VideoWindow::CorrectAspectRatio
+ *****************************************************************************/
+bool
+VideoWindow::CorrectAspectRatio() const
 {
-       if (is_zoomed) return ;
-    winSize = Frame();
+    return fSettings->HasFlags(VideoSettings::FLAG_CORRECT_RATIO);
 }
 
-void VideoWindow::FrameResized( float width, float height )
+/*****************************************************************************
+ * VideoWindow::ToggleFullScreen
+ *****************************************************************************/
+void
+VideoWindow::ToggleFullScreen()
 {
-    float out_width, out_height;
-    float out_left, out_top;
-    float width_scale = width / i_width;
-    float height_scale = height / i_height;
+    SetFullScreen(!IsFullScreen());
+}
 
-    if (width_scale <= height_scale)
+/*****************************************************************************
+ * VideoWindow::SetFullScreen
+ *****************************************************************************/
+void
+VideoWindow::SetFullScreen(bool doIt)
+{
+    if (doIt)
     {
-        out_width = (i_width * width_scale);
-        out_height = (i_height * width_scale);
-        out_left = 0; 
-        out_top = (height - out_height) / 2;
+        SetLook( B_NO_BORDER_WINDOW_LOOK );
+        BScreen screen( this );
+        BRect rect = screen.Frame();
+        Activate();
+        MoveTo(0.0, 0.0);
+        ResizeTo(rect.IntegerWidth(), rect.IntegerHeight());
+        be_app->ObscureCursor();
+        fInterfaceShowing = false;
+        fSettings->AddFlags(VideoSettings::FLAG_FULL_SCREEN);
     }
-    else   /* if the height is proportionally smaller */
+    else
     {
-        out_width = (i_width * height_scale);
-        out_height = (i_height * height_scale);
-        out_top = 0;
-        out_left = (width - out_width) /2;
-    }
-    view->MoveTo(out_left,out_top);
-    view->ResizeTo(out_width, out_height);
-       if (!is_zoomed)
-       {
-        winSize = Frame();
+        SetLook( B_TITLED_WINDOW_LOOK );
+        MoveTo(winSize.left, winSize.top);
+        ResizeTo(winSize.IntegerWidth(), winSize.IntegerHeight());
+        be_app->ShowCursor();
+        fInterfaceShowing = true;
+        fSettings->ClearFlags(VideoSettings::FLAG_FULL_SCREEN);
     }
 }
 
-void VideoWindow::ScreenChanged(BRect frame, color_space mode)
+/*****************************************************************************
+ * VideoWindow::IsFullScreen
+ *****************************************************************************/
+bool
+VideoWindow::IsFullScreen() const
 {
-    BScreen *screen;
-    float refresh;
-    
-    screen = new BScreen(this);
-    display_mode disp_mode; 
-    
-    screen-> GetMode(&disp_mode); 
-    refresh = 
-         (disp_mode.timing.pixel_clock * 1000)/((disp_mode.timing.h_total)* 
-         (disp_mode.timing.v_total)); 
-    if (refresh  < 61) 
-    { 
-        vsync = true; 
-    } 
+    return fSettings->HasFlags(VideoSettings::FLAG_FULL_SCREEN);
 }
 
-void VideoWindow::WindowActivated(bool active)
+/*****************************************************************************
+ * VideoWindow::SetSyncToRetrace
+ *****************************************************************************/
+void
+VideoWindow::SetSyncToRetrace(bool doIt)
 {
+    if (doIt)
+        fSettings->AddFlags(VideoSettings::FLAG_SYNC_RETRACE);
+    else
+        fSettings->ClearFlags(VideoSettings::FLAG_SYNC_RETRACE);
 }
 
-int VideoWindow::SelectDrawingMode(int width, int height)
+/*****************************************************************************
+ * VideoWindow::IsSyncedToRetrace
+ *****************************************************************************/
+bool
+VideoWindow::IsSyncedToRetrace() const
 {
-    int drawingMode = BITMAP;
-    int noOverlay = 0;
+    return fSettings->HasFlags(VideoSettings::FLAG_SYNC_RETRACE);
+}
+
 
-//    int noOverlay = !config_GetIntVariable( "overlay" );
-    for (int i = 0; i < COLOR_COUNT; i++)
+/*****************************************************************************
+ * VideoWindow::_AllocateBuffers
+ *****************************************************************************/
+status_t
+VideoWindow::_AllocateBuffers(int width, int height, int* mode)
+{
+    // clear any old buffers
+    _FreeBuffers();
+    // set default mode
+    *mode = BITMAP;
+    bitmap_count = 3;
+
+    BRect bitmapFrame( 0, 0, width, height );
+    // read from config, if we are supposed to use overlay at all
+    int noOverlay = !config_GetInt( p_vout, "overlay" );
+
+    /* Test for overlay capability: for every chroma in colspace,
+       we try to do double-buffered overlay, single-buffered overlay
+       or basic overlay. If nothing worked, we then have to work with
+       a non-overlay BBitmap. */
+    for( int i = 0; i < COLOR_COUNT; i++ )
     {
-        if (noOverlay) break;
-        bitmap[0] = new BBitmap ( BRect( 0, 0, width, height ), 
-                                  B_BITMAP_WILL_OVERLAY,
-                                  colspace[i].colspace);
+        if( noOverlay )
+            break;
 
-        if(bitmap[0] && bitmap[0]->InitCheck() == B_OK) 
+        bitmap[0] = new BBitmap( bitmapFrame,
+                                 B_BITMAP_WILL_OVERLAY |
+                                 B_BITMAP_RESERVE_OVERLAY_CHANNEL,
+                                 colspace[i].colspace );
+        if( bitmap[0] && bitmap[0]->InitCheck() == B_OK )
         {
             colspace_index = i;
 
-            bitmap[1] = new BBitmap( BRect( 0, 0, width, height ), B_BITMAP_WILL_OVERLAY,
-                                     colspace[colspace_index].colspace);
-            bitmap[2] = new BBitmap( BRect( 0, 0, width, height ), B_BITMAP_WILL_OVERLAY,
+            *mode = OVERLAY;
+            rgb_color key;
+            view->SetViewOverlay( bitmap[0], bitmap[0]->Bounds(),
+                                  view->Bounds(), &key, B_FOLLOW_ALL,
+                                  B_OVERLAY_FILTER_HORIZONTAL |
+                                  B_OVERLAY_FILTER_VERTICAL );
+            view->SetViewColor( key );
+            SetTitle( "VLC " PACKAGE_VERSION " (Overlay)" );
+
+            bitmap[1] = new BBitmap( bitmapFrame, B_BITMAP_WILL_OVERLAY,
                                      colspace[colspace_index].colspace);
-            if ( (bitmap[2] && bitmap[2]->InitCheck() == B_OK) )
+            if( bitmap[1] && bitmap[1]->InitCheck() == B_OK )
             {
-               drawingMode = OVERLAY;
-               rgb_color key;
-               view->SetViewOverlay(bitmap[0], 
-                                    bitmap[0]->Bounds() ,
-                                    view->Bounds(),
-                                    &key, B_FOLLOW_ALL,
-                                           B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL);
-                      view->SetViewColor(key);
-               SetTitle(VOUT_TITLE " (Overlay)");
-               break;
+
+                bitmap[2] = new BBitmap( bitmapFrame, B_BITMAP_WILL_OVERLAY,
+                                         colspace[colspace_index].colspace);
+                if( bitmap[2] && bitmap[2]->InitCheck() == B_OK )
+                {
+                    msg_Dbg( p_vout, "using double-buffered overlay" );
+                }
+                else
+                {
+                    msg_Dbg( p_vout, "using single-buffered overlay" );
+                    bitmap_count = 2;
+                    if( bitmap[2] ) { delete bitmap[2]; bitmap[2] = NULL; }
+                }
             }
             else
             {
-               delete bitmap[0];
-               delete bitmap[1];
-               delete bitmap[2];
+                msg_Dbg( p_vout, "using simple overlay" );
+                bitmap_count = 1;
+                if( bitmap[1] ) { delete bitmap[1]; bitmap[1] = NULL; }
             }
+            break;
         }
         else
         {
-            delete bitmap[0];
-        }        
-       }
+            if( bitmap[0] ) { delete bitmap[0]; bitmap[0] = NULL; }
+        }
+    }
+
+    if (*mode == BITMAP)
+    {
+        msg_Warn( p_vout, "no possible overlay" );
+
+        // fallback to RGB
+        colspace_index = DEFAULT_COL;    // B_RGB32
+        bitmap[0] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
+        bitmap[1] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
+        bitmap[2] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
+        SetTitle( "VLC " PACKAGE_VERSION " (Bitmap)" );
+    }
+    // see if everything went well
+    status_t status = B_ERROR;
+    for (int32_t i = 0; i < bitmap_count; i++)
+    {
+        if (bitmap[i])
+            status = bitmap[i]->InitCheck();
+        if (status < B_OK)
+            break;
+    }
+    if (status >= B_OK)
+    {
+        // clear bitmaps to black
+        for (int32_t i = 0; i < bitmap_count; i++)
+            _BlankBitmap(bitmap[i]);
+    }
+    return status;
+}
 
-    if (drawingMode == BITMAP)
-       {
-        // fallback to RGB16
-        colspace_index = DEFAULT_COL;
-        SetTitle(VOUT_TITLE " (Bitmap)");
-        bitmap[0] = new BBitmap( BRect( 0, 0, width, height ), colspace[colspace_index].colspace);
-        bitmap[1] = new BBitmap( BRect( 0, 0, width, height ), colspace[colspace_index].colspace);
-        bitmap[2] = new BBitmap( BRect( 0, 0, width, height ), colspace[colspace_index].colspace);
+/*****************************************************************************
+ * VideoWindow::_FreeBuffers
+ *****************************************************************************/
+void
+VideoWindow::_FreeBuffers()
+{
+    if( bitmap[0] ) { delete bitmap[0]; bitmap[0] = NULL; }
+    if( bitmap[1] ) { delete bitmap[1]; bitmap[1] = NULL; }
+    if( bitmap[2] ) { delete bitmap[2]; bitmap[2] = NULL; }
+    fInitStatus = B_ERROR;
+}
+
+/*****************************************************************************
+ * VideoWindow::_BlankBitmap
+ *****************************************************************************/
+void
+VideoWindow::_BlankBitmap(BBitmap* bitmap) const
+{
+    // no error checking (we do that earlier on and since it's a private function...
+
+    // YCbCr:
+    // Loss/Saturation points are Y 16-235 (absoulte); Cb/Cr 16-240 (center 128)
+
+    // YUV:
+    // Extrema points are Y 0 - 207 (absolute) U -91 - 91 (offset 128) V -127 - 127 (offset 128)
+
+    // we only handle weird colorspaces with special care
+    switch (bitmap->ColorSpace()) {
+        case B_YCbCr422: {
+            // Y0[7:0]  Cb0[7:0]  Y1[7:0]  Cr0[7:0]  Y2[7:0]  Cb2[7:0]  Y3[7:0]  Cr2[7:0]
+            int32_t height = bitmap->Bounds().IntegerHeight() + 1;
+            uint8_t* bits = (uint8_t*)bitmap->Bits();
+            int32_t bpr = bitmap->BytesPerRow();
+            for (int32_t y = 0; y < height; y++) {
+                // handle 2 bytes at a time
+                for (int32_t i = 0; i < bpr; i += 2) {
+                    // offset into line
+                    bits[i] = 16;
+                    bits[i + 1] = 128;
+                }
+                // next line
+                bits += bpr;
+            }
+            break;
+        }
+        case B_YCbCr420: {
+// TODO: untested!!
+            // Non-interlaced only, Cb0  Y0  Y1  Cb2 Y2  Y3  on even scan lines ...
+            // Cr0  Y0  Y1  Cr2 Y2  Y3  on odd scan lines
+            int32_t height = bitmap->Bounds().IntegerHeight() + 1;
+            uint8_t* bits = (uint8_t*)bitmap->Bits();
+            int32_t bpr = bitmap->BytesPerRow();
+            for (int32_t y = 0; y < height; y += 1) {
+                // handle 3 bytes at a time
+                for (int32_t i = 0; i < bpr; i += 3) {
+                    // offset into line
+                    bits[i] = 128;
+                    bits[i + 1] = 16;
+                    bits[i + 2] = 16;
+                }
+                // next line
+                bits += bpr;
+            }
+            break;
+        }
+        case B_YUV422: {
+// TODO: untested!!
+            // U0[7:0]  Y0[7:0]   V0[7:0]  Y1[7:0]  U2[7:0]  Y2[7:0]   V2[7:0]  Y3[7:0]
+            int32_t height = bitmap->Bounds().IntegerHeight() + 1;
+            uint8_t* bits = (uint8_t*)bitmap->Bits();
+            int32_t bpr = bitmap->BytesPerRow();
+            for (int32_t y = 0; y < height; y += 1) {
+                // handle 2 bytes at a time
+                for (int32_t i = 0; i < bpr; i += 2) {
+                    // offset into line
+                    bits[i] = 128;
+                    bits[i + 1] = 0;
+                }
+                // next line
+                bits += bpr;
+            }
+            break;
+        }
+        default:
+            memset(bitmap->Bits(), 0, bitmap->BitsLength());
+            break;
     }
-    return drawingMode;
 }
 
 /*****************************************************************************
- * VLCView::VLCView
+ * VideoWindow::_SetVideoSize
  *****************************************************************************/
-VLCView::VLCView(BRect bounds) : BView(bounds, "", B_FOLLOW_NONE,
-                                       B_WILL_DRAW)
+void
+VideoWindow::_SetVideoSize(uint32_t mode)
+{
+    // let size depend on aspect correction
+    int32_t width = CorrectAspectRatio() ? i_width : fTrueWidth;
+    int32_t height = CorrectAspectRatio() ? i_height : fTrueHeight;
+    switch (mode)
+    {
+        case RESIZE_50:
+            width /= 2;
+            height /= 2;
+            break;
+        case RESIZE_200:
+            width *= 2;
+            height *= 2;
+            break;
+        case RESIZE_100:
+        default:
+            break;
+    }
+    fSettings->ClearFlags(VideoSettings::FLAG_FULL_SCREEN);
+    ResizeTo(width, height);
+}
+
+/*****************************************************************************
+ * VideoWindow::_SetToSettings
+ *****************************************************************************/
+void
+VideoWindow::_SetToSettings()
+{
+    // adjust dimensions
+    uint32_t mode = RESIZE_100;
+    switch (fSettings->VideoSize())
+    {
+        case VideoSettings::SIZE_50:
+            mode = RESIZE_50;
+            break;
+        case VideoSettings::SIZE_200:
+            mode = RESIZE_200;
+            break;
+        case VideoSettings::SIZE_100:
+        case VideoSettings::SIZE_OTHER:
+        default:
+            break;
+    }
+    bool fullscreen = IsFullScreen();    // remember settings
+    _SetVideoSize(mode);                // because this will reset settings
+    // the fullscreen status is reflected in the settings,
+    // but not yet in the windows state
+    if (fullscreen)
+        SetFullScreen(true);
+    if (fSettings->HasFlags(VideoSettings::FLAG_ON_TOP_ALL))
+        fCachedFeel = B_FLOATING_ALL_WINDOW_FEEL;
+    else
+        fCachedFeel = B_NORMAL_WINDOW_FEEL;
+    SetFeel(fCachedFeel);
+}
 
+/*****************************************************************************
+ * VLCView::VLCView
+ *****************************************************************************/
+VLCView::VLCView(BRect bounds, vout_thread_t *p_vout_instance )
+    : BView(bounds, "video view", B_FOLLOW_NONE, B_WILL_DRAW | B_PULSE_NEEDED),
+      fLastMouseMovedTime(mdate()),
+      fCursorHidden(false),
+      fCursorInside(false),
+      fIgnoreDoubleClick(false)
 {
+    p_vout = p_vout_instance;
     SetViewColor(B_TRANSPARENT_32_BIT);
 }
 
@@ -383,81 +990,214 @@ VLCView::~VLCView()
 {
 }
 
+/*****************************************************************************
+ * VLCVIew::AttachedToWindow
+ *****************************************************************************/
+void
+VLCView::AttachedToWindow()
+{
+    // periodically check if we want to hide the pointer
+    Window()->SetPulseRate(1000000);
+}
+
 /*****************************************************************************
  * VLCVIew::MouseDown
  *****************************************************************************/
-void VLCView::MouseDown(BPoint point)
+void
+VLCView::MouseDown(BPoint where)
 {
+    VideoWindow* videoWindow = dynamic_cast<VideoWindow*>(Window());
     BMessage* msg = Window()->CurrentMessage();
-    int32 clicks = msg->FindInt32("clicks");
+    int32 clicks;
+    uint32_t buttons;
+    msg->FindInt32("clicks", &clicks);
+    msg->FindInt32("buttons", (int32*)&buttons);
+
+    if (videoWindow)
+    {
+        if (buttons & B_PRIMARY_MOUSE_BUTTON)
+        {
+            if (clicks == 2 && !fIgnoreDoubleClick)
+                Window()->Zoom();
+            /* else
+                videoWindow->ToggleInterfaceShowing(); */
+            fIgnoreDoubleClick = false;
+        }
+        else
+        {
+            if (buttons & B_SECONDARY_MOUSE_BUTTON)
+            {
+                // clicks will be 2 next time (if interval short enough)
+                // even if the first click and the second
+                // have not been made with the same mouse button
+                fIgnoreDoubleClick = true;
+                // launch popup menu
+                BPopUpMenu *menu = new BPopUpMenu("context menu");
+                menu->SetRadioMode(false);
+                // In full screen, add an item to show/hide the interface
+                if( videoWindow->IsFullScreen() )
+                {
+                    BMenuItem *intfItem =
+                        new BMenuItem( _("Show Interface"), new BMessage(SHOW_INTERFACE) );
+                    menu->AddItem( intfItem );
+                }
+                // Resize to 50%
+                BMenuItem *halfItem = new BMenuItem(_("50%"), new BMessage(RESIZE_50));
+                menu->AddItem(halfItem);
+                // Resize to 100%
+                BMenuItem *origItem = new BMenuItem(_("100%"), new BMessage(RESIZE_100));
+                menu->AddItem(origItem);
+                // Resize to 200%
+                BMenuItem *doubleItem = new BMenuItem(_("200%"), new BMessage(RESIZE_200));
+                menu->AddItem(doubleItem);
+                // Toggle FullScreen
+                BMenuItem *zoomItem = new BMenuItem(_("Fullscreen"), new BMessage(TOGGLE_FULL_SCREEN));
+                zoomItem->SetMarked(videoWindow->IsFullScreen());
+                menu->AddItem(zoomItem);
+                menu->AddSeparatorItem();
+                // Toggle vSync
+                BMenuItem *vsyncItem = new BMenuItem(_("Vertical Sync"), new BMessage(VERT_SYNC));
+                vsyncItem->SetMarked(videoWindow->IsSyncedToRetrace());
+                menu->AddItem(vsyncItem);
+                // Correct Aspect Ratio
+                BMenuItem *aspectItem = new BMenuItem(_("Correct Aspect Ratio"), new BMessage(ASPECT_CORRECT));
+                aspectItem->SetMarked(videoWindow->CorrectAspectRatio());
+                menu->AddItem(aspectItem);
+                menu->AddSeparatorItem();
+                // Window Feel Items
+/*                BMessage *winNormFeel = new BMessage(WINDOW_FEEL);
+                winNormFeel->AddInt32("WinFeel", (int32_t)B_NORMAL_WINDOW_FEEL);
+                BMenuItem *normWindItem = new BMenuItem("Normal Window", winNormFeel);
+                normWindItem->SetMarked(videoWindow->Feel() == B_NORMAL_WINDOW_FEEL);
+                menu->AddItem(normWindItem);
+                BMessage *winFloatFeel = new BMessage(WINDOW_FEEL);
+                winFloatFeel->AddInt32("WinFeel", (int32_t)B_FLOATING_APP_WINDOW_FEEL);
+                BMenuItem *onTopWindItem = new BMenuItem("App Top", winFloatFeel);
+                onTopWindItem->SetMarked(videoWindow->Feel() == B_FLOATING_APP_WINDOW_FEEL);
+                menu->AddItem(onTopWindItem);
+                BMessage *winAllFeel = new BMessage(WINDOW_FEEL);
+                winAllFeel->AddInt32("WinFeel", (int32_t)B_FLOATING_ALL_WINDOW_FEEL);
+                BMenuItem *allSpacesWindItem = new BMenuItem("On Top All Workspaces", winAllFeel);
+                allSpacesWindItem->SetMarked(videoWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL);
+                menu->AddItem(allSpacesWindItem);*/
+
+                BMessage *windowFeelMsg = new BMessage( WINDOW_FEEL );
+                bool onTop = videoWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL;
+                window_feel feel = onTop ? B_NORMAL_WINDOW_FEEL : B_FLOATING_ALL_WINDOW_FEEL;
+                windowFeelMsg->AddInt32( "WinFeel", (int32_t)feel );
+                BMenuItem *windowFeelItem = new BMenuItem( _("Stay On Top"), windowFeelMsg );
+                windowFeelItem->SetMarked( onTop );
+                menu->AddItem( windowFeelItem );
+
+                menu->AddSeparatorItem();
+
+                BMenuItem* screenShotItem = new BMenuItem( _("Take Screen Shot"),
+                                                           new BMessage( SCREEN_SHOT ) );
+                menu->AddItem( screenShotItem );
+
+                menu->SetTargetForItems( this );
+                ConvertToScreen( &where );
+                BRect mouseRect( where.x - 5, where.y - 5,
+                                 where.x + 5, where.y + 5 );
+                menu->Go( where, true, false, mouseRect, true );
+            }
+        }
+    }
+    fLastMouseMovedTime = mdate();
+    fCursorHidden = false;
+}
+
+/*****************************************************************************
+ * VLCVIew::MouseUp
+ *****************************************************************************/
+void
+VLCView::MouseUp( BPoint where )
+{
+    vlc_value_t val;
+    val.b_bool = VLC_TRUE;
+    var_Set( p_vout, "mouse-clicked", val );
+}
 
-    VideoWindow *vWindow = (VideoWindow *)Window();
-    uint32 mouseButtons;
-    BPoint where;
-    GetMouse(&where, &mouseButtons, true);
+/*****************************************************************************
+ * VLCVIew::MouseMoved
+ *****************************************************************************/
+void
+VLCView::MouseMoved(BPoint point, uint32 transit, const BMessage* dragMessage)
+{
+    fLastMouseMovedTime = mdate();
+    fCursorHidden = false;
+    fCursorInside = ( transit == B_INSIDE_VIEW || transit == B_ENTERED_VIEW );
 
-    if ((mouseButtons & B_PRIMARY_MOUSE_BUTTON) && (clicks == 2))
+    if( !fCursorInside )
     {
-       Window()->Zoom();
-       return;
+        return;
     }
-    else
+
+    vlc_value_t val;
+    unsigned int i_width, i_height, i_x, i_y;
+    vout_PlacePicture( p_vout, (unsigned int)Bounds().Width(),
+                       (unsigned int)Bounds().Height(),
+                       &i_x, &i_y, &i_width, &i_height );
+    val.i_int = ( (int)point.x - i_x ) * p_vout->render.i_width / i_width;
+    var_Set( p_vout, "mouse-x", val );
+    val.i_int = ( (int)point.y - i_y ) * p_vout->render.i_height / i_height;
+    var_Set( p_vout, "mouse-y", val );
+    val.b_bool = VLC_TRUE;
+    var_Set( p_vout, "mouse-moved", val );
+}
+
+/*****************************************************************************
+ * VLCVIew::Pulse
+ *****************************************************************************/
+void
+VLCView::Pulse()
+{
+    // We are getting the pulse messages no matter if the mouse is over
+    // this view. If we are in full screen mode, we want to hide the cursor
+    // even if it is not.
+    VideoWindow *videoWindow = dynamic_cast<VideoWindow*>(Window());
+    if (!fCursorHidden)
     {
-       if (mouseButtons & B_SECONDARY_MOUSE_BUTTON) 
-       {
-           BPopUpMenu *menu = new BPopUpMenu("context menu");
-           menu->SetRadioMode(false);
-           // Toggle FullScreen
-           BMenuItem *zoomItem = new BMenuItem("Fullscreen", new BMessage(TOGGLE_FULL_SCREEN));
-           zoomItem->SetMarked(vWindow->is_zoomed);
-           menu->AddItem(zoomItem);
-           // Resize to 100%
-           BMenuItem *origItem = new BMenuItem("100%", new BMessage(RESIZE_100));
-           menu->AddItem(origItem);
-           // Resize to 200%
-           BMenuItem *doubleItem = new BMenuItem("200%", new BMessage(RESIZE_200));
-           menu->AddItem(doubleItem);
-           menu->AddSeparatorItem();
-           // Toggle vSync
-           BMenuItem *vsyncItem = new BMenuItem("Vertical Sync", new BMessage(VERT_SYNC));
-           vsyncItem->SetMarked(vWindow->vsync);
-           menu->AddItem(vsyncItem);
-           menu->AddSeparatorItem();
-
-                  // Windwo Feel Items
-                  BMessage *winNormFeel = new BMessage(WINDOW_FEEL);
-                  winNormFeel->AddInt16("WinFeel", (int16)B_NORMAL_WINDOW_FEEL);
-           BMenuItem *normWindItem = new BMenuItem("Normal Window", winNormFeel);
-           normWindItem->SetMarked(vWindow->Feel() == B_NORMAL_WINDOW_FEEL);
-           menu->AddItem(normWindItem);
-           
-                  BMessage *winFloatFeel = new BMessage(WINDOW_FEEL);
-                  winFloatFeel->AddInt16("WinFeel", (int16)B_MODAL_ALL_WINDOW_FEEL);
-           BMenuItem *onTopWindItem = new BMenuItem("App Top", winFloatFeel);
-           onTopWindItem->SetMarked(vWindow->Feel() == B_MODAL_ALL_WINDOW_FEEL);
-           menu->AddItem(onTopWindItem);
-           
-                  BMessage *winAllFeel = new BMessage(WINDOW_FEEL);
-                  winAllFeel->AddInt16("WinFeel", (int16)B_FLOATING_ALL_WINDOW_FEEL);
-           BMenuItem *allSpacesWindItem = new BMenuItem("On Top All Workspaces", winAllFeel);
-           allSpacesWindItem->SetMarked(vWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL);
-           menu->AddItem(allSpacesWindItem);
-                  
-           menu->SetTargetForItems(this);
-           ConvertToScreen(&where);
-           menu->Go(where, true, false, true);
+        if (fCursorInside
+            && mdate() - fLastMouseMovedTime > MOUSE_IDLE_TIMEOUT)
+        {
+            be_app->ObscureCursor();
+            fCursorHidden = true;
+            // hide the interface window as well if full screen
+            if (videoWindow && videoWindow->IsFullScreen())
+                videoWindow->SetInterfaceShowing(false);
         }
-       } 
+    }
+
+    // Workaround to disable the screensaver in full screen:
+    // we simulate an activity every 29 seconds
+    if( videoWindow && videoWindow->IsFullScreen() &&
+        mdate() - fLastMouseMovedTime > 29000000 )
+    {
+        BPoint where;
+        uint32 buttons;
+        GetMouse(&where, &buttons, false);
+        ConvertToScreen(&where);
+        set_mouse_position((int32_t) where.x, (int32_t) where.y);
+    }
 }
 
 /*****************************************************************************
  * VLCVIew::Draw
  *****************************************************************************/
-void VLCView::Draw(BRect updateRect) 
+void
+VLCView::Draw(BRect updateRect)
 {
-    VideoWindow *win = (VideoWindow *) Window();
-    if (win->mode == BITMAP)
-      FillRect(updateRect);
+    VideoWindow* window = dynamic_cast<VideoWindow*>( Window() );
+    if ( window && window->mode == BITMAP )
+        FillRect( updateRect );
 }
 
 /*****************************************************************************
@@ -467,6 +1207,7 @@ static int  Init       ( vout_thread_t * );
 static void End        ( vout_thread_t * );
 static int  Manage     ( vout_thread_t * );
 static void Display    ( vout_thread_t *, picture_t * );
+static int  Control    ( vout_thread_t *, int, va_list );
 
 static int  BeosOpenDisplay ( vout_thread_t *p_vout );
 static void BeosCloseDisplay( vout_thread_t *p_vout );
@@ -493,9 +1234,10 @@ int E_(OpenVideo) ( vlc_object_t *p_this )
 
     p_vout->pf_init = Init;
     p_vout->pf_end = End;
-    p_vout->pf_manage = NULL;
+    p_vout->pf_manage = Manage;
     p_vout->pf_render = NULL;
     p_vout->pf_display = Display;
+    p_vout->pf_control = Control;
 
     return( 0 );
 }
@@ -531,7 +1273,9 @@ int Init( vout_thread_t *p_vout )
     p_vout->output.i_gmask  = 0x0000ff00;
     p_vout->output.i_bmask  = 0x000000ff;
 
-    for (int buffer_index = 0 ; buffer_index < 3; buffer_index++)
+    for( int buffer_index = 0 ;
+         buffer_index < p_vout->p_sys->p_window->bitmap_count;
+         buffer_index++ )
     {
        p_pic = NULL;
        /* Find an empty picture slot */
@@ -549,17 +1293,18 @@ int Init( vout_thread_t *p_vout )
        {
            return 0;
        }
-       p_pic->p->p_pixels = (u8*)p_vout->p_sys->p_window->bitmap[buffer_index]->Bits();
+       p_pic->p->p_pixels = (uint8_t*)p_vout->p_sys->p_window->bitmap[buffer_index]->Bits();
        p_pic->p->i_lines = p_vout->p_sys->i_height;
+       p_pic->p->i_visible_lines = p_vout->p_sys->i_height;
 
        p_pic->p->i_pixel_pitch = colspace[p_vout->p_sys->p_window->colspace_index].pixel_bytes;
        p_pic->i_planes = colspace[p_vout->p_sys->p_window->colspace_index].planes;
-       p_pic->p->i_pitch = p_vout->p_sys->p_window->bitmap[buffer_index]->BytesPerRow(); 
+       p_pic->p->i_pitch = p_vout->p_sys->p_window->bitmap[buffer_index]->BytesPerRow();
        p_pic->p->i_visible_pitch = p_pic->p->i_pixel_pitch * ( p_vout->p_sys->p_window->bitmap[buffer_index]->Bounds().IntegerWidth() + 1 );
 
        p_pic->i_status = DESTROYED_PICTURE;
        p_pic->i_type   = DIRECT_PICTURE;
+
        PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
 
        I_OUTPUTPICTURES++;
@@ -576,6 +1321,20 @@ void End( vout_thread_t *p_vout )
     BeosCloseDisplay( p_vout );
 }
 
+/*****************************************************************************
+ * Manage
+ *****************************************************************************/
+static int Manage( vout_thread_t * p_vout )
+{
+    if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
+    {
+        p_vout->p_sys->p_window->PostMessage( TOGGLE_FULL_SCREEN );
+        p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
+    }
+
+    return 0;
+}
+
 /*****************************************************************************
  * CloseVideo: destroy BeOS video thread output method
  *****************************************************************************
@@ -598,14 +1357,20 @@ void Display( vout_thread_t *p_vout, picture_t *p_pic )
 {
     VideoWindow * p_win = p_vout->p_sys->p_window;
 
-    /* draw buffer if required */    
+    /* draw buffer if required */
     if (!p_win->teardownwindow)
-    { 
+    {
        p_win->drawBuffer(p_vout->p_sys->i_index);
     }
     /* change buffer */
-    p_vout->p_sys->i_index = ++p_vout->p_sys->i_index % 3;
-    p_pic->p->p_pixels = (u8*)p_vout->p_sys->p_window->bitmap[p_vout->p_sys->i_index]->Bits();
+    p_vout->p_sys->i_index = ++p_vout->p_sys->i_index %
+        p_vout->p_sys->p_window->bitmap_count;
+    p_pic->p->p_pixels = (uint8_t*)p_vout->p_sys->p_window->bitmap[p_vout->p_sys->i_index]->Bits();
+}
+
+static int Control( vout_thread_t * p_vout, int i_query, va_list args )
+{
+    return vout_vaControlDefault( p_vout, i_query, args );
 }
 
 /* following functions are local */
@@ -614,20 +1379,24 @@ void Display( vout_thread_t *p_vout, picture_t *p_pic )
  * BeosOpenDisplay: open and initialize BeOS device
  *****************************************************************************/
 static int BeosOpenDisplay( vout_thread_t *p_vout )
-{ 
+{
 
     p_vout->p_sys->p_window = new VideoWindow( p_vout->p_sys->i_width - 1,
                                                p_vout->p_sys->i_height - 1,
                                                BRect( 20, 50,
-                                                      20 + p_vout->i_window_width - 1, 
-                                                      50 + p_vout->i_window_height - 1 ));
-
+                                                      20 + p_vout->i_window_width - 1,
+                                                      50 + p_vout->i_window_height - 1 ),
+                                               p_vout );
     if( p_vout->p_sys->p_window == NULL )
     {
         msg_Err( p_vout, "cannot allocate VideoWindow" );
         return( 1 );
-    }   
-    
+    }
+    else
+    {
+        p_vout->p_sys->p_window->Show();
+    }
+
     return( 0 );
 }
 
@@ -638,7 +1407,7 @@ static int BeosOpenDisplay( vout_thread_t *p_vout )
  * state of the device.
  *****************************************************************************/
 static void BeosCloseDisplay( vout_thread_t *p_vout )
-{    
+{
     VideoWindow * p_win = p_vout->p_sys->p_window;
     /* Destroy the video window */
     if( p_win != NULL && !p_win->teardownwindow)
@@ -650,4 +1419,3 @@ static void BeosCloseDisplay( vout_thread_t *p_vout )
     }
     p_win = NULL;
 }
-