/**************************************************************
 * 
 * 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 <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include "tools/debug.hxx"

#include "sal/alloca.h"

#include "vcl/floatwin.hxx"
#include "vcl/svapp.hxx"
#include "vcl/keycodes.hxx"
#include "vcl/printerinfomanager.hxx"
#include "vcl/settings.hxx"

#include <tools/prex.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
#include "FWS.hxx"
#include <X11/extensions/shape.h>
#ifndef SOLARIS
#include <X11/extensions/dpms.h>
#endif
#include <tools/postx.h>

#include "unx/salunx.h"
#include "unx/saldata.hxx"
#include "unx/saldisp.hxx"
#include "unx/salgdi.h"
#include "unx/salframe.h"
#include "unx/soicon.hxx"
#include "unx/dtint.hxx"
#include "unx/sm.hxx"
#include "unx/wmadaptor.hxx"
#include "unx/salprn.h"
#include "unx/salbmp.h"
#include "unx/i18n_ic.hxx"
#include "unx/i18n_keysym.hxx"
#include "unx/i18n_status.hxx"

#include "salinst.hxx"
#include "sallayout.hxx"

#include <com/sun/star/uno/Exception.hpp>

#include <algorithm>

#ifndef Button6
# define Button6 6
#endif
#ifndef Button7
# define Button7 7
#endif

using namespace vcl_sal;
using namespace vcl;

// -=-= #defines -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#define CLIENT_EVENTS			StructureNotifyMask \
								| SubstructureNotifyMask \
								| KeyPressMask \
								| KeyReleaseMask \
								| ButtonPressMask \
								| ButtonReleaseMask \
								| PointerMotionMask \
								| EnterWindowMask \
								| LeaveWindowMask \
								| FocusChangeMask \
								| ExposureMask \
								| VisibilityChangeMask \
								| PropertyChangeMask \
								| ColormapChangeMask

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

static XLIB_Window	hPresentationWindow = None, hPresFocusWindow = None;
static ::std::list< XLIB_Window > aPresentationReparentList;
static int			nVisibleFloats		= 0;

X11SalFrame* X11SalFrame::s_pSaveYourselfFrame = NULL;

// -=-= C++ statics =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
static void doReparentPresentationDialogues( SalDisplay* pDisplay )
{
    pDisplay->GetXLib()->PushXErrorLevel( true );
    while( aPresentationReparentList.begin() != aPresentationReparentList.end() )
    {
        int x, y;
        XLIB_Window aRoot, aChild;
        unsigned int w, h, bw, d;
        XGetGeometry( pDisplay->GetDisplay(),
                      aPresentationReparentList.front(),
                      &aRoot,
                      &x, &y, &w, &h, &bw, &d );
        XTranslateCoordinates( pDisplay->GetDisplay(),
                               hPresentationWindow,
                               aRoot,
                               x, y,
                               &x, &y,
                               &aChild );
        XReparentWindow( pDisplay->GetDisplay(),
                         aPresentationReparentList.front(),
                         aRoot,
                         x, y );
        aPresentationReparentList.pop_front();
    }
    if( hPresFocusWindow )
        XSetInputFocus( pDisplay->GetDisplay(), hPresFocusWindow, PointerRoot, CurrentTime );
    XSync( pDisplay->GetDisplay(), False );
    pDisplay->GetXLib()->PopXErrorLevel();
}

// -=-= SalFrame / X11SalFrame =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

bool X11SalFrame::IsOverrideRedirect() const
{
    return
        ((nStyle_ & SAL_FRAME_STYLE_INTRO) && !pDisplay_->getWMAdaptor()->supportsSplash())
        ||
        (!( nStyle_ & ~SAL_FRAME_STYLE_DEFAULT ) && !pDisplay_->getWMAdaptor()->supportsFullScreen())
        ;
}

bool X11SalFrame::IsFloatGrabWindow() const
{
    static const char* pDisableGrab = getenv( "SAL_DISABLE_FLOATGRAB" );

    return
        ( ( !pDisableGrab || !*pDisableGrab ) &&
          (
           (nStyle_ & SAL_FRAME_STYLE_FLOAT)	&&
           ! (nStyle_ & SAL_FRAME_STYLE_TOOLTIP)	&&
           ! (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION)
           )
          );
}

void X11SalFrame::setXEmbedInfo()
{
    if( m_bXEmbed )
    {
        long aInfo[2];
        aInfo[0] = 1; // XEMBED protocol version
        aInfo[1] = (bMapped_ ? 1 : 0); // XEMBED_MAPPED
        XChangeProperty( pDisplay_->GetDisplay(),
                         mhWindow,
                         pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::XEMBED_INFO ),
                         pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::XEMBED_INFO ),
                         32,
                         PropModeReplace,
                         reinterpret_cast<unsigned char*>(aInfo),
                         sizeof(aInfo)/sizeof(aInfo[0]) );
    }
}

void X11SalFrame::askForXEmbedFocus( sal_Int32 i_nTimeCode )
{
    XEvent aEvent;
    
    rtl_zeroMemory( &aEvent, sizeof(aEvent) );
    aEvent.xclient.window = mhForeignParent;
    aEvent.xclient.type = ClientMessage;
    aEvent.xclient.message_type = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::XEMBED );
    aEvent.xclient.format = 32;
    aEvent.xclient.data.l[0] = i_nTimeCode ? i_nTimeCode : CurrentTime;
    aEvent.xclient.data.l[1] = 3; // XEMBED_REQUEST_FOCUS
    aEvent.xclient.data.l[2] = 0;
    aEvent.xclient.data.l[3] = 0;
    aEvent.xclient.data.l[4] = 0;
    
    GetDisplay()->GetXLib()->PushXErrorLevel( true );
    XSendEvent( pDisplay_->GetDisplay(),
                mhForeignParent,
                False, NoEventMask, &aEvent );
    XSync( pDisplay_->GetDisplay(), False );
    GetDisplay()->GetXLib()->PopXErrorLevel();
}


// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void X11SalFrame::Init( sal_uLong nSalFrameStyle, int nScreen, SystemParentData* pParentData, bool bUseGeometry )
{
    if( nScreen < 0 || nScreen >= GetDisplay()->GetScreenCount() )
        nScreen = GetDisplay()->GetDefaultScreenNumber();
    if( mpParent )
        nScreen = mpParent->m_nScreen;
    
    m_nScreen   = nScreen;
	nStyle_ 	= nSalFrameStyle;
	XWMHints Hints;
    Hints.flags = InputHint;
    Hints.input = (nSalFrameStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) ? False : True;

    int x = 0, y = 0;
    unsigned int w = 500, h = 500;
    XSetWindowAttributes Attributes;

    int nAttrMask =   CWBorderPixel
                    | CWBackPixmap
                    | CWColormap
                    | CWOverrideRedirect
                    | CWEventMask
                    ;
    Attributes.border_pixel             = 0;
    Attributes.background_pixmap		= None;
    Attributes.colormap					= GetDisplay()->GetColormap( m_nScreen ).GetXColormap();
    Attributes.override_redirect		= False;
    Attributes.event_mask				= CLIENT_EVENTS;
    
    const SalVisual& rVis = GetDisplay()->GetVisual( m_nScreen );
    XLIB_Window aFrameParent = pParentData ? pParentData->aWindow : GetDisplay()->GetRootWindow( m_nScreen );
    XLIB_Window aClientLeader = None;
    
    if( bUseGeometry )
    {
        x = maGeometry.nX;
        y = maGeometry.nY;
        w = maGeometry.nWidth;
        h = maGeometry.nHeight;
    }
    
    if( (nSalFrameStyle & SAL_FRAME_STYLE_FLOAT) &&
        ! (nSalFrameStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION)
        )
	{
        if( nShowState_ == SHOWSTATE_UNKNOWN )
        {
            w = 10;
            h = 10;
        }
        Attributes.override_redirect = True;
	}
    else if( (nSalFrameStyle & SAL_FRAME_STYLE_SYSTEMCHILD ) )
    {
        DBG_ASSERT( mpParent, "SAL_FRAME_STYLE_SYSTEMCHILD window without parent" );
        if( mpParent )
        {
            aFrameParent = mpParent->mhWindow;
            // FIXME: since with SAL_FRAME_STYLE_SYSTEMCHILD
            // multiple X11SalFrame objects can have the same shell window
            // dispatching events in saldisp.cxx is unclear (the first frame)
            // wins. HTH this correctly is unclear yet
            // for the time being, treat set the shell window to own window
            // like for a normal frame
            // mhShellWindow = mpParent->GetShellWindow();
        }
    }
	else if( pParentData )
	{
        // plugin parent may be killed unexpectedly by
        // plugging process; ignore XErrors in that case
        GetDisplay()->setHaveSystemChildFrame();

		nStyle_ |= SAL_FRAME_STYLE_PLUG;
        Attributes.override_redirect = True;
        if( pParentData->nSize >= sizeof(SystemParentData) )
            m_bXEmbed = pParentData->bXEmbedSupport;

		int x_ret, y_ret;
		unsigned int bw, d;
		XLIB_Window aRoot, aParent;

		XGetGeometry( GetXDisplay(), pParentData->aWindow,
					  &aRoot, &x_ret, &y_ret, &w, &h, &bw, &d );
		mhForeignParent = pParentData->aWindow;

		mhShellWindow = aParent = mhForeignParent;
		XLIB_Window* pChildren;
		unsigned int nChildren;
        bool bBreak = false;
		do
		{
			XQueryTree( GetDisplay()->GetDisplay(), mhShellWindow,
						&aRoot, &aParent, &pChildren, &nChildren );
			XFree( pChildren );
			if( aParent != aRoot )
				mhShellWindow = aParent;
            int nCount = 0;
            Atom* pProps = XListProperties( GetDisplay()->GetDisplay(),
                                            mhShellWindow,
                                            &nCount );
            for( int i = 0; i < nCount && ! bBreak; ++i )
                bBreak = (pProps[i] == XA_WM_HINTS);
            if( pProps )
                XFree( pProps );
		} while( aParent != aRoot && ! bBreak );

		// check if this is really one of our own frames
		// do not change the input mask in that case
        const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames();
        std::list< SalFrame* >::const_iterator it = rFrames.begin();
        while( it != rFrames.end() && mhForeignParent != static_cast<const X11SalFrame*>(*it)->GetWindow() )
            ++it;

		if( it == rFrames.end() )
		{
			XSelectInput( GetDisplay()->GetDisplay(), mhForeignParent, StructureNotifyMask | FocusChangeMask );
			XSelectInput( GetDisplay()->GetDisplay(), mhShellWindow, StructureNotifyMask | FocusChangeMask );
		}
    }
    else
    {
        if( ! bUseGeometry )
        {
            Size aScreenSize( GetDisplay()->getDataForScreen( m_nScreen ).m_aSize );
            w = aScreenSize.Width();
            h = aScreenSize.Height();
            if( nSalFrameStyle & SAL_FRAME_STYLE_SIZEABLE &&
                nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE )
            {
                // fill in holy default values brought to us by product management
                if( aScreenSize.Width() >= 800 )
                    w = 785;
                if( aScreenSize.Width() >= 1024 )
                    w = 920;
    
                if( aScreenSize.Height() >= 600 )
                    h = 550;
                if( aScreenSize.Height() >= 768 )
                    h = 630;
                if( aScreenSize.Height() >= 1024 )
                    h = 875;
            }
            if( ! mpParent )
            {
                // find the last document window (if any)
                const X11SalFrame* pFrame = NULL;
                const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames();
                std::list< SalFrame* >::const_iterator it = rFrames.begin();
                while( it != rFrames.end() )
                {
                    pFrame = static_cast< const X11SalFrame* >(*it);
                    if( ! ( pFrame->mpParent
                            || pFrame->mbFullScreen
                            || ! ( pFrame->nStyle_ & SAL_FRAME_STYLE_SIZEABLE )
                            || ! pFrame->GetUnmirroredGeometry().nWidth
                            || ! pFrame->GetUnmirroredGeometry().nHeight
                            )
                        )
                        break;
                    ++it;
                }
                
                if( it != rFrames.end() )
                {
                    // set a document position and size
                    // the first frame gets positioned by the window manager
                    const SalFrameGeometry& rGeom( pFrame->GetUnmirroredGeometry() );
                    x = rGeom.nX;
                    y = rGeom.nY;
                    if( x+(int)w+40 <= (int)aScreenSize.Width() &&
                        y+(int)h+40 <= (int)aScreenSize.Height()
                        )
                    {
                        y += 40;
                        x += 40;
                    }
                    else
                    {
                        x = 10; // leave some space for decoration
                        y = 20;
                    }
                }
                else if( GetDisplay()->IsXinerama() )
                {
                    // place frame on same screen as mouse pointer
                    XLIB_Window aRoot, aChild;
                    int root_x = 0, root_y = 0, lx, ly;
                    unsigned int mask;
                    XQueryPointer( GetXDisplay(),
                                   GetDisplay()->GetRootWindow( m_nScreen ),
                                   &aRoot, &aChild,
                                   &root_x, &root_y, &lx, &ly, &mask );
                    const std::vector< Rectangle >& rScreens = GetDisplay()->GetXineramaScreens();
                    for( unsigned int i = 0; i < rScreens.size(); i++ )
                        if( rScreens[i].IsInside( Point( root_x, root_y ) ) )
                        {
                            x = rScreens[i].Left();
                            y = rScreens[i].Top();
                            break;
                        }
                }
            }
        }
        Attributes.win_gravity = pDisplay_->getWMAdaptor()->getInitWinGravity();
        nAttrMask |= CWWinGravity;
        if( mpParent )
        {
            Attributes.save_under = True;
            nAttrMask |= CWSaveUnder;
        }
        if( IsOverrideRedirect() )
            Attributes.override_redirect = True;
        // default icon
        if( (nStyle_ & SAL_FRAME_STYLE_INTRO) == 0 )
        {
            bool bOk=false;
            try
            {
                bOk=SelectAppIconPixmap( pDisplay_, m_nScreen,
                                         mnIconID != 1 ? mnIconID : 
                                         (mpParent ? mpParent->mnIconID : 1), 32,
                                         Hints.icon_pixmap, Hints.icon_mask );
            }
            catch( com::sun::star::uno::Exception& )
            {
                // can happen - no ucb during early startup
            }
            if( bOk )
            {
                Hints.flags		|= IconPixmapHint;
                if( Hints.icon_mask )
                    Hints.flags	|= IconMaskHint;
            }
        }

		// find the top level frame of the transience hierarchy
        X11SalFrame* pFrame = this;
        while( pFrame->mpParent )
            pFrame = pFrame->mpParent;
		if( (pFrame->nStyle_ & SAL_FRAME_STYLE_PLUG ) )
		{
			// if the top level window is a plugin window,
			// then we should place us in the same window group as
			// the parent application (or none if there is no window group
			// hint in the parent).
			if( pFrame->GetShellWindow() )
			{
				XWMHints* pWMHints = XGetWMHints( pDisplay_->GetDisplay(),
					pFrame->GetShellWindow() );
				if( pWMHints )
				{
					if( (pWMHints->flags & WindowGroupHint) )
					{
						Hints.flags |= WindowGroupHint;
						Hints.window_group = pWMHints->window_group;
					}
					XFree( pWMHints );
				}
			}
		}
		else
		{
			Hints.flags			|= WindowGroupHint;
			Hints.window_group	= pFrame->GetShellWindow();
			// note: for a normal document window this will produce None
			// as the window is not yet created and the shell window is
			// initialized to None. This must be corrected after window creation.
			aClientLeader = GetDisplay()->GetDrawable( m_nScreen );
		}
    }

	nShowState_ 				= SHOWSTATE_UNKNOWN;
	bViewable_					= sal_True;
	bMapped_					= sal_False;
	nVisibility_				= VisibilityFullyObscured;
    mhWindow = XCreateWindow( GetXDisplay(),
                              aFrameParent,
                              x, y,
                              w, h,
                              0,
                              rVis.GetDepth(),
                              InputOutput,
                              rVis.GetVisual(),
                              nAttrMask,
                              &Attributes );
    // FIXME: see above: fake shell window for now to own window
    if( /*! IsSysChildWindow() &&*/ pParentData == NULL )
    {
        mhShellWindow = mhWindow;
    }    
	
	// correct window group if necessary
	if( (Hints.flags & WindowGroupHint) == WindowGroupHint )
	{
		if( Hints.window_group == None )
			Hints.window_group = GetShellWindow();
	}

    maGeometry.nX		= x;
    maGeometry.nY		= y;
    maGeometry.nWidth	= w;
    maGeometry.nHeight	= h;
    updateScreenNumber();

    XSync( GetXDisplay(), False );
    setXEmbedInfo();

    XLIB_Time nUserTime = (nStyle_ & (SAL_FRAME_STYLE_OWNERDRAWDECORATION | SAL_FRAME_STYLE_TOOLWINDOW) ) == 0 ?
        pDisplay_->GetLastUserEventTime() : 0;
    pDisplay_->getWMAdaptor()->setUserTime( this, nUserTime );

	if( ! pParentData && ! IsChildWindow() && ! Attributes.override_redirect )
	{
        XSetWMHints( GetXDisplay(), mhWindow, &Hints );
		// WM Protocols && internals
		Atom a[4];
		int  n = 0;
		a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_DELETE_WINDOW );
        if( pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_PING ) )
            a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_PING );
        if( ! s_pSaveYourselfFrame && ! mpParent)
        {
            // at all times have only one frame with SaveYourself
            a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_SAVE_YOURSELF );
            s_pSaveYourselfFrame = this;
        }
        if( (nSalFrameStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) )
            a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_TAKE_FOCUS );
		XSetWMProtocols( GetXDisplay(), GetShellWindow(), a, n );

        XClassHint* pClass = XAllocClassHint();
        pClass->res_name  = const_cast<char*>(X11SalData::getFrameResName());
        pClass->res_class = const_cast<char*>(X11SalData::getFrameClassName());
        XSetClassHint( GetXDisplay(), GetShellWindow(), pClass );
        XFree( pClass );

        XSizeHints* pHints = XAllocSizeHints();
        pHints->flags       = PWinGravity | PPosition;
        pHints->win_gravity = GetDisplay()->getWMAdaptor()->getPositionWinGravity();
        pHints->x           = 0;
        pHints->y           = 0;
        if( mbFullScreen )
        {
            pHints->flags |= PMaxSize | PMinSize;
            pHints->max_width = w+100;
            pHints->max_height = h+100;
            pHints->min_width  = w;
            pHints->min_height = h;
        }
        XSetWMNormalHints( GetXDisplay(),
                           GetShellWindow(),
                           pHints );
        XFree (pHints);
        
        // set PID and WM_CLIENT_MACHINE
        pDisplay_->getWMAdaptor()->setClientMachine( this );
        pDisplay_->getWMAdaptor()->setPID( this );

        // set client leader
		if( aClientLeader )
		{
			XChangeProperty( GetXDisplay(),
            	             mhWindow,
							 pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_CLIENT_LEADER),
							 XA_WINDOW,
							 32,
							 PropModeReplace,
							 (unsigned char*)&aClientLeader,
							 1
							 );
		}
#define DECOFLAGS (SAL_FRAME_STYLE_MOVEABLE | SAL_FRAME_STYLE_SIZEABLE | SAL_FRAME_STYLE_CLOSEABLE)
        int nDecoFlags = WMAdaptor::decoration_All;
        if( (nStyle_ & SAL_FRAME_STYLE_PARTIAL_FULLSCREEN) ||
            (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION)
            )
            nDecoFlags = 0;
        else if( (nStyle_ & DECOFLAGS ) != DECOFLAGS || (nStyle_ & SAL_FRAME_STYLE_TOOLWINDOW) )
        {
            if( nStyle_ & DECOFLAGS )
                // if any decoration, then show a border
                nDecoFlags = WMAdaptor::decoration_Border;
            else
                nDecoFlags = 0;

            if( ! mpParent && (nStyle_ & DECOFLAGS) )
                // don't add a min button if window should be decorationless
                nDecoFlags |= WMAdaptor::decoration_MinimizeBtn;
            if( nStyle_ & SAL_FRAME_STYLE_CLOSEABLE )
                nDecoFlags |= WMAdaptor::decoration_CloseBtn;
            if( nStyle_ & SAL_FRAME_STYLE_SIZEABLE )
            {
                nDecoFlags |= WMAdaptor::decoration_Resize;
                if( ! (nStyle_ & SAL_FRAME_STYLE_TOOLWINDOW) )
                    nDecoFlags |= WMAdaptor::decoration_MaximizeBtn;
            }
            if( nStyle_ & SAL_FRAME_STYLE_MOVEABLE )
                nDecoFlags |= WMAdaptor::decoration_Title;
        }

        WMAdaptor::WMWindowType eType = WMAdaptor::windowType_Normal;
        if( nStyle_ & SAL_FRAME_STYLE_INTRO )
            eType = WMAdaptor::windowType_Splash;
        if( (nStyle_ & SAL_FRAME_STYLE_DIALOG) && hPresentationWindow == None )
            eType = WMAdaptor::windowType_ModelessDialogue;
        if( nStyle_ & SAL_FRAME_STYLE_TOOLWINDOW )
            eType = WMAdaptor::windowType_Utility;
        if( nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION )
            eType = WMAdaptor::windowType_Toolbar;
        if(    (nStyle_ & SAL_FRAME_STYLE_PARTIAL_FULLSCREEN)
            && GetDisplay()->getWMAdaptor()->isLegacyPartialFullscreen() )
            eType = WMAdaptor::windowType_Dock;

        GetDisplay()->getWMAdaptor()->
            setFrameTypeAndDecoration( this,
                                       eType,
                                       nDecoFlags,
                                       hPresentationWindow ? NULL : mpParent );

	    if( (nStyle_ & (SAL_FRAME_STYLE_DEFAULT |
                        SAL_FRAME_STYLE_OWNERDRAWDECORATION|
                        SAL_FRAME_STYLE_FLOAT |
                        SAL_FRAME_STYLE_INTRO |
                        SAL_FRAME_STYLE_PARTIAL_FULLSCREEN) )
             == SAL_FRAME_STYLE_DEFAULT )
            pDisplay_->getWMAdaptor()->maximizeFrame( this, true, true );
	}
        
    m_nWorkArea = GetDisplay()->getWMAdaptor()->getCurrentWorkArea();
    
	// Pointer
	SetPointer( POINTER_ARROW );
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
X11SalFrame::X11SalFrame( SalFrame *pParent, sal_uLong nSalFrameStyle, SystemParentData* pSystemParent )
{
	X11SalData* pSalData = GetX11SalData();

    // initialize frame geometry
    memset( &maGeometry, 0, sizeof(maGeometry) );

    mpParent					= static_cast< X11SalFrame* >( pParent );

    mbTransientForRoot			= false;

	pDisplay_					= pSalData->GetDisplay();
	// insert frame in framelist
    pDisplay_->registerFrame( this );

    mhWindow					= None;
    mhShellWindow				= None;
    mhStackingWindow			= None;
    mhForeignParent				= None;
    mhBackgroundPixmap          = None;
    m_bSetFocusOnMap            = false;

	pGraphics_					= NULL;
	pFreeGraphics_				= NULL;

	hCursor_					= None;
	nCaptured_					= 0;

 	nReleaseTime_				= 0;
	nKeyCode_					= 0;
	nKeyState_					= 0;
	nCompose_					= -1;
    mbKeyMenu					= false;
    mbSendExtKeyModChange		= false;
    mnExtKeyMod					= 0;

	nShowState_ 				= SHOWSTATE_UNKNOWN;
	nWidth_ 					= 0;
	nHeight_					= 0;
	nStyle_ 					= 0;
    mnExtStyle                  = 0;
	bAlwaysOnTop_				= sal_False;

    // set bViewable_ to sal_True: hack GetClientSize to report something
    // different to 0/0 before first map
	bViewable_					= sal_True;
	bMapped_					= sal_False;
	bDefaultPosition_			= sal_True;
	nVisibility_				= VisibilityFullyObscured;
    m_nWorkArea                 = 0;
    mbInShow					= sal_False;
    m_bXEmbed                   = false;

	nScreenSaversTimeout_		= 0;

	mpInputContext 				= NULL;
	mbInputFocus				= False;

    maAlwaysOnTopRaiseTimer.SetTimeoutHdl( LINK( this, X11SalFrame, HandleAlwaysOnTopRaise ) );
    maAlwaysOnTopRaiseTimer.SetTimeout( 100 );

    meWindowType				= WMAdaptor::windowType_Normal;
    mnDecorationFlags			= WMAdaptor::decoration_All;
    mbMaximizedVert				= false;
    mbMaximizedHorz				= false;
    mbShaded					= false;
    mbFullScreen				= false;

    mnIconID					= 1; // ICON_DEFAULT
    
    m_pClipRectangles           = NULL;
    m_nCurClipRect              = 0;
    m_nMaxClipRect              = 0;

	if( mpParent )
		mpParent->maChildren.push_back( this );

	Init( nSalFrameStyle, GetDisplay()->GetDefaultScreenNumber(), pSystemParent );
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void X11SalFrame::passOnSaveYourSelf()
{
    if( this == s_pSaveYourselfFrame )
    {
        // pass on SaveYourself
        const X11SalFrame* pFrame = NULL;
        const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames();
        std::list< SalFrame* >::const_iterator it = rFrames.begin();
        while( it != rFrames.end() )
        {
            pFrame = static_cast< const X11SalFrame* >(*it);
            if( ! ( IsChildWindow() || pFrame->mpParent )
                && pFrame != s_pSaveYourselfFrame )
                    break;
            ++it;    
        }
        
        s_pSaveYourselfFrame = (it != rFrames.end() ) ? const_cast<X11SalFrame*>(pFrame) : NULL;
        if( s_pSaveYourselfFrame )
        {
            Atom a[4];
            int  n = 0;
            a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_DELETE_WINDOW );
            a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_SAVE_YOURSELF );
            if( pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_PING ) )
                a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_PING );
            XSetWMProtocols( GetXDisplay(), s_pSaveYourselfFrame->GetShellWindow(), a, n );
        }
    }
}

X11SalFrame::~X11SalFrame()
{
	notifyDelete();
    
    if( m_pClipRectangles )
    {
        delete [] m_pClipRectangles;
        m_pClipRectangles = NULL;
        m_nCurClipRect = m_nMaxClipRect = 0;
    }
    
    if( mhBackgroundPixmap )
    {
        XSetWindowBackgroundPixmap( GetXDisplay(), GetWindow(), None );
        XFreePixmap( GetXDisplay(), mhBackgroundPixmap ); 
    }
	
    if( mhStackingWindow )
        aPresentationReparentList.remove( mhStackingWindow );

	// remove from parent's list
	if( mpParent )
		mpParent->maChildren.remove( this );

    // deregister on SalDisplay
    pDisplay_->deregisterFrame( this );

	// unselect all events, some may be still in the queue anyway
    if( ! IsSysChildWindow() )
        XSelectInput( GetXDisplay(), GetShellWindow(), 0 );
	XSelectInput( GetXDisplay(), GetWindow(), 0 );

	ShowFullScreen( sal_False, 0 );

	if( bMapped_ )
		Show( sal_False );

    if( mpInputContext )
    {
        mpInputContext->UnsetICFocus( this );
        mpInputContext->Unmap( this );
        delete mpInputContext;
    }

    if( GetWindow() == hPresentationWindow )
    {
        hPresentationWindow = None;
        doReparentPresentationDialogues( GetDisplay() );
    }

	if( pGraphics_ )
	{
		pGraphics_->DeInit();
		delete pGraphics_;
	}

	if( pFreeGraphics_ )
	{
		pFreeGraphics_->DeInit();
		delete pFreeGraphics_;
	}


    XDestroyWindow( GetXDisplay(), mhWindow );

    /*
     *  check if there is only the status frame left
     *  if so, free it
     */
    if( ! GetDisplay()->getFrames().empty() && I18NStatus::exists() )
    {
        SalFrame* pStatusFrame = I18NStatus::get().getStatusFrame();
        std::list< SalFrame* >::const_iterator sit = GetDisplay()->getFrames().begin();
        if( pStatusFrame
            && *sit == pStatusFrame
            && ++sit == GetDisplay()->getFrames().end() )
            vcl::I18NStatus::free();
    }

    passOnSaveYourSelf();
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void X11SalFrame::SetExtendedFrameStyle( SalExtStyle nStyle )
{
    if( nStyle != mnExtStyle && ! IsChildWindow() )
    {
        mnExtStyle = nStyle;
    
        XClassHint* pClass = XAllocClassHint();
        rtl::OString aResHint = X11SalData::getFrameResName( mnExtStyle );
        pClass->res_name  = const_cast<char*>(aResHint.getStr());
        pClass->res_class = const_cast<char*>(X11SalData::getFrameClassName());
        XSetClassHint( GetXDisplay(), GetShellWindow(), pClass );
        XFree( pClass );
    }
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void X11SalFrame::SetBackgroundBitmap( SalBitmap* pBitmap )
{
    if( mhBackgroundPixmap )
    {
        XSetWindowBackgroundPixmap( GetXDisplay(), GetWindow(), None );
        XFreePixmap( GetXDisplay(), mhBackgroundPixmap );
        mhBackgroundPixmap = None;
    }
    if( pBitmap )
    {
        X11SalBitmap* pBM = static_cast<X11SalBitmap*>(pBitmap);
        Size aSize = pBM->GetSize();
        if( aSize.Width() && aSize.Height() )
        {
            mhBackgroundPixmap =
                XCreatePixmap( GetXDisplay(),
                               GetWindow(),
                               aSize.Width(),
                               aSize.Height(),
                               GetDisplay()->GetVisual( m_nScreen ).GetDepth() );
            if( mhBackgroundPixmap )
            {
                SalTwoRect aTwoRect;
                aTwoRect.mnSrcX = aTwoRect.mnSrcY = aTwoRect.mnDestX = aTwoRect.mnDestY = 0;
                aTwoRect.mnSrcWidth = aTwoRect.mnDestWidth = aSize.Width();
                aTwoRect.mnSrcHeight = aTwoRect.mnDestHeight = aSize.Height();
                pBM->ImplDraw( mhBackgroundPixmap,
                               m_nScreen,
                               GetDisplay()->GetVisual( m_nScreen ).GetDepth(),
                               aTwoRect, GetDisplay()->GetCopyGC( m_nScreen ) );
                XSetWindowBackgroundPixmap( GetXDisplay(), GetWindow(), mhBackgroundPixmap );
            }
        }
    }
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

const SystemChildData* X11SalFrame::GetSystemData() const
{
	X11SalFrame *pFrame = const_cast<X11SalFrame*>(this);
	pFrame->maSystemChildData.nSize 		= sizeof( SystemChildData );
	pFrame->maSystemChildData.pDisplay		= GetXDisplay();
	pFrame->maSystemChildData.aWindow		= pFrame->GetWindow();
	pFrame->maSystemChildData.pSalFrame 	= pFrame;
	pFrame->maSystemChildData.pWidget		= NULL;
	pFrame->maSystemChildData.pVisual		= GetDisplay()->GetVisual( m_nScreen ).GetVisual();
	pFrame->maSystemChildData.nScreen		= m_nScreen;
	pFrame->maSystemChildData.nDepth		= GetDisplay()->GetVisual( m_nScreen ).GetDepth();
	pFrame->maSystemChildData.aColormap		= GetDisplay()->GetColormap( m_nScreen ).GetXColormap();
	pFrame->maSystemChildData.pAppContext	= NULL;
	pFrame->maSystemChildData.aShellWindow	= pFrame->GetShellWindow();
	pFrame->maSystemChildData.pShellWidget	= NULL;
	return &maSystemChildData;
}

SalGraphics *X11SalFrame::GetGraphics()
{
	if( pGraphics_ )
		return NULL;

	if( pFreeGraphics_ )
	{
		pGraphics_		= pFreeGraphics_;
		pFreeGraphics_	= NULL;
	}
	else
	{
		pGraphics_ = new X11SalGraphics();
		pGraphics_->Init( this, GetWindow(), m_nScreen );
	}

	return pGraphics_;
}

void X11SalFrame::ReleaseGraphics( SalGraphics *pGraphics )
{
    DBG_ASSERT( pGraphics == pGraphics_, "SalFrame::ReleaseGraphics pGraphics!=pGraphics_" );

	if( pGraphics != pGraphics_ )
		return;

	pFreeGraphics_	= pGraphics_;
	pGraphics_		= NULL;
}

void X11SalFrame::updateGraphics( bool bClear )
{
    Drawable aDrawable = bClear ? None : GetWindow();
    if( pGraphics_ )
        pGraphics_->SetDrawable( aDrawable, m_nScreen );
    if( pFreeGraphics_ )
        pFreeGraphics_->SetDrawable( aDrawable, m_nScreen );
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void X11SalFrame::Enable( sal_Bool /*bEnable*/ )
{
	// NYI: enable/disable frame
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void X11SalFrame::SetIcon( sal_uInt16 nIcon )
{
    if ( ! IsChildWindow() )
    {
        // 0 == default icon -> #1
        if ( nIcon == 0 )
            nIcon = 1;

        mnIconID = nIcon;

        XIconSize *pIconSize = NULL;
        int nSizes = 0;
        int iconSize = 32;
        if ( XGetIconSizes( GetXDisplay(), GetDisplay()->GetRootWindow( m_nScreen ), &pIconSize, &nSizes ) )
        {
#if OSL_DEBUG_LEVEL > 1
            fprintf(stderr, "X11SalFrame::SetIcon(): found %d IconSizes:\n", nSizes);
#endif

            const int ourLargestIconSize = 48;
            bool bFoundIconSize = false;

            int i;
            for( i=0; i<nSizes; i++)
            {
               // select largest supported icon

               // Note: olwm/olvwm reports a huge max icon size of
               // 160x160 pixels; always choosing the max as the
               // preferred icon size is apparently wrong under olvwm
               // - so we keep the safe default |iconSize| when we see
               // unreasonable large max icon sizes (> twice of our
               // largest available icon) reported by XGetIconSizes.
                if( pIconSize[i].max_width > iconSize
                    && pIconSize[i].max_width <= 2*ourLargestIconSize )
                {
                    iconSize = pIconSize[i].max_width;
                    bFoundIconSize = true;
                }
                iconSize = pIconSize[i].max_width;

#if OSL_DEBUG_LEVEL > 1
                fprintf(stderr, "min: %d, %d\nmax: %d, %d\ninc: %d, %d\n\n",
                        pIconSize[i].min_width, pIconSize[i].min_height,
                        pIconSize[i].max_width, pIconSize[i].max_height,
                        pIconSize[i].width_inc, pIconSize[i].height_inc);
#endif
            }

            if ( !bFoundIconSize )
            {
               // Unless someone has fixed olwm/olvwm, we have rejected
               // the max icon size from |XGetIconSizes()|.  Provide a
               // better icon size default value, in case our window manager
               // is olwm/olvwm.
               const String& rWM( pDisplay_->getWMAdaptor()->getWindowManagerName() );

               if ( rWM.EqualsAscii( "Olwm" ) )
                   iconSize = 48;
            }

            XFree( pIconSize );
        }
        else
        {
            const String& rWM( pDisplay_->getWMAdaptor()->getWindowManagerName() );
            if( rWM.EqualsAscii( "KWin" ) )			// assume KDE is running
                iconSize = 48;
            static bool bGnomeIconSize = false;
            static bool bGnomeChecked = false;
            if( ! bGnomeChecked )
            {
                bGnomeChecked=true;
                int nCount = 0;
                Atom* pProps = XListProperties( GetXDisplay(),
                                                GetDisplay()->GetRootWindow( m_nScreen ),
                                                &nCount );
                for( int i = 0; i < nCount && !bGnomeIconSize; i++ )
                 {
                    char* pName = XGetAtomName( GetXDisplay(), pProps[i] );
                    if( !strcmp( pName, "GNOME_PANEL_DESKTOP_AREA" ) )
                        bGnomeIconSize = true;
                    if( pName )
                        XFree( pName );
                 }
                if( pProps )
                    XFree( pProps );
            }
            if( bGnomeIconSize )
                iconSize = 48;
        }

        XWMHints Hints;
        Hints.flags = 0;
		XWMHints *pHints = XGetWMHints( GetXDisplay(), GetShellWindow() );
        if( pHints )
        {
            memcpy(&Hints, pHints, sizeof( XWMHints ));
            XFree( pHints );
        }
        pHints = &Hints;

		sal_Bool bOk = SelectAppIconPixmap( GetDisplay(), m_nScreen,
                                        nIcon, iconSize,
                                        pHints->icon_pixmap, pHints->icon_mask );
        if ( !bOk )
        {
            // load default icon (0)
		    bOk = SelectAppIconPixmap( GetDisplay(), m_nScreen,
                                       0, iconSize,
                                       pHints->icon_pixmap, pHints->icon_mask );
        }
		if( bOk )
        {
    		pHints->flags 	 |= IconPixmapHint;
		    if( pHints->icon_mask )
			    pHints->flags |= IconMaskHint;

		    XSetWMHints( GetXDisplay(), GetShellWindow(), pHints );
        }
	}
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void X11SalFrame::SetMaxClientSize( long nWidth, long nHeight )
{
    if( ! IsChildWindow() )
    {
        if( GetShellWindow() && (nStyle_ & (SAL_FRAME_STYLE_FLOAT|SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) != SAL_FRAME_STYLE_FLOAT )
        {
            XSizeHints* pHints = XAllocSizeHints();
            long nSupplied = 0;
            XGetWMNormalHints( GetXDisplay(),
                               GetShellWindow(),
                               pHints,
                               &nSupplied
                               );
            pHints->max_width	= nWidth;
            pHints->max_height	= nHeight;
            pHints->flags |= PMaxSize;
            XSetWMNormalHints( GetXDisplay(),
                               GetShellWindow(),
                               pHints );
            XFree( pHints );
        }
    }
}

void X11SalFrame::SetMinClientSize( long nWidth, long nHeight )
{
    if( ! IsChildWindow() )
    {
        if( GetShellWindow() && (nStyle_ & (SAL_FRAME_STYLE_FLOAT|SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) != SAL_FRAME_STYLE_FLOAT )
        {
            XSizeHints* pHints = XAllocSizeHints();
            long nSupplied = 0;
            XGetWMNormalHints( GetXDisplay(),
                               GetShellWindow(),
                               pHints,
                               &nSupplied
                               );
            pHints->min_width	= nWidth;
            pHints->min_height	= nHeight;
            pHints->flags |= PMinSize;
            XSetWMNormalHints( GetXDisplay(),
                               GetShellWindow(),
                               pHints );
            XFree( pHints );
        }
    }
}

// Show + Pos (x,y,z) + Size (width,height)
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void X11SalFrame::Show( sal_Bool bVisible, sal_Bool bNoActivate )
{
    if( ( bVisible && bMapped_ )
        || ( !bVisible && !bMapped_ ) )
        return;

    // HACK: this is a workaround for (at least) kwin
    // even though transient frames should be kept above their parent
    // this does not necessarily hold true for DOCK type windows
    // so artificially set ABOVE and remove it again on hide
    if( mpParent && (mpParent->nStyle_ & SAL_FRAME_STYLE_PARTIAL_FULLSCREEN ) && pDisplay_->getWMAdaptor()->isLegacyPartialFullscreen())
        pDisplay_->getWMAdaptor()->enableAlwaysOnTop( this, bVisible );
    
	bMapped_   = bVisible;
	bViewable_ = bVisible;
    setXEmbedInfo();
	if( bVisible )
	{
        SessionManagerClient::open(); // will simply return after the first time

        mbInShow = sal_True;
        if( ! (nStyle_ & SAL_FRAME_STYLE_INTRO) )
        {
            // hide all INTRO frames
            const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames();
            for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it )
            {
                const X11SalFrame* pFrame = static_cast< const X11SalFrame* >(*it);
                // look for intro bit map; if present, hide it
                if( pFrame->nStyle_ & SAL_FRAME_STYLE_INTRO )
                {
                    if( pFrame->bMapped_ )
                        const_cast<X11SalFrame*>(pFrame)->Show( sal_False );
                }
            }
        }
        
        // update NET_WM_STATE which may have been deleted due to earlier Show(sal_False)
        if( nShowState_ == SHOWSTATE_HIDDEN )
            GetDisplay()->getWMAdaptor()->frameIsMapping( this );

        /*
         *  #95097#
         *  Actually this is rather exotic and currently happens only in conjunction
         *  with the basic dialogue editor,
         *  which shows a frame and instantly hides it again. After that the
         *  editor window is shown and the WM takes this as an opportunity
         *  to show our hidden transient frame also. So Show( sal_False ) must
         *  withdraw the frame AND delete the WM_TRANSIENT_FOR property.
         *  In case the frame is shown again, the transient hint must be restored here.
         */
        if(    ! IsChildWindow()
            && ! IsOverrideRedirect()
            && ! IsFloatGrabWindow()
            && mpParent
            )
        {
            GetDisplay()->getWMAdaptor()->changeReferenceFrame( this, mpParent );
        }
        
        // #i45160# switch to desktop where a dialog with parent will appear
        if( mpParent && mpParent->m_nWorkArea != m_nWorkArea )
            GetDisplay()->getWMAdaptor()->switchToWorkArea( mpParent->m_nWorkArea );

        if( IsFloatGrabWindow() &&
            mpParent &&
            nVisibleFloats == 0 &&
            ! GetDisplay()->GetCaptureFrame() )
        {
            /* #i39420#
             * outsmart KWin's "focus strictly under mouse" mode
             * which insists on taking the focus from the document
             * to the new float. Grab focus to parent frame BEFORE
             * showing the float (cannot grab it to the float
             * before show).
             */
            XGrabPointer( GetXDisplay(),
                          mpParent->GetWindow(),
                          True,
                          PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
                          GrabModeAsync,
                          GrabModeAsync,
                          None,
                          mpParent ? mpParent->GetCursor() : None,
                          CurrentTime
                          );
        }

        XLIB_Time nUserTime = 0;
        if( ! bNoActivate && (nStyle_ & (SAL_FRAME_STYLE_OWNERDRAWDECORATION)) == 0 )
            nUserTime = pDisplay_->GetLastUserEventTime( true );
        GetDisplay()->getWMAdaptor()->setUserTime( this, nUserTime );
        if( ! bNoActivate && (nStyle_ & SAL_FRAME_STYLE_TOOLWINDOW) )
            m_bSetFocusOnMap = true;

        // actually map the window
        if( m_bXEmbed )
            askForXEmbedFocus( 0 );
        else
        {
            if( GetWindow() != GetShellWindow() && ! IsSysChildWindow() )
            {
                if( IsChildWindow() )
                    XMapWindow( GetXDisplay(), GetShellWindow() );
                XSelectInput( GetXDisplay(), GetShellWindow(), CLIENT_EVENTS );
            }
            if( nStyle_ & SAL_FRAME_STYLE_FLOAT )
                XMapRaised( GetXDisplay(), GetWindow() );
            else
                XMapWindow( GetXDisplay(), GetWindow() );
        }
		XSelectInput( GetXDisplay(), GetWindow(), CLIENT_EVENTS );

		if( maGeometry.nWidth > 0
            && maGeometry.nHeight > 0
			&& (   nWidth_  != (int)maGeometry.nWidth
				|| nHeight_ != (int)maGeometry.nHeight ) )
		{
			nWidth_  = maGeometry.nWidth;
			nHeight_ = maGeometry.nHeight;
		}

		XSync( GetXDisplay(), False );
        
        if( IsFloatGrabWindow() )
        {
            /*
             *  #95453#
             *  Sawfish and twm can be switched to enter-exit focus behaviour. In this case
             *  we must grab the pointer else the dumb WM will put the focus to the
             *  override-redirect float window. The application window will be deactivated
             *  which causes that the floats are destroyed, so the user can never click on
             *  a menu because it vanishes as soon as he enters it.
             */
            nVisibleFloats++;
            if( nVisibleFloats == 1 && ! GetDisplay()->GetCaptureFrame() )
            {
                /* #i39420# now move grab to the new float window */
                XGrabPointer( GetXDisplay(),
                              GetWindow(),
                              True,
                              PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
                              GrabModeAsync,
                              GrabModeAsync,
                              None,
                              mpParent ? mpParent->GetCursor() : None,
                              CurrentTime
                              );
            }
        }
		CallCallback( SALEVENT_RESIZE, NULL );

        /*
         *  sometimes a message box/dialogue is brought up when a frame is not mapped
         *  the corresponding TRANSIENT_FOR hint is then set to the root window
         *  so that the dialogue shows in all cases. Correct it here if the
         *  frame is shown afterwards.
         */
        if( ! IsChildWindow()
            && ! IsOverrideRedirect()
            && ! IsFloatGrabWindow()
            )
        {
            for( std::list< X11SalFrame* >::const_iterator it = maChildren.begin();
                 it != maChildren.end(); ++it )
            {
                if( (*it)->mbTransientForRoot )
                    GetDisplay()->getWMAdaptor()->changeReferenceFrame( *it, this );
            }
        }
        /*
         *  leave SHOWSTATE_UNKNOWN as this indicates first mapping
         *  and is only reset int HandleSizeEvent
         */
        if( nShowState_ != SHOWSTATE_UNKNOWN )
            nShowState_ = SHOWSTATE_NORMAL;

        /*
         *  #98107# plugged windows don't necessarily get the
         *  focus on show because the parent may already be mapped
         *  and have the focus. So try to set the focus
         *  to the child on Show(sal_True)
         */
        if( (nStyle_ & SAL_FRAME_STYLE_PLUG) && ! m_bXEmbed )
            XSetInputFocus( GetXDisplay(),
                            GetWindow(),
                            RevertToParent,
                            CurrentTime );

        if( mpParent )
        {
            // push this frame so it will be in front of its siblings
            // only necessary for insane transient behaviour of Dtwm/olwm
            mpParent->maChildren.remove( this );
            mpParent->maChildren.push_front(this);
        }
	}
	else
	{
        if( getInputContext() )
            getInputContext()->Unmap( this );

        if( ! IsChildWindow() )
        {
            /*  FIXME: Is deleting the property really necessary ? It hurts
             *  owner drawn windows at least.
             */
            if( mpParent && ! (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION) )
                XDeleteProperty( GetXDisplay(), GetShellWindow(), GetDisplay()->getWMAdaptor()->getAtom( WMAdaptor::WM_TRANSIENT_FOR ) );
            XWithdrawWindow( GetXDisplay(), GetShellWindow(), m_nScreen );
        }
        else if( ! m_bXEmbed )
            XUnmapWindow( GetXDisplay(), GetWindow() );
        
        nShowState_ = SHOWSTATE_HIDDEN;
        if( IsFloatGrabWindow() && nVisibleFloats )
        {
            nVisibleFloats--;
            if( nVisibleFloats == 0  && ! GetDisplay()->GetCaptureFrame() )
                XUngrabPointer( GetXDisplay(),
                                CurrentTime );
        }
        // flush here; there may be a very seldom race between
        // the display connection used for clipboard and our connection
        Flush();
	}
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void X11SalFrame::ToTop( sal_uInt16 nFlags )
{
	if( ( nFlags & SAL_FRAME_TOTOP_RESTOREWHENMIN )
        && ! ( nStyle_ & SAL_FRAME_STYLE_FLOAT )
        && nShowState_ != SHOWSTATE_HIDDEN
        && nShowState_ != SHOWSTATE_UNKNOWN
        )
    {
        GetDisplay()->getWMAdaptor()->frameIsMapping( this );
        if( GetWindow() != GetShellWindow() && ! IsSysChildWindow() )
            XMapWindow( GetXDisplay(), GetShellWindow() );
        XMapWindow( GetXDisplay(), GetWindow() );
    }

    XLIB_Window aToTopWindow = IsSysChildWindow() ? GetWindow() : GetShellWindow();
    if( ! (nFlags & SAL_FRAME_TOTOP_GRABFOCUS_ONLY) )
    {
        XRaiseWindow( GetXDisplay(), aToTopWindow );
        if( ! GetDisplay()->getWMAdaptor()->isTransientBehaviourAsExpected() )
            for( std::list< X11SalFrame* >::const_iterator it = maChildren.begin();
                 it != maChildren.end(); ++it )
                (*it)->ToTop( nFlags & ~SAL_FRAME_TOTOP_GRABFOCUS );
    }

    if( ( ( nFlags & SAL_FRAME_TOTOP_GRABFOCUS ) || ( nFlags & SAL_FRAME_TOTOP_GRABFOCUS_ONLY ) )
        && bMapped_ )
    {
        if( m_bXEmbed )
            askForXEmbedFocus( 0 );
        else
            XSetInputFocus( GetXDisplay(), aToTopWindow, RevertToParent, CurrentTime );
    }
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void X11SalFrame::GetWorkArea( Rectangle& rWorkArea )
{
    rWorkArea = pDisplay_->getWMAdaptor()->getWorkArea( 0 );
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void X11SalFrame::GetClientSize( long &rWidth, long &rHeight )
{
	if( ! bViewable_  )
	{
		rWidth = rHeight = 0;
		return;
	}

	rWidth	= maGeometry.nWidth;
	rHeight = maGeometry.nHeight;

	if( !rWidth || !rHeight )
	{
		XWindowAttributes aAttrib;

		XGetWindowAttributes( GetXDisplay(), GetWindow(), &aAttrib );

		maGeometry.nWidth = rWidth = aAttrib.width;
		maGeometry.nHeight = rHeight = aAttrib.height;
	}
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void X11SalFrame::SetWindowGravity (int nGravity) const
{
    if( ! IsChildWindow() )
    {
        XSizeHints* pHint = XAllocSizeHints();
        long        nFlag;
    
        XGetWMNormalHints (GetXDisplay(), GetShellWindow(), pHint, &nFlag);
        pHint->flags       |= PWinGravity;
        pHint->win_gravity  = nGravity;
    
        XSetWMNormalHints (GetXDisplay(), GetShellWindow(), pHint);
        XSync (GetXDisplay(), False);
    
        XFree (pHint);
    }
}

void X11SalFrame::Center( )
{
	int 			nX, nY, nScreenWidth, nScreenHeight;
	int				nRealScreenWidth, nRealScreenHeight;
	int				nScreenX = 0, nScreenY = 0;

    const Size& aScreenSize = GetDisplay()->getDataForScreen( m_nScreen ).m_aSize;
    nScreenWidth		= aScreenSize.Width();
    nScreenHeight		= aScreenSize.Height();
    nRealScreenWidth	= nScreenWidth;
    nRealScreenHeight	= nScreenHeight;

    if( GetDisplay()->IsXinerama() )
    {
        // get xinerama screen we are on
        // if there is a parent, use its center for screen determination
        // else use the pointer
        XLIB_Window aRoot, aChild;
        int root_x, root_y, x, y;
        unsigned int mask;
        if( mpParent )
        {
            root_x = mpParent->maGeometry.nX + mpParent->maGeometry.nWidth/2;
            root_y = mpParent->maGeometry.nY + mpParent->maGeometry.nHeight/2;
        }
        else
            XQueryPointer( GetXDisplay(),
                           GetShellWindow(),
                           &aRoot, &aChild,
                           &root_x, &root_y,
                           &x, &y,
                           &mask );
        const std::vector< Rectangle >& rScreens = GetDisplay()->GetXineramaScreens();
        for( unsigned int i = 0; i < rScreens.size(); i++ )
            if( rScreens[i].IsInside( Point( root_x, root_y ) ) )
            {
                nScreenX			= rScreens[i].Left();
                nScreenY			= rScreens[i].Top();
                nRealScreenWidth	= rScreens[i].GetWidth();
                nRealScreenHeight	= rScreens[i].GetHeight();
                break;
            }
    }

	if( mpParent )
	{
		X11SalFrame* pFrame = mpParent;
		while( pFrame->mpParent )
			pFrame = pFrame->mpParent;
		if( pFrame->maGeometry.nWidth < 1  || pFrame->maGeometry.nHeight < 1 )
        {
            Rectangle aRect;
			pFrame->GetPosSize( aRect );
            pFrame->maGeometry.nX		= aRect.Left();
            pFrame->maGeometry.nY		= aRect.Top();
            pFrame->maGeometry.nWidth	= aRect.GetWidth();
            pFrame->maGeometry.nHeight	= aRect.GetHeight();
        }

		if( pFrame->nStyle_ & SAL_FRAME_STYLE_PLUG )
		{
			XLIB_Window aRoot;
			unsigned int bw, depth;
			XGetGeometry( GetXDisplay(),
						  pFrame->GetShellWindow(),
						  &aRoot,
						  &nScreenX, &nScreenY,
						  (unsigned int*)&nScreenWidth,
						  (unsigned int*)&nScreenHeight,
						  &bw, &depth );
		}
		else
		{
			nScreenX		= pFrame->maGeometry.nX;
			nScreenY		= pFrame->maGeometry.nY;
			nScreenWidth	= pFrame->maGeometry.nWidth;
			nScreenHeight	= pFrame->maGeometry.nHeight;
		}
	}

	if( mpParent && mpParent->nShowState_ == SHOWSTATE_NORMAL )
	{
		if( maGeometry.nWidth >= mpParent->maGeometry.nWidth &&
			maGeometry.nHeight >= mpParent->maGeometry.nHeight )
		{
			nX = nScreenX + 40;
			nY = nScreenY + 40;
		}
		else
		{
			// center the window relative to the top level frame
			nX = (nScreenWidth	- (int)maGeometry.nWidth ) / 2 + nScreenX;
			nY = (nScreenHeight - (int)maGeometry.nHeight) / 2 + nScreenY;
		}
	}
	else
	{
		// center the window relative to screen
		nX = (nRealScreenWidth	- (int)maGeometry.nWidth ) / 2 + nScreenX;
		nY = (nRealScreenHeight - (int)maGeometry.nHeight) / 2 + nScreenY;
	}
    nX = nX < 0 ? 0 : nX;
    nY = nY < 0 ? 0 : nY;

	bDefaultPosition_ = False;
    if( mpParent )
    {
        nX -= mpParent->maGeometry.nX;
        nY -= mpParent->maGeometry.nY;
    }

    Point aPoint(nX, nY);
	SetPosSize( Rectangle( aPoint, Size( maGeometry.nWidth, maGeometry.nHeight ) ) );
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void X11SalFrame::updateScreenNumber()
{
    if( GetDisplay()->IsXinerama() && GetDisplay()->GetXineramaScreens().size() > 1 )
    {
        Point aPoint( maGeometry.nX, maGeometry.nY );
        const std::vector<Rectangle>& rScreenRects( GetDisplay()->GetXineramaScreens() );
        size_t nScreens = rScreenRects.size();
        for( size_t i = 0; i < nScreens; i++ )
        {
            if( rScreenRects[i].IsInside( aPoint ) )
            {
                maGeometry.nScreenNumber = static_cast<unsigned int>(i);
                break;
            }
        }
    }
    else
        maGeometry.nScreenNumber = static_cast<unsigned int>(m_nScreen);
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void X11SalFrame::SetPosSize( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags )
{
    if( nStyle_ & SAL_FRAME_STYLE_PLUG )
        return;
    
    // relative positioning in X11SalFrame::SetPosSize
    Rectangle aPosSize( Point( maGeometry.nX, maGeometry.nY ), Size( maGeometry.nWidth, maGeometry.nHeight ) );
    aPosSize.Justify();

    if( ! ( nFlags & SAL_FRAME_POSSIZE_X ) )
    {
        nX = aPosSize.Left();
        if( mpParent )
            nX -= mpParent->maGeometry.nX;
    }
    if( ! ( nFlags & SAL_FRAME_POSSIZE_Y ) )
    {
        nY = aPosSize.Top();
        if( mpParent )
            nY -= mpParent->maGeometry.nY;
    }
    if( ! ( nFlags & SAL_FRAME_POSSIZE_WIDTH ) )
        nWidth = aPosSize.GetWidth();
    if( ! ( nFlags & SAL_FRAME_POSSIZE_HEIGHT ) )
        nHeight = aPosSize.GetHeight();

    aPosSize = Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) );

    if( ! ( nFlags & ( SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y ) ) )
    {
        if( bDefaultPosition_ )
        {
            maGeometry.nWidth = aPosSize.GetWidth();
            maGeometry.nHeight = aPosSize.GetHeight();
            Center();
        }
        else
            SetSize( Size( nWidth, nHeight ) );
    }
    else
        SetPosSize( aPosSize );

    bDefaultPosition_ = False;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void X11SalFrame::SetAlwaysOnTop( sal_Bool bOnTop )
{
    if( ! IsOverrideRedirect() )
    {
        bAlwaysOnTop_ = bOnTop;
        pDisplay_->getWMAdaptor()->enableAlwaysOnTop( this, bOnTop );
    }
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

#define _FRAMESTATE_MASK_GEOMETRY \
     (SAL_FRAMESTATE_MASK_X     | SAL_FRAMESTATE_MASK_Y |   \
      SAL_FRAMESTATE_MASK_WIDTH | SAL_FRAMESTATE_MASK_HEIGHT)
#define _FRAMESTATE_MASK_MAXIMIZED_GEOMETRY \
     (SAL_FRAMESTATE_MASK_MAXIMIZED_X     | SAL_FRAMESTATE_MASK_MAXIMIZED_Y |   \
      SAL_FRAMESTATE_MASK_MAXIMIZED_WIDTH | SAL_FRAMESTATE_MASK_MAXIMIZED_HEIGHT)

void X11SalFrame::SetWindowState( const SalFrameState *pState )
{
    if (pState == NULL)
        return;

    // Request for position or size change
    if (pState->mnMask & _FRAMESTATE_MASK_GEOMETRY)
    {
        Rectangle aPosSize;
        bool bDoAdjust = false;
        
        /* #i44325#
         * if maximized, set restore size and guess maximized size from last time
         * in state change below maximize window
         */
        if( ! IsChildWindow() &&
            (pState->mnMask & SAL_FRAMESTATE_MASK_STATE) &&
            (pState->mnState & SAL_FRAMESTATE_MAXIMIZED) &&
            (pState->mnMask & _FRAMESTATE_MASK_GEOMETRY) == _FRAMESTATE_MASK_GEOMETRY &&
            (pState->mnMask & _FRAMESTATE_MASK_MAXIMIZED_GEOMETRY) == _FRAMESTATE_MASK_MAXIMIZED_GEOMETRY
            )
        {
            XSizeHints* pHints = XAllocSizeHints();
            long nSupplied = 0;
            XGetWMNormalHints( GetXDisplay(),
                               GetShellWindow(),
                               pHints,
                               &nSupplied );
            pHints->flags |= PPosition | PWinGravity;
            pHints->x			= pState->mnX;
            pHints->y			= pState->mnY;
            pHints->win_gravity	= pDisplay_->getWMAdaptor()->getPositionWinGravity();
            XSetWMNormalHints( GetXDisplay(),
                               GetShellWindow(),
                               pHints );
            XFree( pHints );
            
            XMoveResizeWindow( GetXDisplay(), GetShellWindow(),
                               pState->mnX, pState->mnY,
                               pState->mnWidth, pState->mnHeight );
            // guess maximized geometry from last time
            maGeometry.nX      = pState->mnMaximizedX;
            maGeometry.nY      = pState->mnMaximizedY;
            maGeometry.nWidth  = pState->mnMaximizedWidth;
            maGeometry.nHeight = pState->mnMaximizedHeight;
            updateScreenNumber();
        }
        else
        {
            // initialize with current geometry
            if ((pState->mnMask & _FRAMESTATE_MASK_GEOMETRY) != _FRAMESTATE_MASK_GEOMETRY)
                GetPosSize (aPosSize);
            
            // change requested properties
            if (pState->mnMask & SAL_FRAMESTATE_MASK_X)
            {
                aPosSize.setX (pState->mnX);
            }
            if (pState->mnMask & SAL_FRAMESTATE_MASK_Y)
            {
                aPosSize.setY (pState->mnY);
            }
            if (pState->mnMask & SAL_FRAMESTATE_MASK_WIDTH)
            {
                long nWidth = pState->mnWidth > 0 ? pState->mnWidth  - 1 : 0;
                aPosSize.setWidth (nWidth);
                bDoAdjust = true;
            }
            if (pState->mnMask & SAL_FRAMESTATE_MASK_HEIGHT)
            {
                int nHeight = pState->mnHeight > 0 ? pState->mnHeight - 1 : 0;
                aPosSize.setHeight (nHeight);
                bDoAdjust = true;
            }
            
            const Size& aScreenSize = pDisplay_->getDataForScreen( m_nScreen ).m_aSize;
            const WMAdaptor *pWM = GetDisplay()->getWMAdaptor();
            
            if( bDoAdjust && aPosSize.GetWidth() <= aScreenSize.Width()
                && aPosSize.GetHeight() <= aScreenSize.Height() )
            {
                SalFrameGeometry aGeom = maGeometry;
                
                if( ! (nStyle_ & ( SAL_FRAME_STYLE_FLOAT | SAL_FRAME_STYLE_PLUG ) ) &&
                    mpParent &&
                aGeom.nLeftDecoration == 0 &&
                aGeom.nTopDecoration == 0 )
                {
                    aGeom = mpParent->maGeometry;
                    if( aGeom.nLeftDecoration == 0 &&
                        aGeom.nTopDecoration == 0 )
                    {
                        aGeom.nLeftDecoration = 5;
                        aGeom.nTopDecoration = 20;
                        aGeom.nRightDecoration = 5;
                        aGeom.nBottomDecoration = 5;
                    }
                }
                
                // adjust position so that frame fits onto screen
                if( aPosSize.Right()+(long)aGeom.nRightDecoration > aScreenSize.Width()-1 )
                    aPosSize.Move( (long)aScreenSize.Width() - (long)aPosSize.Right() - (long)aGeom.nRightDecoration, 0 );
                if( aPosSize.Bottom()+(long)aGeom.nBottomDecoration > aScreenSize.Height()-1 )
                    aPosSize.Move( 0, (long)aScreenSize.Height() - (long)aPosSize.Bottom() - (long)aGeom.nBottomDecoration );
                if( aPosSize.Left() < (long)aGeom.nLeftDecoration )
                    aPosSize.Move( (long)aGeom.nLeftDecoration - (long)aPosSize.Left(), 0 );
                if( aPosSize.Top() < (long)aGeom.nTopDecoration )
                    aPosSize.Move( 0, (long)aGeom.nTopDecoration - (long)aPosSize.Top() );
            }
            
            // resize with new args
            if (pWM->supportsICCCMPos())
            {
                if( mpParent )
                    aPosSize.Move( -mpParent->maGeometry.nX,
                -mpParent->maGeometry.nY );
                SetPosSize( aPosSize );
                bDefaultPosition_ = False;
            }
            else
                SetPosSize( 0, 0, aPosSize.GetWidth(), aPosSize.GetHeight(), SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT );
        }
    }

    // request for status change
    if (pState->mnMask & SAL_FRAMESTATE_MASK_STATE)
    {
	    if (pState->mnState & SAL_FRAMESTATE_MAXIMIZED)
	    {
		    nShowState_ = SHOWSTATE_NORMAL;
            if( ! (pState->mnState & (SAL_FRAMESTATE_MAXIMIZED_HORZ|SAL_FRAMESTATE_MAXIMIZED_VERT) ) )
                Maximize();
            else
            {
                bool bHorz = (pState->mnState & SAL_FRAMESTATE_MAXIMIZED_HORZ) ? true : false;
                bool bVert = (pState->mnState & SAL_FRAMESTATE_MAXIMIZED_VERT) ? true : false;
                GetDisplay()->getWMAdaptor()->maximizeFrame( this, bHorz, bVert );
            }
            maRestorePosSize.Left() = pState->mnX;
            maRestorePosSize.Top() = pState->mnY;
            maRestorePosSize.Right() = maRestorePosSize.Left() + pState->mnWidth;
            maRestorePosSize.Right() = maRestorePosSize.Left() + pState->mnHeight;
	    }
        else if( mbMaximizedHorz || mbMaximizedVert )
            GetDisplay()->getWMAdaptor()->maximizeFrame( this, false, false );

	    if (pState->mnState & SAL_FRAMESTATE_MINIMIZED)
	    {
		    if (nShowState_ == SHOWSTATE_UNKNOWN)
			    nShowState_ = SHOWSTATE_NORMAL;
		    Minimize();
        }
        if (pState->mnState & SAL_FRAMESTATE_NORMAL)
        {
            if (nShowState_ != SHOWSTATE_NORMAL)
                Restore();
        }
        if (pState->mnState & SAL_FRAMESTATE_ROLLUP)
            GetDisplay()->getWMAdaptor()->shade( this, true );
	}
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
sal_Bool X11SalFrame::GetWindowState( SalFrameState* pState )
{
	if( SHOWSTATE_MINIMIZED == nShowState_ )
		pState->mnState = SAL_FRAMESTATE_MINIMIZED;
	else
		pState->mnState = SAL_FRAMESTATE_NORMAL;

	Rectangle aPosSize;
    if( maRestorePosSize.IsEmpty() )
        GetPosSize( aPosSize );
    else
        aPosSize = maRestorePosSize;
    
    if( mbMaximizedHorz )
        pState->mnState |= SAL_FRAMESTATE_MAXIMIZED_HORZ;
    if( mbMaximizedVert )
        pState->mnState |= SAL_FRAMESTATE_MAXIMIZED_VERT;
    if( mbShaded )
        pState->mnState |= SAL_FRAMESTATE_ROLLUP;

	pState->mnX 	 = aPosSize.Left();
	pState->mnY 	 = aPosSize.Top();
	pState->mnWidth  = aPosSize.GetWidth();
	pState->mnHeight = aPosSize.GetHeight();

    pState->mnMask   = _FRAMESTATE_MASK_GEOMETRY | SAL_FRAMESTATE_MASK_STATE;


	if (! maRestorePosSize.IsEmpty() )
	{
        GetPosSize( aPosSize );
		pState->mnState |= SAL_FRAMESTATE_MAXIMIZED;
        pState->mnMaximizedX      = aPosSize.Left();
        pState->mnMaximizedY      = aPosSize.Top();
        pState->mnMaximizedWidth  = aPosSize.GetWidth();
        pState->mnMaximizedHeight = aPosSize.GetHeight();
        pState->mnMask |= _FRAMESTATE_MASK_MAXIMIZED_GEOMETRY;
	}

	return sal_True;
}

// ----------------------------------------------------------------------------
// get a screenshot of the current frame including window manager decoration
SalBitmap* X11SalFrame::SnapShot()
{
    Display* pDisplay = GetXDisplay();

    // make sure the frame has been reparented and all paint timer have been
    // expired
    do
    {
        XSync(pDisplay, False);
        Application::Reschedule ();
    }
    while (XPending(pDisplay));
    TimeValue aVal;
    aVal.Seconds = 0;
    aVal.Nanosec = 50000000;
    osl_waitThread( &aVal );
    do
    {
        XSync(pDisplay, False);
        Application::Reschedule ();
    }
    while (XPending(pDisplay));

    // get the most outer window, usually the window manager decoration
    Drawable hWindow = None;
    if (IsOverrideRedirect())
        hWindow = GetDrawable();
    else
    if (hPresentationWindow != None)
        hWindow = hPresentationWindow;
    else
        hWindow = GetStackingWindow();

    // query the contents of the window
    if (hWindow != None)
    {
        X11SalBitmap *pBmp = new X11SalBitmap;
        if (pBmp->SnapShot (pDisplay, hWindow))
            return pBmp;
        else
            delete pBmp;
    }

    return NULL;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

// native menu implementation - currently empty
void X11SalFrame::DrawMenuBar()
{
}

void X11SalFrame::SetMenu( SalMenu* )
{
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void X11SalFrame::GetPosSize( Rectangle &rPosSize )
{
	if( maGeometry.nWidth < 1 || maGeometry.nHeight < 1 )
	{
        const Size& aScreenSize = pDisplay_->getDataForScreen( m_nScreen ).m_aSize;
		long w = aScreenSize.Width()  - maGeometry.nLeftDecoration - maGeometry.nRightDecoration;
		long h = aScreenSize.Height() - maGeometry.nTopDecoration - maGeometry.nBottomDecoration;

		rPosSize = Rectangle( Point( maGeometry.nX, maGeometry.nY ), Size( w, h ) );
	}
	else
		rPosSize = Rectangle( Point( maGeometry.nX, maGeometry.nY ),
                              Size( maGeometry.nWidth, maGeometry.nHeight ) );
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void X11SalFrame::SetSize( const Size &rSize )
{
	if( rSize.Width() > 0 && rSize.Height() > 0 )
	{
 		if( ! ( nStyle_ & SAL_FRAME_STYLE_SIZEABLE )
            && ! IsChildWindow()
            && ( nStyle_ & (SAL_FRAME_STYLE_FLOAT|SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) != SAL_FRAME_STYLE_FLOAT )
 		{
            XSizeHints* pHints = XAllocSizeHints();
            long nSupplied = 0;
            XGetWMNormalHints( GetXDisplay(),
                               GetShellWindow(),
                               pHints,
                               &nSupplied
                               );
            pHints->min_width	= rSize.Width();
            pHints->min_height	= rSize.Height();
            pHints->max_width	= rSize.Width();
            pHints->max_height	= rSize.Height();
            pHints->flags |= PMinSize | PMaxSize;
            XSetWMNormalHints( GetXDisplay(),
                               GetShellWindow(),
                               pHints );
            XFree( pHints );
 		}
        XResizeWindow( GetXDisplay(), IsSysChildWindow() ? GetWindow() : GetShellWindow(), rSize.Width(), rSize.Height() );
        if( GetWindow() != GetShellWindow() )
        {
            if( (nStyle_ & SAL_FRAME_STYLE_PLUG ) )
                XMoveResizeWindow( GetXDisplay(), GetWindow(), 0, 0, rSize.Width(), rSize.Height() );
            else
                XResizeWindow( GetXDisplay(), GetWindow(), rSize.Width(), rSize.Height() );
        }

        maGeometry.nWidth  = rSize.Width();
        maGeometry.nHeight = rSize.Height();

		// allow the external status window to reposition
		if (mbInputFocus && mpInputContext != NULL)
			mpInputContext->SetICFocus ( this );
	}
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void X11SalFrame::SetPosSize( const Rectangle &rPosSize )
{
	XWindowChanges values;
	values.x		= rPosSize.Left();
	values.y		= rPosSize.Top();
	values.width	= rPosSize.GetWidth();
	values.height	= rPosSize.GetHeight();

    if( !values.width || !values.height )
        return;

 	if( mpParent && ! IsSysChildWindow() )
 	{
        // --- RTL --- (mirror window pos)
        if( Application::GetSettings().GetLayoutRTL() )
            values.x = mpParent->maGeometry.nWidth-values.width-1-values.x;

 		XLIB_Window aChild;
 		// coordinates are relative to parent, so translate to root coordinates
 		XTranslateCoordinates( GetDisplay()->GetDisplay(),
 							   mpParent->GetWindow(),
 							   GetDisplay()->GetRootWindow( m_nScreen ),
 							   values.x, values.y,
 							   &values.x, &values.y,
 							   & aChild );
 	}

    bool bMoved = false;
    bool bSized = false;
    if( values.x != maGeometry.nX || values.y != maGeometry.nY )
        bMoved = true;
    if( values.width != (int)maGeometry.nWidth || values.height != (int)maGeometry.nHeight )
        bSized = true;

	if( ! ( nStyle_ & ( SAL_FRAME_STYLE_PLUG | SAL_FRAME_STYLE_FLOAT ) )
        && !(pDisplay_->GetProperties() & PROPERTY_SUPPORT_WM_ClientPos) )
    {
        values.x	-= maGeometry.nLeftDecoration;
        values.y	-= maGeometry.nTopDecoration;
    }

    // do net set WMNormalHints for ..
    if(
        // child windows
        ! IsChildWindow()
        // popups (menu, help window, etc.)
        && 	(nStyle_ & (SAL_FRAME_STYLE_FLOAT|SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) != SAL_FRAME_STYLE_FLOAT
        // shown, sizeable windows
        && ( nShowState_ == SHOWSTATE_UNKNOWN ||
             nShowState_ == SHOWSTATE_HIDDEN ||
             ! ( nStyle_ & SAL_FRAME_STYLE_SIZEABLE )
             )
        )
    {
        XSizeHints* pHints = XAllocSizeHints();
        long nSupplied = 0;
        XGetWMNormalHints( GetXDisplay(),
                           GetShellWindow(),
                           pHints,
                           &nSupplied
                           );
        if( ! ( nStyle_ & SAL_FRAME_STYLE_SIZEABLE ) )
        {
            pHints->min_width	= rPosSize.GetWidth();
            pHints->min_height	= rPosSize.GetHeight();
            pHints->max_width	= rPosSize.GetWidth();
            pHints->max_height	= rPosSize.GetHeight();
            pHints->flags |= PMinSize | PMaxSize;
        }
        if( nShowState_ == SHOWSTATE_UNKNOWN || nShowState_ == SHOWSTATE_HIDDEN )
        {
            pHints->flags |= PPosition | PWinGravity;
            pHints->x			= values.x;
            pHints->y			= values.y;
            pHints->win_gravity	= pDisplay_->getWMAdaptor()->getPositionWinGravity();
        }
        if( mbFullScreen )
        {
            pHints->max_width	= 10000;
            pHints->max_height	= 10000;
            pHints->flags |= PMaxSize;
        }
        XSetWMNormalHints( GetXDisplay(),
                           GetShellWindow(),
                           pHints );
        XFree( pHints );
    }

    XMoveResizeWindow( GetXDisplay(), IsSysChildWindow() ? GetWindow() : GetShellWindow(), values.x, values.y, values.width, values.height );
    if( GetShellWindow() != GetWindow() )
    {
        if( (nStyle_ & SAL_FRAME_STYLE_PLUG ) )
            XMoveResizeWindow( GetXDisplay(), GetWindow(), 0, 0, values.width, values.height );
        else
            XMoveResizeWindow( GetXDisplay(), GetWindow(), values.x, values.y, values.width, values.height );
    }            

    maGeometry.nX		= values.x;
    maGeometry.nY		= values.y;
    maGeometry.nWidth	= values.width;
    maGeometry.nHeight	= values.height;
    if( IsSysChildWindow() && mpParent )
    {
        // translate back to root coordinates
        maGeometry.nX += mpParent->maGeometry.nX;
        maGeometry.nY += mpParent->maGeometry.nY;
    }
    
    updateScreenNumber();
    if( bSized && ! bMoved )
        CallCallback( SALEVENT_RESIZE, NULL );
    else if( bMoved && ! bSized )
        CallCallback( SALEVENT_MOVE, NULL );
    else
        CallCallback( SALEVENT_MOVERESIZE, NULL );

	// allow the external status window to reposition
	if (mbInputFocus && mpInputContext != NULL)
		mpInputContext->SetICFocus ( this );
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void X11SalFrame::Minimize()
{
    if( IsSysChildWindow() )
        return;
    
	if( SHOWSTATE_UNKNOWN == nShowState_ || SHOWSTATE_HIDDEN == nShowState_ )
	{
		stderr0( "X11SalFrame::Minimize on withdrawn window\n" );
		return;
	}

	if( XIconifyWindow( GetXDisplay(),
						GetShellWindow(),
						pDisplay_->GetDefaultScreenNumber() ) )
		nShowState_ = SHOWSTATE_MINIMIZED;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void X11SalFrame::Maximize()
{
    if( IsSysChildWindow() )
        return;
    
	if( SHOWSTATE_MINIMIZED == nShowState_ )
	{
        GetDisplay()->getWMAdaptor()->frameIsMapping( this );
		XMapWindow( GetXDisplay(), GetShellWindow() );
		nShowState_ = SHOWSTATE_NORMAL;
	}

    pDisplay_->getWMAdaptor()->maximizeFrame( this, true, true );
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void X11SalFrame::Restore()
{
    if( IsSysChildWindow() )
        return;
    
	if( SHOWSTATE_UNKNOWN == nShowState_ || SHOWSTATE_HIDDEN == nShowState_ )
	{
		stderr0( "X11SalFrame::Restore on withdrawn window\n" );
		return;
	}

	if( SHOWSTATE_MINIMIZED == nShowState_ )
	{
        GetDisplay()->getWMAdaptor()->frameIsMapping( this );
		XMapWindow( GetXDisplay(), GetShellWindow() );
		nShowState_ = SHOWSTATE_NORMAL;
	}

    pDisplay_->getWMAdaptor()->maximizeFrame( this, false, false );
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void X11SalFrame::SetScreenNumber( unsigned int nNewScreen )
{
    if( nNewScreen == maGeometry.nScreenNumber )
        return;
    
    if( GetDisplay()->IsXinerama() && GetDisplay()->GetXineramaScreens().size() > 1 )
    {
        if( nNewScreen >= GetDisplay()->GetXineramaScreens().size() )
            return;
        
        Rectangle aOldScreenRect( GetDisplay()->GetXineramaScreens()[maGeometry.nScreenNumber] );
        Rectangle aNewScreenRect( GetDisplay()->GetXineramaScreens()[nNewScreen] );
        bool bVisible = bMapped_;
        if( bVisible )
            Show( sal_False );
        maGeometry.nX = aNewScreenRect.Left() + (maGeometry.nX - aOldScreenRect.Left());
        maGeometry.nY = aNewScreenRect.Top() + (maGeometry.nY - aOldScreenRect.Top());
        createNewWindow( None, m_nScreen );
        if( bVisible )
            Show( sal_True );
        maGeometry.nScreenNumber = nNewScreen;
    }
    else if( sal_Int32(nNewScreen) < GetDisplay()->GetScreenCount() )
    {
        bool bVisible = bMapped_;
        if( bVisible )
            Show( sal_False );
        createNewWindow( None, nNewScreen );
        if( bVisible )
            Show( sal_True );
        maGeometry.nScreenNumber = nNewScreen;
    }
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void X11SalFrame::ShowFullScreen( sal_Bool bFullScreen, sal_Int32 nScreen )
{
    if( GetDisplay()->IsXinerama() && GetDisplay()->GetXineramaScreens().size() > 1 )
    {
        if( mbFullScreen == (bool)bFullScreen )
            return;
        if( bFullScreen )
        {
            maRestorePosSize = Rectangle( Point( maGeometry.nX, maGeometry.nY ),
                                          Size( maGeometry.nWidth, maGeometry.nHeight ) );
            Rectangle aRect;
            if( nScreen < 0 || nScreen >= static_cast<int>(GetDisplay()->GetXineramaScreens().size()) )
                aRect = Rectangle( Point(0,0), GetDisplay()->GetScreenSize( m_nScreen ) );
            else
                aRect = GetDisplay()->GetXineramaScreens()[nScreen];
            nStyle_ |= SAL_FRAME_STYLE_PARTIAL_FULLSCREEN;
            bool bVisible = bMapped_;
            if( bVisible )
                Show( sal_False );
            maGeometry.nX = aRect.Left();
            maGeometry.nY = aRect.Top();
            maGeometry.nWidth = aRect.GetWidth();
            maGeometry.nHeight = aRect.GetHeight();
            mbMaximizedHorz = mbMaximizedVert = false;
            mbFullScreen = true;
            createNewWindow( None, m_nScreen );
            if( GetDisplay()->getWMAdaptor()->isLegacyPartialFullscreen() )
                GetDisplay()->getWMAdaptor()->enableAlwaysOnTop( this, true );
            else
            {
                GetDisplay()->getWMAdaptor()->setFullScreenMonitors( GetShellWindow(), nScreen );
                GetDisplay()->getWMAdaptor()->showFullScreen( this, true );
            }
            if( bVisible )
                Show(sal_True);

        }
        else
        {
            mbFullScreen = false;
            nStyle_ &= ~SAL_FRAME_STYLE_PARTIAL_FULLSCREEN;
            bool bVisible = bMapped_;
            Rectangle aRect = maRestorePosSize;
            maRestorePosSize = Rectangle();
            if( bVisible )
                Show( sal_False );
            createNewWindow( None, m_nScreen );
            if( !aRect.IsEmpty() )
                SetPosSize( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(),
                            SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y |
                            SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT );
            if( bVisible )
                Show( sal_True );
        }
    }
    else
    {
        if( nScreen < 0 || nScreen >= GetDisplay()->GetScreenCount() )
            nScreen = m_nScreen;
        if( nScreen != m_nScreen )
        {
            bool bVisible = bMapped_;
            if( mbFullScreen )
                pDisplay_->getWMAdaptor()->showFullScreen( this, false );
            if( bVisible )
                Show( sal_False );
            createNewWindow( None, nScreen );
            if( mbFullScreen )
                pDisplay_->getWMAdaptor()->showFullScreen( this, true );
            if( bVisible )
                Show( sal_True );
        }
        if( mbFullScreen == (bool)bFullScreen )
            return;
    
        pDisplay_->getWMAdaptor()->showFullScreen( this, bFullScreen );
        if( IsOverrideRedirect()
            && WMSupportsFWS( GetXDisplay(), GetDisplay()->GetRootWindow( m_nScreen ) ) )
        {
            AddFwsProtocols( GetXDisplay(), GetShellWindow() );
            RegisterFwsWindow( GetXDisplay(), GetShellWindow() );
        }
    }
}

/* ---------------------------------------------------------------------
   the xautolock pseudo screen saver needs special treatment since it
   doesn't cooperate with XxxxScreenSaver settings
   ------------------------------------------------------------------- */

static Bool
IsRunningXAutoLock( Display *p_display, XLIB_Window a_window )
{
	const char *p_atomname = "XAUTOLOCK_SEMAPHORE_PID";
	Atom		a_pidatom;

	// xautolock interns this atom
	a_pidatom    = XInternAtom( p_display, p_atomname, True );
	if ( a_pidatom == None )
		return False;

	Atom          a_type;
	int           n_format;
	unsigned long n_items;
	unsigned long n_bytes_after;
	pid_t		 *p_pid;
	pid_t         n_pid;
	// get pid of running xautolock
	XGetWindowProperty (p_display, a_window, a_pidatom, 0L, 2L, False,
    		AnyPropertyType, &a_type, &n_format, &n_items, &n_bytes_after,
            (unsigned char**) &p_pid );
	n_pid = *p_pid;
	XFree( p_pid );

  	if ( a_type == XA_INTEGER )
  	{
		// check if xautolock pid points to a running process
		if ( kill(n_pid, 0) == -1 )
			return False;
		else
			return True;
	}

	return False;
}

/* definitions from xautolock.c (pl15) */
#define XAUTOLOCK_DISABLE 1
#define XAUTOLOCK_ENABLE  2

static Bool
MessageToXAutoLock( Display *p_display, int n_message )
{
	const char *p_atomname = "XAUTOLOCK_MESSAGE" ;
	Atom        a_messageatom;
	XLIB_Window a_rootwindow;

	a_rootwindow = RootWindowOfScreen( ScreenOfDisplay(p_display, 0) );
	if ( ! IsRunningXAutoLock(p_display, a_rootwindow) )
	{
		// remove any pending messages
		a_messageatom = XInternAtom( p_display, p_atomname, True );
		if ( a_messageatom != None )
			XDeleteProperty( p_display, a_rootwindow, a_messageatom );
		return False;
	}

	a_messageatom = XInternAtom( p_display, p_atomname, False );
	XChangeProperty (p_display, a_rootwindow, a_messageatom, XA_INTEGER,
    		8, PropModeReplace, (unsigned char*)&n_message, sizeof(n_message) );

	return True;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void X11SalFrame::StartPresentation( sal_Bool bStart )
{
    I18NStatus::get().show( !bStart, I18NStatus::presentation );
	if ( bStart )
		MessageToXAutoLock( GetXDisplay(), XAUTOLOCK_DISABLE );
	else
		MessageToXAutoLock( GetXDisplay(), XAUTOLOCK_ENABLE );

    if( ! bStart && hPresentationWindow != None )
        doReparentPresentationDialogues( GetDisplay() );
    hPresentationWindow = (bStart && IsOverrideRedirect() ) ? GetWindow() : None;
	
	
	// needs static here to save DPMS settings
    int dummy; 	
    static bool DPMSExtensionAvailable =
#ifndef SOLARIS
        (DPMSQueryExtension(GetXDisplay(), &dummy, &dummy) != 0);
	static sal_Bool DPMSEnabled = false;
#else
        false;
    bool DPMSEnabled = false;
    (void)dummy;
#define CARD16 unsigned short
#endif
	static CARD16 dpms_standby_timeout=0;
	static CARD16 dpms_suspend_timeout=0;
	static CARD16 dpms_off_timeout=0;
		
				
	if( bStart || nScreenSaversTimeout_ || DPMSEnabled)
	{
        if( hPresentationWindow )
        {
            /*  #i10559# workaround for WindowMaker: try to restore
             *  current focus after presentation window is gone
             */
            int revert_to = 0;
            XGetInputFocus( GetXDisplay(), &hPresFocusWindow, &revert_to );
        }
		int timeout, interval, prefer_blanking, allow_exposures;
		XGetScreenSaver( GetXDisplay(),
						 &timeout,
						 &interval,
						 &prefer_blanking,
						 &allow_exposures );
						 
				
		// get the DPMS state right before the start
		if (DPMSExtensionAvailable)
        {
#ifndef SOLARIS
			CARD16 state; // card16 is defined in Xdm.h 
			DPMSInfo(	GetXDisplay(), 
						&state, 
						&DPMSEnabled);
#endif
		} 				 
		if( bStart ) // start show 
		{	
			if ( timeout )
			{
				nScreenSaversTimeout_ = timeout;
				XResetScreenSaver( GetXDisplay() );
				XSetScreenSaver( GetXDisplay(),
								 0,
								 interval,
								 prefer_blanking,
								 allow_exposures );	  
			}
#ifndef SOLARIS
			if( DPMSEnabled )
			{
				if ( DPMSExtensionAvailable )
				{
					DPMSGetTimeouts(	GetXDisplay(), 
										&dpms_standby_timeout, 
										&dpms_suspend_timeout, 
										&dpms_off_timeout); 
					DPMSSetTimeouts(GetXDisplay(), 0,0,0); 	
				}
			}
#endif
		}				 
		else // if( !bStart ) // end of show
		{
			if( nScreenSaversTimeout_ ) 
			{
				XSetScreenSaver( GetXDisplay(),
							 nScreenSaversTimeout_,
							 interval,
							 prefer_blanking,
							 allow_exposures );
				nScreenSaversTimeout_ = 0;		
			}
#ifndef SOLARIS
			if ( DPMSEnabled )
			{			
				if ( DPMSExtensionAvailable )
				{
				// restore timeouts 
					DPMSSetTimeouts(GetXDisplay(), dpms_standby_timeout, 
						dpms_suspend_timeout, dpms_off_timeout); 
				}
			}
#endif
		}
	}
}

// Pointer
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void X11SalFrame::SetPointer( PointerStyle ePointerStyle )
{
	hCursor_ = pDisplay_->GetPointer( ePointerStyle );
	XDefineCursor( GetXDisplay(), GetWindow(), hCursor_ );

	if( IsCaptured() || nVisibleFloats > 0 )
		XChangeActivePointerGrab( GetXDisplay(),
						PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
						hCursor_,
						CurrentTime );
}

void X11SalFrame::SetPointerPos(long nX, long nY)
{
    /* #87921# when the application tries to center the mouse in the dialog the
     * window isn't mapped already. So use coordinates relative to the root window.
     */
    unsigned int nWindowLeft = maGeometry.nX + nX;
    unsigned int nWindowTop  = maGeometry.nY + nY;

    XWarpPointer( GetXDisplay(), None, pDisplay_->GetRootWindow( pDisplay_->GetDefaultScreenNumber() ),
                  0, 0, 0, 0, nWindowLeft, nWindowTop);
}

// delay handling of extended text input
#if !defined(__synchronous_extinput__)
void
X11SalFrame::PostExtTextEvent (sal_uInt16 nExtTextEventType, void *pExtTextEvent)
{
	XLIB_Window nFocusWindow = GetWindow();
	Atom 		nEventAtom	 = GetDisplay()->getWMAdaptor()->getAtom( WMAdaptor::SAL_EXTTEXTEVENT );

    XEvent aEvent;
    aEvent.xclient.type			= ClientMessage;
    aEvent.xclient.serial		= 0;
    aEvent.xclient.send_event	= True;
    aEvent.xclient.display		= GetXDisplay();
    aEvent.xclient.window		= nFocusWindow;
    aEvent.xclient.message_type	= nEventAtom;
    aEvent.xclient.format		= 32;

#if SAL_TYPES_SIZEOFLONG > 4
    aEvent.xclient.data.l[0] = (sal_uInt32)((long)pExtTextEvent & 0xffffffff);
    aEvent.xclient.data.l[1] = (sal_uInt32)((long)pExtTextEvent >> 32);
#else
    aEvent.xclient.data.l[0] = (sal_uInt32)((long)pExtTextEvent);
    aEvent.xclient.data.l[1] = 0;
#endif
    aEvent.xclient.data.l[2] = (sal_uInt32)nExtTextEventType;
    aEvent.xclient.data.l[3] = 0;
    aEvent.xclient.data.l[4] = 0;

    XPutBackEvent( GetXDisplay(), &aEvent );
}

void
X11SalFrame::HandleExtTextEvent (XClientMessageEvent *pEvent)
{
	#if SAL_TYPES_SIZEOFLONG > 4
	void* pExtTextEvent = (void*)(  (pEvent->data.l[0] & 0xffffffff)
								  | (pEvent->data.l[1] << 32) );
	#else
	void* pExtTextEvent = (void*)(pEvent->data.l[0]);
	#endif
	sal_uInt16 nExtTextEventType = sal_uInt16(pEvent->data.l[2]);

	CallCallback(nExtTextEventType, pExtTextEvent);

	switch (nExtTextEventType)
	{
		case SALEVENT_ENDEXTTEXTINPUT:
			break;

		case SALEVENT_EXTTEXTINPUT:
			break;

		default:

			fprintf(stderr, "X11SalFrame::HandleExtTextEvent: invalid extended input\n");
	}
}
#endif /* defined(__synchronous_extinput__) */

// PostEvent
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
sal_Bool X11SalFrame::PostEvent( void *pData )
{
    GetDisplay()->SendInternalEvent( this, pData );
	return sal_True;
}

// Title
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void X11SalFrame::SetTitle( const XubString& rTitle )
{
    if( ! ( IsChildWindow() || (nStyle_ & SAL_FRAME_STYLE_FLOAT ) ) )
    {
        m_aTitle = rTitle;
        GetDisplay()->getWMAdaptor()->setWMName( this, rTitle );
    }
}

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

void X11SalFrame::Flush()
{
	XFlush( GetDisplay()->GetDisplay() );
}

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

void X11SalFrame::Sync()
{
	XSync( GetDisplay()->GetDisplay(), False );
}

// Keyboard
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

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

void X11SalFrame::SetInputContext( SalInputContext* pContext )
{
  	if (pContext == NULL)
		return;

  	// 1. We should create an input context for this frame
  	//    only when SAL_INPUTCONTEXT_TEXT is set.

  	if (!(pContext->mnOptions & SAL_INPUTCONTEXT_TEXT))
    {
        if( mpInputContext )
            mpInputContext->Unmap( this );
		return;
    }

	// 2. We should use on-the-spot inputstyle
  	//    only when SAL_INPUTCONTEXT_EXTTEXTINPUT is set.

  	if (mpInputContext == NULL)
	{
        I18NStatus& rStatus( I18NStatus::get() );
        rStatus.setParent( this );
        mpInputContext = new SalI18N_InputContext( this );
		if (mpInputContext->UseContext())
		{
	  		mpInputContext->ExtendEventMask( GetShellWindow() );
	  		if (pContext->mnOptions & SAL_INPUTCONTEXT_CHANGELANGUAGE)
				mpInputContext->SetLanguage(pContext->meLanguage);
			if (mbInputFocus)
				mpInputContext->SetICFocus( this );
		}
  	}
    else
        mpInputContext->Map( this );
  	return;
}

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

void X11SalFrame::EndExtTextInput( sal_uInt16 nFlags )
{
    if (mpInputContext != NULL)
  	    mpInputContext->EndExtTextInput( nFlags );
}

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

XubString X11SalFrame::GetKeyName( sal_uInt16 nKeyCode )
{
	return GetDisplay()->GetKeyName( nKeyCode );
}

XubString X11SalFrame::GetSymbolKeyName( const XubString&, sal_uInt16 nKeyCode )
{
  return GetKeyName( nKeyCode );
}

sal_Bool X11SalFrame::MapUnicodeToKeyCode( sal_Unicode , LanguageType , KeyCode& )
{
    // not supported yet
    return sal_False;
}

LanguageType X11SalFrame::GetInputLanguage()
{
    // could be improved by checking unicode ranges of the last input
    return LANGUAGE_DONTKNOW;
}

// Settings
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

inline Color getColorFromLong( long nColor )
{
	return Color( (nColor & 0xff), (nColor & 0xff00)>>8, (nColor & 0xff0000)>>16);
}

void X11SalFrame::UpdateSettings( AllSettings& rSettings )
{

    DtIntegrator* pIntegrator = GetDisplay()->getDtIntegrator();
#if OSL_DEBUG_LEVEL > 1
    fprintf( stderr, "DtIntegrator: %d\n", pIntegrator ? pIntegrator->GetDtType() : -1 );
#endif
    if( pIntegrator )
        pIntegrator->GetSystemLook( rSettings );
}

void X11SalFrame::CaptureMouse( sal_Bool bCapture )
{
    nCaptured_ = pDisplay_->CaptureMouse( bCapture ? this : NULL );
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void X11SalFrame::SetParent( SalFrame* pNewParent )
{
    if( mpParent != pNewParent )
    {
        if( mpParent )
            mpParent->maChildren.remove( this );

        mpParent = static_cast<X11SalFrame*>(pNewParent);
        mpParent->maChildren.push_back( this );
        if( mpParent->m_nScreen != m_nScreen )
            createNewWindow( None, mpParent->m_nScreen );
        GetDisplay()->getWMAdaptor()->changeReferenceFrame( this, mpParent );
    }
}

SalFrame* X11SalFrame::GetParent() const
{
    return mpParent;
}

void X11SalFrame::createNewWindow( XLIB_Window aNewParent, int nScreen )
{
    bool bWasVisible = bMapped_;
    if( bWasVisible )
        Show( sal_False );
    
    if( nScreen < 0 || nScreen >= GetDisplay()->GetScreenCount() )
        nScreen = m_nScreen;

    SystemParentData aParentData;
    aParentData.aWindow = aNewParent;
    aParentData.bXEmbedSupport = (aNewParent != None && m_bXEmbed); // caution: this is guesswork
    if( aNewParent == None )
    {
        aNewParent = GetDisplay()->GetRootWindow(nScreen);
        aParentData.aWindow = None;
        m_bXEmbed = false;
    }
    else
    {
        // is new parent a root window ?
        Display* pDisp = GetDisplay()->GetDisplay();
        int nScreens = GetDisplay()->GetScreenCount();
        for( int i = 0; i < nScreens; i++ )
        {
            if( aNewParent == RootWindow( pDisp, i ) )
            {
                nScreen = i;
                aParentData.aWindow = None;
                m_bXEmbed = false;
                break;
            }
        }
    }

    // first deinit frame
    updateGraphics(true);
    if( mpInputContext )
    {
        mpInputContext->UnsetICFocus( this );
        mpInputContext->Unmap( this );
    }
    if( GetWindow() == hPresentationWindow )
    {
        hPresentationWindow = None;
        doReparentPresentationDialogues( GetDisplay() );
    }
    XDestroyWindow( GetXDisplay(), mhWindow );
    mhWindow = None;

    passOnSaveYourSelf();

    // now init with new parent again
    if ( aParentData.aWindow != None )
	    Init( nStyle_ | SAL_FRAME_STYLE_PLUG, nScreen, &aParentData );
    else
	    Init( nStyle_ & ~SAL_FRAME_STYLE_PLUG, nScreen, NULL, true );

	// update graphics if necessary
    updateGraphics(false);
    
    if( m_aTitle.Len() )
        SetTitle( m_aTitle );
    
    if( mpParent )
    {
        if( mpParent->m_nScreen != m_nScreen )
            SetParent( NULL );
        else
            pDisplay_->getWMAdaptor()->changeReferenceFrame( this, mpParent );
    }

    if( bWasVisible )
        Show( sal_True );
    
    std::list< X11SalFrame* > aChildren = maChildren;
    for( std::list< X11SalFrame* >::iterator it = aChildren.begin(); it != aChildren.end(); ++it )
        (*it)->createNewWindow( None, m_nScreen );
    
    // FIXME: SalObjects
}

bool X11SalFrame::SetPluginParent( SystemParentData* pNewParent )
{
    if( pNewParent->nSize >= sizeof(SystemParentData) )
        m_bXEmbed = pNewParent->aWindow != None && pNewParent->bXEmbedSupport;
    createNewWindow( pNewParent ? pNewParent->aWindow : None );

    return true;
}

// Sound
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void X11SalFrame::Beep( SoundType eSoundType ) // not fully suported
{
    switch( eSoundType )
    {
        case SOUND_DEFAULT:
        case SOUND_ERROR:
            GetDisplay()->Beep();
            break;
        default:
            // Excessive beeping averted
            break;
    }
}

// Event Handling
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
static sal_uInt16 sal_GetCode( int state )
{
	sal_uInt16 nCode = 0;

	if( state & Button1Mask )
		nCode |= MOUSE_LEFT;
	if( state & Button2Mask )
		nCode |= MOUSE_MIDDLE;
	if( state & Button3Mask )
		nCode |= MOUSE_RIGHT;

	if( state & ShiftMask )
		nCode |= KEY_SHIFT;
	if( state & ControlMask )
		nCode |= KEY_MOD1;
	if( state & Mod1Mask )
		nCode |= KEY_MOD2;

        // Map Meta/Super modifier to MOD3 on all Unix systems
        // except Mac OS X
        if( (state & Mod3Mask) )
            nCode |= KEY_MOD3;

	return nCode;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

SalFrame::SalPointerState X11SalFrame::GetPointerState()
{
    SalPointerState aState;
    XLIB_Window aRoot, aChild;
    int rx, ry, wx, wy;
    unsigned int nMask = 0;
    XQueryPointer( GetXDisplay(),
                   GetShellWindow(),
                   &aRoot,
                   &aChild,
                   &rx, &ry,
                   &wx, &wy,
                   &nMask
                   );

    aState.maPos = Point(wx, wy);
    aState.mnState = sal_GetCode( nMask );
    return aState;
}

long X11SalFrame::HandleMouseEvent( XEvent *pEvent )
{
	SalMouseEvent		aMouseEvt;
	sal_uInt16				nEvent = 0;
    bool				bClosePopups = false;

    if( nVisibleFloats && pEvent->type == EnterNotify )
        return 0;

	// Solaris X86: clicking the right button on a two-button mouse
	// generates a button2 event not a button3 event
	if (pDisplay_->GetProperties() & PROPERTY_SUPPORT_3ButtonMouse )
	{
		switch (pEvent->type)
		{
			case EnterNotify:
			case LeaveNotify:
				if ( pEvent->xcrossing.state & Button2Mask )
				{
					pEvent->xcrossing.state &= ~Button2Mask;
					pEvent->xcrossing.state |=	Button3Mask;
				}
				break;

			case MotionNotify:
				if ( pEvent->xmotion.state & Button2Mask )
				{
					pEvent->xmotion.state &= ~Button2Mask;
					pEvent->xmotion.state |=  Button3Mask;
				}
				break;

			default:
				if ( Button2 == pEvent->xbutton.button )
				{
					pEvent->xbutton.state &= ~Button2Mask;
					pEvent->xbutton.state |=  Button3Mask;
					pEvent->xbutton.button =  Button3;
				}
				break;
		}
	}


	if( LeaveNotify == pEvent->type || EnterNotify == pEvent->type )
	{
        /*
         *  #89075# #89335#
         *
         *  some WMs (and/or) applications  have a passive grab on
         *  mouse buttons (XGrabButton). This leads to enter/leave notifies
         *  with mouse buttons pressed in the state mask before the actual
         *  ButtonPress event gets dispatched. But EnterNotify
         *  is reported in vcl as MouseMove event. Some office code
         *  decides that a pressed button in a MouseMove belongs to
         *  a drag operation which leads to doing things differently.
         *
         *  #95901#
         *  ignore Enter/LeaveNotify resulting from grabs so that
         *  help windows do not disappear just after appearing
         *
         *  hopefully this workaround will not break anything.
         */
        if( pEvent->xcrossing.mode == NotifyGrab || pEvent->xcrossing.mode == NotifyUngrab  )
            return 0;

		aMouseEvt.mnX		= pEvent->xcrossing.x;
		aMouseEvt.mnY		= pEvent->xcrossing.y;
		aMouseEvt.mnTime	= pEvent->xcrossing.time;
        aMouseEvt.mnCode	= sal_GetCode( pEvent->xcrossing.state );
		aMouseEvt.mnButton	= 0;

		nEvent				= LeaveNotify == pEvent->type
							  ? SALEVENT_MOUSELEAVE
							  : SALEVENT_MOUSEMOVE;
	}
	else if( pEvent->type == MotionNotify )
	{
		aMouseEvt.mnX		= pEvent->xmotion.x;
		aMouseEvt.mnY		= pEvent->xmotion.y;
		aMouseEvt.mnTime	= pEvent->xmotion.time;
		aMouseEvt.mnCode	= sal_GetCode( pEvent->xmotion.state );

		aMouseEvt.mnButton	= 0;

		nEvent				= SALEVENT_MOUSEMOVE;
        if( nVisibleFloats > 0 && mpParent )
        {
            XLIB_Cursor aCursor = mpParent->GetCursor();
            if( pEvent->xmotion.x >= 0 && pEvent->xmotion.x < (int)maGeometry.nWidth &&
                pEvent->xmotion.y >= 0 && pEvent->xmotion.y < (int)maGeometry.nHeight )
                aCursor = None;

            XChangeActivePointerGrab( GetXDisplay(),
                                      PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
                                      aCursor,
                                      CurrentTime );
        }
	}
	else
	{
        // let mouse events reach the correct window
        if( nVisibleFloats < 1 )
        {
            if( ! (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION) )
                XUngrabPointer( GetXDisplay(), CurrentTime );
        }
        else if( pEvent->type == ButtonPress )
        {
            // see if the user clicks outside all of the floats
            // if yes release the grab
            bool bInside = false;
            const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames();
            for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it )
            {
                const X11SalFrame* pFrame = static_cast< const X11SalFrame* >(*it);
                if( pFrame->IsFloatGrabWindow()										&&
                    pFrame->bMapped_												&&
                    pEvent->xbutton.x_root >= pFrame->maGeometry.nX								&&
                    pEvent->xbutton.x_root < pFrame->maGeometry.nX + (int)pFrame->maGeometry.nWidth	&&
                    pEvent->xbutton.y_root >= pFrame->maGeometry.nY								&&
                    pEvent->xbutton.y_root < pFrame->maGeometry.nY + (int)pFrame->maGeometry.nHeight )
                {
                    bInside = true;
                    break;
                }
            }
            if( ! bInside )
            {
                // need not take care of the XUngrabPointer in Show( sal_False )
                // because XUngrabPointer does not produce errors if pointer
                // is not grabbed
                XUngrabPointer( GetXDisplay(), CurrentTime );
                bClosePopups = true;

                /*  #i15246# only close popups if pointer is outside all our frames
                 *  cannot use our own geometry data here because stacking
                 *  is unknown (the above case implicitly assumes
                 *  that floats are on top which should be true)
                 */
                XLIB_Window aRoot, aChild;
                int root_x, root_y, win_x, win_y;
                unsigned int mask_return;
                if( XQueryPointer( GetXDisplay(),
                                   GetDisplay()->GetRootWindow( m_nScreen ),
                                   &aRoot, &aChild,
                                   &root_x, &root_y,
                                   &win_x, &win_y,
                                   &mask_return )
                    && aChild // pointer may not be in any child
                    )
                {
                    for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it )
                    {
                        const X11SalFrame* pFrame = static_cast< const X11SalFrame* >(*it);
                        if( ! pFrame->IsFloatGrabWindow()
                            && ( pFrame->GetWindow() == aChild ||
                                 pFrame->GetShellWindow() == aChild ||
                                 pFrame->GetStackingWindow() == aChild )
                            )
                        {
                            // #i63638# check that pointer is inside window, not
                            // only inside stacking window
                            if( root_x >= pFrame->maGeometry.nX && root_x < sal::static_int_cast< int >(pFrame->maGeometry.nX+pFrame->maGeometry.nWidth) &&
                                root_y >= pFrame->maGeometry.nY && root_y < sal::static_int_cast< int >(pFrame->maGeometry.nX+pFrame->maGeometry.nHeight) )
                            {
                                bClosePopups = false;
                            }
                            break;
                        }
                    }
                }
            }
        }
        
        if( m_bXEmbed && pEvent->xbutton.button == Button1 )
            askForXEmbedFocus( pEvent->xbutton.time );

		if( pEvent->xbutton.button == Button1 ||
			pEvent->xbutton.button == Button2 ||
			pEvent->xbutton.button == Button3 )
		{
			aMouseEvt.mnX		= pEvent->xbutton.x;
			aMouseEvt.mnY		= pEvent->xbutton.y;
			aMouseEvt.mnTime	= pEvent->xbutton.time;
			aMouseEvt.mnCode	= sal_GetCode( pEvent->xbutton.state );

			if( Button1 == pEvent->xbutton.button )
				aMouseEvt.mnButton	= MOUSE_LEFT;
			else if( Button2 == pEvent->xbutton.button )
				aMouseEvt.mnButton	= MOUSE_MIDDLE;
			else if( Button3 == pEvent->xbutton.button )
				aMouseEvt.mnButton	= MOUSE_RIGHT;

			nEvent				= ButtonPress == pEvent->type
				? SALEVENT_MOUSEBUTTONDOWN
				: SALEVENT_MOUSEBUTTONUP;
		}
		else if( pEvent->xbutton.button == Button4 ||
                 pEvent->xbutton.button == Button5 ||
                 pEvent->xbutton.button == Button6 ||
                 pEvent->xbutton.button == Button7 )
		{
            const bool bIncrement( 
                pEvent->xbutton.button == Button4 ||
                pEvent->xbutton.button == Button6 );
            const bool bHoriz( 
                pEvent->xbutton.button == Button6 ||
                pEvent->xbutton.button == Button7 );

            if( pEvent->type == ButtonRelease )
                return 0;

            static sal_uLong		nLines = 0;
			if( ! nLines )
			{
				char* pEnv = getenv( "SAL_WHEELLINES" );
				nLines = pEnv ? atoi( pEnv ) : 3;
				if( nLines > 10 )
					nLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
			}

			SalWheelMouseEvent	aWheelEvt;
			aWheelEvt.mnTime		= pEvent->xbutton.time;
			aWheelEvt.mnX			= pEvent->xbutton.x;
			aWheelEvt.mnY			= pEvent->xbutton.y;
			aWheelEvt.mnDelta		= bIncrement ? 120 : -120;
			aWheelEvt.mnNotchDelta	= bIncrement ? 1 : -1;
			aWheelEvt.mnScrollLines = nLines;
			aWheelEvt.mnCode		= sal_GetCode( pEvent->xbutton.state );
			aWheelEvt.mbHorz		= bHoriz;

			nEvent = SALEVENT_WHEELMOUSE;

            // --- RTL --- (mirror mouse pos)
            if( Application::GetSettings().GetLayoutRTL() )
                aWheelEvt.mnX = nWidth_-1-aWheelEvt.mnX;
			return CallCallback( nEvent, &aWheelEvt );
		}
	}

    int nRet = 0;
	if( nEvent == SALEVENT_MOUSELEAVE
		|| ( aMouseEvt.mnX <  nWidth_  && aMouseEvt.mnX >  -1 &&
			 aMouseEvt.mnY <  nHeight_ && aMouseEvt.mnY >  -1 )
		|| pDisplay_->MouseCaptured( this )
        )
    {
        // --- RTL --- (mirror mouse pos)
        if( Application::GetSettings().GetLayoutRTL() )
            aMouseEvt.mnX = nWidth_-1-aMouseEvt.mnX;
		nRet = CallCallback( nEvent, &aMouseEvt );
    }

    if( bClosePopups )
    {
        /*  #108213# close popups after dispatching the event outside the popup;
         *  applications do weird things.
         */
        ImplSVData* pSVData = ImplGetSVData();
        if ( pSVData->maWinData.mpFirstFloat )
        {
            static const char* pEnv = getenv( "SAL_FLOATWIN_NOAPPFOCUSCLOSE" );
            if ( !(pSVData->maWinData.mpFirstFloat->GetPopupModeFlags() & FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE) && !(pEnv && *pEnv) )
                pSVData->maWinData.mpFirstFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
        }
    }

	return nRet;
}

// F10 means either KEY_F10 or KEY_MENU, which has to be decided
// in the independent part.
struct KeyAlternate
{
	sal_uInt16			nKeyCode;
	sal_Unicode		nCharCode;
	KeyAlternate() : nKeyCode( 0 ), nCharCode( 0 ) {}
	KeyAlternate( sal_uInt16 nKey, sal_Unicode nChar = 0 ) : nKeyCode( nKey ), nCharCode( nChar ) {}
};

inline KeyAlternate
GetAlternateKeyCode( const sal_uInt16 nKeyCode )
{
	KeyAlternate aAlternate;

	switch( nKeyCode )
	{
		case KEY_F10: aAlternate = KeyAlternate( KEY_MENU );break;
		case KEY_F24: aAlternate = KeyAlternate( KEY_SUBTRACT, '-' );break;
	}

	return aAlternate;
}

void X11SalFrame::beginUnicodeSequence()
{
    rtl::OUString& rSeq( GetX11SalData()->GetUnicodeAccumulator() );
    DeletionListener aDeleteWatch( this );

    if( rSeq.getLength() )
        endUnicodeSequence();

    rSeq = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "u" ) );

    if( ! aDeleteWatch.isDeleted() )
    {
        sal_uInt16 nTextAttr = SAL_EXTTEXTINPUT_ATTR_UNDERLINE;
        SalExtTextInputEvent aEv;
        aEv.mnTime          = 0;
        aEv.maText          = rSeq;
        aEv.mpTextAttr      = &nTextAttr;
        aEv.mnCursorPos     = 0;
        aEv.mnDeltaStart    = 0;
        aEv.mnCursorFlags   = 0;
        aEv.mbOnlyCursor    = sal_False;
        
        CallCallback(SALEVENT_EXTTEXTINPUT, (void*)&aEv);
    }
}

bool X11SalFrame::appendUnicodeSequence( sal_Unicode c )
{
    bool bRet = false;
    rtl::OUString& rSeq( GetX11SalData()->GetUnicodeAccumulator() );
    if( rSeq.getLength() > 0 )
    {
        // range check
        if( (c >= sal_Unicode('0') && c <= sal_Unicode('9')) ||
            (c >= sal_Unicode('a') && c <= sal_Unicode('f')) ||
            (c >= sal_Unicode('A') && c <= sal_Unicode('F')) )
        {
            rtl::OUStringBuffer aBuf( rSeq.getLength() + 1 );
            aBuf.append( rSeq );
            aBuf.append( c );
            rSeq = aBuf.makeStringAndClear();
            std::vector<sal_uInt16> attribs( rSeq.getLength(), SAL_EXTTEXTINPUT_ATTR_UNDERLINE );

            SalExtTextInputEvent aEv;
            aEv.mnTime          = 0;
            aEv.maText          = rSeq;
            aEv.mpTextAttr      = &attribs[0];
            aEv.mnCursorPos     = 0;
            aEv.mnDeltaStart    = 0;
            aEv.mnCursorFlags   = 0;
            aEv.mbOnlyCursor    = sal_False;
            
            CallCallback(SALEVENT_EXTTEXTINPUT, (void*)&aEv);
            bRet = true;
        }
        else
            bRet = endUnicodeSequence();
    }
    else
        endUnicodeSequence();
    return bRet;
}

bool X11SalFrame::endUnicodeSequence()
{
    rtl::OUString& rSeq( GetX11SalData()->GetUnicodeAccumulator() );

    DeletionListener aDeleteWatch( this );
    if( rSeq.getLength() > 1 && rSeq.getLength() < 6 )
    {
        // cut the "u"
        rtl::OUString aNumbers( rSeq.copy( 1 ) );
        sal_Int32 nValue = aNumbers.toInt32( 16 );
        if( nValue >= 32 )
        {
            sal_uInt16 nTextAttr = SAL_EXTTEXTINPUT_ATTR_UNDERLINE;
            SalExtTextInputEvent aEv;
            aEv.mnTime          = 0;
            aEv.maText          = rtl::OUString( sal_Unicode(nValue) );
            aEv.mpTextAttr      = &nTextAttr;
            aEv.mnCursorPos     = 0;
            aEv.mnDeltaStart    = 0;
            aEv.mnCursorFlags   = 0;
            aEv.mbOnlyCursor    = sal_False;
            CallCallback(SALEVENT_EXTTEXTINPUT, (void*)&aEv);
        }
    }
    bool bWasInput = rSeq.getLength() > 0;
    rSeq = rtl::OUString();
    if( bWasInput && ! aDeleteWatch.isDeleted() )
        CallCallback(SALEVENT_ENDEXTTEXTINPUT, NULL);
    return bWasInput;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
long X11SalFrame::HandleKeyEvent( XKeyEvent *pEvent )
{
	KeySym			nKeySym;
    KeySym          nUnmodifiedKeySym;
	int 			nLen = 2048;
	unsigned char	*pPrintable = (unsigned char*)alloca( nLen );

	// singlebyte code composed by input method, the new default
	if (mpInputContext != NULL && mpInputContext->UseContext())
	{
		// returns a keysym as well as the pPrintable (in system encoding)
		// printable may be empty.
		Status nStatus;
    	nKeySym = pDisplay_->GetKeySym( pEvent, pPrintable, &nLen,
                                        &nUnmodifiedKeySym,
                                        &nStatus, mpInputContext->GetContext() );
		if ( nStatus == XBufferOverflow )
		{
			nLen *= 2;
			pPrintable = (unsigned char*)alloca( nLen );
			nKeySym = pDisplay_->GetKeySym( pEvent, pPrintable, &nLen,
                                            &nUnmodifiedKeySym,
                                            &nStatus, mpInputContext->GetContext() );
		}
	}
	else
	{
		// fallback, this should never ever be called
		Status nStatus = 0;
       	nKeySym = pDisplay_->GetKeySym( pEvent, pPrintable, &nLen, &nUnmodifiedKeySym, &nStatus );
 	}

	SalKeyEvent aKeyEvt;
	sal_uInt16      nKeyCode;
	sal_uInt16 nModCode = 0;
	char		aDummy;

	if( pEvent->state & ShiftMask )
		nModCode |= KEY_SHIFT;
	if( pEvent->state & ControlMask )
		nModCode |= KEY_MOD1;
	if( pEvent->state & Mod1Mask )
		nModCode |= KEY_MOD2;
    
    if( nModCode != (KEY_SHIFT|KEY_MOD1) )
        endUnicodeSequence();

	if( 	nKeySym == XK_Shift_L 	|| nKeySym == XK_Shift_R
		|| 	nKeySym == XK_Control_L || nKeySym == XK_Control_R
		|| 	nKeySym == XK_Alt_L		|| nKeySym == XK_Alt_R
		|| 	nKeySym == XK_Meta_L 	|| nKeySym == XK_Meta_R
                ||      nKeySym == XK_Super_L   || nKeySym == XK_Super_R )
	{
		SalKeyModEvent aModEvt;
        aModEvt.mnModKeyCode = 0;
        if( pEvent->type == XLIB_KeyPress && mnExtKeyMod == 0 )
            mbSendExtKeyModChange = true;
        else if( pEvent->type == KeyRelease && mbSendExtKeyModChange )
        {
            aModEvt.mnModKeyCode = mnExtKeyMod;
            mnExtKeyMod = 0;
        }

		// pressing just the ctrl key leads to a keysym of XK_Control but
		// the event state does not contain ControlMask. In the release
		// event its the other way round: it does contain the Control mask.
		// The modifier mode therefore has to be adapted manually.
        sal_uInt16 nExtModMask = 0;
        sal_uInt16 nModMask = 0;
        switch( nKeySym )
        {
            case XK_Control_L:
                nExtModMask = MODKEY_LMOD1;
                nModMask = KEY_MOD1;
                break;
            case XK_Control_R:
                nExtModMask = MODKEY_RMOD1;
                nModMask = KEY_MOD1;
                break;
            case XK_Alt_L:
                nExtModMask = MODKEY_LMOD2;
                nModMask = KEY_MOD2;
                break;
            case XK_Alt_R:
                nExtModMask = MODKEY_RMOD2;
                nModMask = KEY_MOD2;
                break;
            case XK_Shift_L:
                nExtModMask = MODKEY_LSHIFT;
                nModMask = KEY_SHIFT;
                break;
            case XK_Shift_R:
                nExtModMask = MODKEY_RSHIFT;
                nModMask = KEY_SHIFT;
                break;
            // Map Meta/Super keys to MOD3 modifier on all Unix systems
            // except Mac OS X
            case XK_Meta_L:
            case XK_Super_L:
                nExtModMask = MODKEY_LMOD3;
                nModMask = KEY_MOD3;
                break;
            case XK_Meta_R:
            case XK_Super_R:
                nExtModMask = MODKEY_RMOD3;
                nModMask = KEY_MOD3;
                break;
        }
        if( pEvent->type == KeyRelease )
        {
            nModCode &= ~nModMask;
            mnExtKeyMod &= ~nExtModMask;
        }
        else
        {
            nModCode |= nModMask;
            mnExtKeyMod |= nExtModMask;
        }

		aModEvt.mnCode = nModCode;
		aModEvt.mnTime = pEvent->time;

		int nRet = CallCallback( SALEVENT_KEYMODCHANGE, &aModEvt );

        // emulate KEY_MENU
        if ( ( (nKeySym == XK_Alt_L) || (nKeySym == XK_Alt_R) ) &&
             ( (nModCode & ~(KEY_MOD3|KEY_MOD2)) == 0 ) )
        {
            if( pEvent->type == XLIB_KeyPress )
                mbKeyMenu = true;
            else if( mbKeyMenu )
            {
                // simulate KEY_MENU
                aKeyEvt.mnCode	   = KEY_MENU | nModCode;
                aKeyEvt.mnRepeat   = 0;
                aKeyEvt.mnTime	   = pEvent->time;
                aKeyEvt.mnCharCode = 0;
                nRet = CallCallback( SALEVENT_KEYINPUT, &aKeyEvt );
                nRet = CallCallback( SALEVENT_KEYUP, &aKeyEvt );
            }
        }
        else
            mbKeyMenu = false;
        return nRet;
	}

    mbSendExtKeyModChange = mbKeyMenu = false;

	// try to figure out the vcl code for the keysym
    // #i52338# use the unmodified KeySym if there is none for the real KeySym
    // because the independent part has only keycodes for unshifted keys
	nKeyCode = pDisplay_->GetKeyCode( nKeySym, &aDummy );
    if( nKeyCode == 0 )
        nKeyCode = pDisplay_->GetKeyCode( nUnmodifiedKeySym, &aDummy );

	// try to figure out a printable if XmbLookupString returns only a keysym
	// and NOT a printable. Do not store it in pPrintable[0] since it is expected to
	// be in system encoding, not unicode.
    // #i8988##, if KeySym and printable look equally promising then prefer KeySym
    // the printable is bound to the encoding so the KeySym might contain more
    // information (in et_EE locale: "Compose + Z + <" delivers "," in printable and
    // (the desired) Zcaron in KeySym
	sal_Unicode nKeyString = 0x0;
	if (   (nLen == 0) 
        || ((nLen == 1) && (nKeySym > 0)) )
		nKeyString = KeysymToUnicode (nKeySym);
	// if we have nothing we give up
	if( !nKeyCode && !nLen && !nKeyString)
		return 0;
    
    DeletionListener aDeleteWatch( this );

    if( nModCode == (KEY_SHIFT | KEY_MOD1) && pEvent->type == XLIB_KeyPress )
    {
        sal_uInt16 nSeqKeyCode = pDisplay_->GetKeyCode( nUnmodifiedKeySym, &aDummy );
        if( nSeqKeyCode == KEY_U )
        {
            beginUnicodeSequence();
            return 1;
        }
        else if( nSeqKeyCode >= KEY_0 && nSeqKeyCode <= KEY_9 )
        {
            if( appendUnicodeSequence( sal_Unicode( '0' ) + sal_Unicode(nSeqKeyCode - KEY_0) ) )
                return 1;
        }
        else if( nSeqKeyCode >= KEY_A && nSeqKeyCode <= KEY_F )
        {
            if( appendUnicodeSequence( sal_Unicode( 'a' ) + sal_Unicode(nSeqKeyCode - KEY_A) ) )
                return 1;
        }
        else
            endUnicodeSequence();
    }
    
    if( aDeleteWatch.isDeleted() )
        return 0;

	rtl_TextEncoding nEncoding;

    if (mpInputContext != NULL && mpInputContext->IsMultiLingual() )
        nEncoding = RTL_TEXTENCODING_UTF8;
    else
        nEncoding = osl_getThreadTextEncoding();

	sal_Unicode *pBuffer;
	sal_Unicode *pString;
	sal_Size     nBufferSize = nLen * 2;
	sal_Size     nSize;
	pBuffer = (sal_Unicode*) malloc( nBufferSize + 2 );
	pBuffer[ 0 ] = 0;

	if (nKeyString != 0)
	{
		pString = &nKeyString;
		nSize = 1;
	}
	else
	if (nLen > 0 && nEncoding != RTL_TEXTENCODING_UNICODE)
	{
		// create text converter
		rtl_TextToUnicodeConverter aConverter =
				rtl_createTextToUnicodeConverter( nEncoding );
		rtl_TextToUnicodeContext aContext =
			 	rtl_createTextToUnicodeContext( aConverter );

		sal_uInt32  nConversionInfo;
		sal_Size    nConvertedChars;

		// convert to single byte text stream
		nSize = rtl_convertTextToUnicode(
				                aConverter, aContext,
                                (char*)pPrintable, nLen,
                                pBuffer, nBufferSize,
                                RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_IGNORE |
                                RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE,
                                &nConversionInfo, &nConvertedChars );

		// destroy converter
		rtl_destroyTextToUnicodeContext( aConverter, aContext );
		rtl_destroyTextToUnicodeConverter( aConverter );

		pString = pBuffer;
	}
	else
	if (nLen > 0 /* nEncoding == RTL_TEXTENCODING_UNICODE */)
	{
		pString = (sal_Unicode*)pPrintable;
	  	nSize = nLen;
	}
    else
    {
        pString = pBuffer;
        nSize   = 0;
    }

	if (   mpInputContext != NULL
		&& mpInputContext->UseContext()
		&& KeyRelease != pEvent->type
		&& (   (nSize >  1)
            || (nSize >  0 && mpInputContext->IsPreeditMode())) )
	{
        mpInputContext->CommitKeyEvent(pString, nSize);
	}
	else
    // normal single character keyinput
	{
		aKeyEvt.mnCode	   = nKeyCode | nModCode;
		aKeyEvt.mnRepeat   = 0;
		aKeyEvt.mnTime	   = pEvent->time;
		aKeyEvt.mnCharCode = pString[ 0 ];

		if( KeyRelease == pEvent->type )
		{
			CallCallback( SALEVENT_KEYUP, &aKeyEvt );
		}
		else
		{
			if ( ! CallCallback(SALEVENT_KEYINPUT, &aKeyEvt) )
			{
				// independent layer doesnt want to handle key-event, so check
				// whether the keycode may have an alternate meaning
				KeyAlternate aAlternate = GetAlternateKeyCode( nKeyCode );
				if ( aAlternate.nKeyCode != 0 )
				{
					aKeyEvt.mnCode = aAlternate.nKeyCode | nModCode;
					if( aAlternate.nCharCode )
						aKeyEvt.mnCharCode = aAlternate.nCharCode;
					CallCallback(SALEVENT_KEYINPUT, &aKeyEvt);
				}
			}
		}
	}

  	//
  	// update the spot location for PreeditPosition IME style
  	//
    if (! aDeleteWatch.isDeleted())
    {
        if (mpInputContext != NULL && mpInputContext->UseContext())
            mpInputContext->UpdateSpotLocation();
    }

	free (pBuffer);
	return True;
}


// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
long X11SalFrame::HandleFocusEvent( XFocusChangeEvent *pEvent )
{
    // #107739# ReflectionX in Windows mode changes focus while mouse is grabbed
	if( nVisibleFloats > 0 && GetDisplay()->getWMAdaptor()->getWindowManagerName().EqualsAscii( "ReflectionX Windows" ) )
		return 1;

	/*	#55691# ignore focusout resulting from keyboard grabs
	 *	we do not grab it and are not interested when
	 *	someone else does CDE e.g. does a XGrabKey on arrow keys
	 *	#73179# handle focus events with mode NotifyWhileGrabbed
	 *	because with CDE alt-tab focus changing we do not get
	 *	normal focus events
	 *	#71791# cast focus event to the input context, otherwise the
	 *	status window does not follow the application frame
	 */

	if ( mpInputContext != NULL  )
	{
		if( FocusIn == pEvent->type )
            mpInputContext->SetICFocus( this );
        else
        {
            /*
             *  do not unset the IC focuse here because would kill
             *  a lookup choice windows that might have the focus now
             *  	mpInputContext->UnsetICFocus( this );
             */
            I18NStatus::get().show( false, I18NStatus::focus );
        }
	}


	if ( pEvent->mode == NotifyNormal || pEvent->mode == NotifyWhileGrabbed ||
         ( ( nStyle_ & SAL_FRAME_STYLE_PLUG ) && pEvent->window == GetShellWindow() )
         )
	{
        if( hPresentationWindow != None && hPresentationWindow != GetShellWindow() )
            return 0;

		if( FocusIn == pEvent->type )
		{
            vcl_sal::PrinterUpdate::update();
			mbInputFocus = True;
            ImplSVData* pSVData = ImplGetSVData();



			long nRet = CallCallback( SALEVENT_GETFOCUS,  0 );
            if ((mpParent != NULL && nStyle_ == 0)
                && pSVData->maWinData.mpFirstFloat )
            {
                sal_uLong nMode = pSVData->maWinData.mpFirstFloat->GetPopupModeFlags();
                pSVData->maWinData.mpFirstFloat->SetPopupModeFlags(
                                        nMode & ~(FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE));
            }
            return nRet;
		}
		else
		{
			mbInputFocus = False;
            mbSendExtKeyModChange = mbKeyMenu = false;
            mnExtKeyMod = 0;
			return CallCallback( SALEVENT_LOSEFOCUS, 0 );
		}
	}

	return 0;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

long X11SalFrame::HandleExposeEvent( XEvent *pEvent )
{
	XRectangle	aRect = { 0, 0, 0, 0 };
	sal_uInt16		nCount = 0;

	if( pEvent->type == Expose )
	{
		aRect.x 		= pEvent->xexpose.x;
		aRect.y 		= pEvent->xexpose.y;
		aRect.width 	= pEvent->xexpose.width;
		aRect.height	= pEvent->xexpose.height;
		nCount			= pEvent->xexpose.count;
	}
	else if( pEvent->type == GraphicsExpose )
	{
		aRect.x 		= pEvent->xgraphicsexpose.x;
		aRect.y 		= pEvent->xgraphicsexpose.y;
		aRect.width 	= pEvent->xgraphicsexpose.width;
		aRect.height	= pEvent->xgraphicsexpose.height;
		nCount			= pEvent->xgraphicsexpose.count;
	}

    if( IsOverrideRedirect() && mbFullScreen &&
        aPresentationReparentList.begin() == aPresentationReparentList.end() )
		// we are in fullscreen mode -> override redirect
 		// focus is possibly lost, so reget it
 		XSetInputFocus( GetXDisplay(), GetShellWindow(), RevertToNone, CurrentTime );

    // width and height are extents, so they are of by one for rectangle
    maPaintRegion.Union( Rectangle( Point(aRect.x, aRect.y), Size(aRect.width+1, aRect.height+1) ) );

	if( nCount )
        // wait for last expose rectangle, do not wait for resize timer
        // if a completed graphics expose sequence is available
		return 1;

	SalPaintEvent aPEvt( maPaintRegion.Left(), maPaintRegion.Top(), maPaintRegion.GetWidth(), maPaintRegion.GetHeight() );

 	CallCallback( SALEVENT_PAINT, &aPEvt );
    maPaintRegion = Rectangle();

	return 1;
}

void X11SalFrame::RestackChildren( XLIB_Window* pTopLevelWindows, int nTopLevelWindows )
{
    if( maChildren.begin() != maChildren.end() )
    {
        int nWindow = nTopLevelWindows;
        while( nWindow-- )
            if( pTopLevelWindows[nWindow] == GetStackingWindow() )
                break;
        if( nWindow < 0 )
            return;

        std::list< X11SalFrame* >::const_iterator it;
        for( it = maChildren.begin(); it != maChildren.end(); ++it )
        {
            X11SalFrame* pData = *it;
            if( pData->bMapped_ )
            {
                int nChild = nWindow;
                while( nChild-- )
                {
                    if( pTopLevelWindows[nChild] == pData->GetStackingWindow() )
                    {
                        // if a child is behind its parent, place it above the
                        // parent (for insane WMs like Dtwm and olwm)
                        XWindowChanges aCfg;
                        aCfg.sibling	= GetStackingWindow();
                        aCfg.stack_mode	= Above;
                        XConfigureWindow( GetXDisplay(), pData->GetStackingWindow(), CWSibling|CWStackMode, &aCfg );
                        break;
                    }
                }
            }
        }
        for( it = maChildren.begin(); it != maChildren.end(); ++it )
        {
            X11SalFrame* pData = *it;
            pData->RestackChildren( pTopLevelWindows, nTopLevelWindows );
        }
    }
}

void X11SalFrame::RestackChildren()
{
    if( ! GetDisplay()->getWMAdaptor()->isTransientBehaviourAsExpected()
        && maChildren.begin() != maChildren.end() )
    {
        XLIB_Window aRoot, aParent, *pChildren = NULL;
        unsigned int nChildren;
        if( XQueryTree( GetXDisplay(),
                        GetDisplay()->GetRootWindow( m_nScreen ),
                        &aRoot,
                        &aParent,
                        &pChildren,
                        &nChildren ) )
        {
            RestackChildren( pChildren, nChildren );
            XFree( pChildren );
        }
    }
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
long X11SalFrame::HandleSizeEvent( XConfigureEvent *pEvent )
{
	if (   pEvent->window != GetShellWindow()
           && pEvent->window != GetWindow()
           && pEvent->window != GetForeignParent()
           && pEvent->window != GetStackingWindow()
           )
	{
		// could be as well a sys-child window (aka SalObject)
		return 1;
	}


	if( ( nStyle_ & SAL_FRAME_STYLE_PLUG ) && pEvent->window == GetShellWindow() )
	{
		// just update the children's positions
		RestackChildren();
		return 1;
	}

	if( pEvent->window == GetForeignParent() )
        XResizeWindow( GetXDisplay(),
                       GetWindow(),
                       pEvent->width,
                       pEvent->height );

	XLIB_Window hDummy;
	XTranslateCoordinates( GetXDisplay(),
						   GetWindow(),
						   pDisplay_->GetRootWindow( pDisplay_->GetDefaultScreenNumber() ),
						   0, 0,
						   &pEvent->x, &pEvent->y,
						   &hDummy );

    if( pEvent->window == GetStackingWindow() )
    {
        if( maGeometry.nX != pEvent->x || maGeometry.nY != pEvent->y )
        {
            maGeometry.nX = pEvent->x;
            maGeometry.nY = pEvent->y;
            CallCallback( SALEVENT_MOVE, NULL );
        }
        return 1;
    }

    // check size hints in first time SalFrame::Show
	if( SHOWSTATE_UNKNOWN == nShowState_ && bMapped_ )
        nShowState_ = SHOWSTATE_NORMAL;

    nWidth_ 	= pEvent->width;
    nHeight_	= pEvent->height;

    bool bMoved = ( pEvent->x != maGeometry.nX || pEvent->y != maGeometry.nY );
    bool bSized = ( pEvent->width != (int)maGeometry.nWidth || pEvent->height != (int)maGeometry.nHeight );

    maGeometry.nX		= pEvent->x;
    maGeometry.nY		= pEvent->y;
    maGeometry.nWidth	= pEvent->width;
    maGeometry.nHeight	= pEvent->height;
    updateScreenNumber();

	// update children's position
	RestackChildren();

    if( bSized && ! bMoved )
        CallCallback( SALEVENT_RESIZE, NULL );
    else if( bMoved && ! bSized )
        CallCallback( SALEVENT_MOVE, NULL );
    else if( bMoved && bSized )
        CallCallback( SALEVENT_MOVERESIZE, NULL );

	return 1;
}

IMPL_LINK( X11SalFrame, HandleAlwaysOnTopRaise, void*, EMPTYARG )
{
    if( bMapped_ )
        ToTop( 0 );
    return 0;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
long X11SalFrame::HandleReparentEvent( XReparentEvent *pEvent )
{
	Display 	   *pDisplay   = pEvent->display;
	XLIB_Window 	hWM_Parent;
	XLIB_Window 	hRoot, *Children, hDummy;
	unsigned int	nChildren;
	sal_Bool			bNone = pDisplay_->GetProperties()
							& PROPERTY_SUPPORT_WM_Parent_Pixmap_None;
    sal_Bool            bAccessParentWindow = ! (pDisplay_->GetProperties()
							& PROPERTY_FEATURE_TrustedSolaris);

	static const char* pDisableStackingCheck = getenv( "SAL_DISABLE_STACKING_CHECK" );

    GetDisplay()->GetXLib()->PushXErrorLevel( true );

    /*
     *  #89186# don't rely on the new parent from the event.
     *  the event may be "out of date", that is the window manager
     *  window may not exist anymore. This can happen if someone
     *  shows a frame and hides it again quickly (not that that would
     *  be very sensible)
     */
    hWM_Parent = GetShellWindow();
    do
    {
        Children = NULL;
        XQueryTree( pDisplay,
                    hWM_Parent,
                    &hRoot,
                    &hDummy,
                    &Children,
                    &nChildren );
        if( GetDisplay()->GetXLib()->HasXErrorOccured() )
        {
            hWM_Parent = GetShellWindow();
            break;
        }
         /* #107048# this sometimes happens if a Show(sal_True) is
         *  immediately followed by Show(sal_False) (which is braindead anyway)
         */
        if(  hDummy == hWM_Parent )
            hDummy = hRoot;
        if( hDummy != hRoot )
        {
            hWM_Parent = hDummy;
            if( bAccessParentWindow && bNone )
                XSetWindowBackgroundPixmap( pDisplay, hWM_Parent, None );
        }
        if( Children )
            XFree( Children );
    } while( hDummy != hRoot );

	if( GetStackingWindow() == None
        && hWM_Parent != hPresentationWindow
        && hWM_Parent != GetShellWindow()
        && ( ! pDisableStackingCheck || ! *pDisableStackingCheck )
        )
	{
		mhStackingWindow = hWM_Parent;
		if (bAccessParentWindow)
            XSelectInput( pDisplay, GetStackingWindow(), StructureNotifyMask );
	}

	if( 	hWM_Parent == pDisplay_->GetRootWindow( pDisplay_->GetDefaultScreenNumber() )
            || 	hWM_Parent == GetForeignParent()
            || 	pEvent->parent == pDisplay_->GetRootWindow( pDisplay_->GetDefaultScreenNumber() )
            || ( nStyle_ & SAL_FRAME_STYLE_FLOAT ) )
	{
		// Reparenting before Destroy
        aPresentationReparentList.remove( GetStackingWindow() );
		mhStackingWindow = None;
        GetDisplay()->GetXLib()->PopXErrorLevel();
		return 0;
	}

    /*
     *  evil hack to show decorated windows on top
     *  of override redirect presentation windows:
     *  reparent the window manager window to the presentation window
     *  does not work with non-reparenting WMs
     *  in future this should not be necessary anymore with
     *  _NET_WM_STATE_FULLSCREEN available
     */
    if( hPresentationWindow != None
        && hPresentationWindow != GetWindow()
        && GetStackingWindow() != None
        && GetStackingWindow() != GetDisplay()->GetRootWindow( m_nScreen )
        )
    {
        int x = 0, y = 0;
        XLIB_Window aChild;
        XTranslateCoordinates( GetXDisplay(),
                               GetStackingWindow(),
                               GetDisplay()->GetRootWindow( m_nScreen ),
                               0, 0,
                               &x, &y,
                               &aChild
                               );
        XReparentWindow( GetXDisplay(),
                         GetStackingWindow(),
                         hPresentationWindow,
                         x, y
                         );
        aPresentationReparentList.push_back( GetStackingWindow() );
    }

    int nLeft = 0, nTop = 0;
	XTranslateCoordinates( GetXDisplay(),
                           GetShellWindow(),
                           hWM_Parent,
                           0, 0,
                           &nLeft,
                           &nTop,
                           &hDummy );
    maGeometry.nLeftDecoration	= nLeft > 0 ? nLeft-1 : 0;
    maGeometry.nTopDecoration	= nTop  > 0 ? nTop-1  : 0;

    /*
     *  decorations are not symmetric,
     *  so need real geometries here
     *  (this will fail with virtual roots ?)
     */
    GetDisplay()->GetXLib()->ResetXErrorOccured();
    int xp, yp, x, y;
    unsigned int wp, w, hp, h, bw, d;
    XGetGeometry( GetXDisplay(),
                  GetShellWindow(),
                  &hRoot,
                  &x, &y, &w, &h, &bw, &d );
    XGetGeometry( GetXDisplay(),
                  hWM_Parent,
                  &hRoot,
                  &xp, &yp, &wp, &hp, &bw, &d );
    bool bResized = false;
    if( ! GetDisplay()->GetXLib()->HasXErrorOccured() )
    {
        maGeometry.nRightDecoration 	= wp - w - maGeometry.nLeftDecoration;
        maGeometry.nBottomDecoration	= hp - h - maGeometry.nTopDecoration;
        /*
         *  note: this works because hWM_Parent is direct child of root,
         *  not necessarily parent of GetShellWindow()
         */
        maGeometry.nX		= xp + nLeft;
        maGeometry.nY		= yp + nTop;
        bResized = w != maGeometry.nWidth || h != maGeometry.nHeight;
        maGeometry.nWidth	= w;
        maGeometry.nHeight = h;
    }


    // limit width and height if we are too large: #47757
    // olwm and fvwm need this, it doesnt harm the rest

    // #i81311# do this only for sizable frames
    if( (nStyle_ & SAL_FRAME_STYLE_SIZEABLE) != 0 )
    {
        Size aScreenSize = GetDisplay()->GetScreenSize( m_nScreen );
        int nScreenWidth  = aScreenSize.Width();
        int nScreenHeight = aScreenSize.Height();
        int nFrameWidth   = maGeometry.nWidth + maGeometry.nLeftDecoration + maGeometry.nRightDecoration;
        int nFrameHeight  = maGeometry.nHeight + maGeometry.nTopDecoration  + maGeometry.nBottomDecoration;
    
        if ((nFrameWidth > nScreenWidth) || (nFrameHeight > nScreenHeight))
        {
            Size aSize(maGeometry.nWidth, maGeometry.nHeight);
    
            if (nFrameWidth  > nScreenWidth)
                aSize.Width()  = nScreenWidth  - maGeometry.nRightDecoration - maGeometry.nLeftDecoration;
            if (nFrameHeight > nScreenHeight)
                aSize.Height() = nScreenHeight - maGeometry.nBottomDecoration - maGeometry.nTopDecoration;
    
            SetSize( aSize );
            bResized = false;
        }
    }
    if( bResized )
        CallCallback( SALEVENT_RESIZE, NULL );

    GetDisplay()->GetXLib()->PopXErrorLevel();

	return 1;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
long X11SalFrame::HandleColormapEvent( XColormapEvent* )
{
	return 0;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
long X11SalFrame::HandleStateEvent( XPropertyEvent *pEvent )
{
	Atom		  actual_type;
	int 		  actual_format;
	unsigned long nitems, bytes_after;
	unsigned char *prop = NULL;

	if( 0 != XGetWindowProperty( GetXDisplay(),
								 GetShellWindow(),
								 pEvent->atom,			// property
								 0, 					// long_offset (32bit)
								 2, 					// long_length (32bit)
								 False, 				// delete
								 pEvent->atom,			// req_type
								 &actual_type,
								 &actual_format,
								 &nitems,
								 &bytes_after,
								 &prop )
		|| ! prop
		)
		return 0;

	DBG_ASSERT( actual_type = pEvent->atom
				&& 32 == actual_format
				&&	2 == nitems
				&&	0 == bytes_after, "HandleStateEvent" );

	if( *(unsigned long*)prop == NormalState )
		nShowState_ = SHOWSTATE_NORMAL;
	else if( *(unsigned long*)prop == IconicState )
		nShowState_ = SHOWSTATE_MINIMIZED;

	XFree( prop );
	return 1;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
long X11SalFrame::HandleClientMessage( XClientMessageEvent *pEvent )
{
    const WMAdaptor& rWMAdaptor( *pDisplay_->getWMAdaptor() );

#if !defined(__synchronous_extinput__)
	if( pEvent->message_type == rWMAdaptor.getAtom( WMAdaptor::SAL_EXTTEXTEVENT ) )
	{
		HandleExtTextEvent (pEvent);
		return 1;
	}
#endif
	else if( pEvent->message_type == rWMAdaptor.getAtom( WMAdaptor::SAL_QUITEVENT ) )
	{
		stderr0( "X11SalFrame::Dispatch Quit\n" );
		Close(); // ???
		return 1;
	}
	else if( pEvent->message_type == rWMAdaptor.getAtom( WMAdaptor::WM_PROTOCOLS ) )
    {
        if( (Atom)pEvent->data.l[0] == rWMAdaptor.getAtom( WMAdaptor::NET_WM_PING ) )
            rWMAdaptor.answerPing( this, pEvent );
        else if( ! ( nStyle_ & SAL_FRAME_STYLE_PLUG )
              && ! (( nStyle_ & SAL_FRAME_STYLE_FLOAT ) && (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION))
             )
        {
            if( (Atom)pEvent->data.l[0] == rWMAdaptor.getAtom( WMAdaptor::WM_DELETE_WINDOW ) )
            {
                Close();
                return 1;
            }
            else if( (Atom)pEvent->data.l[0] == rWMAdaptor.getAtom( WMAdaptor::WM_TAKE_FOCUS ) )
            {
                // do nothing, we set the input focus in ToTop() if necessary
    #if OSL_DEBUG_LEVEL > 1
                fprintf( stderr, "got WM_TAKE_FOCUS on %s window\n",
                         (nStyle_&SAL_FRAME_STYLE_OWNERDRAWDECORATION) ?
                         "ownerdraw" : "NON OWNERDRAW" );
    #endif
            }
            else if( (Atom)pEvent->data.l[0] == rWMAdaptor.getAtom( WMAdaptor::WM_SAVE_YOURSELF ) )
            {
                bool bSession = rWMAdaptor.getWindowManagerName().EqualsAscii( "Dtwm" );
                
                if( ! bSession )
                {
                    if( this == s_pSaveYourselfFrame )
                    {
                        ByteString aExec( SessionManagerClient::getExecName(), osl_getThreadTextEncoding() );
                        const char* argv[2];
                        argv[0] = "/bin/sh";
                        argv[1] = const_cast<char*>(aExec.GetBuffer());
    #if OSL_DEBUG_LEVEL > 1
                        fprintf( stderr, "SaveYourself request, setting command: %s %s\n", argv[0], argv[1] );
    #endif
                        XSetCommand( GetXDisplay(), GetShellWindow(), (char**)argv, 2 );
                    }
                    else
                        // can only happen in race between WM and window closing
                        XChangeProperty( GetXDisplay(), GetShellWindow(), rWMAdaptor.getAtom( WMAdaptor::WM_COMMAND ), XA_STRING, 8, PropModeReplace, (unsigned char*)"", 0 );
                }
                else
                {
                    // save open documents; would be good for non Dtwm, too,
                    // but there is no real Shutdown message in the ancient
                    // SM protocol; on Dtwm SaveYourself really means Shutdown, too.
                    IceSalSession::handleOldX11SaveYourself( this );
                }
            }
        }
    }
    else if( pEvent->message_type == rWMAdaptor.getAtom( WMAdaptor::XEMBED ) &&
             pEvent->window == GetWindow() )
    {
        if( pEvent->data.l[1] == 1 || // XEMBED_WINDOW_ACTIVATE
            pEvent->data.l[1] == 2 )  // XEMBED_WINDOW_DEACTIVATE
        {
            XFocusChangeEvent aEvent;
            aEvent.type         = (pEvent->data.l[1] == 1 ? FocusIn : FocusOut);
            aEvent.serial       = pEvent->serial;
            aEvent.send_event   = True;
            aEvent.display      = pEvent->display;
            aEvent.window       = pEvent->window;
            aEvent.mode         = NotifyNormal;
            aEvent.detail       = NotifyDetailNone;
            HandleFocusEvent( &aEvent );
        }
    }
	return 0;
}

void X11SalFrame::SaveYourselfDone( SalFrame* pSaveFrame )
{
    // session save was done, inform dtwm
    if( s_pSaveYourselfFrame && pSaveFrame )
    {
        ByteString aExec( SessionManagerClient::getExecName(), osl_getThreadTextEncoding() );
        const char* argv[2];
        argv[0] = "/bin/sh";
        argv[1] = const_cast<char*>(aExec.GetBuffer());
#if OSL_DEBUG_LEVEL > 1
        fprintf( stderr, "SaveYourself request, setting command: %s %s\n", argv[0], argv[1] );
#endif
        XSetCommand( s_pSaveYourselfFrame->GetXDisplay(),
                     s_pSaveYourselfFrame->GetShellWindow(),
                     (char**)argv, 2 );
        if( pSaveFrame != s_pSaveYourselfFrame )
        {
            // check if it still exists
            const X11SalFrame* pFrame = NULL;
            const std::list< SalFrame* >& rFrames = static_cast<X11SalFrame*>(pSaveFrame)->GetDisplay()->getFrames();
            std::list< SalFrame* >::const_iterator it = rFrames.begin();
            while( it != rFrames.end() )
            {
                pFrame = static_cast< const X11SalFrame* >(*it);
                if( pFrame == pSaveFrame )
                    break;
                ++it; 
            }
            if( pFrame == pSaveFrame )
            {
                const WMAdaptor& rWMAdaptor( *pFrame->pDisplay_->getWMAdaptor() );
                XChangeProperty( pFrame->GetXDisplay(),
                                 pFrame->GetShellWindow(),
                                 rWMAdaptor.getAtom( WMAdaptor::WM_COMMAND ), XA_STRING, 8, PropModeReplace, (unsigned char*)"", 0 );
            }
        }
        s_pSaveYourselfFrame->ShutDown();
    }
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

extern "C"
{
Bool call_checkKeyReleaseForRepeat( Display* pDisplay, XEvent* pCheck, XPointer pX11SalFrame )
{
    return X11SalFrame::checkKeyReleaseForRepeat( pDisplay, pCheck, pX11SalFrame );
}
}

Bool X11SalFrame::checkKeyReleaseForRepeat( Display*, XEvent* pCheck, XPointer pX11SalFrame )
{
	X11SalFrame* pThis = (X11SalFrame*)pX11SalFrame;
	return
		pCheck->type			== XLIB_KeyPress &&
		pCheck->xkey.state		== pThis->nKeyState_ &&
		pCheck->xkey.keycode	== pThis->nKeyCode_ &&
		pCheck->xkey.time		== pThis->nReleaseTime_  ? True : False;
}

long X11SalFrame::Dispatch( XEvent *pEvent )
{
	long nRet = 0;

	if( -1 == nCaptured_ )
	{
		CaptureMouse( sal_True );
#ifdef DBG_UTIL
		if( -1 != nCaptured_ )
			pDisplay_->PrintEvent( "Captured", pEvent );
#endif
	}

	if( pEvent->xany.window == GetShellWindow() || pEvent->xany.window == GetWindow() )
	{
		switch( pEvent->type )
		{
			case XLIB_KeyPress:
				nKeyCode_	= pEvent->xkey.keycode;
				nKeyState_	= pEvent->xkey.state;
				nRet		= HandleKeyEvent( &pEvent->xkey );
				break;

			case KeyRelease:
				if( -1 == nCompose_ )
				{
					nReleaseTime_ = pEvent->xkey.time;
					XEvent aEvent;
					if( XCheckIfEvent( pEvent->xkey.display, &aEvent, call_checkKeyReleaseForRepeat, (XPointer)this ) )
						XPutBackEvent( pEvent->xkey.display, &aEvent );
					else
						nRet		= HandleKeyEvent( &pEvent->xkey );
				}
			break;

			case ButtonPress:
				// #74406# if we loose the focus in presentation mode
				// there are good chances that we never get it back
				// since the WM ignores us
 				if( IsOverrideRedirect() )
 				{
 					XSetInputFocus( GetXDisplay(), GetShellWindow(),
 							RevertToNone, CurrentTime );
 				}

			case ButtonRelease:
			case MotionNotify:
			case EnterNotify:
			case LeaveNotify:
				nRet = HandleMouseEvent( pEvent );
				break;

			case FocusIn:
			case FocusOut:
				nRet = HandleFocusEvent( &pEvent->xfocus );
				break;

			case Expose:
			case GraphicsExpose:
				nRet = HandleExposeEvent( pEvent );
				break;

			case MapNotify:
				if( pEvent->xmap.window == GetShellWindow() )
				{
                    if( nShowState_ == SHOWSTATE_HIDDEN )
                    {
                        /*
                         *  #95097# workaround for (at least) KWin 2.2.2
                         *  which will map windows that were once transient
                         *  even if they are withdrawn when the respective
                         *  document is mapped.
                         */
                        if( ! (nStyle_ & SAL_FRAME_STYLE_PLUG) )
                            XUnmapWindow( GetXDisplay(), GetShellWindow() );
                        break;
                    }
					bMapped_   = sal_True;
					bViewable_ = sal_True;
					nRet = sal_True;
					if ( mpInputContext != NULL )
						mpInputContext->Map( this );
                    CallCallback( SALEVENT_RESIZE, NULL );
                    if( pDisplay_->GetServerVendor() == vendor_hummingbird )
                    {
                        /*
                         *  With Exceed sometimes there does not seem to be
                         *  an Expose after the MapNotify.
                         *  so start a delayed paint here
                         */
                        maPaintRegion.Union( Rectangle( Point( 0, 0 ), Size( maGeometry.nWidth, maGeometry.nHeight ) ) );
                        XEvent aEvent;
                        aEvent.xexpose.type		= Expose;
                        aEvent.xexpose.display	= pDisplay_->GetDisplay();
                        aEvent.xexpose.x		= 0;
                        aEvent.xexpose.y		= 0;
                        aEvent.xexpose.width	= maGeometry.nWidth;
                        aEvent.xexpose.height	= maGeometry.nHeight;
                        aEvent.xexpose.count	= 0;
                        XSendEvent( pDisplay_->GetDisplay(),
                                    GetWindow(),
                                    True,
                                    ExposureMask,
                                    &aEvent );
                    }

                    bool bSetFocus = m_bSetFocusOnMap;
                    /*  #99570# another workaround for sawfish: if a transient window for the same parent is shown
                     *  sawfish does not set the focus to it. Applies only for click to focus mode.
                     */
                    if( ! (nStyle_ & SAL_FRAME_STYLE_FLOAT ) && mbInShow && GetDisplay()->getWMAdaptor()->getWindowManagerName().EqualsAscii( "Sawfish" ) )
                    {
                        // #101775# don't set the focus into the IME status window
                        // since this will lead to a parent loose-focus, close status,
                        // reget focus, open status, .... flicker loop
                        if ( (I18NStatus::get().getStatusFrame() != this) )
                            bSetFocus = true;
                    }

                    /*
                     *  sometimes a message box/dialogue is brought up when a frame is not mapped
                     *  the corresponding TRANSIENT_FOR hint is then set to the root window
                     *  so that the dialogue shows in all cases. Correct it here if the
                     *  frame is shown afterwards.
                     */
                    if( ! IsChildWindow()
                        && ! IsOverrideRedirect()
                        && ! IsFloatGrabWindow()
                        )
                    {
                        for( std::list< X11SalFrame* >::const_iterator it = maChildren.begin();
                             it != maChildren.end(); ++it )
                        {
                            if( (*it)->mbTransientForRoot )
                                pDisplay_->getWMAdaptor()->changeReferenceFrame( *it, this );
                        }
                    }

                    if( hPresentationWindow != None && GetShellWindow() == hPresentationWindow )
                        XSetInputFocus( GetXDisplay(), GetShellWindow(), RevertToParent, CurrentTime );
                    /*  For unknown reasons Dtwm does respect the input_hint
                     *  set to False, but not when mapping the window. So
                     *  emulate the correct behaviour and set the focus back
                     *  to where it most probably should have been.
                     */
                    if( (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION) &&
                        mpParent &&
                        GetDisplay()->getWMAdaptor()->getWindowManagerName().EqualsAscii( "Dtwm" )
                        )
                    {
                        XSetInputFocus( GetXDisplay(),
                                        mpParent->GetShellWindow(),
                                        RevertToParent,
                                        CurrentTime );
                        bSetFocus = false;
                    }
                    
                    if( bSetFocus )
                    {
                        XSetInputFocus( GetXDisplay(),
                                        GetShellWindow(),
                                        RevertToParent,
                                        CurrentTime );
                    }
                    

                    RestackChildren();
                    mbInShow = sal_False;
                    m_bSetFocusOnMap = false;
				}
				break;

			case UnmapNotify:
				if( pEvent->xunmap.window == GetShellWindow() )
				{
					bMapped_   = sal_False;
					bViewable_ = sal_False;
					nRet = sal_True;
					if ( mpInputContext != NULL )
						mpInputContext->Unmap( this );
					CallCallback( SALEVENT_RESIZE, NULL );
				}
				break;

			case ConfigureNotify:
				if( pEvent->xconfigure.window == GetShellWindow()
                    || pEvent->xconfigure.window == GetWindow() )
					nRet = HandleSizeEvent( &pEvent->xconfigure );
				break;

			case VisibilityNotify:
				nVisibility_ = pEvent->xvisibility.state;
				nRet = sal_True;
                if( bAlwaysOnTop_
                    && bMapped_
                    && ! GetDisplay()->getWMAdaptor()->isAlwaysOnTopOK()
                    && nVisibility_ != VisibilityUnobscured )
                    maAlwaysOnTopRaiseTimer.Start();
            break;

			case ReparentNotify:
				nRet = HandleReparentEvent( &pEvent->xreparent );
				break;

			case MappingNotify:
				if( MappingPointer != pEvent->xmapping.request )
					nRet = CallCallback( SALEVENT_KEYBOARDCHANGED, 0 );
				break;

			case ColormapNotify:
				nRet = HandleColormapEvent( &pEvent->xcolormap );
				break;

			case PropertyNotify:
			{
				if( pEvent->xproperty.atom == pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_STATE ) )
					nRet = HandleStateEvent( &pEvent->xproperty );
				else
					nRet = pDisplay_->getWMAdaptor()->handlePropertyNotify( this, &pEvent->xproperty );
				break;
			}

			case ClientMessage:
				nRet = HandleClientMessage( &pEvent->xclient );
				break;
		}
	}
	else
	{
		switch( pEvent->type )
		{
 			case FocusIn:
 			case FocusOut:
                if( ( nStyle_ & SAL_FRAME_STYLE_PLUG )
                    && ( pEvent->xfocus.window == GetShellWindow()
                         || pEvent->xfocus.window == GetForeignParent() )
                    )
                {
                    nRet = HandleFocusEvent( &pEvent->xfocus );
                }
 				break;

			case ConfigureNotify:
				if( pEvent->xconfigure.window == GetForeignParent() ||
					pEvent->xconfigure.window == GetShellWindow() )
					nRet = HandleSizeEvent( &pEvent->xconfigure );

				if( pEvent->xconfigure.window == GetStackingWindow() )
                    nRet = HandleSizeEvent( &pEvent->xconfigure );

				RestackChildren();
				break;
		}
	}

	return nRet;
}

void X11SalFrame::ResetClipRegion()
{
    delete [] m_pClipRectangles;
    m_pClipRectangles = NULL;
    m_nCurClipRect = m_nMaxClipRect = 0;
    
	const int	dest_kind	= ShapeBounding;
	const int	op			= ShapeSet;
	const int	ordering	= YSorted;

	XWindowAttributes win_attrib;
	XRectangle		  win_size;

	XLIB_Window aShapeWindow = mhShellWindow;

	XGetWindowAttributes ( GetDisplay()->GetDisplay(),
						   aShapeWindow,
						   &win_attrib );

	win_size.x		= 0;
	win_size.y		= 0;
	win_size.width	= win_attrib.width;
	win_size.height = win_attrib.height;

	XShapeCombineRectangles ( GetDisplay()->GetDisplay(),
							  aShapeWindow,
							  dest_kind,
							  0, 0, 			// x_off, y_off
							  &win_size,		// list of rectangles
							  1,				// number of rectangles
							  op, ordering );
}

void X11SalFrame::BeginSetClipRegion( sal_uLong nRects )
{
    if( m_pClipRectangles )
        delete [] m_pClipRectangles;
    if( nRects )
        m_pClipRectangles = new XRectangle[nRects];
    else
        m_pClipRectangles = NULL;
    m_nMaxClipRect = static_cast<int>(nRects);
    m_nCurClipRect = 0;
}

void X11SalFrame::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
{
    if( m_pClipRectangles && m_nCurClipRect < m_nMaxClipRect )
    {
        m_pClipRectangles[m_nCurClipRect].x      = nX;
        m_pClipRectangles[m_nCurClipRect].y      = nY;
        m_pClipRectangles[m_nCurClipRect].width  = nWidth;
        m_pClipRectangles[m_nCurClipRect].height = nHeight;
        m_nCurClipRect++;
    }
}

void X11SalFrame::EndSetClipRegion()
{
	const int	dest_kind	= ShapeBounding;
	const int	ordering	= YSorted;
	const int	op = ShapeSet;

	XLIB_Window aShapeWindow = mhShellWindow;
	XShapeCombineRectangles ( GetDisplay()->GetDisplay(),
							  aShapeWindow,
							  dest_kind,
							  0, 0, // x_off, y_off
							  m_pClipRectangles,
							  m_nCurClipRect,
							  op, ordering );

}

