diff options
Diffstat (limited to 'vcl/aqua/source')
-rw-r--r-- | vcl/aqua/source/a11y/aqua11yrolehelper.mm | 56 | ||||
-rwxr-xr-x | vcl/aqua/source/gdi/salatslayout.cxx | 102 | ||||
-rw-r--r-- | vcl/aqua/source/gdi/salgdi.cxx | 108 | ||||
-rw-r--r-- | vcl/aqua/source/gdi/salnativewidgets.cxx | 71 | ||||
-rwxr-xr-x | vcl/aqua/source/window/salframeview.mm | 153 | ||||
-rw-r--r-- | vcl/aqua/source/window/salmenu.cxx | 17 |
6 files changed, 385 insertions, 122 deletions
diff --git a/vcl/aqua/source/a11y/aqua11yrolehelper.mm b/vcl/aqua/source/a11y/aqua11yrolehelper.mm index cec0064e420f..4bf88d49d04a 100644 --- a/vcl/aqua/source/a11y/aqua11yrolehelper.mm +++ b/vcl/aqua/source/a11y/aqua11yrolehelper.mm @@ -264,58 +264,12 @@ using namespace ::com::sun::star::uno; return nativeSubrole; } -// TODO: the role description requires a localized string with a short description of the specific control -// i.e. "button" if the Role is AccessibleRole::PUSH_BUTTON. the OOo-a11y-API does not have such an attribute -// possible solution: hard-coded, non localized (english) descriptions (better than nothing, and voiceover -// reads the text in english pronounciation anyway) -// Use: NSAccessibilityRoleDescription +(id)getRoleDescriptionFrom: (NSString *) role with: (NSString *) subRole { - id roleDescription = @""; - if ( [ role isEqualToString: NSAccessibilityUnknownRole ] ) { - roleDescription = @"unknown"; - } else if ( [ role isEqualToString: NSAccessibilityComboBoxRole ] ) { - roleDescription = @"combo box"; - } else if ( [ role isEqualToString: NSAccessibilityStaticTextRole ] ) { - roleDescription = @"text"; - } else if ( [ role isEqualToString: NSAccessibilityListRole ] ) { - roleDescription = @"list"; - } else if ( [ role isEqualToString: NSAccessibilityMenuRole ] ) { - roleDescription = @"menu"; - } else if ( [ role isEqualToString: NSAccessibilityMenuItemRole ] ) { - roleDescription = @"menu item"; - } else if ( [ role isEqualToString: NSAccessibilityButtonRole ] ) { - roleDescription = @"button"; - } else if ( [ role isEqualToString: NSAccessibilityScrollBarRole ] ) { - roleDescription = @"scroll bar"; - } else if ( [ role isEqualToString: NSAccessibilityScrollAreaRole ] ) { - roleDescription = @"scroll area"; - } else if ( [ role isEqualToString: NSAccessibilityGroupRole ] ) { - roleDescription = @"group"; - } else if ( [ role isEqualToString: NSAccessibilityTextAreaRole ] ) { - roleDescription = @"text entry area"; - } else if ( [ role isEqualToString: NSAccessibilityToolbarRole ] ) { - roleDescription = @"toolbar"; - } else if ( [ role isEqualToString: NSAccessibilityTableRole ] ) { - roleDescription = @"table"; - } else if ( [ role isEqualToString: NSAccessibilityTabGroupRole ] ) { - roleDescription = @"tab group"; - } else if ( [ role isEqualToString: NSAccessibilityCheckBoxRole ] ) { - roleDescription = @"check box"; - } else if ( [ role isEqualToString: NSAccessibilityRadioGroupRole ] ) { - roleDescription = @"radio group"; - } else if ( [ role isEqualToString: NSAccessibilityRadioButtonRole ] ) { - roleDescription = @"radio button"; - } else if ( [ role isEqualToString: NSAccessibilityRowRole ] ) { - if ( [ subRole isEqualToString: NSAccessibilityOutlineRowSubrole ] ) { - roleDescription = @"outline row"; - } else if ( [ subRole isEqualToString: NSAccessibilityTableRowSubrole ] ) { - roleDescription = @"table row"; - } - } else if ( [ role isEqualToString: NSAccessibilityMenuButtonRole ] ) { - roleDescription = @"menu button"; - } else if ( [ role isEqualToString: NSAccessibilityPopUpButtonRole ] ) { - roleDescription = @"popup menu button"; - } + id roleDescription; + if ( [ subRole length ] == 0 ) + roleDescription = NSAccessibilityRoleDescription( role, nil ); + else + roleDescription = NSAccessibilityRoleDescription( role, subRole ); return roleDescription; } diff --git a/vcl/aqua/source/gdi/salatslayout.cxx b/vcl/aqua/source/gdi/salatslayout.cxx index a4827870efa9..929c8dd19c64 100755 --- a/vcl/aqua/source/gdi/salatslayout.cxx +++ b/vcl/aqua/source/gdi/salatslayout.cxx @@ -35,6 +35,8 @@ #include "salatsuifontutils.hxx" #include "tools/debug.hxx" +#include <math.h> + // ======================================================================= class ATSLayout : public SalLayout @@ -86,6 +88,7 @@ private: // mutable members since these details are all lazy initialized mutable int mnGlyphCount; // glyph count mutable Fixed mnCachedWidth; // cached value of resulting typographical width + int mnTrailingSpaceWidth; // in Pixels mutable ATSGlyphRef* mpGlyphIds; // ATSU glyph ids mutable Fixed* mpCharWidths; // map relative charpos to charwidth @@ -104,8 +107,8 @@ private: mutable class FallbackInfo* mpFallbackInfo; // x-offset relative to layout origin - // currently always zero since we use native glyph fallback - static const Fixed mnBaseAdv = 0; + // currently only used in RTL-layouts + mutable Fixed mnBaseAdv; }; class FallbackInfo @@ -130,6 +133,7 @@ ATSLayout::ATSLayout( ATSUStyle& rATSUStyle, float fFontScale ) mfFontScale( fFontScale ), mnGlyphCount( -1 ), mnCachedWidth( 0 ), + mnTrailingSpaceWidth( 0 ), mpGlyphIds( NULL ), mpCharWidths( NULL ), mpChars2Glyphs( NULL ), @@ -138,7 +142,8 @@ ATSLayout::ATSLayout( ATSUStyle& rATSUStyle, float fFontScale ) mpGlyphAdvances( NULL ), mpGlyphOrigAdvs( NULL ), mpDeltaY( NULL ), - mpFallbackInfo( NULL ) + mpFallbackInfo( NULL ), + mnBaseAdv( 0 ) {} // ----------------------------------------------------------------------- @@ -240,20 +245,43 @@ bool ATSLayout::LayoutText( ImplLayoutArgs& rArgs ) if( eStatus != noErr ) return false; - // enable "glyph fallback" - ATSUAttributeTag theTags[1]; - ByteCount theSizes[1]; - ATSUAttributeValuePtr theValues[1]; + // prepare setting of layout controls + static const int nMaxTagCount = 1; + ATSUAttributeTag aTagAttrs[ nMaxTagCount ]; + ByteCount aTagSizes[ nMaxTagCount ]; + ATSUAttributeValuePtr aTagValues[ nMaxTagCount ]; + + // prepare control of "glyph fallback" + const SalData* pSalData = GetSalData(); + ATSUFontFallbacks aFontFallbacks = pSalData->mpFontList->maFontFallbacks; + aTagAttrs[0] = kATSULineFontFallbacksTag; + aTagSizes[0] = sizeof( ATSUFontFallbacks ); + aTagValues[0] = &aFontFallbacks; - SalData* pSalData = GetSalData(); - ATSUFontFallbacks theFontFallbacks = pSalData->mpFontList->maFontFallbacks; - theTags[0] = kATSULineFontFallbacksTag; - theSizes[0] = sizeof( ATSUFontFallbacks ); - theValues[0] = &theFontFallbacks; + // set paragraph layout controls + ATSUSetLayoutControls( maATSULayout, 1, aTagAttrs, aTagSizes, aTagValues ); - ATSUSetLayoutControls( maATSULayout, 1, theTags, theSizes, theValues ); + // enable "glyph fallback" ATSUSetTransientFontMatching( maATSULayout, true ); + // control run-specific layout controls + if( (rArgs.mnFlags & SAL_LAYOUT_BIDI_STRONG) != 0 ) + { + // control BiDi defaults + MacOSBOOL nLineDirTag = kATSULeftToRightBaseDirection; + if( (rArgs.mnFlags & SAL_LAYOUT_BIDI_RTL) != 0 ) + nLineDirTag = kATSURightToLeftBaseDirection; + aTagAttrs[0] = kATSULineDirectionTag; + aTagSizes[0] = sizeof( nLineDirTag ); + aTagValues[0] = &nLineDirTag; + // set run-specific layout controls +#if 0 // why don't line-controls work as reliably as layout-controls??? + ATSUSetLineControls( maATSULayout, rArgs.mnMinCharPos, 1, aTagAttrs, aTagSizes, aTagValues ); +#else + ATSUSetLayoutControls( maATSULayout, 1, aTagAttrs, aTagSizes, aTagValues ); +#endif + } + return true; } @@ -277,12 +305,16 @@ void ATSLayout::AdjustLayout( ImplLayoutArgs& rArgs ) nPixelWidth = rArgs.mpDXArray[ mnCharCount - 1 ]; // workaround for ATSUI not using trailing spaces for justification - int nTrailingSpaceWidth = 0; + mnTrailingSpaceWidth = 0; int i = mnCharCount; while( (--i > 0) && IsSpacingGlyph( rArgs.mpStr[mnMinCharPos+i]|GF_ISCHAR ) ) - nTrailingSpaceWidth += rArgs.mpDXArray[i] - rArgs.mpDXArray[i-1]; - nOrigWidth -= nTrailingSpaceWidth; - nPixelWidth -= nTrailingSpaceWidth; + mnTrailingSpaceWidth += rArgs.mpDXArray[i] - rArgs.mpDXArray[i-1]; + nOrigWidth -= mnTrailingSpaceWidth; + nPixelWidth -= mnTrailingSpaceWidth; + // trailing spaces can be leftmost spaces in RTL-layouts + // TODO: use BiDi-algorithm to thoroughly check this assumption + if( rArgs.mnFlags & SAL_LAYOUT_BIDI_RTL) + mnBaseAdv = mnTrailingSpaceWidth; // TODO: use all mpDXArray elements for layouting } @@ -387,9 +419,19 @@ void ATSLayout::DrawText( SalGraphics& rGraphics ) const for(; it != maSubPortions.end(); ++it ) { const SubPortion& rSubPortion = *it; + // calculate sub-portion offset for rotated text + Fixed nXOfsFixed = 0, nYOfsFixed = 0; + if( rAquaGraphics.mnATSUIRotation != 0 ) + { + const double fRadians = rAquaGraphics.mnATSUIRotation * (M_PI/0xB40000); + nXOfsFixed = +rSubPortion.mnXOffset * cos( fRadians ); + nYOfsFixed = +rSubPortion.mnXOffset * sin( fRadians ); + } + + // draw sub-portions ATSUDrawText( maATSULayout, rSubPortion.mnMinCharPos, rSubPortion.mnEndCharPos - rSubPortion.mnMinCharPos, - nFixedX + rSubPortion.mnXOffset, nFixedY ); + nFixedX + nXOfsFixed, nFixedY + nYOfsFixed ); } } @@ -564,7 +606,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 ) { @@ -604,9 +648,11 @@ long ATSLayout::GetTextWidth() const // measure the bound extremas mnCachedWidth = nRightBound - nLeftBound; + // adjust for eliminated trailing space widths } - const int nScaledWidth = Fixed2Vcl( mnCachedWidth ); + int nScaledWidth = Fixed2Vcl( mnCachedWidth ); + nScaledWidth += mnTrailingSpaceWidth; return nScaledWidth; } @@ -626,6 +672,9 @@ long ATSLayout::FillDXArray( long* pDXArray ) const if( !pDXArray ) return GetTextWidth(); + // check assumptions + DBG_ASSERT( !mnTrailingSpaceWidth, "ATSLayout::FillDXArray() with nTSW!=0" ); + // initialize details about the resulting layout InitGIA(); @@ -659,9 +708,16 @@ 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; + // check assumptions + DBG_ASSERT( !mnTrailingSpaceWidth, "ATSLayout::GetTextBreak() with nTSW!=0" ); + + // initial measurement of text break position UniCharArrayOffset nBreakPos = mnMinCharPos; const ATSUTextMeasurement nATSUMaxWidth = Vcl2Fixed( nPixelWidth ); OSStatus nStatus = ATSUBreakLine( maATSULayout, mnMinCharPos, @@ -889,7 +945,8 @@ bool ATSLayout::InitGIA( ImplLayoutArgs* pArgs ) const if( pArgs && pArgs->mpDXArray ) { // TODO: non-strong-LTR case cases should be handled too - if( 0 == (~pArgs->mnFlags & (TEXT_LAYOUT_BIDI_STRONG|TEXT_LAYOUT_BIDI_LTR)) ) + if( (pArgs->mnFlags & TEXT_LAYOUT_BIDI_STRONG) + && !(pArgs->mnFlags & TEXT_LAYOUT_BIDI_RTL) ) { Fixed nSumCharWidths = 0; SubPortion aSubPortion = { mnMinCharPos, 0, 0 }; @@ -973,6 +1030,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..c39dc26f370f 100644 --- a/vcl/aqua/source/gdi/salgdi.cxx +++ b/vcl/aqua/source/gdi/salgdi.cxx @@ -36,20 +36,22 @@ #include "salbmp.h" #include "salframe.h" #include "salcolorutils.hxx" +#include "list.h" +#include "sft.h" +#include "salatsuifontutils.hxx" + #include "vcl/impfont.hxx" -#include "psprint/list.h" -#include "psprint/sft.h" +#include "vcl/sysdata.hxx" +#include "vcl/sallayout.hxx" +#include "vcl/svapp.hxx" + #include "osl/file.hxx" -#include "vos/mutex.hxx" #include "osl/process.h" -#include "rtl/bootstrap.h" -#include "rtl/strbuf.hxx" -#include "vcl/sysdata.hxx" +#include "vos/mutex.hxx" -#include "vcl/sallayout.hxx" -#include "salatsuifontutils.hxx" -#include "vcl/svapp.hxx" +#include "rtl/bootstrap.h" +#include "rtl/strbuf.hxx" #include "basegfx/range/b2drectangle.hxx" #include "basegfx/polygon/b2dpolygon.hxx" @@ -916,12 +918,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 +971,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 +1245,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; } @@ -1699,19 +1747,39 @@ BOOL AquaSalGraphics::GetGlyphOutline( long nGlyphId, basegfx::B2DPolyPolygon& r long AquaSalGraphics::GetGraphicsWidth() const { + long w = 0; if( mrContext && (mbWindow || mbVirDev) ) { - return mnWidth; //CGBitmapContextGetWidth( mrContext ); + w = mnWidth; } - else - return 0; + + if( w == 0 ) + { + if( mbWindow && mpFrame ) + w = mpFrame->maGeometry.nWidth; + } + + return w; } // ----------------------------------------------------------------------- -BOOL AquaSalGraphics::GetGlyphBoundRect( long nIndex, Rectangle& ) +BOOL AquaSalGraphics::GetGlyphBoundRect( long nGlyphId, Rectangle& rRect ) { - return sal_False; + ATSUStyle rATSUStyle = maATSUStyle; // TODO: handle glyph fallback + GlyphID aGlyphId = nGlyphId; + ATSGlyphScreenMetrics aGlyphMetrics; + OSStatus eStatus = ATSUGlyphGetScreenMetrics( rATSUStyle, + 1, &aGlyphId, 0, FALSE, !mbNonAntialiasedText, &aGlyphMetrics ); + if( eStatus != noErr ) + return false; + + const long nMinX = (long)(+aGlyphMetrics.topLeft.x * mfFontScale - 0.5); + const long nMaxX = (long)(aGlyphMetrics.width * mfFontScale + 0.5) + nMinX; + const long nMinY = (long)(-aGlyphMetrics.topLeft.y * mfFontScale - 0.5); + const long nMaxY = (long)(aGlyphMetrics.height * mfFontScale + 0.5) + nMinY; + rRect = Rectangle( nMinX, nMinY, nMaxX, nMaxY ); + return true; } // ----------------------------------------------------------------------- @@ -1815,7 +1883,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 +2529,4 @@ bool XorEmulation::UpdateTarget() } // ======================================================================= + diff --git a/vcl/aqua/source/gdi/salnativewidgets.cxx b/vcl/aqua/source/gdi/salnativewidgets.cxx index d57e42899a14..9f2c7c4fa3a7 100644 --- a/vcl/aqua/source/gdi/salnativewidgets.cxx +++ b/vcl/aqua/source/gdi/salnativewidgets.cxx @@ -290,8 +290,6 @@ BOOL AquaSalGraphics::IsNativeControlSupported( ControlType nType, ControlPart n break; case CTRL_SPINBUTTONS: - if( nPart == PART_ENTIRE_CONTROL || - nPart == PART_ALL_BUTTONS ) return false; break; @@ -695,26 +693,58 @@ BOOL AquaSalGraphics::drawNativeControl(ControlType nType, case CTRL_LISTNODE: { - HIThemeButtonDrawInfo aInfo; - aInfo.version = 0; - aInfo.kind = kThemeDisclosureButton; - aInfo.state = getState( nState ); - - aInfo.adornment = kThemeAdornmentNone; - ButtonValue aButtonValue = aValue.getTristateVal(); - switch( aButtonValue ) { - case BUTTONVALUE_ON: aInfo.value = kThemeDisclosureDown;//expanded - break; - case BUTTONVALUE_OFF: aInfo.value = kThemeDisclosureRight;//collapsed - break; - case BUTTONVALUE_DONTKNOW: //what to do? - default: - break; + if( Application::GetSettings().GetLayoutRTL() && aButtonValue == BUTTONVALUE_OFF ) + { + // FIXME: a value of kThemeDisclosureLeft + // should draw a theme compliant left disclosure triangle + // sadly this does not seem to work, so we'll draw a left + // grey equilateral triangle here ourselves. + // Perhaps some other HIThemeButtonDrawInfo setting would do the trick ? + + CGContextSetShouldAntialias( mrContext, true ); + float aGrey[] = { 0.45, 0.45, 0.45, 1.0 }; + CGContextSetFillColor( mrContext, aGrey ); + CGContextBeginPath( mrContext ); + float x = rc.origin.x + rc.size.width; + float y = rc.origin.y; + CGContextMoveToPoint( mrContext, x, y ); + y += rc.size.height; + CGContextAddLineToPoint( mrContext, x, y ); + x -= rc.size.height * 0.866; // cos( 30 degree ) is approx. 0.866 + y -= rc.size.height/2; + CGContextAddLineToPoint( mrContext, x, y ); + CGContextDrawPath( mrContext, kCGPathEOFill ); } + else + { + HIThemeButtonDrawInfo aInfo; + aInfo.version = 0; + aInfo.kind = kThemeDisclosureTriangle; + aInfo.value = kThemeDisclosureRight; + aInfo.state = getState( nState ); + + aInfo.adornment = kThemeAdornmentNone; + + switch( aButtonValue ) { + case BUTTONVALUE_ON: aInfo.value = kThemeDisclosureDown;//expanded + break; + case BUTTONVALUE_OFF: + // FIXME: this should have drawn a theme compliant disclosure triangle + // (see above) + if( Application::GetSettings().GetLayoutRTL() ) + { + aInfo.value = kThemeDisclosureLeft;//collapsed, RTL + } + break; + case BUTTONVALUE_DONTKNOW: //what to do? + default: + break; + } - HIThemeDrawButton( &rc, &aInfo, mrContext, kHIThemeOrientationNormal, NULL ); + HIThemeDrawButton( &rc, &aInfo, mrContext, kHIThemeOrientationNormal, NULL ); + } bOK = true; } break; @@ -1041,7 +1071,10 @@ BOOL AquaSalGraphics::drawNativeControl(ControlType nType, HIRect buttonRc = ImplGetHIRectFromRectangle(aSpinRect); // FIXME: without this fuzz factor there is some unwanted clipping - buttonRc.origin.x += FOCUS_RING_WIDTH + CLIP_FUZZ; + if( Application::GetSettings().GetLayoutRTL() ) + buttonRc.origin.x -= FOCUS_RING_WIDTH - CLIP_FUZZ; + else + buttonRc.origin.x += FOCUS_RING_WIDTH + CLIP_FUZZ; switch( aValue.getTristateVal() ) { diff --git a/vcl/aqua/source/window/salframeview.mm b/vcl/aqua/source/window/salframeview.mm index aee1bd351839..b491318bbb0d 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; @@ -773,18 +889,45 @@ private: if( pInsert && ( nLen = [pInsert length] ) > 0 ) { OUString aInsertString( GetOUString( pInsert ) ); - USHORT nKeyCode = 0; // aCharCode initializer is safe since aInsertString will at least contain '\0' sal_Unicode aCharCode = *aInsertString.getStr(); - // 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]; + USHORT nKeyCode = ImplMapCharCode( aCharCode ); + unsigned int nLastModifiers = mpFrame->mnLastModifierFlags; + + // #i99567# + // find out the unmodified key code + + // sanity check + if( mpLastEvent && ( [mpLastEvent type] == NSKeyDown || [mpLastEvent type] == NSKeyUp ) ) + { + // get unmodified string + NSString* pUnmodifiedString = [mpLastEvent charactersIgnoringModifiers]; + if( pUnmodifiedString && [pUnmodifiedString length] == 1 ) + { + // map the unmodified key code + unichar keyChar = [pUnmodifiedString characterAtIndex: 0]; + nKeyCode = ImplMapCharCode( keyChar ); + } + nLastModifiers = [mpLastEvent modifierFlags]; + + } + // #i99567# + // applications and vcl's edit fields ignore key events with ALT + // however we're at a place where we know text should be inserted + // so it seems we need to strip the Alt modifier here + if( (nLastModifiers & (NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask)) + == NSAlternateKeyMask ) + { + nLastModifiers = 0; + } + [self sendKeyInputAndReleaseToFrame: nKeyCode character: aCharCode modifiers: nLastModifiers]; } else { diff --git a/vcl/aqua/source/window/salmenu.cxx b/vcl/aqua/source/window/salmenu.cxx index 8128f9171ce1..9b4499cc1233 100644 --- a/vcl/aqua/source/window/salmenu.cxx +++ b/vcl/aqua/source/window/salmenu.cxx @@ -346,7 +346,6 @@ bool AquaSalMenu::ShowNativePopupMenu(FloatingWindow * pWin, const Rectangle& rR // set offsets for positioning const float offset = 9.0; - const float lineHeight = 17.0; // get the pointers AquaSalFrame * pParentAquaSalFrame = (AquaSalFrame *) pWin->ImplGetWindowImpl()->mpRealParent->ImplGetFrame(); @@ -360,21 +359,19 @@ bool AquaSalMenu::ShowNativePopupMenu(FloatingWindow * pWin, const Rectangle& rR NSMenu* pCopyMenu = [mpMenu copy]; // filter disabled elements - sal_Int32 drawnItems = removeUnusedItemsRunner( pCopyMenu ); + removeUnusedItemsRunner( pCopyMenu ); // create frame rect NSRect displayPopupFrame = NSMakeRect( rRect.nLeft+(offset-1), rRect.nTop+(offset+1), popupFrame.size.width, 0 ); pParentAquaSalFrame->VCLToCocoa(displayPopupFrame, false); - // adjust frame rect when necessary + // do the same strange semantics as vcl popup windows to arrive at a frame geometry + // in mirrored UI case; best done by actually executing the same code USHORT nArrangeIndex; - Point position = pWin->ImplCalcPos( pWin, rRect, nFlags, nArrangeIndex ); - if( position.Y() < rRect.nTop ) { - displayPopupFrame.origin.y += ( lineHeight*drawnItems ); - } - if( position.X() < rRect.nLeft ) { - displayPopupFrame.origin.x -= popupFrame.size.width; - } + pWin->SetPosPixel( pWin->ImplCalcPos( pWin, rRect, nFlags, nArrangeIndex ) ); + displayPopupFrame.origin.x = pWin->ImplGetFrame()->maGeometry.nX - pParentAquaSalFrame->maGeometry.nX + offset; + displayPopupFrame.origin.y = pWin->ImplGetFrame()->maGeometry.nY - pParentAquaSalFrame->maGeometry.nY + offset; + pParentAquaSalFrame->VCLToCocoa(displayPopupFrame, false); // open popup menu NSPopUpButtonCell * pPopUpButtonCell = [[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]; |