summaryrefslogtreecommitdiff
path: root/vcl/aqua/source
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/aqua/source')
-rw-r--r--vcl/aqua/source/a11y/aqua11yrolehelper.mm56
-rwxr-xr-xvcl/aqua/source/gdi/salatslayout.cxx102
-rw-r--r--vcl/aqua/source/gdi/salgdi.cxx108
-rw-r--r--vcl/aqua/source/gdi/salnativewidgets.cxx71
-rwxr-xr-xvcl/aqua/source/window/salframeview.mm153
-rw-r--r--vcl/aqua/source/window/salmenu.cxx17
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];