summaryrefslogtreecommitdiff
path: root/vcl/source/window/window2.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source/window/window2.cxx')
-rw-r--r--vcl/source/window/window2.cxx1384
1 files changed, 1384 insertions, 0 deletions
diff --git a/vcl/source/window/window2.cxx b/vcl/source/window/window2.cxx
new file mode 100644
index 000000000000..6fc297a1cfa0
--- /dev/null
+++ b/vcl/source/window/window2.cxx
@@ -0,0 +1,1384 @@
+/*************************************************************************
+ *
+ * $RCSfile: window2.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:40 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (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.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define _SV_WINDOW_CXX
+
+#include <limits.h>
+#ifndef _SV_SVSYS_HXX
+#include <svsys.h>
+#endif
+#ifndef REMOTE_APPSERVER
+#ifndef _SV_SALGDI_HXX
+#include <salgdi.hxx>
+#endif
+#ifndef _SV_SALFRAME_HXX
+#include <salframe.hxx>
+#endif
+#else
+#include <rmoutdev.hxx>
+#endif
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+#ifndef _SV_SVDATA_HXX
+#include <svdata.hxx>
+#endif
+#ifndef _SV_BITMAP_HXX
+#include <bitmap.hxx>
+#endif
+#ifndef _SV_EVENT_HXX
+#include <event.hxx>
+#endif
+#ifndef _SV_TIMER_HXX
+#include <timer.hxx>
+#endif
+#ifndef _SV_METRIC_HXX
+#include <metric.hxx>
+#endif
+#ifndef _SV_OUTFONT_HXX
+#include <outfont.hxx>
+#endif
+#ifndef _SV_OUTDEV_H
+#include <outdev.h>
+#endif
+#ifndef _SV_ACCESS_HXX
+#include <access.hxx>
+#endif
+#ifndef _SV_POLY_H
+#include <poly.h>
+#endif
+#ifndef _SV_POLY_HXX
+#include <poly.hxx>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <virdev.hxx>
+#endif
+#ifndef _SV_WINDOW_H
+#include <window.h>
+#endif
+#ifndef _SV_WINDOW_HXX
+#include <window.hxx>
+#endif
+#ifndef _SV_SCRBAR_HXX
+#include <scrbar.hxx>
+#endif
+#ifndef _SV_SCRWND_HXX
+#include <scrwnd.hxx>
+#endif
+
+#pragma hdrstop
+
+// =======================================================================
+
+DBG_NAMEEX( Window );
+
+// =======================================================================
+
+#define IMPL_MAXSAVEBACKSIZE (640*480)
+#define IMPL_MAXALLSAVEBACKSIZE (800*600*2)
+
+// =======================================================================
+
+struct ImplFocusDelData : public ImplDelData
+{
+ Window* mpFocusWin;
+};
+
+// =======================================================================
+
+BOOL Window::ImplIsWindowInFront( const Window* pTestWindow ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+ DBG_CHKOBJ( pTestWindow, Window, ImplDbgCheckWindow );
+
+ // Testen, ob es Fenster untereinander liegen
+ pTestWindow = pTestWindow->ImplGetFirstOverlapWindow();
+ const Window* pTempWindow = pTestWindow;
+ const Window* pThisWindow = ImplGetFirstOverlapWindow();
+ if ( pTempWindow == pThisWindow )
+ return FALSE;
+ do
+ {
+ if ( pTempWindow == pThisWindow )
+ return TRUE;
+ if ( pTempWindow->mbFrame )
+ break;
+ pTempWindow = pTempWindow->mpOverlapWindow;
+ }
+ while ( pTempWindow );
+ pTempWindow = pThisWindow;
+ do
+ {
+ if ( pTempWindow == pTestWindow )
+ return FALSE;
+ if ( pTempWindow->mbFrame )
+ break;
+ pTempWindow = pTempWindow->mpOverlapWindow;
+ }
+ while ( pTempWindow );
+
+ // Fenster auf gleiche Ebene bringen
+ if ( pThisWindow->mpOverlapWindow != pTestWindow->mpOverlapWindow )
+ {
+ USHORT nThisLevel = 0;
+ USHORT nTestLevel = 0;
+ pTempWindow = pThisWindow;
+ do
+ {
+ nThisLevel++;
+ pTempWindow = pTempWindow->mpOverlapWindow;
+ }
+ while ( !pTempWindow->mbFrame );
+ pTempWindow = pTestWindow;
+ do
+ {
+ nTestLevel++;
+ pTempWindow = pTempWindow->mpOverlapWindow;
+ }
+ while ( !pTempWindow->mbFrame );
+
+ if ( nThisLevel < nTestLevel )
+ {
+ do
+ {
+ if ( pTestWindow->mpOverlapWindow == pThisWindow->mpOverlapWindow )
+ break;
+ if ( pTestWindow->mbFrame )
+ break;
+ pTestWindow = pTestWindow->mpOverlapWindow;
+ }
+ while ( pTestWindow );
+ }
+ else
+ {
+ do
+ {
+ if ( pThisWindow->mpOverlapWindow == pTempWindow->mpOverlapWindow )
+ break;
+ if ( pThisWindow->mbFrame )
+ break;
+ pThisWindow = pThisWindow->mpOverlapWindow;
+ }
+ while ( pThisWindow );
+ }
+ }
+
+ // Wenn TestWindow vor ThisWindow kommt, liegt es vorne
+ pTempWindow = pTestWindow;
+ do
+ {
+ if ( pTempWindow == pThisWindow )
+ return TRUE;
+ pTempWindow = pTempWindow->mpNext;
+ }
+ while ( pTempWindow );
+
+ return FALSE;
+}
+
+// =======================================================================
+
+void Window::ImplSaveOverlapBackground()
+{
+ DBG_ASSERT( !mpOverlapData->mpSaveBackDev, "Window::ImplSaveOverlapBackground() - Background already saved" );
+
+ if ( !mbFrame )
+ {
+ ULONG nSaveBackSize = mnOutWidth*mnOutHeight;
+ if ( nSaveBackSize <= IMPL_MAXSAVEBACKSIZE )
+ {
+ if ( nSaveBackSize+mpFrameData->mnAllSaveBackSize <= IMPL_MAXALLSAVEBACKSIZE )
+ {
+ Size aOutSize( mnOutWidth, mnOutHeight );
+ mpOverlapData->mpSaveBackDev = new VirtualDevice( *mpFrameWindow );
+ if ( mpOverlapData->mpSaveBackDev->SetOutputSizePixel( aOutSize ) )
+ {
+ mpFrameWindow->ImplUpdateAll();
+
+ if ( mbInitWinClipRegion )
+ ImplInitWinClipRegion();
+
+ mpOverlapData->mnSaveBackSize = nSaveBackSize;
+ mpFrameData->mnAllSaveBackSize += nSaveBackSize;
+ Point aDevPt;
+ mpFrameWindow->ImplGetFrameDev( Point( mnOutOffX, mnOutOffY ),
+ aDevPt, aOutSize,
+ *(mpOverlapData->mpSaveBackDev) );
+ mpOverlapData->mpNextBackWin = mpFrameData->mpFirstBackWin;
+ mpFrameData->mpFirstBackWin = this;
+ }
+ else
+ {
+ delete mpOverlapData->mpSaveBackDev;
+ mpOverlapData->mpSaveBackDev = NULL;
+ }
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::ImplRestoreOverlapBackground( Region& rInvRegion )
+{
+ if ( mpOverlapData->mpSaveBackDev )
+ {
+ if ( mbInitWinClipRegion )
+ ImplInitWinClipRegion();
+
+ if ( mpOverlapData->mpSaveBackDev )
+ {
+ Point aDevPt;
+ Point aDestPt( mnOutOffX, mnOutOffY );
+ Size aDevSize = mpOverlapData->mpSaveBackDev->GetOutputSizePixel();
+ if ( mpOverlapData->mpSaveBackRgn )
+ {
+ mpOverlapData->mpSaveBackRgn->Intersect( maWinClipRegion );
+ rInvRegion = maWinClipRegion;
+ rInvRegion.Exclude( *mpOverlapData->mpSaveBackRgn );
+ mpFrameWindow->ImplDrawFrameDev( aDestPt, aDevPt, aDevSize,
+ *(mpOverlapData->mpSaveBackDev),
+ *mpOverlapData->mpSaveBackRgn );
+ }
+ else
+ {
+ mpFrameWindow->ImplDrawFrameDev( aDestPt, aDevPt, aDevSize,
+ *(mpOverlapData->mpSaveBackDev),
+ maWinClipRegion );
+ }
+ ImplDeleteOverlapBackground();
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplDeleteOverlapBackground()
+{
+ if ( mpOverlapData->mpSaveBackDev )
+ {
+ mpFrameData->mnAllSaveBackSize -= mpOverlapData->mnSaveBackSize;
+ delete mpOverlapData->mpSaveBackDev;
+ mpOverlapData->mpSaveBackDev = NULL;
+ if ( mpOverlapData->mpSaveBackRgn )
+ {
+ delete mpOverlapData->mpSaveBackRgn;
+ mpOverlapData->mpSaveBackRgn = NULL;
+ }
+
+ // Fenster aus der Liste entfernen
+ if ( mpFrameData->mpFirstBackWin == this )
+ mpFrameData->mpFirstBackWin = mpOverlapData->mpNextBackWin;
+ else
+ {
+ Window* pTemp = mpFrameData->mpFirstBackWin;
+ while ( pTemp->mpOverlapData->mpNextBackWin != this )
+ pTemp = pTemp->mpOverlapData->mpNextBackWin;
+ pTemp->mpOverlapData->mpNextBackWin = mpOverlapData->mpNextBackWin;
+ }
+ mpOverlapData->mpNextBackWin = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplInvalidateAllOverlapBackgrounds()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Window* pWindow = mpFrameData->mpFirstBackWin;
+ while ( pWindow )
+ {
+ // Naechstes Fenster schon hier merken, da dieses Fenster in
+ // der if-Abfrage aus der Liste entfernt werden kann
+ Window* pNext = pWindow->mpOverlapData->mpNextBackWin;
+
+ if ( ImplIsWindowInFront( pWindow ) )
+ {
+ Rectangle aRect1( Point( mnOutOffX, mnOutOffY ),
+ Size( mnOutWidth, mnOutHeight ) );
+ Rectangle aRect2( Point( pWindow->mnOutOffX, pWindow->mnOutOffY ),
+ Size( pWindow->mnOutWidth, pWindow->mnOutHeight ) );
+ aRect1.Intersection( aRect2 );
+ if ( !aRect1.IsEmpty() )
+ {
+ if ( !pWindow->mpOverlapData->mpSaveBackRgn )
+ pWindow->mpOverlapData->mpSaveBackRgn = new Region( aRect2 );
+ pWindow->mpOverlapData->mpSaveBackRgn->Exclude( aRect1 );
+ if ( pWindow->mpOverlapData->mpSaveBackRgn->IsEmpty() )
+ pWindow->ImplDeleteOverlapBackground();
+ }
+
+ }
+
+ pWindow = pNext;
+ }
+}
+
+// =======================================================================
+
+Bitmap Window::SnapShot() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Bitmap aBmp;
+
+ if ( mpBorderWindow )
+ aBmp = mpBorderWindow->SnapShot();
+ else if ( IsReallyVisible() )
+ mpFrameWindow->ImplGetFrameBitmap( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ), aBmp );
+
+ return aBmp;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ShowFocus( const Rectangle& rRect )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplWinData* pWinData = ImplGetWinData();
+
+ if ( !mbInPaint )
+ {
+ if ( mbFocusVisible )
+ {
+ if ( *(pWinData->mpFocusRect) == rRect )
+ return;
+
+ ImplInvertFocus( *(pWinData->mpFocusRect) );
+ }
+
+ ImplInvertFocus( rRect );
+ }
+
+ if ( !pWinData->mpFocusRect )
+ pWinData->mpFocusRect = new Rectangle( rRect );
+ else
+ *(pWinData->mpFocusRect) = rRect;
+ mbFocusVisible = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::HideFocus()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( !mbFocusVisible )
+ return;
+
+ if ( !mbInPaint )
+ ImplInvertFocus( *(ImplGetWinData()->mpFocusRect) );
+ mbFocusVisible = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Invert( const Rectangle& rRect, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
+
+ if ( aRect.IsEmpty() )
+ return;
+ aRect.Justify();
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if ( mbOutputClipped )
+ return;
+
+ SalInvert nSalFlags = 0;
+ if ( nFlags & INVERT_HIGHLIGHT )
+ nSalFlags |= SAL_INVERT_HIGHLIGHT;
+ if ( nFlags & INVERT_50 )
+ nSalFlags |= SAL_INVERT_50;
+ mpGraphics->Invert( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), nSalFlags );
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ pGraphics->Invert( aRect, nFlags );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void Window::Invert( const Polygon& rPoly, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ USHORT nPoints = rPoly.GetSize();
+
+ if ( nPoints < 2 )
+ return;
+
+ Polygon aPoly( ImplLogicToDevicePixel( rPoly ) );
+
+#ifndef REMOTE_APPSERVER
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if ( mbOutputClipped )
+ return;
+
+ SalInvert nSalFlags = 0;
+ if ( nFlags & INVERT_HIGHLIGHT )
+ nSalFlags |= SAL_INVERT_HIGHLIGHT;
+ if ( nFlags & INVERT_50 )
+ nSalFlags |= SAL_INVERT_50;
+ const SalPoint* pPtAry = (const SalPoint*)aPoly.ImplGetConstPointAry();
+ mpGraphics->Invert( nPoints, pPtAry, nSalFlags );
+#else
+ ImplServerGraphics* pGraphics = ImplGetServerGraphics();
+ if ( pGraphics )
+ pGraphics->Invert( aPoly, nFlags );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ShowTracking( const Rectangle& rRect, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplWinData* pWinData = ImplGetWinData();
+
+ if ( !mbInPaint || !(nFlags & SHOWTRACK_WINDOW) )
+ {
+ if ( mbTrackVisible )
+ {
+ if ( (*(pWinData->mpTrackRect) == rRect) &&
+ (pWinData->mnTrackFlags == nFlags) )
+ return;
+
+ InvertTracking( *(pWinData->mpTrackRect), pWinData->mnTrackFlags );
+ }
+
+ InvertTracking( rRect, nFlags );
+ }
+
+ if ( !pWinData->mpTrackRect )
+ pWinData->mpTrackRect = new Rectangle( rRect );
+ else
+ *(pWinData->mpTrackRect) = rRect;
+ pWinData->mnTrackFlags = nFlags;
+ mbTrackVisible = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::HideTracking()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mbTrackVisible )
+ {
+ ImplWinData* pWinData = ImplGetWinData();
+ if ( !mbInPaint || !(pWinData->mnTrackFlags & SHOWTRACK_WINDOW) )
+ InvertTracking( *(pWinData->mpTrackRect), pWinData->mnTrackFlags );
+ mbTrackVisible = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::InvertTracking( const Rectangle& rRect, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
+
+ if ( aRect.IsEmpty() )
+ return;
+ aRect.Justify();
+
+#ifndef REMOTE_APPSERVER
+ SalGraphics* pGraphics;
+
+ if ( nFlags & SHOWTRACK_WINDOW )
+ {
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if ( mbOutputClipped )
+ return;
+
+ pGraphics = mpGraphics;
+ }
+ else
+ {
+ pGraphics = ImplGetFrameGraphics();
+
+ if ( nFlags & SHOWTRACK_CLIP )
+ {
+ Point aPoint( mnOutOffX, mnOutOffY );
+ Region aRegion( Rectangle( aPoint,
+ Size( mnOutWidth, mnOutHeight ) ) );
+ ImplClipBoundaries( aRegion, FALSE, FALSE );
+ ImplSelectClipRegion( pGraphics, aRegion );
+ }
+ }
+
+ USHORT nStyle = nFlags & SHOWTRACK_STYLE;
+ if ( nStyle == SHOWTRACK_OBJECT )
+ pGraphics->Invert( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), SAL_INVERT_TRACKFRAME );
+ else if ( nStyle == SHOWTRACK_SPLIT )
+ pGraphics->Invert( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), SAL_INVERT_50 );
+ else
+ {
+ long nBorder = 1;
+ if ( nStyle == SHOWTRACK_BIG )
+ nBorder = 3;
+ pGraphics->Invert( aRect.Left(), aRect.Top(), aRect.GetWidth(), nBorder, SAL_INVERT_50 );
+ pGraphics->Invert( aRect.Left(), aRect.Bottom()-nBorder+1, aRect.GetWidth(), nBorder, SAL_INVERT_50 );
+ pGraphics->Invert( aRect.Left(), aRect.Top()+nBorder, nBorder, aRect.GetHeight()-(nBorder*2), SAL_INVERT_50 );
+ pGraphics->Invert( aRect.Right()-nBorder+1, aRect.Top()+nBorder, nBorder, aRect.GetHeight()-(nBorder*2), SAL_INVERT_50 );
+ }
+#else
+ ImplServerGraphics* pGraphics;
+ if ( nFlags & SHOWTRACK_WINDOW )
+ {
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ pGraphics = ImplGetServerGraphics();
+ }
+ else
+ {
+ pGraphics = ImplGetServerGraphics( TRUE );
+
+ if ( nFlags & SHOWTRACK_CLIP )
+ {
+ Point aTmpPoint( mnOutOffX, mnOutOffY );
+ Size aTmpSize( mnOutWidth, mnOutHeight );
+ Rectangle aTmpRect( aTmpPoint, aTmpSize );
+ Region aRegion( aTmpRect );
+ ImplClipBoundaries( aRegion, FALSE, FALSE );
+ pGraphics->SetClipRegion( aRegion );
+ }
+ }
+
+ if ( pGraphics )
+ pGraphics->InvertTracking( aRect, nFlags );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+void Window::InvertTracking( const Polygon& rPoly, USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ USHORT nPoints = rPoly.GetSize();
+
+ if ( nPoints < 2 )
+ return;
+
+ Polygon aPoly( ImplLogicToDevicePixel( rPoly ) );
+
+#ifndef REMOTE_APPSERVER
+ SalGraphics* pGraphics;
+
+ if ( nFlags & SHOWTRACK_WINDOW )
+ {
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ // we need a graphics
+ if ( !mpGraphics )
+ {
+ if ( !ImplGetGraphics() )
+ return;
+ }
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if ( mbOutputClipped )
+ return;
+
+ pGraphics = mpGraphics;
+ }
+ else
+ {
+ pGraphics = ImplGetFrameGraphics();
+
+ if ( nFlags & SHOWTRACK_CLIP )
+ {
+ Point aPoint( mnOutOffX, mnOutOffY );
+ Region aRegion( Rectangle( aPoint,
+ Size( mnOutWidth, mnOutHeight ) ) );
+ ImplClipBoundaries( aRegion, FALSE, FALSE );
+ ImplSelectClipRegion( pGraphics, aRegion );
+ }
+ }
+
+ const SalPoint* pPtAry = (const SalPoint*)aPoly.ImplGetConstPointAry();
+ pGraphics->Invert( nPoints, pPtAry, SAL_INVERT_TRACKFRAME );
+#else
+ ImplServerGraphics* pGraphics;
+ if ( nFlags & SHOWTRACK_WINDOW )
+ {
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ pGraphics = ImplGetServerGraphics();
+ }
+ else
+ {
+ pGraphics = ImplGetServerGraphics( TRUE );
+
+ if ( nFlags & SHOWTRACK_CLIP )
+ {
+ Point aTmpPoint( mnOutOffX, mnOutOffY );
+ Size aTmpSize( mnOutWidth, mnOutHeight );
+ Rectangle aTmpRect( aTmpPoint, aTmpSize );
+ Region aRegion( aTmpRect );
+ ImplClipBoundaries( aRegion, FALSE, FALSE );
+ pGraphics->SetClipRegion( aRegion );
+ }
+ }
+
+ if ( pGraphics )
+ pGraphics->InvertTracking( aPoly, nFlags );
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( Window, ImplTrackTimerHdl, Timer*, pTimer )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Bei Button-Repeat muessen wir den Timeout umsetzen
+ if ( pSVData->maWinData.mnTrackFlags & STARTTRACK_BUTTONREPEAT )
+ pTimer->SetTimeout( GetSettings().GetMouseSettings().GetButtonRepeat() );
+
+ // Tracking-Event erzeugen
+ Point aMousePos( mpFrameData->mnLastMouseX, mpFrameData->mnLastMouseY );
+ MouseEvent aMEvt( ImplFrameToOutput( aMousePos ),
+ mpFrameData->mnClickCount, 0,
+ mpFrameData->mnMouseCode, mpFrameData->mnMouseCode );
+ TrackingEvent aTEvt( aMEvt, TRACKING_REPEAT );
+ Tracking( aTEvt );
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::StartTracking( USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( pSVData->maWinData.mpTrackWin != this )
+ {
+ if ( pSVData->maWinData.mpTrackWin )
+ pSVData->maWinData.mpTrackWin->EndTracking( ENDTRACK_CANCEL );
+ }
+
+ if ( nFlags & (STARTTRACK_SCROLLREPEAT | STARTTRACK_BUTTONREPEAT) )
+ {
+ pSVData->maWinData.mpTrackTimer = new AutoTimer;
+
+ if ( nFlags & STARTTRACK_SCROLLREPEAT )
+ pSVData->maWinData.mpTrackTimer->SetTimeout( GetSettings().GetMouseSettings().GetScrollRepeat() );
+ else
+ pSVData->maWinData.mpTrackTimer->SetTimeout( GetSettings().GetMouseSettings().GetButtonStartRepeat() );
+ pSVData->maWinData.mpTrackTimer->SetTimeoutHdl( LINK( this, Window, ImplTrackTimerHdl ) );
+ pSVData->maWinData.mpTrackTimer->Start();
+ }
+
+ pSVData->maWinData.mpTrackWin = this;
+ pSVData->maWinData.mnTrackFlags = nFlags;
+ CaptureMouse();
+}
+
+// -----------------------------------------------------------------------
+
+void Window::EndTracking( USHORT nFlags )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( pSVData->maWinData.mpTrackWin == this )
+ {
+ // Hier wegen DbgChkThis geklammert, da Window im Handler zerstoert
+ // werden kann
+ {
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( pSVData->maWinData.mpTrackTimer )
+ {
+ delete pSVData->maWinData.mpTrackTimer;
+ pSVData->maWinData.mpTrackTimer = NULL;
+ }
+
+ pSVData->maWinData.mpTrackWin = NULL;
+ pSVData->maWinData.mnTrackFlags = 0;
+ ReleaseMouse();
+ }
+
+ // EndTracking rufen, wenn es gerufen werden soll
+ if ( !(nFlags & ENDTRACK_DONTCALLHDL) )
+ {
+ Point aMousePos( mpFrameData->mnLastMouseX, mpFrameData->mnLastMouseY );
+ MouseEvent aMEvt( ImplFrameToOutput( aMousePos ),
+ mpFrameData->mnClickCount, 0,
+ mpFrameData->mnMouseCode, mpFrameData->mnMouseCode );
+ TrackingEvent aTEvt( aMEvt, nFlags | ENDTRACK_END );
+ Tracking( aTEvt );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::IsTracking() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ return (ImplGetSVData()->maWinData.mpTrackWin == this);
+}
+
+// -----------------------------------------------------------------------
+
+void Window::StartAutoScroll( USHORT nFlags )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( pSVData->maWinData.mpAutoScrollWin != this )
+ {
+ if ( pSVData->maWinData.mpAutoScrollWin )
+ pSVData->maWinData.mpAutoScrollWin->EndAutoScroll();
+ }
+
+ pSVData->maWinData.mpAutoScrollWin = this;
+ pSVData->maWinData.mnAutoScrollFlags = nFlags;
+ pSVData->maAppData.mpWheelWindow = new ImplWheelWindow( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::EndAutoScroll()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( pSVData->maWinData.mpAutoScrollWin == this )
+ {
+ pSVData->maWinData.mpAutoScrollWin = NULL;
+ pSVData->maWinData.mnAutoScrollFlags = 0;
+ delete pSVData->maAppData.mpWheelWindow;
+ pSVData->maAppData.mpWheelWindow = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::IsAutoScroll() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ return (ImplGetSVData()->maWinData.mpAutoScrollWin == this);
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SaveBackground( const Point& rPos, const Size& rSize,
+ const Point& rDestOff, VirtualDevice& rSaveDevice )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpPaintRegion )
+ {
+ Region aClip( *mpPaintRegion );
+ const Point aPixPos( LogicToPixel( rPos ) );
+
+ aClip.Move( -mnOutOffX, -mnOutOffY );
+ aClip.Intersect( Rectangle( aPixPos, LogicToPixel( rSize ) ) );
+
+ if ( !aClip.IsEmpty() )
+ {
+ const Region aOldClip( rSaveDevice.GetClipRegion() );
+ const Point aPixOffset( rSaveDevice.LogicToPixel( rDestOff ) );
+ const Point aPixTopLeft( aClip.GetBoundRect().TopLeft() );
+ const BOOL bMap = rSaveDevice.IsMapModeEnabled();
+
+ // move clip region to have the same distance to DestOffset
+ aClip.Move( aPixOffset.X() - aPixPos.X(), aPixOffset.Y() - aPixPos.Y() );
+
+ // set pixel clip region
+ rSaveDevice.EnableMapMode( FALSE );
+ rSaveDevice.SetClipRegion( aClip );
+ rSaveDevice.EnableMapMode( bMap );
+ rSaveDevice.DrawOutDev( rDestOff, rSize, rPos, rSize, *this );
+ rSaveDevice.SetClipRegion( aOldClip );
+ }
+ }
+ else
+ rSaveDevice.DrawOutDev( rDestOff, rSize, rPos, rSize, *this );
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Window::SaveFocus()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( pSVData->maWinData.mpFocusWin )
+ {
+ ImplFocusDelData* pDelData = new ImplFocusDelData;
+ pSVData->maWinData.mpFocusWin->ImplAddDel( pDelData );
+ pDelData->mpFocusWin = pSVData->maWinData.mpFocusWin;
+ return (ULONG)(void*)pDelData;
+ }
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::EndSaveFocus( ULONG nSaveId, BOOL bRestore )
+{
+ if ( !nSaveId )
+ return FALSE;
+ else
+ {
+ BOOL bOK = TRUE;
+ ImplFocusDelData* pDelData = (ImplFocusDelData*)(void*)nSaveId;
+ if ( !pDelData->IsDelete() )
+ {
+ pDelData->mpFocusWin->ImplRemoveDel( pDelData );
+ if ( bRestore )
+ pDelData->mpFocusWin->GrabFocus();
+ }
+ else
+ bOK = !bRestore;
+ delete pDelData;
+ return bOK;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetZoom( const Fraction& rZoom )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( maZoom != rZoom )
+ {
+ maZoom = rZoom;
+ StateChanged( STATE_CHANGE_ZOOM );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+inline long WinFloatRound( double fVal )
+{
+ return( fVal > 0.0 ? (long) ( fVal + 0.5 ) : -(long) ( -fVal + 0.5 ) );
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetZoomedPointFont( const Font& rFont )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ const Fraction& rZoom = GetZoom();
+ if ( rZoom.GetNumerator() != rZoom.GetDenominator() )
+ {
+ Font aFont( rFont );
+ Size aSize = aFont.GetSize();
+ double n = (double)aSize.Width();
+ n *= (double)rZoom.GetNumerator();
+ n /= (double)rZoom.GetDenominator();
+ aSize.Width() = WinFloatRound( n );
+ n = (double)aSize.Height();
+ n *= (double)rZoom.GetNumerator();
+ n /= (double)rZoom.GetDenominator();
+ aSize.Height() = WinFloatRound( n );
+ aFont.SetSize( aSize );
+ SetPointFont( aFont );
+
+ // Wenn Darstellung skaliert wird, nehmen wir gegebenenfalls
+ // einen anderen Font, wenn der aktuelle nicht skalierbar ist
+ FontMetric aMetric = GetFontMetric();
+ long nFontDiff = Abs( GetFont().GetSize().Height()-aMetric.GetSize().Height() );
+ if ( (aMetric.GetType() == TYPE_RASTER) && (nFontDiff >= 2) )
+ {
+ ImplDevFontListData* pStdFont = NULL;
+ USHORT nStdFont = 0xFFFF;
+ if ( aMetric.GetPitch() == PITCH_FIXED )
+ nStdFont = PITCH_FIXED;
+ else if ( aMetric.GetFamily() == FAMILY_SWISS )
+ nStdFont = IMPL_STDFONT_SWISS;
+ else if ( aMetric.GetFamily() == FAMILY_ROMAN )
+ nStdFont = IMPL_STDFONT_ROMAN;
+ if ( nStdFont != 0xFFFF )
+ {
+ if ( mpFontList )
+ pStdFont = mpFontList->GetStandardFont( nStdFont );
+ if ( pStdFont && (aFont.GetName() != pStdFont->maName) )
+ {
+ aFont.SetName( pStdFont->maName );
+ SetPointFont( aFont );
+ }
+ }
+ }
+ }
+ else
+ SetPointFont( rFont );
+}
+
+// -----------------------------------------------------------------------
+
+long Window::CalcZoom( long nCalc ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ const Fraction& rZoom = GetZoom();
+ if ( rZoom.GetNumerator() != rZoom.GetDenominator() )
+ {
+ double n = (double)nCalc;
+ n *= (double)rZoom.GetNumerator();
+ n /= (double)rZoom.GetDenominator();
+ nCalc = WinFloatRound( n );
+ }
+ return nCalc;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetControlFont()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpControlFont )
+ {
+ delete mpControlFont;
+ mpControlFont = NULL;
+ StateChanged( STATE_CHANGE_CONTROLFONT );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetControlFont( const Font& rFont )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( rFont == Font() )
+ {
+ SetControlFont();
+ return;
+ }
+
+ if ( mpControlFont )
+ {
+ if ( *mpControlFont == rFont )
+ return;
+ *mpControlFont = rFont;
+ }
+ else
+ mpControlFont = new Font( rFont );
+
+ StateChanged( STATE_CHANGE_CONTROLFONT );
+}
+
+// -----------------------------------------------------------------------
+
+Font Window::GetControlFont() const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mpControlFont )
+ return *mpControlFont;
+ else
+ {
+ Font aFont;
+ return aFont;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetControlForeground()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mbControlForeground )
+ {
+ maControlForeground = Color( COL_TRANSPARENT );
+ mbControlForeground = FALSE;
+ StateChanged( STATE_CHANGE_CONTROLFOREGROUND );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetControlForeground( const Color& rColor )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( rColor.GetTransparency() )
+ {
+ if ( mbControlForeground )
+ {
+ maControlForeground = Color( COL_TRANSPARENT );
+ mbControlForeground = FALSE;
+ StateChanged( STATE_CHANGE_CONTROLFOREGROUND );
+ }
+ }
+ else
+ {
+ if ( maControlForeground != rColor )
+ {
+ maControlForeground = rColor;
+ mbControlForeground = TRUE;
+ StateChanged( STATE_CHANGE_CONTROLFOREGROUND );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetControlBackground()
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( mbControlBackground )
+ {
+ maControlBackground = Color( COL_TRANSPARENT );
+ mbControlBackground = FALSE;
+ StateChanged( STATE_CHANGE_CONTROLBACKGROUND );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::SetControlBackground( const Color& rColor )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ if ( rColor.GetTransparency() )
+ {
+ if ( mbControlBackground )
+ {
+ maControlBackground = Color( COL_TRANSPARENT );
+ mbControlBackground = FALSE;
+ StateChanged( STATE_CHANGE_CONTROLBACKGROUND );
+ }
+ }
+ else
+ {
+ if ( maControlBackground != rColor )
+ {
+ maControlBackground = rColor;
+ mbControlBackground = TRUE;
+ StateChanged( STATE_CHANGE_CONTROLBACKGROUND );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Size Window::CalcWindowSize( const Size& rOutSz ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Size aSz = rOutSz;
+ aSz.Width() += mnLeftBorder+mnRightBorder;
+ aSz.Height() += mnTopBorder+mnBottomBorder;
+ return aSz;
+}
+
+// -----------------------------------------------------------------------
+
+Size Window::CalcOutputSize( const Size& rWinSz ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Size aSz = rWinSz;
+ aSz.Width() -= mnLeftBorder+mnRightBorder;
+ aSz.Height() -= mnTopBorder+mnBottomBorder;
+ return aSz;
+}
+
+// -----------------------------------------------------------------------
+
+Font Window::GetDrawPixelFont( OutputDevice* pDev ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ Font aFont = GetPointFont();
+ Size aFontSize = aFont.GetSize();
+ MapMode aPtMapMode( MAP_POINT );
+ aFontSize = pDev->LogicToPixel( aFontSize, aPtMapMode );
+ aFont.SetSize( aFontSize );
+ return aFont;
+}
+
+// -----------------------------------------------------------------------
+
+long Window::GetDrawPixel( OutputDevice* pDev, long nPixels ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ long nP = nPixels;
+ if ( pDev->GetOutDevType() != OUTDEV_WINDOW )
+ {
+ MapMode aMap( MAP_100TH_MM );
+ Size aSz( nP, 0 );
+ aSz = PixelToLogic( aSz, aMap );
+ aSz = pDev->LogicToPixel( aSz, aMap );
+ nP = aSz.Width();
+ }
+ return nP;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Window::HandleScrollCommand( const CommandEvent& rCmd,
+ ScrollBar* pHScrl, ScrollBar* pVScrl )
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ BOOL bRet = FALSE;
+
+ if ( pHScrl || pVScrl )
+ {
+ switch( rCmd.GetCommand() )
+ {
+ case COMMAND_STARTAUTOSCROLL:
+ {
+ USHORT nFlags = 0;
+ if ( pHScrl )
+ {
+ if ( (pHScrl->GetVisibleSize() < pHScrl->GetRangeMax()) &&
+ pHScrl->IsEnabled() && pHScrl->IsInputEnabled() )
+ nFlags |= AUTOSCROLL_HORZ;
+ }
+ if ( pVScrl )
+ {
+ if ( (pVScrl->GetVisibleSize() < pVScrl->GetRangeMax()) &&
+ pVScrl->IsEnabled() && pVScrl->IsInputEnabled() )
+ nFlags |= AUTOSCROLL_VERT;
+ }
+
+ if ( nFlags )
+ {
+ StartAutoScroll( nFlags );
+ bRet = TRUE;
+ }
+ }
+ break;
+
+ case COMMAND_WHEEL:
+ {
+ const CommandWheelData* pData = rCmd.GetWheelData();
+
+ if ( pData && (COMMAND_WHEEL_SCROLL == pData->GetMode()) && !pData->IsHorz() )
+ {
+ ULONG nScrollLines = pData->GetScrollLines();
+ long nLines;
+ if ( nScrollLines == COMMAND_WHEEL_PAGESCROLL )
+ {
+ if ( pData->GetDelta() < 0 )
+ nLines = -LONG_MAX;
+ else
+ nLines = LONG_MAX;
+ }
+ else
+ nLines = pData->GetNotchDelta() * (long)nScrollLines;
+ if ( nLines )
+ {
+ ImplHandleScroll( NULL, 0L, pVScrl, nLines );
+ bRet = TRUE;
+ }
+ }
+ }
+ break;
+
+ case COMMAND_AUTOSCROLL:
+ {
+ const CommandScrollData* pData = rCmd.GetAutoScrollData();
+ if ( pData && (pData->GetDeltaX() || pData->GetDeltaY()) )
+ {
+ ImplHandleScroll( pHScrl, pData->GetDeltaX(),
+ pVScrl, pData->GetDeltaY() );
+ bRet = TRUE;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+void Window::ImplHandleScroll( ScrollBar* pHScrl, long nX,
+ ScrollBar* pVScrl, long nY )
+{
+ if ( pHScrl && nX && pHScrl->IsEnabled() && pHScrl->IsInputEnabled() )
+ {
+ long nNewPos = pHScrl->GetThumbPos();
+
+ if ( nX == -LONG_MAX )
+ nNewPos += pHScrl->GetPageSize();
+ else if ( nX == LONG_MAX )
+ nNewPos -= pHScrl->GetPageSize();
+ else
+ {
+ const double fVal = (double)nNewPos - ((double)nX * pHScrl->GetLineSize());
+
+ if ( fVal < LONG_MIN )
+ nNewPos = LONG_MIN;
+ else if ( fVal > LONG_MAX )
+ nNewPos = LONG_MAX;
+ else
+ nNewPos = (long)fVal;
+ }
+
+ pHScrl->DoScroll( nNewPos );
+ }
+
+ if ( pVScrl && nY && pVScrl->IsEnabled() && pVScrl->IsInputEnabled() )
+ {
+ long nNewPos = pVScrl->GetThumbPos();
+
+ if ( nY == -LONG_MAX )
+ nNewPos += pVScrl->GetPageSize();
+ else if ( nY == LONG_MAX )
+ nNewPos -= pVScrl->GetPageSize();
+ else
+ {
+ const double fVal = (double)nNewPos - ((double)nY * pVScrl->GetLineSize());
+
+ if ( fVal < LONG_MIN )
+ nNewPos = LONG_MIN;
+ else if ( fVal > LONG_MAX )
+ nNewPos = LONG_MAX;
+ else
+ nNewPos = (long)fVal;
+ }
+
+ pVScrl->DoScroll( nNewPos );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Window::GetAccessObject( AccessObjectRef& rAcc ) const
+{
+ DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+ rAcc = new AccessObject( (void*) this, ACCESS_TYPE_WND );
+}