diff options
author | Oliver Bolte <obo@openoffice.org> | 2009-02-11 10:53:35 +0000 |
---|---|---|
committer | Oliver Bolte <obo@openoffice.org> | 2009-02-11 10:53:35 +0000 |
commit | df3d827f86c0fb7a046175a1d2c8cc0a662fc4b3 (patch) | |
tree | e6ff3903eb20005d893732c909978f5e631b8c5e | |
parent | b8128f15549ddc463545f068d482a79bb3ef30f8 (diff) |
CWS-TOOLING: integrate CWS vcl98
2009-01-16 15:17:38 +0100 pl r266422 : #i93515# add fix for compiz (thanks cmc)
2009-01-15 10:55:36 +0100 thb r266352 : #i97399# start==end angle means no arc at all
2009-01-14 18:54:37 +0100 pl r266327 : #i96536# #i96396# add: pagescroll for wheel events (thanks mod)
2009-01-14 18:21:06 +0100 pl r266325 : #i96536# #i96396# add: gestures, bracket matching (thanks mod)
2009-01-13 12:03:29 +0100 hdu r266206 : #i98024# preserve glyph zero-advance for artificial bold and vertical layout (thanks CMC!)
2009-01-12 16:32:20 +0100 hdu r266167 : #i97991# fix rotated text: temporary workaround for #i87686#
2009-01-08 17:16:17 +0100 hdu r266028 : #159054# ignore empty ATSULayout
2009-01-08 16:59:05 +0100 hdu r266026 : #159054# prevent invalid ATSUStyle
2009-01-07 19:04:06 +0100 pl r265976 : #158288# add extraction of fonts and individual object streams to pdfunzip
2009-01-07 14:42:17 +0100 pl r265969 : #i93011# workaround our ancient accelerator mechanisms to have deeper child window hirearchies working
2009-01-07 14:39:15 +0100 pl r265967 : #i93011# workaround our ancient accelerator mechanisms to have deeper child window hirearchies working
2009-01-07 11:10:58 +0100 hdu r265956 : #i97522# getPixel() returns COL_BLACK on printers or when out of bounds
2009-01-06 18:41:48 +0100 pl r265938 : #i97696# do not force user password to owner password after all
2009-01-06 18:00:52 +0100 pl r265934 : #i97157# fix a snafu
2009-01-06 13:23:38 +0100 pl r265914 : #i93515# support for _NET_WM_USER_TIME (thanks cmc)
2009-01-06 12:50:37 +0100 hdu r265912 : #i97538# get rid of compiler warnings for complex logical expressions
2009-01-06 12:49:09 +0100 hdu r265911 : #i97538# get rid of compiler warnings for complex logical expressions
2009-01-06 12:14:07 +0100 hdu r265906 : #i97522# implemented AquaSalGraphics::getPixel()
2008-12-18 16:46:59 +0100 pl r265706 : #i96343# reset quick job flag
2008-12-18 16:44:22 +0100 pl r265705 : #i96343# reset quick job flag
2008-12-18 14:08:22 +0100 pl r265688 : #i93241# fix bit field query
2008-12-18 12:41:52 +0100 pl r265682 : #i93241# eliminate useless static locale variable
2008-12-17 19:23:07 +0100 pl r265654 : #i97064# set language to OOo user configured UI language (thanks cmc)
2008-12-17 17:44:38 +0100 hdu r265651 : #i97326# debug-helper: print cairo version
2008-12-17 17:43:15 +0100 hdu r265650 : #i97326# ignore cairo changing the transformation of our FT_FACE
2008-12-17 14:44:32 +0100 pl r265604 : #i93631# refine control positioning
2008-12-17 12:40:39 +0100 hdu r265596 : #i97167# update VCL.xcu for MacOSX for Japanese (thanks maho!)
2008-12-17 11:59:51 +0100 hdu r265592 : #i97317# code movement to prevent needless and expensive construction/destruction in error path
2008-12-17 11:54:43 +0100 hdu r265590 : #i97317# workaround QUARTZ bug with drawing small polygons
2008-12-16 17:57:02 +0100 pl r265567 : #i97138# select num copies when grabbing focus
2008-12-16 17:15:11 +0100 pl r265561 : #i93173# lazy deletion of toolbars
2008-12-16 16:33:51 +0100 pl r265558 : #i93173# lazy deletion of toolbars: reparent floating DockingWindows in doLazyDelete
2008-12-16 13:23:17 +0100 pl r265536 : #i97196# ensure style engine has been loaded (thanks cmc)
-rw-r--r-- | psprint/source/fontsubset/gsub.cxx | 15 | ||||
-rw-r--r-- | svtools/source/dialogs/printdlg.cxx | 4 | ||||
-rwxr-xr-x | vcl/aqua/inc/salframeview.h | 3 | ||||
-rwxr-xr-x | vcl/aqua/source/gdi/salatslayout.cxx | 10 | ||||
-rw-r--r-- | vcl/aqua/source/gdi/salgdi.cxx | 58 | ||||
-rwxr-xr-x | vcl/aqua/source/window/salframeview.mm | 121 | ||||
-rw-r--r-- | vcl/inc/vcl/print.hxx | 5 | ||||
-rw-r--r-- | vcl/inc/vcl/wintypes.hxx | 1 | ||||
-rw-r--r-- | vcl/source/gdi/cvtsvm.cxx | 23 | ||||
-rw-r--r-- | vcl/source/gdi/outdev3.cxx | 17 | ||||
-rw-r--r-- | vcl/source/gdi/pdfwriter_impl.cxx | 62 | ||||
-rw-r--r-- | vcl/source/gdi/print.cxx | 6 | ||||
-rw-r--r-- | vcl/source/glyphs/gcach_ftyp.cxx | 52 | ||||
-rw-r--r-- | vcl/source/window/dlgctrl.cxx | 145 | ||||
-rw-r--r-- | vcl/source/window/window.cxx | 4 | ||||
-rw-r--r-- | vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx | 14 | ||||
-rw-r--r-- | vcl/unx/gtk/window/gtkframe.cxx | 91 | ||||
-rw-r--r-- | vcl/unx/inc/saldisp.hxx | 3 | ||||
-rw-r--r-- | vcl/unx/inc/wmadaptor.hxx | 7 | ||||
-rw-r--r-- | vcl/unx/source/app/saldisp.cxx | 44 | ||||
-rw-r--r-- | vcl/unx/source/app/wmadaptor.cxx | 30 | ||||
-rw-r--r-- | vcl/unx/source/gdi/salgdi3.cxx | 3 | ||||
-rw-r--r-- | vcl/unx/source/window/salframe.cxx | 11 |
23 files changed, 570 insertions, 159 deletions
diff --git a/psprint/source/fontsubset/gsub.cxx b/psprint/source/fontsubset/gsub.cxx index f49eb54c575a..578daa4646b5 100644 --- a/psprint/source/fontsubset/gsub.cxx +++ b/psprint/source/fontsubset/gsub.cxx @@ -180,11 +180,16 @@ int ReadGSUB( struct _TrueTypeFont* pTTFile, const ULONG nTag = NEXT_Long( pFeatureHeader ); // e.g. locl/vert/trad/smpl/liga/fina/... const USHORT nOffset= NEXT_UShort( pFeatureHeader ); - // feature (required && (requested || available))? - if( (aFeatureIndexList[0] != nFeatureIndex) - && (!std::count( aReqFeatureTagList.begin(), aReqFeatureTagList.end(), nTag)) - || (!std::count( aFeatureIndexList.begin(), aFeatureIndexList.end(), nFeatureIndex) ) ) - continue; + // ignore unneeded feature lookups + if( aFeatureIndexList[0] != nFeatureIndex ) // do not ignore the required feature + { + const int nRequested = std::count( aFeatureIndexList.begin(), aFeatureIndexList.end(), nFeatureIndex); + if( !nRequested ) // ignore features that are not requested + continue; + const int nAvailable = std::count( aReqFeatureTagList.begin(), aReqFeatureTagList.end(), nTag); + if( !nAvailable ) // some fonts don't provide features they request! + continue; + } const FT_Byte* pFeatureTable = pGsubBase + nOfsFeatureTable + nOffset; if( pGsubLimit < pFeatureTable + 2 ) diff --git a/svtools/source/dialogs/printdlg.cxx b/svtools/source/dialogs/printdlg.cxx index 0a392eaddba4..68acffc62a74 100644 --- a/svtools/source/dialogs/printdlg.cxx +++ b/svtools/source/dialogs/printdlg.cxx @@ -158,8 +158,6 @@ PrintDialog::PrintDialog( Window* pWindow, bool bWithSheetsAndCells ) : maRbtAll.Check(); ImplSetImages(); - - maNumCopies.GrabFocus(); } // ----------------------------------------------------------------------- @@ -773,6 +771,8 @@ short PrintDialog::Execute() ImplSetInfo(); maStatusTimer.Start(); ImplInitControls(); + maNumCopies.GrabFocus(); + maNumCopies.SetSelection( Selection( 0, maNumCopies.GetText().Len() ) ); ImplModifyControlHdl( NULL ); // Dialog starten diff --git a/vcl/aqua/inc/salframeview.h b/vcl/aqua/inc/salframeview.h index 0b44d742d776..174c04b1e476 100755 --- a/vcl/aqua/inc/salframeview.h +++ b/vcl/aqua/inc/salframeview.h @@ -100,6 +100,9 @@ -(void)otherMouseDragged: (NSEvent*)pEvent; -(void)otherMouseUp: (NSEvent*)pEvent; -(void)scrollWheel: (NSEvent*)pEvent; +-(void)magnifyWithEvent: (NSEvent*)pEvent; +-(void)rotateWithEvent: (NSEvent*)pEvent; +-(void)swipeWithEvent: (NSEvent*)pEvent; -(void)keyDown: (NSEvent*)pEvent; -(void)flagsChanged: (NSEvent*)pEvent; -(void)sendMouseEventToFrame:(NSEvent*)pEvent button:(USHORT)nButton eventtype:(USHORT)nEvent; diff --git a/vcl/aqua/source/gdi/salatslayout.cxx b/vcl/aqua/source/gdi/salatslayout.cxx index a4827870efa9..ca1a38c94043 100755 --- a/vcl/aqua/source/gdi/salatslayout.cxx +++ b/vcl/aqua/source/gdi/salatslayout.cxx @@ -564,7 +564,9 @@ long ATSLayout::GetTextWidth() const if( mnCharCount <= 0 ) return 0; - DBG_ASSERT( (maATSULayout != NULL), "ATSLayout::GetTextWidth() with maATSULayout==NULL !\n"); + DBG_ASSERT( (maATSULayout!=NULL), "ATSLayout::GetTextWidth() with maATSULayout==NULL !\n"); + if( !maATSULayout ) + return 0; if( !mnCachedWidth ) { @@ -659,6 +661,9 @@ long ATSLayout::FillDXArray( long* pDXArray ) const **/ int ATSLayout::GetTextBreak( long nMaxWidth, long nCharExtra, int nFactor ) const { + if( !maATSULayout ) + return STRING_LEN; + // get a quick overview on what could fit const long nPixelWidth = (nMaxWidth - (nCharExtra * mnCharCount)) / nFactor; @@ -973,6 +978,9 @@ bool ATSLayout::GetDeltaY() const return true; #if 1 + if( !maATSULayout ) + return false; + // get and keep the y-deltas in the mpDeltaY member variable // => release it in the destructor ItemCount nDeltaCount = 0; diff --git a/vcl/aqua/source/gdi/salgdi.cxx b/vcl/aqua/source/gdi/salgdi.cxx index bc7082c33d1c..c93a5da11c30 100644 --- a/vcl/aqua/source/gdi/salgdi.cxx +++ b/vcl/aqua/source/gdi/salgdi.cxx @@ -916,12 +916,20 @@ bool AquaSalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPol const ::basegfx::B2DPolygon rPolygon = rPolyPoly.getB2DPolygon( nPolyIdx ); AddPolygonToPath( xPath, rPolygon, true, !getAntiAliasB2DDraw(), IsPenVisible() ); } + + // use the path to prepare the graphics context CGContextSaveGState( mrContext ); CGContextBeginPath( mrContext ); CGContextAddPath( mrContext, xPath ); const CGRect aRefreshRect = CGPathGetBoundingBox( xPath ); CGPathRelease( xPath ); +#ifndef NO_I97317_WORKAROUND + // #i97317# workaround for Quartz having problems with drawing small polygons + if( (aRefreshRect.size.width <= 0.125) && (aRefreshRect.size.height <= 0.125) ) + return true; +#endif + // draw path with antialiased polygon CGContextSetShouldAntialias( mrContext, true ); CGContextSetAlpha( mrContext, 1.0 - fTransparency ); @@ -961,11 +969,19 @@ bool AquaSalGraphics::drawPolyLine( const ::basegfx::B2DPolygon& rPolyLine, // setup poly-polygon path CGMutablePathRef xPath = CGPathCreateMutable(); AddPolygonToPath( xPath, rPolyLine, rPolyLine.isClosed(), !getAntiAliasB2DDraw(), true ); + + // use the path to prepare the graphics context CGContextSaveGState( mrContext ); CGContextAddPath( mrContext, xPath ); const CGRect aRefreshRect = CGPathGetBoundingBox( xPath ); CGPathRelease( xPath ); +#ifndef NO_I97317_WORKAROUND + // #i97317# workaround for Quartz having problems with drawing small polygons + if( (aRefreshRect.size.width <= 0.125) && (aRefreshRect.size.height <= 0.125) ) + return true; +#endif + // draw path with antialiased line CGContextSetShouldAntialias( mrContext, true ); CGContextSetLineJoin( mrContext, aCGLineJoin ); @@ -1227,7 +1243,37 @@ SalBitmap* AquaSalGraphics::getBitmap( long nX, long nY, long nDX, long nDY SalColor AquaSalGraphics::getPixel( long nX, long nY ) { - SalColor nSalColor = 0; + // return default value on printers or when out of bounds + if( !mxLayer + || (nX < 0) || (nX >= mnWidth) + || (nY < 0) || (nY >= mnHeight)) + return COL_BLACK; + + // prepare creation of matching a CGBitmapContext + CGColorSpaceRef aCGColorSpace = GetSalData()->mxRGBSpace; + CGBitmapInfo aCGBmpInfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Big; +#if __BIG_ENDIAN__ + struct{ unsigned char b, g, r, a; } aPixel; +#else + struct{ unsigned char a, r, g, b; } aPixel; +#endif + + // create a one-pixel bitmap context + // TODO: is it worth to cache it? + CGContextRef xOnePixelContext = ::CGBitmapContextCreate( &aPixel, + 1, 1, 8, sizeof(aPixel), aCGColorSpace, aCGBmpInfo ); + + // update this graphics layer + ApplyXorContext(); + + // copy the requested pixel into the bitmap context + if( IsFlipped() ) + nY = mnHeight - nY; + const CGPoint aCGPoint = {-nX, -nY}; + CGContextDrawLayerAtPoint( xOnePixelContext, aCGPoint, mxLayer ); + CGContextRelease( xOnePixelContext ); + + SalColor nSalColor = MAKE_SALCOLOR( aPixel.r, aPixel.g, aPixel.b ); return nSalColor; } @@ -1815,7 +1861,14 @@ USHORT AquaSalGraphics::SetFont( ImplFontSelectData* pReqFont, int nFallbackLeve static const int nTagCount = sizeof(aTag) / sizeof(*aTag); OSStatus eStatus = ATSUSetAttributes( maATSUStyle, nTagCount, aTag, aValueSize, aValue ); - DBG_ASSERT( (eStatus==noErr), "AquaSalGraphics::SetFont() : Could not set font attributes!\n"); + // reset ATSUstyle if there was an error + if( eStatus != noErr ) + { + DBG_WARNING( "AquaSalGraphics::SetFont() : Could not set font attributes!\n"); + ATSUClearStyle( maATSUStyle ); + mpMacFontData = NULL; + return 0; + } // prepare font stretching const ATSUAttributeTag aMatrixTag = kATSUFontMatrixTag; @@ -2454,3 +2507,4 @@ bool XorEmulation::UpdateTarget() } // ======================================================================= + diff --git a/vcl/aqua/source/window/salframeview.mm b/vcl/aqua/source/window/salframeview.mm index aee1bd351839..ec52d86528c9 100755 --- a/vcl/aqua/source/window/salframeview.mm +++ b/vcl/aqua/source/window/salframeview.mm @@ -626,6 +626,121 @@ private: [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SALEVENT_MOUSEBUTTONUP]; } +- (void)magnifyWithEvent: (NSEvent*)pEvent +{ + YIELD_GUARD; + + // TODO: ?? -(float)magnification; + if( AquaSalFrame::isAlive( mpFrame ) ) + { + mpFrame->mnLastEventTime = static_cast<ULONG>( [pEvent timestamp] * 1000.0 ); + mpFrame->mnLastModifierFlags = [pEvent modifierFlags]; + + float dZ = 0.0; + for(;;) + { + dZ += [pEvent deltaZ]; + NSEvent* pNextEvent = [NSApp nextEventMatchingMask: NSScrollWheelMask + untilDate: nil inMode: NSDefaultRunLoopMode dequeue: YES ]; + if( !pNextEvent ) + break; + pEvent = pNextEvent; + } + + NSPoint aPt = [NSEvent mouseLocation]; + mpFrame->CocoaToVCL( aPt ); + + SalWheelMouseEvent aEvent; + aEvent.mnTime = mpFrame->mnLastEventTime; + aEvent.mnX = static_cast<long>(aPt.x) - mpFrame->maGeometry.nX; + aEvent.mnY = static_cast<long>(aPt.y) - mpFrame->maGeometry.nY; + aEvent.mnCode = ImplGetModifierMask( mpFrame->mnLastModifierFlags ); + aEvent.mnCode |= KEY_MOD1; // we want zooming, no scrolling + + // --- RTL --- (mirror mouse pos) + if( Application::GetSettings().GetLayoutRTL() ) + aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX; + + if( dZ != 0.0 ) + { + aEvent.mnDelta = static_cast<long>(floor(dZ)); + aEvent.mnNotchDelta = aEvent.mnDelta / 8; + if( aEvent.mnNotchDelta == 0 ) + aEvent.mnNotchDelta = dZ < 0.0 ? -1 : 1; + aEvent.mbHorz = FALSE; + aEvent.mnScrollLines = aEvent.mnNotchDelta > 0 ? aEvent.mnNotchDelta : -aEvent.mnNotchDelta; + if( aEvent.mnScrollLines == 0 ) + aEvent.mnScrollLines = 1; + mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent ); + } + } +} + +- (void)rotateWithEvent: (NSEvent*)pEvent +{ + //Rotation : -(float)rotation; + // TODO: create new CommandType so rotation is available to the applications +} + +- (void)swipeWithEvent: (NSEvent*)pEvent +{ + YIELD_GUARD; + + if( AquaSalFrame::isAlive( mpFrame ) ) + { + mpFrame->mnLastEventTime = static_cast<ULONG>( [pEvent timestamp] * 1000.0 ); + mpFrame->mnLastModifierFlags = [pEvent modifierFlags]; + + // merge pending scroll wheel events + float dX = 0.0; + float dY = 0.0; + for(;;) + { + dX += [pEvent deltaX]; + dY += [pEvent deltaY]; + NSEvent* pNextEvent = [NSApp nextEventMatchingMask: NSScrollWheelMask + untilDate: nil inMode: NSDefaultRunLoopMode dequeue: YES ]; + if( !pNextEvent ) + break; + pEvent = pNextEvent; + } + + NSPoint aPt = [NSEvent mouseLocation]; + mpFrame->CocoaToVCL( aPt ); + + SalWheelMouseEvent aEvent; + aEvent.mnTime = mpFrame->mnLastEventTime; + aEvent.mnX = static_cast<long>(aPt.x) - mpFrame->maGeometry.nX; + aEvent.mnY = static_cast<long>(aPt.y) - mpFrame->maGeometry.nY; + aEvent.mnCode = ImplGetModifierMask( mpFrame->mnLastModifierFlags ); + + // --- RTL --- (mirror mouse pos) + if( Application::GetSettings().GetLayoutRTL() ) + aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX; + + if( dX != 0.0 ) + { + aEvent.mnDelta = static_cast<long>(floor(dX)); + aEvent.mnNotchDelta = aEvent.mnDelta / 8; + if( aEvent.mnNotchDelta == 0 ) + aEvent.mnNotchDelta = dX < 0.0 ? -1 : 1; + aEvent.mbHorz = TRUE; + aEvent.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL; + mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent ); + } + if( dY != 0.0 && AquaSalFrame::isAlive( mpFrame )) + { + aEvent.mnDelta = static_cast<long>(floor(dY)); + aEvent.mnNotchDelta = aEvent.mnDelta / 8; + if( aEvent.mnNotchDelta == 0 ) + aEvent.mnNotchDelta = dY < 0.0 ? -1 : 1; + aEvent.mbHorz = FALSE; + aEvent.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL; + mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent ); + } + } +} + -(void)scrollWheel: (NSEvent*)pEvent { YIELD_GUARD; @@ -694,6 +809,7 @@ private: } } + -(void)keyDown: (NSEvent*)pEvent { YIELD_GUARD; @@ -774,14 +890,15 @@ private: { OUString aInsertString( GetOUString( pInsert ) ); USHORT nKeyCode = 0; + // aCharCode initializer is safe since aInsertString will at least contain '\0' sal_Unicode aCharCode = *aInsertString.getStr(); + nKeyCode = ImplMapCharCode( aCharCode ); // FIXME: will probably break somehow in less than trivial text input mode if( nLen == 1 && aCharCode < 0x80 && aCharCode > 0x1f && - ( nKeyCode = ImplMapCharCode( aCharCode ) ) != 0 - && ! [self hasMarkedText ] + ! [self hasMarkedText ] ) { [self sendKeyInputAndReleaseToFrame: nKeyCode character: aCharCode]; diff --git a/vcl/inc/vcl/print.hxx b/vcl/inc/vcl/print.hxx index 2f579f4e4dc2..fdc7f2ba9c69 100644 --- a/vcl/inc/vcl/print.hxx +++ b/vcl/inc/vcl/print.hxx @@ -393,8 +393,11 @@ public: * on JobSetup will be preferred. However if no "IsQuickJob" value is set, * setting SetNextJobIsQuick will cause the following StartJob to set this value * to "true" in the current JobSetup. + * + * the paramter can be set to "false" again in case a job was not started and the + * printer is to be reused. */ - void SetNextJobIsQuick(); + void SetNextJobIsQuick( bool bQuick = true ); /** checks the printer list and updates it necessary * diff --git a/vcl/inc/vcl/wintypes.hxx b/vcl/inc/vcl/wintypes.hxx index d97135a99bd5..f5869eca55e4 100644 --- a/vcl/inc/vcl/wintypes.hxx +++ b/vcl/inc/vcl/wintypes.hxx @@ -185,6 +185,7 @@ typedef sal_Int64 WinBits; #define WB_DOCKABLE ((WinBits)SAL_CONST_INT64(0x20000000)) #define WB_AUTOVSCROLL ((WinBits)SAL_CONST_INT64(0x40000000)) #define WB_HYPHENATION (((WinBits)SAL_CONST_INT64(0x80000000)) | WB_WORDBREAK) +#define WB_CHILDDLGCTRL ((WinBits)SAL_CONST_INT64(0x100000000000)) // system floating window #define WB_SYSTEMFLOATWIN ((WinBits)SAL_CONST_INT64(0x100000000)) diff --git a/vcl/source/gdi/cvtsvm.cxx b/vcl/source/gdi/cvtsvm.cxx index 14c211e4e045..c1c02b673658 100644 --- a/vcl/source/gdi/cvtsvm.cxx +++ b/vcl/source/gdi/cvtsvm.cxx @@ -397,13 +397,8 @@ SVMConverter::SVMConverter( SvStream& rStm, GDIMetaFile& rMtf, ULONG nConvertMod void SVMConverter::ImplConvertFromSVM1( SvStream& rIStm, GDIMetaFile& rMtf ) { - LineInfo aLineInfo( LINE_NONE, 0 ); - Stack aLIStack; - ULONG nPos = rIStm.Tell(); + const ULONG nPos = rIStm.Tell(); const USHORT nOldFormat = rIStm.GetNumberFormatInt(); - rtl_TextEncoding eActualCharSet = gsl_getSystemTextEncoding(); - BOOL bFatLine = FALSE; - VirtualDevice aFontVDev; rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); @@ -412,14 +407,14 @@ void SVMConverter::ImplConvertFromSVM1( SvStream& rIStm, GDIMetaFile& rMtf ) INT16 nSize; INT16 nVersion; - // Header lesen + // read header rIStm.Read( (char*) &aCode, sizeof( aCode ) ); // Kennung rIStm >> nSize; // Size rIStm >> nVersion; // Version rIStm >> aPrefSz.Width(); // PrefSize.Width() rIStm >> aPrefSz.Height(); // PrefSize.Height() - // Header-Kennung und Versionsnummer pruefen + // check header-magic and version if( rIStm.GetError() || ( memcmp( aCode, "SVGDI", sizeof( aCode ) ) != 0 ) || ( nVersion != 200 ) ) @@ -427,9 +422,16 @@ void SVMConverter::ImplConvertFromSVM1( SvStream& rIStm, GDIMetaFile& rMtf ) rIStm.SetError( SVSTREAM_FILEFORMAT_ERROR ); rIStm.SetNumberFormatInt( nOldFormat ); rIStm.Seek( nPos ); + return; } - else - { + + LineInfo aLineInfo( LINE_NONE, 0 ); + Stack aLIStack; + VirtualDevice aFontVDev; + rtl_TextEncoding eActualCharSet = gsl_getSystemTextEncoding(); + BOOL bFatLine = FALSE; + + // TODO: fix reindentation below if you can accept being blamed by the SCM MapMode aMapMode; Polygon aActionPoly; Rectangle aRect; @@ -1157,7 +1159,6 @@ void SVMConverter::ImplConvertFromSVM1( SvStream& rIStm, GDIMetaFile& rMtf ) // cleanup push-pop stack if neccessary for( void* pLineInfo = aLIStack.Pop(); pLineInfo; pLineInfo = aLIStack.Pop() ) delete (LineInfo*) pLineInfo; - } rIStm.SetNumberFormatInt( nOldFormat ); } diff --git a/vcl/source/gdi/outdev3.cxx b/vcl/source/gdi/outdev3.cxx index a77d8c2ac294..e421cb59aa4c 100644 --- a/vcl/source/gdi/outdev3.cxx +++ b/vcl/source/gdi/outdev3.cxx @@ -5241,15 +5241,15 @@ long OutputDevice::ImplGetTextLines( ImplMultiTextLineInfo& rLineInfo, if ( xBI.is() ) { - static const com::sun::star::lang::Locale aDefLocale(Application::GetSettings().GetUILocale()); + const com::sun::star::lang::Locale& rDefLocale(Application::GetSettings().GetUILocale()); xub_StrLen nSoftBreak = GetTextBreak( rStr, nWidth, nPos, nBreakPos - nPos ); DBG_ASSERT( nSoftBreak < nBreakPos, "Break?!" ); //aHyphOptions.hyphenIndex = nSoftBreak; - i18n::LineBreakResults aLBR = xBI->getLineBreak( aText, nSoftBreak, aDefLocale, nPos, aHyphOptions, aUserOptions ); + i18n::LineBreakResults aLBR = xBI->getLineBreak( aText, nSoftBreak, rDefLocale, nPos, aHyphOptions, aUserOptions ); nBreakPos = (xub_StrLen)aLBR.breakIndex; if ( nBreakPos <= nPos ) nBreakPos = nSoftBreak; - if ( nStyle & TEXT_DRAW_WORDBREAK_HYPHENATION ) + if ( (nStyle & TEXT_DRAW_WORDBREAK_HYPHENATION) == TEXT_DRAW_WORDBREAK_HYPHENATION ) { // Egal ob Trenner oder nicht: Das Wort nach dem Trenner durch // die Silbentrennung jagen... @@ -5261,7 +5261,7 @@ long OutputDevice::ImplGetTextLines( ImplMultiTextLineInfo& rLineInfo, { sal_Unicode cAlternateReplChar = 0; sal_Unicode cAlternateExtraChar = 0; - i18n::Boundary aBoundary = xBI->getWordBoundary( aText, nBreakPos, aDefLocale, ::com::sun::star::i18n::WordType::DICTIONARY_WORD, sal_True ); + i18n::Boundary aBoundary = xBI->getWordBoundary( aText, nBreakPos, rDefLocale, ::com::sun::star::i18n::WordType::DICTIONARY_WORD, sal_True ); // sal_uInt16 nWordStart = nBreakPos; // sal_uInt16 nBreakPos_OLD = nBreakPos; sal_uInt16 nWordStart = nPos; @@ -5277,7 +5277,7 @@ long OutputDevice::ImplGetTextLines( ImplMultiTextLineInfo& rLineInfo, sal_uInt16 nMinTrail = static_cast<sal_uInt16>(nWordEnd-nSoftBreak+1); //+1: Vor dem angeknacksten Buchstaben uno::Reference< linguistic2::XHyphenatedWord > xHyphWord; if (xHyph.is()) - xHyphWord = xHyph->hyphenate( aWord, aDefLocale, aWord.Len() - nMinTrail, uno::Sequence< beans::PropertyValue >() ); + xHyphWord = xHyph->hyphenate( aWord, rDefLocale, aWord.Len() - nMinTrail, uno::Sequence< beans::PropertyValue >() ); if (xHyphWord.is()) { sal_Bool bAlternate = xHyphWord->isAlternativeSpelling(); @@ -5344,7 +5344,7 @@ long OutputDevice::ImplGetTextLines( ImplMultiTextLineInfo& rLineInfo, } // if (xHyphWord.is()) } // if ( ( nWordEnd >= nSoftBreak ) && ( nWordLen > 3 ) ) } // if ( xHyph.is() ) - } // if ( nStyle & TEXT_DRAW_WORDBREAK_HYPHENATION ) + } // if ( (nStyle & TEXT_DRAW_WORDBREAK_HYPHENATION) == TEXT_DRAW_WORDBREAK_HYPHENATION ) } nLineWidth = GetTextWidth( rStr, nPos, nBreakPos-nPos ); } @@ -6408,7 +6408,10 @@ SalLayout* OutputDevice::ImplLayout( const String& rOrigStr, sal_Int32* pAry = (sal_Int32*)alloca(sizeof(sal_Int32)*nLen); if( nCutStart > nMinIndex ) memcpy( pAry, pDXArray, sizeof(sal_Int32)*(nCutStart-nMinIndex) ); - memcpy( pAry+nCutStart-nMinIndex, pDXArray + nOrgLen - (nCutStop-nMinIndex), nLen - (nCutStop-nMinIndex) ); + // note: nCutStart will never be smaller than nMinIndex + memcpy( pAry+nCutStart-nMinIndex, + pDXArray + nOrgLen - (nCutStop-nMinIndex), + sizeof(sal_Int32)*(nLen - (nCutStart-nMinIndex)) ); pDXArray = pAry; } } diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index 69f4674cae9c..0754f5c5b3dc 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -6845,11 +6845,12 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const String& rText, bool bT FontMetric aRefDevFontMetric = m_pReferenceDevice->GetFontMetric(); // collect the glyphs into a single array + const int nTmpMaxGlyphs = rLayout.GetOrientation() ? 1 : nMaxGlyphs; // #i97991# temporary workaround for #i87686# std::vector< PDFGlyph > aGlyphs; - aGlyphs.reserve( nMaxGlyphs ); + aGlyphs.reserve( nTmpMaxGlyphs ); // first get all the glyphs and register them; coordinates still in Pixel Point aGNGlyphPos; - while( (nGlyphs = rLayout.GetNextGlyphs( nMaxGlyphs, pGlyphs, aGNGlyphPos, nIndex, nAdvanceWidths, pCharPosAry )) != 0 ) + while( (nGlyphs = rLayout.GetNextGlyphs( nTmpMaxGlyphs, pGlyphs, aGNGlyphPos, nIndex, nAdvanceWidths, pCharPosAry )) != 0 ) { for( int i = 0; i < nGlyphs; i++ ) { @@ -8299,18 +8300,18 @@ void PDFWriterImpl::drawArc( const Rectangle& rRect, const Point& rStart, const return; // calculate start and stop angles - double fStartAngle = calcAngle( rRect, rStart ); + const double fStartAngle = calcAngle( rRect, rStart ); double fStopAngle = calcAngle( rRect, rStop ); while( fStopAngle < fStartAngle ) fStopAngle += 2.0*M_PI; - int nFragments = (int)((fStopAngle-fStartAngle)/(M_PI/2.0))+1; - double fFragmentDelta = (fStopAngle-fStartAngle)/(double)nFragments; - double kappa = fabs( 4.0 * (1.0-cos(fFragmentDelta/2.0))/sin(fFragmentDelta/2.0) / 3.0); - double halfWidth = (double)rRect.GetWidth()/2.0; - double halfHeight = (double)rRect.GetHeight()/2.0; + const int nFragments = (int)((fStopAngle-fStartAngle)/(M_PI/2.0))+1; + const double fFragmentDelta = (fStopAngle-fStartAngle)/(double)nFragments; + const double kappa = fabs( 4.0 * (1.0-cos(fFragmentDelta/2.0))/sin(fFragmentDelta/2.0) / 3.0); + const double halfWidth = (double)rRect.GetWidth()/2.0; + const double halfHeight = (double)rRect.GetHeight()/2.0; - Point aCenter( (rRect.Left()+rRect.Right()+1)/2, - (rRect.Top()+rRect.Bottom()+1)/2 ); + const Point aCenter( (rRect.Left()+rRect.Right()+1)/2, + (rRect.Top()+rRect.Bottom()+1)/2 ); OStringBuffer aLine( 30*nFragments ); Point aPoint( (int)(halfWidth * cos(fStartAngle) ), @@ -8318,27 +8319,30 @@ void PDFWriterImpl::drawArc( const Rectangle& rRect, const Point& rStart, const aPoint += aCenter; m_aPages.back().appendPoint( aPoint, aLine ); aLine.append( " m " ); - for( int i = 0; i < nFragments; i++ ) - { - double fStartFragment = fStartAngle + (double)i*fFragmentDelta; - double fStopFragment = fStartFragment + fFragmentDelta; - aPoint = Point( (int)(halfWidth * (cos(fStartFragment) - kappa*sin(fStartFragment) ) ), - -(int)(halfHeight * (sin(fStartFragment) + kappa*cos(fStartFragment) ) ) ); - aPoint += aCenter; - m_aPages.back().appendPoint( aPoint, aLine ); - aLine.append( ' ' ); + if( !basegfx::fTools::equal(fStartAngle, fStopAngle) ) + { + for( int i = 0; i < nFragments; i++ ) + { + const double fStartFragment = fStartAngle + (double)i*fFragmentDelta; + const double fStopFragment = fStartFragment + fFragmentDelta; + aPoint = Point( (int)(halfWidth * (cos(fStartFragment) - kappa*sin(fStartFragment) ) ), + -(int)(halfHeight * (sin(fStartFragment) + kappa*cos(fStartFragment) ) ) ); + aPoint += aCenter; + m_aPages.back().appendPoint( aPoint, aLine ); + aLine.append( ' ' ); - aPoint = Point( (int)(halfWidth * (cos(fStopFragment) + kappa*sin(fStopFragment) ) ), - -(int)(halfHeight * (sin(fStopFragment) - kappa*cos(fStopFragment) ) ) ); - aPoint += aCenter; - m_aPages.back().appendPoint( aPoint, aLine ); - aLine.append( ' ' ); + aPoint = Point( (int)(halfWidth * (cos(fStopFragment) + kappa*sin(fStopFragment) ) ), + -(int)(halfHeight * (sin(fStopFragment) - kappa*cos(fStopFragment) ) ) ); + aPoint += aCenter; + m_aPages.back().appendPoint( aPoint, aLine ); + aLine.append( ' ' ); - aPoint = Point( (int)(halfWidth * cos(fStopFragment) ), - -(int)(halfHeight * sin(fStopFragment) ) ); - aPoint += aCenter; - m_aPages.back().appendPoint( aPoint, aLine ); - aLine.append( " c\n" ); + aPoint = Point( (int)(halfWidth * cos(fStopFragment) ), + -(int)(halfHeight * sin(fStopFragment) ) ); + aPoint += aCenter; + m_aPages.back().appendPoint( aPoint, aLine ); + aLine.append( " c\n" ); + } } if( bWithChord || bWithPie ) { diff --git a/vcl/source/gdi/print.cxx b/vcl/source/gdi/print.cxx index 11bed4b7ae67..0a5fbb189885 100644 --- a/vcl/source/gdi/print.cxx +++ b/vcl/source/gdi/print.cxx @@ -674,11 +674,11 @@ Printer::~Printer() } // ----------------------------------------------------------------------- -void Printer::SetNextJobIsQuick() +void Printer::SetNextJobIsQuick( bool bQuick ) { - mpPrinterData->mbNextJobIsQuick = true; + mpPrinterData->mbNextJobIsQuick = bQuick; if( mpQPrinter ) - mpQPrinter->SetNextJobIsQuick(); + mpQPrinter->SetNextJobIsQuick( bQuick ); } // ----------------------------------------------------------------------- diff --git a/vcl/source/glyphs/gcach_ftyp.cxx b/vcl/source/glyphs/gcach_ftyp.cxx index 6bc5bb5b44c9..f6d93963540b 100644 --- a/vcl/source/glyphs/gcach_ftyp.cxx +++ b/vcl/source/glyphs/gcach_ftyp.cxx @@ -831,6 +831,10 @@ FreetypeServerFont::FreetypeServerFont( const ImplFontSelectData& rFSD, FtFontIn // TODO: query GASP table for load flags mnLoadFlags = FT_LOAD_DEFAULT; +#if 1 // #i97326# cairo sometimes uses FT_Set_Transform() on our FT_FACE + // we are not using FT_Set_Transform() yet, so just ignore it for now + mnLoadFlags |= FT_LOAD_IGNORE_TRANSFORM; +#endif mbArtItalic = (rFSD.meItalic != ITALIC_NONE && pFI->GetFontAttributes().GetSlant() == ITALIC_NONE); mbArtBold = (rFSD.meWeight > WEIGHT_MEDIUM && pFI->GetFontAttributes().GetWeight() <= WEIGHT_MEDIUM); @@ -1243,6 +1247,25 @@ int FreetypeServerFont::GetGlyphIndex( sal_UCS4 aChar ) const // ----------------------------------------------------------------------- +static int lcl_GetCharWidth( FT_FaceRec_* pFaceFT, double fStretch, int nGlyphFlags ) +{ + int nCharWidth = pFaceFT->glyph->metrics.horiAdvance; + + if( nGlyphFlags & GF_ROTMASK ) // for bVertical rotated glyphs + { + const FT_Size_Metrics& rMetrics = pFaceFT->size->metrics; +#if (FTVERSION < 2000) + nCharWidth = (int)((rMetrics.height - rMetrics.descender) * fStretch); +#else + nCharWidth = (int)((rMetrics.height + rMetrics.descender) * fStretch); +#endif + } + + return (nCharWidth + 32) >> 6; +} + +// ----------------------------------------------------------------------- + void FreetypeServerFont::InitGlyphData( int nGlyphIndex, GlyphData& rGD ) const { if( maSizeFT ) @@ -1282,20 +1305,12 @@ void FreetypeServerFont::InitGlyphData( int nGlyphIndex, GlyphData& rGD ) const return; } + const bool bOriginallyZeroWidth = (maFaceFT->glyph->metrics.horiAdvance == 0); if( mbArtBold && pFTEmbolden ) (*pFTEmbolden)( maFaceFT->glyph ); - int nCharWidth = maFaceFT->glyph->metrics.horiAdvance; - - if( nGlyphFlags & GF_ROTMASK ) { // for bVertical rotated glyphs - const FT_Size_Metrics& rMetrics = maFaceFT->size->metrics; -#if (FTVERSION < 2000) - nCharWidth = (int)((rMetrics.height - rMetrics.descender) * mfStretch); -#else - nCharWidth = (int)((rMetrics.height + rMetrics.descender) * mfStretch); -#endif - } - rGD.SetCharWidth( (nCharWidth + 32) >> 6 ); + const int nCharWidth = bOriginallyZeroWidth ? 0 : lcl_GetCharWidth( maFaceFT, mfStretch, nGlyphFlags ); + rGD.SetCharWidth( nCharWidth ); FT_Glyph pGlyphFT; rc = FT_Get_Glyph( maFaceFT->glyph, &pGlyphFT ); @@ -2365,11 +2380,16 @@ bool FreetypeServerFont::ApplyGSUB( const ImplFontSelectData& rFSD ) const USHORT nOffset= GetUShort( pFeatureHeader+4 ); pFeatureHeader += 6; - // feature (required && (requested || available))? - if( (aFeatureIndexList[0] != nFeatureIndex) - && (!std::count( aReqFeatureTagList.begin(), aReqFeatureTagList.end(), nTag)) - || (!std::count( aFeatureIndexList.begin(), aFeatureIndexList.end(), nFeatureIndex) ) ) - continue; + // short circuit some feature lookups + if( aFeatureIndexList[0] != nFeatureIndex ) // required feature? + { + const int nRequested = std::count( aFeatureIndexList.begin(), aFeatureIndexList.end(), nFeatureIndex); + if( !nRequested ) // ignore features that are not requested + continue; + const int nAvailable = std::count( aReqFeatureTagList.begin(), aReqFeatureTagList.end(), nTag); + if( !nAvailable ) // some fonts don't provide features they request! + continue; + } const FT_Byte* pFeatureTable = pGsubBase + nOfsFeatureTable + nOffset; const USHORT nCntLookups = GetUShort( pFeatureTable+0 ); diff --git a/vcl/source/window/dlgctrl.cxx b/vcl/source/window/dlgctrl.cxx index 5348d04c1a5d..16a0e5a05ad6 100644 --- a/vcl/source/window/dlgctrl.cxx +++ b/vcl/source/window/dlgctrl.cxx @@ -44,9 +44,6 @@ using namespace ::com::sun::star; - - - // ======================================================================= static Window* ImplGetSubChildWindow( Window* pParent, USHORT n, USHORT& nIndex ) @@ -274,65 +271,6 @@ Window* Window::ImplGetDlgWindow( USHORT nIndex, USHORT nType, // ----------------------------------------------------------------------- -static Window* ImplFindAccelWindow( Window* pParent, USHORT& rIndex, xub_Unicode cCharCode, - USHORT nFormStart, USHORT nFormEnd, BOOL bCheckEnable = TRUE ) -{ - DBG_ASSERT( (rIndex >= nFormStart) && (rIndex <= nFormEnd), - "Window::ImplFindAccelWindow() - rIndex not in Form" ); - - xub_Unicode cCompareChar; - USHORT nStart = rIndex; - USHORT i = rIndex; - int bSearch = TRUE; - Window* pWindow; - - // MT: Where can we keep the CharClass?! - static uno::Reference< i18n::XCharacterClassification > xCharClass; - if ( !xCharClass.is() ) - xCharClass = vcl::unohelper::CreateCharacterClassification(); - - const ::com::sun::star::lang::Locale& rLocale = Application::GetSettings().GetUILocale(); - cCharCode = xCharClass->toUpper( String(cCharCode), 0, 1, rLocale )[0]; - - if ( i < nFormEnd ) - pWindow = ImplGetNextWindow( pParent, i, i, TRUE ); - else - pWindow = ImplGetChildWindow( pParent, nFormStart, i, TRUE ); - while ( bSearch ) - { - const XubString aStr = pWindow->GetText(); - USHORT nPos = aStr.Search( '~' ); - while ( nPos != STRING_NOTFOUND ) - { - cCompareChar = aStr.GetChar( nPos+1 ); - cCompareChar = xCharClass->toUpper( String(cCompareChar), 0, 1, rLocale )[0]; - if ( cCompareChar == cCharCode ) - { - // Bei Static-Controls auf das naechste Controlm weiterschalten - if ( (pWindow->GetType() == WINDOW_FIXEDTEXT) || - (pWindow->GetType() == WINDOW_FIXEDLINE) || - (pWindow->GetType() == WINDOW_GROUPBOX) ) - pWindow = pParent->ImplGetDlgWindow( i, DLGWINDOW_NEXT ); - rIndex = i; - return pWindow; - } - nPos = aStr.Search( '~', nPos+1 ); - } - - if ( i == nStart ) - break; - - if ( i < nFormEnd ) - pWindow = ImplGetNextWindow( pParent, i, i, bCheckEnable ); - else - pWindow = ImplGetChildWindow( pParent, nFormStart, i, bCheckEnable ); - } - - return NULL; -} - -// ----------------------------------------------------------------------- - static Window* ImplFindDlgCtrlWindow( Window* pParent, Window* pWindow, USHORT& rIndex, USHORT& rFormStart, USHORT& rFormEnd ) { @@ -347,6 +285,10 @@ static Window* ImplFindDlgCtrlWindow( Window* pParent, Window* pWindow, USHORT& // Focus-Fenster in der Child-Liste suchen pSWindow = ImplGetChildWindow( pParent, 0, i, FALSE ); + + if( pWindow == NULL ) + pWindow = pSWindow; + while ( pSWindow ) { if ( pSWindow->ImplGetWindow()->IsDialogControlStart() ) @@ -404,6 +346,85 @@ static Window* ImplFindDlgCtrlWindow( Window* pParent, Window* pWindow, USHORT& // ----------------------------------------------------------------------- +static Window* ImplFindAccelWindow( Window* pParent, USHORT& rIndex, xub_Unicode cCharCode, + USHORT nFormStart, USHORT nFormEnd, BOOL bCheckEnable = TRUE ) +{ + DBG_ASSERT( (rIndex >= nFormStart) && (rIndex <= nFormEnd), + "Window::ImplFindAccelWindow() - rIndex not in Form" ); + + xub_Unicode cCompareChar; + USHORT nStart = rIndex; + USHORT i = rIndex; + int bSearch = TRUE; + Window* pWindow; + + // MT: Where can we keep the CharClass?! + static uno::Reference< i18n::XCharacterClassification > xCharClass; + if ( !xCharClass.is() ) + xCharClass = vcl::unohelper::CreateCharacterClassification(); + + const ::com::sun::star::lang::Locale& rLocale = Application::GetSettings().GetUILocale(); + cCharCode = xCharClass->toUpper( String(cCharCode), 0, 1, rLocale )[0]; + + if ( i < nFormEnd ) + pWindow = ImplGetNextWindow( pParent, i, i, TRUE ); + else + pWindow = ImplGetChildWindow( pParent, nFormStart, i, TRUE ); + while ( bSearch ) + { + const XubString aStr = pWindow->GetText(); + USHORT nPos = aStr.Search( '~' ); + while ( nPos != STRING_NOTFOUND ) + { + cCompareChar = aStr.GetChar( nPos+1 ); + cCompareChar = xCharClass->toUpper( String(cCompareChar), 0, 1, rLocale )[0]; + if ( cCompareChar == cCharCode ) + { + // Bei Static-Controls auf das naechste Controlm weiterschalten + if ( (pWindow->GetType() == WINDOW_FIXEDTEXT) || + (pWindow->GetType() == WINDOW_FIXEDLINE) || + (pWindow->GetType() == WINDOW_GROUPBOX) ) + pWindow = pParent->ImplGetDlgWindow( i, DLGWINDOW_NEXT ); + rIndex = i; + return pWindow; + } + nPos = aStr.Search( '~', nPos+1 ); + } + + // #i93011# it would have made sense to have this really recursive + // right from the start. However this would cause unpredictable side effects now + // so instead we have a style bit for some child windows, that want their + // children checked for accelerators + if( (pWindow->GetStyle() & WB_CHILDDLGCTRL) != 0 ) + { + USHORT nChildIndex; + USHORT nChildFormStart; + USHORT nChildFormEnd; + + // get form start and end + ::ImplFindDlgCtrlWindow( pWindow, NULL, + nChildIndex, nChildFormStart, nChildFormEnd ); + Window* pAccelWin = ImplFindAccelWindow( pWindow, nChildIndex, cCharCode, + nChildFormStart, nChildFormEnd, + bCheckEnable ); + if( pAccelWin ) + return pAccelWin; + } + + if ( i == nStart ) + break; + + if ( i < nFormEnd ) + pWindow = ImplGetNextWindow( pParent, i, i, bCheckEnable ); + else + pWindow = ImplGetChildWindow( pParent, nFormStart, i, bCheckEnable ); + } + + return NULL; +} + +// ----------------------------------------------------------------------- + void Window::ImplControlFocus( USHORT nFlags ) { if ( nFlags & GETFOCUS_MNEMONIC ) diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx index d9891430f29d..caa43c3bef1e 100644 --- a/vcl/source/window/window.cxx +++ b/vcl/source/window/window.cxx @@ -4763,7 +4763,9 @@ Window::~Window() // ----------------------------------------------------------------------- void Window::doLazyDelete() { - if( dynamic_cast<SystemWindow*>(this) ) + SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(this); + DockingWindow* pDockWin = dynamic_cast<DockingWindow*>(this); + if( pSysWin || ( pDockWin && pDockWin->IsFloatingMode() ) ) SetParent( ImplGetDefaultWindow() ); vcl::LazyDeletor<Window>::Delete( this ); } diff --git a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx index d0618328e59c..0d2880d22754 100644 --- a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx +++ b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx @@ -406,8 +406,16 @@ void GtkData::initNWF( void ) // open first menu on F10 pSVData->maNWFData.mbOpenMenuOnF10 = true; + int nScreens = GetX11SalData()->GetDisplay()->GetScreenCount(); + gWidgetData = std::vector<NWFWidgetData>( nScreens ); + for( int i = 0; i < nScreens; i++ ) + gWidgetData[i].gNWPixmapCacheList = new NWPixmapCacheList; + + if( SalGetDesktopEnvironment().equalsAscii( "KDE" ) ) { + // #i97196# ensure a widget exists and the style engine was loaded + NWEnsureGTKButton( 0 ); if( g_type_from_name( "QtEngineStyle" ) ) { // KDE 3.3 invented a bug in the qt<->gtk theme engine @@ -420,12 +428,6 @@ void GtkData::initNWF( void ) if( pEnv && *pEnv ) GtkSalGraphics::bNeedPixmapPaint = GtkSalGraphics::bGlobalNeedPixmapPaint = true; - int nScreens = GetX11SalData()->GetDisplay()->GetScreenCount(); - gWidgetData = std::vector<NWFWidgetData>( nScreens ); - for( int i = 0; i < nScreens; i++ ) - gWidgetData[i].gNWPixmapCacheList = new NWPixmapCacheList; - - #if OSL_DEBUG_LEVEL > 1 std::fprintf( stderr, "GtkPlugin: using %s NWF\n", GtkSalGraphics::bNeedPixmapPaint ? "offscreen" : "direct" ); diff --git a/vcl/unx/gtk/window/gtkframe.cxx b/vcl/unx/gtk/window/gtkframe.cxx index ceeb17be66dd..630b034733a4 100644 --- a/vcl/unx/gtk/window/gtkframe.cxx +++ b/vcl/unx/gtk/window/gtkframe.cxx @@ -652,6 +652,10 @@ extern "C" { typedef void(*setAcceptFn)( GtkWindow*, gboolean ); static setAcceptFn p_gtk_window_set_accept_focus = NULL; static bool bGetAcceptFocusFn = true; + + typedef void(*setUserTimeFn)( GdkWindow*, guint32 ); + static setUserTimeFn p_gdk_x11_window_set_user_time = NULL; + static bool bGetSetUserTimeFn = true; } static void lcl_set_accept_focus( GtkWindow* pWindow, gboolean bAccept, bool bBeforeRealize ) @@ -659,8 +663,7 @@ static void lcl_set_accept_focus( GtkWindow* pWindow, gboolean bAccept, bool bBe if( bGetAcceptFocusFn ) { bGetAcceptFocusFn = false; - OUString aSym( RTL_CONSTASCII_USTRINGPARAM( "gtk_window_set_accept_focus" ) ); - p_gtk_window_set_accept_focus = (setAcceptFn)osl_getFunctionSymbol( GetSalData()->m_pPlugin, aSym.pData ); + p_gtk_window_set_accept_focus = (setAcceptFn)osl_getAsciiFunctionSymbol( GetSalData()->m_pPlugin, "gtk_window_set_accept_focus" ); } if( p_gtk_window_set_accept_focus && bBeforeRealize ) p_gtk_window_set_accept_focus( pWindow, bAccept ); @@ -679,6 +682,9 @@ static void lcl_set_accept_focus( GtkWindow* pWindow, gboolean bAccept, bool bBe XSetWMHints( pDisplay, aWindow, pHints ); XFree( pHints ); + if (GetX11SalData()->GetDisplay()->getWMAdaptor()->getWindowManagerName().EqualsAscii("compiz")) + return; + /* remove WM_TAKE_FOCUS protocol; this would usually be the * right thing, but gtk handles it internally whereas we * want to handle it ourselves (as to sometimes not get @@ -713,6 +719,28 @@ static void lcl_set_accept_focus( GtkWindow* pWindow, gboolean bAccept, bool bBe } } } +static void lcl_set_user_time( GdkWindow* i_pWindow, guint32 i_nTime ) +{ + if( bGetSetUserTimeFn ) + { + bGetSetUserTimeFn = false; + p_gdk_x11_window_set_user_time = (setUserTimeFn)osl_getAsciiFunctionSymbol( GetSalData()->m_pPlugin, "gdk_x11_window_set_user_time" ); + } + if( p_gdk_x11_window_set_user_time ) + p_gdk_x11_window_set_user_time( i_pWindow, i_nTime ); + else + { + Display* pDisplay = GetX11SalData()->GetDisplay()->GetDisplay(); + XLIB_Window aWindow = GDK_WINDOW_XWINDOW( i_pWindow ); + Atom nUserTime = XInternAtom( pDisplay, "_NET_WM_USER_TIME", True ); + if( nUserTime ) + { + XChangeProperty( pDisplay, aWindow, + nUserTime, XA_CARDINAL, 32, + PropModeReplace, (unsigned char*)&i_nTime, 1 ); + } + } +}; GtkSalFrame *GtkSalFrame::getFromWindow( GtkWindow *pWindow ) { @@ -734,6 +762,9 @@ void GtkSalFrame::Init( SalFrame* pParent, ULONG nStyle ) m_aForeignTopLevelWindow = None; m_nStyle = nStyle; + GtkWindowType eWinType = ((nStyle & SAL_FRAME_STYLE_FLOAT) && ! (nStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION)) + ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL; + if( nStyle & SAL_FRAME_STYLE_SYSTEMCHILD ) { m_pWindow = gtk_event_box_new(); @@ -746,7 +777,7 @@ void GtkSalFrame::Init( SalFrame* pParent, ULONG nStyle ) } } else - m_pWindow = gtk_widget_new( GTK_TYPE_WINDOW, "type", ((nStyle & SAL_FRAME_STYLE_FLOAT) && ! (nStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION)) ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL, "visible", FALSE, NULL ); + m_pWindow = gtk_widget_new( GTK_TYPE_WINDOW, "type", eWinType, "visible", FALSE, NULL ); g_object_set_data( G_OBJECT( m_pWindow ), "SalFrame", this ); // force wm class hint @@ -777,6 +808,7 @@ void GtkSalFrame::Init( SalFrame* pParent, ULONG nStyle ) { eType = GDK_WINDOW_TYPE_HINT_UTILITY; gtk_window_set_skip_taskbar_hint( GTK_WINDOW(m_pWindow), true ); + lcl_set_accept_focus( GTK_WINDOW(m_pWindow), FALSE, true ); } else if( (nStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) { @@ -806,10 +838,18 @@ void GtkSalFrame::Init( SalFrame* pParent, ULONG nStyle ) InitCommon(); + if( eWinType == GTK_WINDOW_TOPLEVEL ) + { + guint32 nUserTime = 0; + if( (nStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION|SAL_FRAME_STYLE_TOOLWINDOW)) == 0 ) + nUserTime = gdk_x11_get_server_time(GTK_WIDGET (m_pWindow)->window); + lcl_set_user_time(GTK_WIDGET(m_pWindow)->window, nUserTime); + } + if( bDecoHandling ) { gtk_window_set_resizable( GTK_WINDOW(m_pWindow), (nStyle & SAL_FRAME_STYLE_SIZEABLE) ? TRUE : FALSE ); - if( (nStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) + if( ( (nStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) || ( (nStyle & SAL_FRAME_STYLE_TOOLWINDOW ) ) ) lcl_set_accept_focus( GTK_WINDOW(m_pWindow), FALSE, false ); } @@ -1228,7 +1268,7 @@ static void initClientId() } } -void GtkSalFrame::Show( BOOL bVisible, BOOL /*bNoActivate*/ ) +void GtkSalFrame::Show( BOOL bVisible, BOOL bNoActivate ) { if( m_pWindow ) { @@ -1264,7 +1304,46 @@ void GtkSalFrame::Show( BOOL bVisible, BOOL /*bNoActivate*/ ) */ m_pParent->grabPointer( TRUE, TRUE ); } + + guint32 nUserTime = 0; + if( ! bNoActivate && (m_nStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION|SAL_FRAME_STYLE_TOOLWINDOW)) == 0 ) + nUserTime = gdk_x11_get_server_time(GTK_WIDGET (m_pWindow)->window); + + //For these floating windows we don't want the main window to lose focus, and metacity has... + // metacity-2.24.0/src/core/window.c + // + // if ((focus_window != NULL) && XSERVER_TIME_IS_BEFORE (compare, focus_window->net_wm_user_time)) + // "compare" window focus prevented by other activity + // + // where "compare" is this window + + // which leads to... + + // /* This happens for error dialogs or alerts; these need to remain on + // * top, but it would be confusing to have its ancestor remain + // * focused. + // */ + // if (meta_window_is_ancestor_of_transient (focus_window, window)) + // "The focus window %s is an ancestor of the newly mapped " + // "window %s which isn't being focused. Unfocusing the " + // "ancestor.\n", + // + // i.e. having a time < that of the toplevel frame means that the toplevel frame gets unfocused. + // awesome. + if( nUserTime == 0 && + ( + getDisplay()->getWMAdaptor()->getWindowManagerName().EqualsAscii("Metacity") || + getDisplay()->getWMAdaptor()->getWindowManagerName().EqualsAscii("compiz") + ) + ) + { + nUserTime = gdk_x11_get_server_time(GTK_WIDGET (m_pWindow)->window); + } + + lcl_set_user_time( GTK_WIDGET(m_pWindow)->window, nUserTime ); + gtk_widget_show( m_pWindow ); + if( isFloatGrabWindow() ) { m_nFloats++; @@ -1954,7 +2033,7 @@ void GtkSalFrame::ToTop( USHORT nFlags ) if( ! (nFlags & SAL_FRAME_TOTOP_GRABFOCUS_ONLY) ) gtk_window_present( GTK_WINDOW(m_pWindow) ); else - gdk_window_focus( m_pWindow->window, GDK_CURRENT_TIME ); + gdk_window_focus( m_pWindow->window, gdk_x11_get_server_time(GTK_WIDGET (m_pWindow)->window) ); /* need to do an XSetInputFocus here because * gdk_window_focus will ask a EWMH compliant WM to put the focus * to our window - which it of course won't since our input hint diff --git a/vcl/unx/inc/saldisp.hxx b/vcl/unx/inc/saldisp.hxx index d662ce51d855..dbb8b7bd7ec4 100644 --- a/vcl/unx/inc/saldisp.hxx +++ b/vcl/unx/inc/saldisp.hxx @@ -399,6 +399,8 @@ protected: bool m_bUseRandRWrapper; // don't use randr on gtk, use gdk signals there + mutable XLIB_Time m_nLastUserEventTime; // mutable because changed on first access + void DestroyFontCache(); virtual long Dispatch( XEvent *pEvent ) = 0; void InitXinerama(); @@ -495,6 +497,7 @@ public: bool GetExactResolution() const { return mbExactResolution; } ULONG GetProperties() const { return nProperties_; } ULONG GetMaxRequestSize() const { return nMaxRequestSize_; } + XLIB_Time GetLastUserEventTime() const; BOOL MouseCaptured( const SalFrame *pFrameData ) const { return m_pCapture == pFrameData; } diff --git a/vcl/unx/inc/wmadaptor.hxx b/vcl/unx/inc/wmadaptor.hxx index 1eec613d7568..a6146748fb8a 100644 --- a/vcl/unx/inc/wmadaptor.hxx +++ b/vcl/unx/inc/wmadaptor.hxx @@ -73,6 +73,7 @@ public: NET_WM_STATE_FULLSCREEN, NET_WM_STRUT, NET_WM_STRUT_PARTIAL, + NET_WM_USER_TIME, NET_WM_WINDOW_TYPE, NET_WM_WINDOW_TYPE_DESKTOP, NET_WM_WINDOW_TYPE_DIALOG, @@ -117,6 +118,7 @@ public: SAL_QUITEVENT, SAL_USEREVENT, SAL_EXTTEXTEVENT, + SAL_GETTIMEEVENT, DTWM_IS_RUNNING, VCL_SYSTEM_SETTINGS, XSETTINGS, @@ -241,6 +243,11 @@ public: int top_start_x, int top_end_x, int bottom_start_x, int bottom_end_x ) const; /* + * set _NET_WM_USER_TIME property, if NetWM + */ + virtual void setUserTime( X11SalFrame* i_pFrame, long i_nUserTime ) const; + + /* * tells whether fullscreen mode is supported by WM */ bool supportsFullScreen() const { return m_aWMAtoms[ NET_WM_STATE_FULLSCREEN ] != 0; } diff --git a/vcl/unx/source/app/saldisp.cxx b/vcl/unx/source/app/saldisp.cxx index f18d31890247..e09346d6cfff 100644 --- a/vcl/unx/source/app/saldisp.cxx +++ b/vcl/unx/source/app/saldisp.cxx @@ -519,7 +519,8 @@ SalDisplay::SalDisplay( Display *display ) : pDisp_( display ), m_pWMAdaptor( NULL ), m_pDtIntegrator( NULL ), - m_bUseRandRWrapper( true ) + m_bUseRandRWrapper( true ), + m_nLastUserEventTime( 0 ) { #if OSL_DEBUG_LEVEL > 1 fprintf( stderr, "SalDisplay::SalDisplay()\n" ); @@ -2331,6 +2332,7 @@ long SalX11Display::Dispatch( XEvent *pEvent ) ButtonMotionMask, pEvent ) ) ; + m_nLastUserEventTime = pEvent->xmotion.time; break; case PropertyNotify: if( pEvent->xproperty.atom == getWMAdaptor()->getAtom( WMAdaptor::VCL_SYSTEM_SETTINGS ) ) @@ -2358,7 +2360,14 @@ long SalX11Display::Dispatch( XEvent *pEvent ) GetKeyboardName( TRUE ); } break; - + case ButtonPress: + case ButtonRelease: + m_nLastUserEventTime = pEvent->xbutton.time; + break; + case XLIB_KeyPress: + case KeyRelease: + m_nLastUserEventTime = pEvent->xkey.time; + break; default: if ( GetKbdExtension()->UseExtension() @@ -2718,6 +2727,37 @@ void SalDisplay::deregisterFrame( SalFrame* pFrame ) } +extern "C" +{ + static Bool timestamp_predicate( Display*, XEvent* i_pEvent, XPointer i_pArg ) + { + SalDisplay* pSalDisplay = reinterpret_cast<SalDisplay*>(i_pArg); + if( i_pEvent->type == PropertyNotify && + i_pEvent->xproperty.window == pSalDisplay->GetDrawable( pSalDisplay->GetDefaultScreenNumber() ) && + i_pEvent->xproperty.atom == pSalDisplay->getWMAdaptor()->getAtom( WMAdaptor::SAL_GETTIMEEVENT ) + ) + return True; + + return False; + } +} + +XLIB_Time SalDisplay::GetLastUserEventTime() const +{ + if( m_nLastUserEventTime == 0 ) + { + // get current server time + unsigned char c = 0; + XEvent aEvent; + Atom nAtom = getWMAdaptor()->getAtom( WMAdaptor::SAL_GETTIMEEVENT ); + XChangeProperty( GetDisplay(), GetDrawable( GetDefaultScreenNumber() ), + nAtom, nAtom, 8, PropModeReplace, &c, 1 ); + XIfEvent( GetDisplay(), &aEvent, timestamp_predicate, (XPointer)this ); + m_nLastUserEventTime = aEvent.xproperty.time; + } + return m_nLastUserEventTime; +} + // -=-= SalVisual -=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= SalVisual::SalVisual() diff --git a/vcl/unx/source/app/wmadaptor.cxx b/vcl/unx/source/app/wmadaptor.cxx index 6c1ae35b7e3d..e099af0de0fb 100644 --- a/vcl/unx/source/app/wmadaptor.cxx +++ b/vcl/unx/source/app/wmadaptor.cxx @@ -79,6 +79,7 @@ public: int right_start_y, int right_end_y, int top_start_x, int top_end_x, int bottom_start_x, int bottom_end_x ) const; + virtual void setUserTime( X11SalFrame* i_pFrame, long i_nUserTime ) const; }; class GnomeWMAdaptor : public WMAdaptor @@ -175,11 +176,13 @@ static const WMAdaptorProtocol aAtomTab[] = { "SAL_QUITEVENT", WMAdaptor::SAL_QUITEVENT }, { "SAL_USEREVENT", WMAdaptor::SAL_USEREVENT }, { "SAL_EXTTEXTEVENT", WMAdaptor::SAL_EXTTEXTEVENT }, + { "SAL_GETTIMEEVENT", WMAdaptor::SAL_GETTIMEEVENT }, { "VCL_SYSTEM_SETTINGS", WMAdaptor::VCL_SYSTEM_SETTINGS }, { "DTWM_IS_RUNNING", WMAdaptor::DTWM_IS_RUNNING }, { "_XSETTINGS_SETTINGS", WMAdaptor::XSETTINGS }, { "_XEMBED", WMAdaptor::XEMBED }, - { "_XEMBED_INFO", WMAdaptor::XEMBED_INFO } + { "_XEMBED_INFO", WMAdaptor::XEMBED_INFO }, + { "_NET_WM_USER_TIME", WMAdaptor::NET_WM_USER_TIME } }; extern "C" { @@ -2393,3 +2396,28 @@ void NetWMAdaptor::setFrameStruts( X11SalFrame* pFrame, } } +/* + * WMAdaptor::setUserTime + */ +void WMAdaptor::setUserTime( X11SalFrame*, long ) const +{ +} + +/* + * NetWMAdaptor::setUserTime + */ +void NetWMAdaptor::setUserTime( X11SalFrame* i_pFrame, long i_nUserTime ) const +{ + if( m_aWMAtoms[NET_WM_USER_TIME] ) + { + XChangeProperty( m_pDisplay, + i_pFrame->GetShellWindow(), + m_aWMAtoms[NET_WM_USER_TIME], + XA_CARDINAL, + 32, + PropModeReplace, + (unsigned char*)&i_nUserTime, + 1 + ); + } +} diff --git a/vcl/unx/source/gdi/salgdi3.cxx b/vcl/unx/source/gdi/salgdi3.cxx index 55bb81ea5d6b..47b5f5263ce5 100644 --- a/vcl/unx/source/gdi/salgdi3.cxx +++ b/vcl/unx/source/gdi/salgdi3.cxx @@ -804,11 +804,12 @@ CairoWrapper::CairoWrapper() if( !mpCairoLib ) return; -#if 0 +#ifdef DEBUG // check cairo version int (*p_version)(); p_version = (int(*)()) osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_version" ); const int nVersion = p_version ? (*p_version)() : 0; + fprintf( stderr, "CAIRO version=%d\n", nVersion ); #endif mp_xlib_surface_create_with_xrender_format = (cairo_surface_t* (*)(Display *, Drawable , Screen *, XRenderPictFormat *, int , int )) diff --git a/vcl/unx/source/window/salframe.cxx b/vcl/unx/source/window/salframe.cxx index 65645f7b0369..053935856d27 100644 --- a/vcl/unx/source/window/salframe.cxx +++ b/vcl/unx/source/window/salframe.cxx @@ -506,6 +506,10 @@ void X11SalFrame::Init( ULONG nSalFrameStyle, int nScreen, SystemParentData* pPa 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 ); @@ -1104,7 +1108,7 @@ void X11SalFrame::SetMinClientSize( long nWidth, long nHeight ) // Show + Pos (x,y,z) + Size (width,height) // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -void X11SalFrame::Show( BOOL bVisible, BOOL /*bNoActivate*/ ) +void X11SalFrame::Show( BOOL bVisible, BOOL bNoActivate ) { if( ( bVisible && bMapped_ ) || ( !bVisible && !bMapped_ ) ) @@ -1192,6 +1196,11 @@ void X11SalFrame::Show( BOOL bVisible, BOOL /*bNoActivate*/ ) ); } + XLIB_Time nUserTime = 0; + if( ! bNoActivate && (nStyle_ & (SAL_FRAME_STYLE_OWNERDRAWDECORATION|SAL_FRAME_STYLE_TOOLWINDOW)) == 0 ) + nUserTime = pDisplay_->GetLastUserEventTime(); + GetDisplay()->getWMAdaptor()->setUserTime( this, nUserTime ); + // actually map the window if( m_bXEmbed ) askForXEmbedFocus( 0 ); |