3a8d16ba8c
kCGColorSpaceGenericGray is deprecated and should be kCGColorSpaceGenericGrayGamma2_2, and kCGColorSpaceGenericRGB is similary deprecated and now should be kCGColorSpaceSRGB. This fixes the "color skew" issue found in a variety of tests. Change-Id: I8088b2377e03cde3f8e03e9d3778a40fc3081c4a Reviewed-on: https://gerrit.libreoffice.org/82809 Tested-by: Julien Nabet <serval2412@yahoo.fr> Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
298 lines
13 KiB
C++
298 lines
13 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
#include <config_features.h>
|
|
|
|
#include <osl/diagnose.h>
|
|
#include <osx/saldata.hxx>
|
|
#include <osx/salnsmenu.h>
|
|
#include <osx/salinst.h>
|
|
#include <o3tl/enumarray.hxx>
|
|
#include <tools/stream.hxx>
|
|
#include <vcl/ImageTree.hxx>
|
|
#include <vcl/settings.hxx>
|
|
#include <i18nlangtag/languagetag.hxx>
|
|
#include <sal/log.hxx>
|
|
#include <bitmaps.hlst>
|
|
#include <cursor_hotspots.hxx>
|
|
|
|
#import "apple_remote/RemoteMainController.h"
|
|
|
|
oslThreadKey SalData::s_aAutoReleaseKey = nullptr;
|
|
|
|
static void releasePool( void* pPool )
|
|
{
|
|
if( pPool )
|
|
[static_cast<NSAutoreleasePool*>(pPool) release];
|
|
}
|
|
|
|
SalData::SalData()
|
|
:
|
|
mpTimerProc( nullptr ),
|
|
mpInstance( nullptr ),
|
|
mpFirstObject( nullptr ),
|
|
mpFirstVD( nullptr ),
|
|
mpFirstPrinter( nullptr ),
|
|
mpFontList( nullptr ),
|
|
mpStatusItem( nil ),
|
|
mxRGBSpace( CGColorSpaceCreateWithName(kCGColorSpaceSRGB) ),
|
|
mxGraySpace( CGColorSpaceCreateWithName(kCGColorSpaceGenericGrayGamma2_2) ),
|
|
maCursors(),
|
|
mbIsScrollbarDoubleMax( false ),
|
|
#if !HAVE_FEATURE_MACOSX_SANDBOX
|
|
mpAppleRemoteMainController( nullptr ),
|
|
#endif
|
|
mpDockIconClickHandler( nil ),
|
|
mnDPIX( 0 ),
|
|
mnDPIY( 0 )
|
|
{
|
|
SetSalData(this);
|
|
maCursors.fill( INVALID_CURSOR_PTR );
|
|
if( s_aAutoReleaseKey == nullptr )
|
|
s_aAutoReleaseKey = osl_createThreadKey( releasePool );
|
|
}
|
|
|
|
SalData::~SalData()
|
|
{
|
|
CGColorSpaceRelease( mxRGBSpace );
|
|
CGColorSpaceRelease( mxGraySpace );
|
|
for( NSCursor* pCurs : maCursors )
|
|
{
|
|
if( pCurs && pCurs != INVALID_CURSOR_PTR )
|
|
[pCurs release];
|
|
}
|
|
if( s_aAutoReleaseKey )
|
|
{
|
|
// release the last pool
|
|
NSAutoreleasePool* pPool = reinterpret_cast<NSAutoreleasePool*>( osl_getThreadKeyData( s_aAutoReleaseKey ) );
|
|
if( pPool )
|
|
{
|
|
osl_setThreadKeyData( s_aAutoReleaseKey, nullptr );
|
|
[pPool release];
|
|
}
|
|
|
|
osl_destroyThreadKey( s_aAutoReleaseKey );
|
|
s_aAutoReleaseKey = nullptr;
|
|
}
|
|
#if !HAVE_FEATURE_MACOSX_SANDBOX
|
|
if ( mpAppleRemoteMainController )
|
|
[mpAppleRemoteMainController release];
|
|
#endif
|
|
|
|
if( mpStatusItem )
|
|
{
|
|
[mpStatusItem release];
|
|
mpStatusItem = nil;
|
|
}
|
|
SetSalData( nullptr );
|
|
}
|
|
|
|
void SalData::ensureThreadAutoreleasePool()
|
|
{
|
|
NSAutoreleasePool* pPool = nil;
|
|
if( s_aAutoReleaseKey )
|
|
{
|
|
pPool = reinterpret_cast<NSAutoreleasePool*>( osl_getThreadKeyData( s_aAutoReleaseKey ) );
|
|
if( ! pPool )
|
|
{
|
|
pPool = [[NSAutoreleasePool alloc] init];
|
|
osl_setThreadKeyData( s_aAutoReleaseKey, pPool );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OSL_FAIL( "no autorelease key" );
|
|
}
|
|
}
|
|
|
|
namespace {
|
|
|
|
NSImage* load_icon_by_name(const OUString& rIconName)
|
|
{
|
|
OUString sIconTheme = Application::GetSettings().GetStyleSettings().DetermineIconTheme();
|
|
OUString sUILang = Application::GetSettings().GetUILanguageTag().getBcp47();
|
|
auto xMemStm = ImageTree::get().getImageStream(rIconName, sIconTheme, sUILang);
|
|
if (!xMemStm)
|
|
return nullptr;
|
|
|
|
auto data = xMemStm->GetData();
|
|
auto length = xMemStm->TellEnd();
|
|
NSData * byteData = [NSData dataWithBytes:data length:length];
|
|
NSBitmapImageRep * imageRep = [NSBitmapImageRep imageRepWithData:byteData];
|
|
NSSize imageSize = NSMakeSize(CGImageGetWidth([imageRep CGImage]), CGImageGetHeight([imageRep CGImage]));
|
|
|
|
NSImage * image = [[NSImage alloc] initWithSize:imageSize];
|
|
[image addRepresentation:imageRep];
|
|
return image;
|
|
}
|
|
|
|
}
|
|
|
|
#define MAKE_CURSOR( vcl_name, name, name2 ) \
|
|
case vcl_name: \
|
|
aHotSpot = NSPoint{name##curs_x_hot, name##curs_y_hot}; \
|
|
aIconName = name2; \
|
|
break
|
|
|
|
NSCursor* SalData::getCursor( PointerStyle i_eStyle )
|
|
{
|
|
NSCursor* pCurs = maCursors[ i_eStyle ];
|
|
if( pCurs != INVALID_CURSOR_PTR )
|
|
return pCurs;
|
|
|
|
NSPoint aHotSpot;
|
|
OUString aIconName;
|
|
|
|
switch( i_eStyle )
|
|
{
|
|
// TODO
|
|
MAKE_CURSOR( PointerStyle::Wait, wait_, RID_CURSOR_WAIT );
|
|
MAKE_CURSOR( PointerStyle::NWSize, nwsize_, RID_CURSOR_NWSIZE );
|
|
MAKE_CURSOR( PointerStyle::NESize, nesize_, RID_CURSOR_NESIZE );
|
|
MAKE_CURSOR( PointerStyle::SWSize, swsize_, RID_CURSOR_SWSIZE );
|
|
MAKE_CURSOR( PointerStyle::SESize, sesize_, RID_CURSOR_SESIZE );
|
|
MAKE_CURSOR( PointerStyle::WindowNWSize, window_nwsize_, RID_CURSOR_WINDOW_NWSIZE );
|
|
MAKE_CURSOR( PointerStyle::WindowNESize, window_nesize_, RID_CURSOR_WINDOW_NESIZE );
|
|
MAKE_CURSOR( PointerStyle::WindowSWSize, window_swsize_, RID_CURSOR_WINDOW_SWSIZE );
|
|
MAKE_CURSOR( PointerStyle::WindowSESize, window_sesize_, RID_CURSOR_WINDOW_SESIZE );
|
|
|
|
MAKE_CURSOR( PointerStyle::Help, help_, RID_CURSOR_HELP );
|
|
MAKE_CURSOR( PointerStyle::Pen, pen_, RID_CURSOR_PEN );
|
|
MAKE_CURSOR( PointerStyle::Null, null, RID_CURSOR_NULL );
|
|
MAKE_CURSOR( PointerStyle::Magnify, magnify_, RID_CURSOR_MAGNIFY );
|
|
MAKE_CURSOR( PointerStyle::Fill, fill_, RID_CURSOR_FILL );
|
|
MAKE_CURSOR( PointerStyle::MoveData, movedata_, RID_CURSOR_MOVE_DATA );
|
|
MAKE_CURSOR( PointerStyle::CopyData, copydata_, RID_CURSOR_COPY_DATA );
|
|
MAKE_CURSOR( PointerStyle::MoveFile, movefile_, RID_CURSOR_MOVE_FILE );
|
|
MAKE_CURSOR( PointerStyle::CopyFile, copyfile_, RID_CURSOR_COPY_FILE );
|
|
MAKE_CURSOR( PointerStyle::MoveFiles, movefiles_, RID_CURSOR_MOVE_FILES );
|
|
MAKE_CURSOR( PointerStyle::CopyFiles, copyfiles_, RID_CURSOR_COPY_FILES );
|
|
MAKE_CURSOR( PointerStyle::NotAllowed, nodrop_, RID_CURSOR_NOT_ALLOWED );
|
|
MAKE_CURSOR( PointerStyle::Rotate, rotate_, RID_CURSOR_ROTATE );
|
|
MAKE_CURSOR( PointerStyle::HShear, hshear_, RID_CURSOR_H_SHEAR );
|
|
MAKE_CURSOR( PointerStyle::VShear, vshear_, RID_CURSOR_V_SHEAR );
|
|
MAKE_CURSOR( PointerStyle::DrawLine, drawline_, RID_CURSOR_DRAW_LINE );
|
|
MAKE_CURSOR( PointerStyle::DrawRect, drawrect_, RID_CURSOR_DRAW_RECT );
|
|
MAKE_CURSOR( PointerStyle::DrawPolygon, drawpolygon_, RID_CURSOR_DRAW_POLYGON );
|
|
MAKE_CURSOR( PointerStyle::DrawBezier, drawbezier_, RID_CURSOR_DRAW_BEZIER );
|
|
MAKE_CURSOR( PointerStyle::DrawArc, drawarc_, RID_CURSOR_DRAW_ARC );
|
|
MAKE_CURSOR( PointerStyle::DrawPie, drawpie_, RID_CURSOR_DRAW_PIE );
|
|
MAKE_CURSOR( PointerStyle::DrawCircleCut, drawcirclecut_, RID_CURSOR_DRAW_CIRCLE_CUT );
|
|
MAKE_CURSOR( PointerStyle::DrawEllipse, drawellipse_, RID_CURSOR_DRAW_ELLIPSE );
|
|
MAKE_CURSOR( PointerStyle::DrawConnect, drawconnect_, RID_CURSOR_DRAW_CONNECT );
|
|
MAKE_CURSOR( PointerStyle::DrawText, drawtext_, RID_CURSOR_DRAW_TEXT );
|
|
MAKE_CURSOR( PointerStyle::Mirror, mirror_, RID_CURSOR_MIRROR );
|
|
MAKE_CURSOR( PointerStyle::Crook, crook_, RID_CURSOR_CROOK );
|
|
MAKE_CURSOR( PointerStyle::Crop, crop_, RID_CURSOR_CROP );
|
|
MAKE_CURSOR( PointerStyle::MovePoint, movepoint_, RID_CURSOR_MOVE_POINT );
|
|
MAKE_CURSOR( PointerStyle::MoveBezierWeight, movebezierweight_, RID_CURSOR_MOVE_BEZIER_WEIGHT );
|
|
MAKE_CURSOR( PointerStyle::DrawFreehand, drawfreehand_, RID_CURSOR_DRAW_FREEHAND );
|
|
MAKE_CURSOR( PointerStyle::DrawCaption, drawcaption_, RID_CURSOR_DRAW_CAPTION );
|
|
MAKE_CURSOR( PointerStyle::LinkData, linkdata_, RID_CURSOR_LINK_DATA );
|
|
MAKE_CURSOR( PointerStyle::MoveDataLink, movedlnk_, RID_CURSOR_MOVE_DATA_LINK );
|
|
MAKE_CURSOR( PointerStyle::CopyDataLink, copydlnk_, RID_CURSOR_COPY_DATA_LINK );
|
|
MAKE_CURSOR( PointerStyle::LinkFile, linkfile_, RID_CURSOR_LINK_FILE );
|
|
MAKE_CURSOR( PointerStyle::MoveFileLink, moveflnk_, RID_CURSOR_MOVE_FILE_LINK );
|
|
MAKE_CURSOR( PointerStyle::CopyFileLink, copyflnk_, RID_CURSOR_COPY_FILE_LINK );
|
|
MAKE_CURSOR( PointerStyle::Chart, chart_, RID_CURSOR_CHART );
|
|
MAKE_CURSOR( PointerStyle::Detective, detective_, RID_CURSOR_DETECTIVE );
|
|
MAKE_CURSOR( PointerStyle::PivotCol, pivotcol_, RID_CURSOR_PIVOT_COLUMN );
|
|
MAKE_CURSOR( PointerStyle::PivotRow, pivotrow_, RID_CURSOR_PIVOT_ROW );
|
|
MAKE_CURSOR( PointerStyle::PivotField, pivotfld_, RID_CURSOR_PIVOT_FIELD );
|
|
MAKE_CURSOR( PointerStyle::PivotDelete, pivotdel_, RID_CURSOR_PIVOT_DELETE );
|
|
MAKE_CURSOR( PointerStyle::Chain, chain_, RID_CURSOR_CHAIN );
|
|
MAKE_CURSOR( PointerStyle::ChainNotAllowed, chainnot_, RID_CURSOR_CHAIN_NOT_ALLOWED );
|
|
MAKE_CURSOR( PointerStyle::AutoScrollN, asn_, RID_CURSOR_AUTOSCROLL_N );
|
|
MAKE_CURSOR( PointerStyle::AutoScrollS, ass_, RID_CURSOR_AUTOSCROLL_S );
|
|
MAKE_CURSOR( PointerStyle::AutoScrollW, asw_, RID_CURSOR_AUTOSCROLL_W );
|
|
MAKE_CURSOR( PointerStyle::AutoScrollE, ase_, RID_CURSOR_AUTOSCROLL_E );
|
|
MAKE_CURSOR( PointerStyle::AutoScrollNW, asnw_, RID_CURSOR_AUTOSCROLL_NW );
|
|
MAKE_CURSOR( PointerStyle::AutoScrollNE, asne_, RID_CURSOR_AUTOSCROLL_NE );
|
|
MAKE_CURSOR( PointerStyle::AutoScrollSW, assw_, RID_CURSOR_AUTOSCROLL_SW );
|
|
MAKE_CURSOR( PointerStyle::AutoScrollSE, asse_, RID_CURSOR_AUTOSCROLL_SE );
|
|
MAKE_CURSOR( PointerStyle::AutoScrollNS, asns_, RID_CURSOR_AUTOSCROLL_NS );
|
|
MAKE_CURSOR( PointerStyle::AutoScrollWE, aswe_, RID_CURSOR_AUTOSCROLL_WE );
|
|
MAKE_CURSOR( PointerStyle::AutoScrollNSWE, asnswe_, RID_CURSOR_AUTOSCROLL_NSWE );
|
|
MAKE_CURSOR( PointerStyle::TextVertical, vertcurs_, RID_CURSOR_TEXT_VERTICAL );
|
|
|
|
// #i32329#
|
|
MAKE_CURSOR( PointerStyle::TabSelectS, tblsels_, RID_CURSOR_TAB_SELECT_S );
|
|
MAKE_CURSOR( PointerStyle::TabSelectE, tblsele_, RID_CURSOR_TAB_SELECT_E );
|
|
MAKE_CURSOR( PointerStyle::TabSelectSE, tblselse_, RID_CURSOR_TAB_SELECT_SE );
|
|
MAKE_CURSOR( PointerStyle::TabSelectW, tblselw_, RID_CURSOR_TAB_SELECT_W );
|
|
MAKE_CURSOR( PointerStyle::TabSelectSW, tblselsw_, RID_CURSOR_TAB_SELECT_SW );
|
|
|
|
MAKE_CURSOR( PointerStyle::HideWhitespace, hidewhitespace_, RID_CURSOR_HIDE_WHITESPACE );
|
|
MAKE_CURSOR( PointerStyle::ShowWhitespace, showwhitespace_, RID_CURSOR_SHOW_WHITESPACE );
|
|
|
|
default:
|
|
SAL_WARN( "vcl", "pointer style " << static_cast<sal_Int32>(i_eStyle) << "not implemented" );
|
|
assert( false && "pointer style not implemented" );
|
|
break;
|
|
}
|
|
|
|
NSImage* theImage = load_icon_by_name(aIconName);
|
|
assert ([theImage size].width == 128 || [theImage size].width == 32);
|
|
if ([theImage size].width == 128)
|
|
{
|
|
// If we have a 128x128 image, generate scaled versions of it.
|
|
// This will result in macOS picking a reasonably sized image for different screen dpi.
|
|
NSSize cursorSize = NSMakeSize(32,32);
|
|
NSImage *multiResImage = [[NSImage alloc] initWithSize:cursorSize];
|
|
for (int scale = 1; scale <= 4; scale++) {
|
|
NSAffineTransform *xform = [[NSAffineTransform alloc] init];
|
|
[xform scaleBy:scale];
|
|
id hints = @{ NSImageHintCTM: xform };
|
|
CGImageRef rasterCGImage = [theImage CGImageForProposedRect:nullptr context:nil hints:hints];
|
|
NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithCGImage:rasterCGImage];
|
|
[rep setSize:cursorSize];
|
|
[multiResImage addRepresentation:rep];
|
|
}
|
|
pCurs = [[NSCursor alloc] initWithImage: multiResImage hotSpot: aHotSpot];
|
|
}
|
|
else
|
|
pCurs = [[NSCursor alloc] initWithImage: theImage hotSpot: aHotSpot];
|
|
|
|
maCursors[ i_eStyle ] = pCurs;
|
|
return pCurs;
|
|
}
|
|
|
|
NSStatusItem* SalData::getStatusItem()
|
|
{
|
|
SalData* pData = GetSalData();
|
|
if( ! pData->mpStatusItem )
|
|
{
|
|
NSStatusBar* pStatBar =[NSStatusBar systemStatusBar];
|
|
if( pStatBar )
|
|
{
|
|
pData->mpStatusItem = [pStatBar statusItemWithLength: NSVariableStatusItemLength];
|
|
[pData->mpStatusItem retain];
|
|
OOStatusItemView* pView = [[OOStatusItemView alloc] init];
|
|
SAL_WNODEPRECATED_DECLARATIONS_PUSH
|
|
// "'setView:' is deprecated: first deprecated in macOS 10.14 - Use the standard
|
|
// button property instead"
|
|
[pData->mpStatusItem setView: pView ];
|
|
SAL_WNODEPRECATED_DECLARATIONS_POP
|
|
[pView display];
|
|
}
|
|
}
|
|
return pData->mpStatusItem;
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|