/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"

#include <svdata.hxx>
#include <brdwin.hxx>
#include <window.h>
#include <salframe.hxx>

#include <vcl/svapp.hxx>
#include <vcl/wrkwin.hxx>
#include <vcl/event.hxx>
#include <vcl/toolbox.hxx>
#include <vcl/floatwin.hxx>

#include <tools/rc.h>
#include <tools/debug.hxx>


// =======================================================================

class FloatingWindow::ImplData
{
public:
    ImplData();
    ~ImplData();

	ToolBox* 		mpBox;
	Rectangle		maItemEdgeClipRect; // used to clip the common edge between a toolbar item and the border of this window
};

FloatingWindow::ImplData::ImplData()
{
    mpBox = NULL;
}

FloatingWindow::ImplData::~ImplData()
{
}

Rectangle& FloatingWindow::ImplGetItemEdgeClipRect()
{
    return mpImplData->maItemEdgeClipRect;
}

// =======================================================================

void FloatingWindow::ImplInit( Window* pParent, WinBits nStyle )
{
    mpImplData = new ImplData;

    mpWindowImpl->mbFloatWin = sal_True;
    mbInCleanUp = sal_False;
    mbGrabFocus = sal_False;

    DBG_ASSERT( pParent, "FloatWindow::FloatingWindow(): - pParent == NULL!" );

    if ( !pParent )
        pParent = ImplGetSVData()->maWinData.mpAppWin;

    DBG_ASSERT( pParent, "FloatWindow::FloatingWindow(): - pParent == NULL and no AppWindow exists" );

    // no Border, then we dont need a border window
    if ( !nStyle )
    {
        mpWindowImpl->mbOverlapWin = sal_True;
        nStyle |= WB_DIALOGCONTROL;
        SystemWindow::ImplInit( pParent, nStyle, NULL );
    }
    else
    {
        if ( !(nStyle & WB_NODIALOGCONTROL) )
            nStyle |= WB_DIALOGCONTROL;

        if( nStyle & (WB_MOVEABLE | WB_SIZEABLE | WB_ROLLABLE | WB_CLOSEABLE | WB_STANDALONE)
            && !(nStyle & WB_OWNERDRAWDECORATION) )
        {
            WinBits nFloatWinStyle = nStyle;
            // #99154# floaters are not closeable by default anymore, eg fullscreen floater
            // nFloatWinStyle |= WB_CLOSEABLE;
            mpWindowImpl->mbFrame = sal_True;
            mpWindowImpl->mbOverlapWin = sal_True;
            SystemWindow::ImplInit( pParent, nFloatWinStyle & ~WB_BORDER, NULL );
        }
        else
        {
            ImplBorderWindow*   pBorderWin;
            sal_uInt16              nBorderStyle = BORDERWINDOW_STYLE_BORDER | BORDERWINDOW_STYLE_FLOAT;

            if( nStyle & WB_OWNERDRAWDECORATION ) nBorderStyle |= BORDERWINDOW_STYLE_FRAME;
            else                                  nBorderStyle |= BORDERWINDOW_STYLE_OVERLAP;

            if ( (nStyle & WB_SYSTEMWINDOW) && !(nStyle & (WB_MOVEABLE | WB_SIZEABLE)) )
            {
                nBorderStyle |= BORDERWINDOW_STYLE_FRAME;
                nStyle |= WB_CLOSEABLE; // make undecorated floaters closeable
            }
            pBorderWin  = new ImplBorderWindow( pParent, nStyle, nBorderStyle );
            SystemWindow::ImplInit( pBorderWin, nStyle & ~WB_BORDER, NULL );
            pBorderWin->mpWindowImpl->mpClientWindow = this;
            pBorderWin->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
            pBorderWin->SetDisplayActive( sal_True );
            mpWindowImpl->mpBorderWindow  = pBorderWin;
            mpWindowImpl->mpRealParent    = pParent;
        }
    }
    SetActivateMode( 0 );

    mpNextFloat             = NULL;
    mpFirstPopupModeWin     = NULL;
    mnPostId                = 0;
    mnTitle                 = (nStyle & WB_MOVEABLE) ? FLOATWIN_TITLE_NORMAL : FLOATWIN_TITLE_NONE;
    mnOldTitle              = mnTitle;
    mnPopupModeFlags        = 0;
    mbInPopupMode           = sal_False;
    mbPopupMode             = sal_False;
    mbPopupModeCanceled     = sal_False;
    mbPopupModeTearOff      = sal_False;
    mbMouseDown             = sal_False;

    ImplInitSettings();
}

// -----------------------------------------------------------------------

void FloatingWindow::ImplInitSettings()
{
    const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();

    Color aColor;
    if ( IsControlBackground() )
        aColor = GetControlBackground();
    else if ( Window::GetStyle() & WB_3DLOOK )
        aColor = rStyleSettings.GetFaceColor();
    else
        aColor = rStyleSettings.GetWindowColor();
    SetBackground( aColor );
}

// =======================================================================

FloatingWindow::FloatingWindow( Window* pParent, WinBits nStyle ) :
    SystemWindow( WINDOW_FLOATINGWINDOW )
{
    ImplInit( pParent, nStyle );
}

// -----------------------------------------------------------------------

FloatingWindow::FloatingWindow( Window* pParent, const ResId& rResId ) :
    SystemWindow( WINDOW_FLOATINGWINDOW )
{
    rResId.SetRT( RSC_FLOATINGWINDOW );
    WinBits nStyle = ImplInitRes( rResId );
    ImplInit( pParent, nStyle );
    ImplLoadRes( rResId );

    if ( !(nStyle & WB_HIDE) )
        Show();
}

// -----------------------------------------------------------------------

void FloatingWindow::ImplLoadRes( const ResId& rResId )
{
    SystemWindow::ImplLoadRes( rResId );

    sal_uLong nObjMask = ReadLongRes();

    if ( (RSC_FLOATINGWINDOW_WHMAPMODE | RSC_FLOATINGWINDOW_WIDTH |
          RSC_FLOATINGWINDOW_HEIGHT) & nObjMask )
    {
        // Groessenangabe aus der Resource verwenden
        Size    aSize;
        MapUnit eSizeMap = MAP_PIXEL;

        if ( RSC_FLOATINGWINDOW_WHMAPMODE & nObjMask )
            eSizeMap = (MapUnit) ReadShortRes();
        if ( RSC_FLOATINGWINDOW_WIDTH & nObjMask )
            aSize.Width() = ReadShortRes();
        if ( RSC_FLOATINGWINDOW_HEIGHT & nObjMask )
            aSize.Height() = ReadShortRes();

        SetRollUpOutputSizePixel( LogicToPixel( aSize, eSizeMap ) );
    }

    if (nObjMask & RSC_FLOATINGWINDOW_ZOOMIN )
    {
        if ( ReadShortRes() )
            RollUp();
    }
}

// -----------------------------------------------------------------------

FloatingWindow::~FloatingWindow()
{
    if( mbPopupModeCanceled )
        // indicates that ESC key was pressed
        // will be handled in Window::ImplGrabFocus()
        SetDialogControlFlags( GetDialogControlFlags() | WINDOW_DLGCTRL_FLOATWIN_POPUPMODEEND_CANCEL );

    if ( IsInPopupMode() )
        EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL | FLOATWIN_POPUPMODEEND_DONTCALLHDL );

    if ( mnPostId )
        Application::RemoveUserEvent( mnPostId );

    delete mpImplData;
}

// -----------------------------------------------------------------------

Point FloatingWindow::CalcFloatingPosition( Window* pWindow, const Rectangle& rRect, sal_uLong nFlags, sal_uInt16& rArrangeIndex )
{
    return ImplCalcPos( pWindow, rRect, nFlags, rArrangeIndex );
}

// -----------------------------------------------------------------------

Point FloatingWindow::ImplCalcPos( Window* pWindow,
                                   const Rectangle& rRect, sal_uLong nFlags,
                                   sal_uInt16& rArrangeIndex )
{
    // Fenster-Position ermitteln
    Point       aPos;
    Size        aSize = pWindow->GetSizePixel();
    Rectangle   aScreenRect = pWindow->ImplGetFrameWindow()->GetDesktopRectPixel();
    FloatingWindow *pFloatingWindow = dynamic_cast<FloatingWindow*>( pWindow );

    // convert....
    Window* pW = pWindow;
    if ( pW->mpWindowImpl->mpRealParent )
        pW = pW->mpWindowImpl->mpRealParent;

    Rectangle normRect( rRect );  // rRect is already relative to top-level window
    normRect.SetPos( pW->ScreenToOutputPixel( normRect.TopLeft() ) );

    sal_Bool bRTL = Application::GetSettings().GetLayoutRTL();

    Rectangle devRect(  pW->OutputToAbsoluteScreenPixel( normRect.TopLeft() ), 
                        pW->OutputToAbsoluteScreenPixel( normRect.BottomRight() ) );

    Rectangle devRectRTL( devRect );
    if( bRTL )
        // create a rect that can be compared to desktop coordinates
        devRectRTL = pW->ImplOutputToUnmirroredAbsoluteScreenPixel( normRect );
    if( Application::GetScreenCount() > 1 && ! Application::IsMultiDisplay() )
        aScreenRect = Application::GetScreenPosSizePixel(
            Application::GetBestScreen( bRTL ? devRectRTL : devRect ) );


    sal_uInt16      nArrangeAry[5];
    sal_uInt16      nArrangeIndex;
    sal_Bool        bBreak;
    Point       e1,e2;  // the common edge between the item rect and the floating window

    if ( nFlags & FLOATWIN_POPUPMODE_LEFT )
    {
        nArrangeAry[0]  = FLOATWIN_POPUPMODE_LEFT;
        nArrangeAry[1]  = FLOATWIN_POPUPMODE_RIGHT;
        nArrangeAry[2]  = FLOATWIN_POPUPMODE_UP;
        nArrangeAry[3]  = FLOATWIN_POPUPMODE_DOWN;
        nArrangeAry[4]  = FLOATWIN_POPUPMODE_LEFT;
    }
    else if ( nFlags & FLOATWIN_POPUPMODE_RIGHT )
    {
        nArrangeAry[0]  = FLOATWIN_POPUPMODE_RIGHT;
        nArrangeAry[1]  = FLOATWIN_POPUPMODE_LEFT;
        nArrangeAry[2]  = FLOATWIN_POPUPMODE_UP;
        nArrangeAry[3]  = FLOATWIN_POPUPMODE_DOWN;
        nArrangeAry[4]  = FLOATWIN_POPUPMODE_RIGHT;
    }
    else if ( nFlags & FLOATWIN_POPUPMODE_UP )
    {
        nArrangeAry[0]  = FLOATWIN_POPUPMODE_UP;
        nArrangeAry[1]  = FLOATWIN_POPUPMODE_DOWN;
        nArrangeAry[2]  = FLOATWIN_POPUPMODE_RIGHT;
        nArrangeAry[3]  = FLOATWIN_POPUPMODE_LEFT;
        nArrangeAry[4]  = FLOATWIN_POPUPMODE_UP;
    }
    else
    {
        nArrangeAry[0]  = FLOATWIN_POPUPMODE_DOWN;
        nArrangeAry[1]  = FLOATWIN_POPUPMODE_UP;
        nArrangeAry[2]  = FLOATWIN_POPUPMODE_RIGHT;
        nArrangeAry[3]  = FLOATWIN_POPUPMODE_LEFT;
        nArrangeAry[4]  = FLOATWIN_POPUPMODE_DOWN;
    }
    if ( nFlags & FLOATWIN_POPUPMODE_NOAUTOARRANGE )
        nArrangeIndex = 4;
    else
        nArrangeIndex = 0;

    for ( ; nArrangeIndex < 5; nArrangeIndex++ )
    {
        bBreak = sal_True;
        switch ( nArrangeAry[nArrangeIndex] )
        {

            case FLOATWIN_POPUPMODE_LEFT:
                aPos.X() = devRect.Left()-aSize.Width()+1;
                aPos.Y() = devRect.Top();
                aPos.Y() -= pWindow->mpWindowImpl->mnTopBorder;
                if( bRTL ) // --- RTL --- we're comparing screen coordinates here
                {
                    if( (devRectRTL.Right()+aSize.Width()) > aScreenRect.Right() )
                        bBreak = sal_False;
                }
                else
                {
                    if ( aPos.X() < aScreenRect.Left() )
                        bBreak = sal_False;
                }
                if( bBreak )
                {   
                    e1 = devRect.TopLeft();
                    e2 = devRect.BottomLeft();
                    // set non-zero width
                    e2.X()++;
                    // don't clip corners
                    e1.Y()++;   
                    e2.Y()--;
                }
                break;
            case FLOATWIN_POPUPMODE_RIGHT:
                aPos     = devRect.TopRight();
                aPos.Y() -= pWindow->mpWindowImpl->mnTopBorder;
                if( bRTL ) // --- RTL --- we're comparing screen coordinates here
                {
                    if( (devRectRTL.Left() - aSize.Width()) < aScreenRect.Left() )
                        bBreak = sal_False;
                }
                else
                {
                    if ( aPos.X()+aSize.Width() > aScreenRect.Right() )
                        bBreak = sal_False;
                }
                if( bBreak )
                {   
                    e1 = devRect.TopRight();
                    e2 = devRect.BottomRight();
                    // set non-zero width
                    e2.X()++;
                    // don't clip corners
                    e1.Y()++;   
                    e2.Y()--;
                }
                break;
            case FLOATWIN_POPUPMODE_UP:
                aPos.X() = devRect.Left();
                aPos.Y() = devRect.Top()-aSize.Height()+1;
                if ( aPos.Y() < aScreenRect.Top() )
                    bBreak = sal_False;
                if( bBreak )
                {   
                    e1 = devRect.TopLeft();
                    e2 = devRect.TopRight();
                    // set non-zero height
                    e2.Y()++;
                    // don't clip corners
                    e1.X()++;   
                    e2.X()--;
                }
                break;
            case FLOATWIN_POPUPMODE_DOWN:
                aPos = devRect.BottomLeft();
                if ( aPos.Y()+aSize.Height() > aScreenRect.Bottom() )
                    bBreak = sal_False;
                if( bBreak )
                {   
                    e1 = devRect.BottomLeft();
                    e2 = devRect.BottomRight();
                    // set non-zero height
                    e2.Y()++;
                    // don't clip corners
                    e1.X()++;   
                    e2.X()--;
                }
                break;
        }

        // Evt. noch anpassen
        if ( bBreak && !(nFlags & FLOATWIN_POPUPMODE_NOAUTOARRANGE) )
        {
            if ( (nArrangeAry[nArrangeIndex] == FLOATWIN_POPUPMODE_LEFT)  ||
                 (nArrangeAry[nArrangeIndex] == FLOATWIN_POPUPMODE_RIGHT) )
            {
                if ( aPos.Y()+aSize.Height() > aScreenRect.Bottom() )
                {
                    aPos.Y() = devRect.Bottom()-aSize.Height()+1;
                    if ( aPos.Y() < aScreenRect.Top() )
                        aPos.Y() = aScreenRect.Top();
                }
            }
            else
            {
                if( bRTL ) // --- RTL --- we're comparing screen coordinates here
                {
                    if( devRectRTL.Right()-aSize.Width()+1 < aScreenRect.Left() )
                        aPos.X() -= aScreenRect.Left() - devRectRTL.Right() + aSize.Width() - 1;
                    else if( aPos.X() + aSize.Width() > aScreenRect.Right() )
                    {
                        aPos.X() -= aSize.Width()-2; // popup to left instead
                        aPos.Y() -= 2;
                    }
                }
                else if ( aPos.X()+aSize.Width() > aScreenRect.Right() )
                {
                    aPos.X() = devRect.Right()-aSize.Width()+1;
                    if ( aPos.X() < aScreenRect.Left() )
                        aPos.X() = aScreenRect.Left();
                }
            }
        }

        if ( bBreak )
            break;
    }
    if ( nArrangeIndex > 4 )
        nArrangeIndex = 4;

    rArrangeIndex = nArrangeIndex;

    aPos = pW->AbsoluteScreenToOutputPixel( aPos );

    // store a cliprect that can be used to clip the common edge of the itemrect and the floating window
    if( pFloatingWindow )
    {
        pFloatingWindow->mpImplData->maItemEdgeClipRect =
            Rectangle( e1, e2 );
    }

    // caller expects cordinates relative to top-level win
    return pW->OutputToScreenPixel( aPos );
}

// -----------------------------------------------------------------------

FloatingWindow* FloatingWindow::ImplFloatHitTest( Window* pReference, const Point& rPos, sal_uInt16& rHitTest )
{
    FloatingWindow* pWin = this;

    Point aAbsolute( rPos );

    // compare coordinates in absolute screen coordinates
    if( pReference->ImplHasMirroredGraphics()  )
    {
        if(!pReference->IsRTLEnabled() )
            // --- RTL --- re-mirror back to get device coordiantes
            pReference->ImplReMirror( aAbsolute );

        Rectangle aRect( pReference->ScreenToOutputPixel(aAbsolute), Size(1,1) ) ;
        aRect = pReference->ImplOutputToUnmirroredAbsoluteScreenPixel( aRect );
        aAbsolute = aRect.TopLeft();
    }
    else
        aAbsolute = Point( pReference->OutputToAbsoluteScreenPixel(
            pReference->ScreenToOutputPixel(rPos) ) );
    
    do
    {
        // compute the floating window's size in absolute screen coordinates

        // use the border window to have the exact position
        Window *pBorderWin = pWin->GetWindow( WINDOW_BORDER );

        Point aPt;  // the top-left corner in output coordinates ie (0,0)
        Rectangle devRect( pBorderWin->ImplOutputToUnmirroredAbsoluteScreenPixel( Rectangle( aPt, pBorderWin->GetSizePixel()) ) ) ;
        if ( devRect.IsInside( aAbsolute ) )
        {
            rHitTest = IMPL_FLOATWIN_HITTEST_WINDOW;
            return pWin;
        }

        // test, if mouse is in rectangle, (this is typically the rect of the active 
        // toolbox item or similar) 
        // note: maFloatRect is set in FloatingWindow::StartPopupMode() and
        //       is already in absolute device coordinates
        if ( pWin->maFloatRect.IsInside( aAbsolute ) )
        {
            rHitTest = IMPL_FLOATWIN_HITTEST_RECT;
            return pWin;
        }

        pWin = pWin->mpNextFloat;
    }
    while ( pWin );

    rHitTest = IMPL_FLOATWIN_HITTEST_OUTSIDE;
    return NULL;
}

// -----------------------------------------------------------------------

FloatingWindow* FloatingWindow::ImplFindLastLevelFloat()
{
    FloatingWindow* pWin = this;
    FloatingWindow* pLastFoundWin = pWin;

    do
    {
        if ( pWin->GetPopupModeFlags() & FLOATWIN_POPUPMODE_NEWLEVEL )
            pLastFoundWin = pWin;

        pWin = pWin->mpNextFloat;
    }
    while ( pWin );

    return pLastFoundWin;
}

// -----------------------------------------------------------------------

sal_Bool FloatingWindow::ImplIsFloatPopupModeWindow( const Window* pWindow )
{
    FloatingWindow* pWin = this;

    do
    {
        if ( pWin->mpFirstPopupModeWin == pWindow )
            return sal_True;

        pWin = pWin->mpNextFloat;
    }
    while ( pWin );

    return sal_False;
}

// -----------------------------------------------------------------------

IMPL_LINK( FloatingWindow, ImplEndPopupModeHdl, void*, EMPTYARG )
{
    mnPostId            = 0;
    mnPopupModeFlags    = 0;
    mbPopupMode         = sal_False;
    PopupModeEnd();
    return 0;
}

// -----------------------------------------------------------------------

long FloatingWindow::Notify( NotifyEvent& rNEvt )
{
    // Zuerst Basisklasse rufen wegen TabSteuerung
    long nRet = SystemWindow::Notify( rNEvt );
    if ( !nRet )
    {
        if ( rNEvt.GetType() == EVENT_KEYINPUT )
        {
            const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
            KeyCode         aKeyCode = pKEvt->GetKeyCode();
            sal_uInt16          nKeyCode = aKeyCode.GetCode();

            if ( (nKeyCode == KEY_ESCAPE) && (GetStyle() & WB_CLOSEABLE) )
            {
                Close();
                return sal_True;
            }
        }
    }

    return nRet;
}

// -----------------------------------------------------------------------

void FloatingWindow::StateChanged( StateChangedType nType )
{
    SystemWindow::StateChanged( nType );

    if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
    {
        ImplInitSettings();
        Invalidate();
    }
}

// -----------------------------------------------------------------------

void FloatingWindow::DataChanged( const DataChangedEvent& rDCEvt )
{
    SystemWindow::DataChanged( rDCEvt );

    if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
         (rDCEvt.GetFlags() & SETTINGS_STYLE) )
    {
        ImplInitSettings();
        Invalidate();
    }
}

// -----------------------------------------------------------------------

void FloatingWindow::ImplCallPopupModeEnd()
{
    // PopupMode wurde beendet
    mbInPopupMode = sal_False;

    // Handler asyncron rufen
    if ( !mnPostId )
        Application::PostUserEvent( mnPostId, LINK( this, FloatingWindow, ImplEndPopupModeHdl ) );
}

// -----------------------------------------------------------------------

void FloatingWindow::PopupModeEnd()
{
    maPopupModeEndHdl.Call( this );
}

// -----------------------------------------------------------------------

void FloatingWindow::SetTitleType( sal_uInt16 nTitle )
{
    if ( (mnTitle != nTitle) && mpWindowImpl->mpBorderWindow )
    {
        mnTitle = nTitle;
        Size aOutSize = GetOutputSizePixel();
        sal_uInt16 nTitleStyle;
        if ( nTitle == FLOATWIN_TITLE_NORMAL )
            nTitleStyle = BORDERWINDOW_TITLE_SMALL;
        else if ( nTitle == FLOATWIN_TITLE_TEAROFF )
            nTitleStyle = BORDERWINDOW_TITLE_TEAROFF;
        else // nTitle == FLOATWIN_TITLE_NONE
            nTitleStyle = BORDERWINDOW_TITLE_NONE;
        ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetTitleType( nTitleStyle, aOutSize );
        ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
    }
}

// -----------------------------------------------------------------------

void FloatingWindow::StartPopupMode( const Rectangle& rRect, sal_uLong nFlags )
{
    // avoid flickering
    if ( IsVisible() )
        Show( sal_False, SHOW_NOFOCUSCHANGE );

    if ( IsRollUp() )
        RollDown();

    // remove title 
    mnOldTitle = mnTitle;
    if ( nFlags & FLOATWIN_POPUPMODE_ALLOWTEAROFF )
        SetTitleType( FLOATWIN_TITLE_TEAROFF );
    else
        SetTitleType( FLOATWIN_TITLE_NONE );

    // avoid close on focus change for decorated floating windows only
    if( mpWindowImpl->mbFrame && (GetStyle() & WB_MOVEABLE) )
        nFlags |= FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE;

    // #102010# For debugging Accessibility
    static const char* pEnv = getenv("SAL_FLOATWIN_NOAPPFOCUSCLOSE" );
    if( pEnv && *pEnv )
        nFlags |= FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE;

    // compute window position according to flags and arrangement
    sal_uInt16 nArrangeIndex;
    SetPosPixel( ImplCalcPos( this, rRect, nFlags, nArrangeIndex ) );

    // set data and display window
    // convert maFloatRect to absolute device coordinates
    // so they can be compared across different frames
    // !!! rRect is expected to be in screen coordinates of the parent frame window !!!
    maFloatRect             = rRect;
    if( GetParent()->ImplHasMirroredGraphics() )
    {
        maFloatRect.SetPos( GetParent()->ScreenToOutputPixel( rRect.TopLeft() ) );
        maFloatRect = GetParent()->ImplOutputToUnmirroredAbsoluteScreenPixel( maFloatRect );
    }
    else
        maFloatRect.SetPos( GetParent()->OutputToAbsoluteScreenPixel( GetParent()->ScreenToOutputPixel( rRect.TopLeft() ) ) );

    maFloatRect.Left()     -= 2;
    maFloatRect.Top()      -= 2;
    maFloatRect.Right()    += 2;
    maFloatRect.Bottom()   += 2;
    mnPopupModeFlags        = nFlags;
    mbInPopupMode           = sal_True;
    mbPopupMode             = sal_True;
    mbPopupModeCanceled     = sal_False;
    mbPopupModeTearOff      = sal_False;
    mbMouseDown             = sal_False;

    mbOldSaveBackMode       = IsSaveBackgroundEnabled();
    EnableSaveBackground();

    // add FloatingWindow to list of windows that are in popup mode
    ImplSVData* pSVData = ImplGetSVData();
    mpNextFloat = pSVData->maWinData.mpFirstFloat;
    pSVData->maWinData.mpFirstFloat = this;
    if( nFlags & FLOATWIN_POPUPMODE_GRABFOCUS )
    {
        // force key input even without focus (useful for menues)
        mbGrabFocus = sal_True;
    }
    Show( sal_True, SHOW_NOACTIVATE );
}

// -----------------------------------------------------------------------

void FloatingWindow::StartPopupMode( ToolBox* pBox, sal_uLong nFlags )
{
    // get selected button
    sal_uInt16 nItemId = pBox->GetDownItemId();
    if ( !nItemId )
        return;

    mpImplData->mpBox = pBox;
    pBox->ImplFloatControl( sal_True, this );

    // retrieve some data from the ToolBox
    Rectangle aRect = pBox->GetItemRect( nItemId );
    Point aPos;
    // convert to parent's screen coordinates
    aPos = GetParent()->OutputToScreenPixel( GetParent()->AbsoluteScreenToOutputPixel( pBox->OutputToAbsoluteScreenPixel( aRect.TopLeft() ) ) );
    aRect.SetPos( aPos );

    nFlags |=
        FLOATWIN_POPUPMODE_NOFOCUSCLOSE 	|
//        FLOATWIN_POPUPMODE_NOMOUSECLOSE		|
        FLOATWIN_POPUPMODE_ALLMOUSEBUTTONCLOSE |
//        FLOATWIN_POPUPMODE_NOMOUSERECTCLOSE	|   // #105968# floating toolboxes should close when clicked in (parent's) float rect
        FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE;
//        	|      FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE;

/*
 *  FLOATWIN_POPUPMODE_NOKEYCLOSE		|
 *  don't set since it disables closing floaters with escape
 */

    // Flags fuer Positionierung bestimmen
    if ( !(nFlags & (FLOATWIN_POPUPMODE_DOWN | FLOATWIN_POPUPMODE_UP |
                     FLOATWIN_POPUPMODE_LEFT | FLOATWIN_POPUPMODE_RIGHT |
                     FLOATWIN_POPUPMODE_NOAUTOARRANGE)) )
    {
         if ( pBox->IsHorizontal() )
             nFlags |= FLOATWIN_POPUPMODE_DOWN;
         else
             nFlags |= FLOATWIN_POPUPMODE_RIGHT;
    }

    // FloatingModus starten
    StartPopupMode( aRect, nFlags );
}

// -----------------------------------------------------------------------

void FloatingWindow::ImplEndPopupMode( sal_uInt16 nFlags, sal_uLong nFocusId )
{
    if ( !mbInPopupMode )
        return;

    ImplSVData* pSVData = ImplGetSVData();

    mbInCleanUp = sal_True; // prevent killing this window due to focus change while working with it

    // Bei allen nachfolgenden PopupMode-Fenster den Modus auch beenden
    while ( pSVData->maWinData.mpFirstFloat && pSVData->maWinData.mpFirstFloat != this )
        pSVData->maWinData.mpFirstFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL );

    
    // Fenster aus der Liste austragen
    pSVData->maWinData.mpFirstFloat = mpNextFloat;
    mpNextFloat = NULL;

    sal_uLong nPopupModeFlags = mnPopupModeFlags;

    // Wenn nicht abgerissen wurde, dann Fenster wieder Hiden
    if ( !(nFlags & FLOATWIN_POPUPMODEEND_TEAROFF) ||
         !(nPopupModeFlags & FLOATWIN_POPUPMODE_ALLOWTEAROFF) )
    {
        Show( sal_False, SHOW_NOFOCUSCHANGE );

        // Focus evt. auf ein entsprechendes FloatingWindow weiterschalten
        if ( nFocusId )
            Window::EndSaveFocus( nFocusId );
        else if ( pSVData->maWinData.mpFocusWin && pSVData->maWinData.mpFirstFloat &&
                  ImplIsWindowOrChild( pSVData->maWinData.mpFocusWin ) )
            pSVData->maWinData.mpFirstFloat->GrabFocus();
        mbPopupModeTearOff = sal_False;
    }
    else
    {
        mbPopupModeTearOff = sal_True;
        if ( nFocusId )
            Window::EndSaveFocus( nFocusId, sal_False );
    }
    EnableSaveBackground( mbOldSaveBackMode );

    mbPopupModeCanceled = (nFlags & FLOATWIN_POPUPMODEEND_CANCEL) != 0;

    // Gegebenenfalls den Title wieder herstellen
    SetTitleType( mnOldTitle );

    // ToolBox wieder auf normal schalten
    if ( mpImplData->mpBox )
    {
        mpImplData->mpBox->ImplFloatControl( sal_False, this );
        mpImplData->mpBox = NULL;
    }

    // Je nach Parameter den PopupModeEnd-Handler rufen
    if ( !(nFlags & FLOATWIN_POPUPMODEEND_DONTCALLHDL) )
        ImplCallPopupModeEnd();

    // Je nach Parameter die restlichen Fenster auch noch schliessen
    if ( nFlags & FLOATWIN_POPUPMODEEND_CLOSEALL )
    {
        if ( !(nPopupModeFlags & FLOATWIN_POPUPMODE_NEWLEVEL) )
        {
            if ( pSVData->maWinData.mpFirstFloat )
            {
                FloatingWindow* pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
                pLastLevelFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
            }
        }
    }

    mbInCleanUp = sal_False;
}

// -----------------------------------------------------------------------

void FloatingWindow::EndPopupMode( sal_uInt16 nFlags )
{
    ImplEndPopupMode( nFlags );
}

// -----------------------------------------------------------------------

void FloatingWindow::AddPopupModeWindow( Window* pWindow )
{
    // !!! bisher erst 1 Fenster und noch keine Liste
    mpFirstPopupModeWin = pWindow;
}

// -----------------------------------------------------------------------

void FloatingWindow::RemovePopupModeWindow( Window* pWindow )
{
    // !!! bisher erst 1 Fenster und noch keine Liste
    if ( mpFirstPopupModeWin == pWindow )
        mpFirstPopupModeWin = NULL;
}

