Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / vcl / osx / saldata.cxx
blobef46d6f4aa604f44f967a839308352a55715c56e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
22 #include <osl/diagnose.h>
23 #include <osx/saldata.hxx>
24 #include <osx/salnsmenu.h>
25 #include <osx/salinst.h>
26 #include <o3tl/enumarray.hxx>
27 #include <tools/stream.hxx>
28 #include <vcl/ImageTree.hxx>
29 #include <vcl/settings.hxx>
30 #include <i18nlangtag/languagetag.hxx>
31 #include <sal/log.hxx>
32 #include <bitmaps.hlst>
33 #include <cursor_hotspots.hxx>
35 #import "apple_remote/RemoteMainController.h"
37 oslThreadKey SalData::s_aAutoReleaseKey = nullptr;
39 static void releasePool( void* pPool )
41 if( pPool )
42 [static_cast<NSAutoreleasePool*>(pPool) release];
45 SalData::SalData()
47 mpTimerProc( nullptr ),
48 mpInstance( nullptr ),
49 mpFirstObject( nullptr ),
50 mpFirstVD( nullptr ),
51 mpFirstPrinter( nullptr ),
52 mpFontList( nullptr ),
53 mpStatusItem( nil ),
54 mxRGBSpace( CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB) ),
55 mxGraySpace( CGColorSpaceCreateWithName(kCGColorSpaceGenericGray) ),
56 maCursors(),
57 mbIsScrollbarDoubleMax( false ),
58 #if !HAVE_FEATURE_MACOSX_SANDBOX
59 mpAppleRemoteMainController( nullptr ),
60 #endif
61 mpDockIconClickHandler( nil ),
62 mnDPIX( 0 ),
63 mnDPIY( 0 )
65 SetSalData(this);
66 maCursors.fill( INVALID_CURSOR_PTR );
67 if( s_aAutoReleaseKey == nullptr )
68 s_aAutoReleaseKey = osl_createThreadKey( releasePool );
71 SalData::~SalData()
73 CGColorSpaceRelease( mxRGBSpace );
74 CGColorSpaceRelease( mxGraySpace );
75 for( NSCursor* pCurs : maCursors )
77 if( pCurs && pCurs != INVALID_CURSOR_PTR )
78 [pCurs release];
80 if( s_aAutoReleaseKey )
82 // release the last pool
83 NSAutoreleasePool* pPool = reinterpret_cast<NSAutoreleasePool*>( osl_getThreadKeyData( s_aAutoReleaseKey ) );
84 if( pPool )
86 osl_setThreadKeyData( s_aAutoReleaseKey, nullptr );
87 [pPool release];
90 osl_destroyThreadKey( s_aAutoReleaseKey );
91 s_aAutoReleaseKey = nullptr;
93 #if !HAVE_FEATURE_MACOSX_SANDBOX
94 if ( mpAppleRemoteMainController )
95 [mpAppleRemoteMainController release];
96 #endif
98 if( mpStatusItem )
100 [mpStatusItem release];
101 mpStatusItem = nil;
103 SetSalData( nullptr );
106 void SalData::ensureThreadAutoreleasePool()
108 NSAutoreleasePool* pPool = nil;
109 if( s_aAutoReleaseKey )
111 pPool = reinterpret_cast<NSAutoreleasePool*>( osl_getThreadKeyData( s_aAutoReleaseKey ) );
112 if( ! pPool )
114 pPool = [[NSAutoreleasePool alloc] init];
115 osl_setThreadKeyData( s_aAutoReleaseKey, pPool );
118 else
120 OSL_FAIL( "no autorelease key" );
124 namespace {
126 NSImage* load_icon_by_name(const OUString& rIconName)
128 OUString sIconTheme = Application::GetSettings().GetStyleSettings().DetermineIconTheme();
129 OUString sUILang = Application::GetSettings().GetUILanguageTag().getBcp47();
130 auto xMemStm = ImageTree::get().getImageStream(rIconName, sIconTheme, sUILang);
131 if (!xMemStm)
132 return nullptr;
134 auto data = xMemStm->GetData();
135 auto length = xMemStm->TellEnd();
136 NSData * byteData = [NSData dataWithBytes:data length:length];
137 NSBitmapImageRep * imageRep = [NSBitmapImageRep imageRepWithData:byteData];
138 NSSize imageSize = NSMakeSize(CGImageGetWidth([imageRep CGImage]), CGImageGetHeight([imageRep CGImage]));
140 NSImage * image = [[NSImage alloc] initWithSize:imageSize];
141 [image addRepresentation:imageRep];
142 return image;
147 #define MAKE_CURSOR( vcl_name, name, name2 ) \
148 case vcl_name: \
149 aHotSpot = NSPoint{name##curs_x_hot, name##curs_y_hot}; \
150 aIconName = name2; \
151 break
153 NSCursor* SalData::getCursor( PointerStyle i_eStyle )
155 NSCursor* pCurs = maCursors[ i_eStyle ];
156 if( pCurs != INVALID_CURSOR_PTR )
157 return pCurs;
159 NSPoint aHotSpot;
160 OUString aIconName;
162 switch( i_eStyle )
164 // TODO
165 MAKE_CURSOR( PointerStyle::Wait, wait_, RID_CURSOR_WAIT );
166 MAKE_CURSOR( PointerStyle::NWSize, nwsize_, RID_CURSOR_NWSIZE );
167 MAKE_CURSOR( PointerStyle::NESize, nesize_, RID_CURSOR_NESIZE );
168 MAKE_CURSOR( PointerStyle::SWSize, swsize_, RID_CURSOR_SWSIZE );
169 MAKE_CURSOR( PointerStyle::SESize, sesize_, RID_CURSOR_SESIZE );
170 MAKE_CURSOR( PointerStyle::WindowNWSize, window_nwsize_, RID_CURSOR_WINDOW_NWSIZE );
171 MAKE_CURSOR( PointerStyle::WindowNESize, window_nesize_, RID_CURSOR_WINDOW_NESIZE );
172 MAKE_CURSOR( PointerStyle::WindowSWSize, window_swsize_, RID_CURSOR_WINDOW_SWSIZE );
173 MAKE_CURSOR( PointerStyle::WindowSESize, window_sesize_, RID_CURSOR_WINDOW_SESIZE );
175 MAKE_CURSOR( PointerStyle::Help, help_, RID_CURSOR_HELP );
176 MAKE_CURSOR( PointerStyle::Pen, pen_, RID_CURSOR_PEN );
177 MAKE_CURSOR( PointerStyle::Null, null, RID_CURSOR_NULL );
178 MAKE_CURSOR( PointerStyle::Magnify, magnify_, RID_CURSOR_MAGNIFY );
179 MAKE_CURSOR( PointerStyle::Fill, fill_, RID_CURSOR_FILL );
180 MAKE_CURSOR( PointerStyle::MoveData, movedata_, RID_CURSOR_MOVE_DATA );
181 MAKE_CURSOR( PointerStyle::CopyData, copydata_, RID_CURSOR_COPY_DATA );
182 MAKE_CURSOR( PointerStyle::MoveFile, movefile_, RID_CURSOR_MOVE_FILE );
183 MAKE_CURSOR( PointerStyle::CopyFile, copyfile_, RID_CURSOR_COPY_FILE );
184 MAKE_CURSOR( PointerStyle::MoveFiles, movefiles_, RID_CURSOR_MOVE_FILES );
185 MAKE_CURSOR( PointerStyle::CopyFiles, copyfiles_, RID_CURSOR_COPY_FILES );
186 MAKE_CURSOR( PointerStyle::NotAllowed, nodrop_, RID_CURSOR_NOT_ALLOWED );
187 MAKE_CURSOR( PointerStyle::Rotate, rotate_, RID_CURSOR_ROTATE );
188 MAKE_CURSOR( PointerStyle::HShear, hshear_, RID_CURSOR_H_SHEAR );
189 MAKE_CURSOR( PointerStyle::VShear, vshear_, RID_CURSOR_V_SHEAR );
190 MAKE_CURSOR( PointerStyle::DrawLine, drawline_, RID_CURSOR_DRAW_LINE );
191 MAKE_CURSOR( PointerStyle::DrawRect, drawrect_, RID_CURSOR_DRAW_RECT );
192 MAKE_CURSOR( PointerStyle::DrawPolygon, drawpolygon_, RID_CURSOR_DRAW_POLYGON );
193 MAKE_CURSOR( PointerStyle::DrawBezier, drawbezier_, RID_CURSOR_DRAW_BEZIER );
194 MAKE_CURSOR( PointerStyle::DrawArc, drawarc_, RID_CURSOR_DRAW_ARC );
195 MAKE_CURSOR( PointerStyle::DrawPie, drawpie_, RID_CURSOR_DRAW_PIE );
196 MAKE_CURSOR( PointerStyle::DrawCircleCut, drawcirclecut_, RID_CURSOR_DRAW_CIRCLE_CUT );
197 MAKE_CURSOR( PointerStyle::DrawEllipse, drawellipse_, RID_CURSOR_DRAW_ELLIPSE );
198 MAKE_CURSOR( PointerStyle::DrawConnect, drawconnect_, RID_CURSOR_DRAW_CONNECT );
199 MAKE_CURSOR( PointerStyle::DrawText, drawtext_, RID_CURSOR_DRAW_TEXT );
200 MAKE_CURSOR( PointerStyle::Mirror, mirror_, RID_CURSOR_MIRROR );
201 MAKE_CURSOR( PointerStyle::Crook, crook_, RID_CURSOR_CROOK );
202 MAKE_CURSOR( PointerStyle::Crop, crop_, RID_CURSOR_CROP );
203 MAKE_CURSOR( PointerStyle::MovePoint, movepoint_, RID_CURSOR_MOVE_POINT );
204 MAKE_CURSOR( PointerStyle::MoveBezierWeight, movebezierweight_, RID_CURSOR_MOVE_BEZIER_WEIGHT );
205 MAKE_CURSOR( PointerStyle::DrawFreehand, drawfreehand_, RID_CURSOR_DRAW_FREEHAND );
206 MAKE_CURSOR( PointerStyle::DrawCaption, drawcaption_, RID_CURSOR_DRAW_CAPTION );
207 MAKE_CURSOR( PointerStyle::LinkData, linkdata_, RID_CURSOR_LINK_DATA );
208 MAKE_CURSOR( PointerStyle::MoveDataLink, movedlnk_, RID_CURSOR_MOVE_DATA_LINK );
209 MAKE_CURSOR( PointerStyle::CopyDataLink, copydlnk_, RID_CURSOR_COPY_DATA_LINK );
210 MAKE_CURSOR( PointerStyle::LinkFile, linkfile_, RID_CURSOR_LINK_FILE );
211 MAKE_CURSOR( PointerStyle::MoveFileLink, moveflnk_, RID_CURSOR_MOVE_FILE_LINK );
212 MAKE_CURSOR( PointerStyle::CopyFileLink, copyflnk_, RID_CURSOR_COPY_FILE_LINK );
213 MAKE_CURSOR( PointerStyle::Chart, chart_, RID_CURSOR_CHART );
214 MAKE_CURSOR( PointerStyle::Detective, detective_, RID_CURSOR_DETECTIVE );
215 MAKE_CURSOR( PointerStyle::PivotCol, pivotcol_, RID_CURSOR_PIVOT_COLUMN );
216 MAKE_CURSOR( PointerStyle::PivotRow, pivotrow_, RID_CURSOR_PIVOT_ROW );
217 MAKE_CURSOR( PointerStyle::PivotField, pivotfld_, RID_CURSOR_PIVOT_FIELD );
218 MAKE_CURSOR( PointerStyle::PivotDelete, pivotdel_, RID_CURSOR_PIVOT_DELETE );
219 MAKE_CURSOR( PointerStyle::Chain, chain_, RID_CURSOR_CHAIN );
220 MAKE_CURSOR( PointerStyle::ChainNotAllowed, chainnot_, RID_CURSOR_CHAIN_NOT_ALLOWED );
221 MAKE_CURSOR( PointerStyle::AutoScrollN, asn_, RID_CURSOR_AUTOSCROLL_N );
222 MAKE_CURSOR( PointerStyle::AutoScrollS, ass_, RID_CURSOR_AUTOSCROLL_S );
223 MAKE_CURSOR( PointerStyle::AutoScrollW, asw_, RID_CURSOR_AUTOSCROLL_W );
224 MAKE_CURSOR( PointerStyle::AutoScrollE, ase_, RID_CURSOR_AUTOSCROLL_E );
225 MAKE_CURSOR( PointerStyle::AutoScrollNW, asnw_, RID_CURSOR_AUTOSCROLL_NW );
226 MAKE_CURSOR( PointerStyle::AutoScrollNE, asne_, RID_CURSOR_AUTOSCROLL_NE );
227 MAKE_CURSOR( PointerStyle::AutoScrollSW, assw_, RID_CURSOR_AUTOSCROLL_SW );
228 MAKE_CURSOR( PointerStyle::AutoScrollSE, asse_, RID_CURSOR_AUTOSCROLL_SE );
229 MAKE_CURSOR( PointerStyle::AutoScrollNS, asns_, RID_CURSOR_AUTOSCROLL_NS );
230 MAKE_CURSOR( PointerStyle::AutoScrollWE, aswe_, RID_CURSOR_AUTOSCROLL_WE );
231 MAKE_CURSOR( PointerStyle::AutoScrollNSWE, asnswe_, RID_CURSOR_AUTOSCROLL_NSWE );
232 MAKE_CURSOR( PointerStyle::TextVertical, vertcurs_, RID_CURSOR_TEXT_VERTICAL );
234 // #i32329#
235 MAKE_CURSOR( PointerStyle::TabSelectS, tblsels_, RID_CURSOR_TAB_SELECT_S );
236 MAKE_CURSOR( PointerStyle::TabSelectE, tblsele_, RID_CURSOR_TAB_SELECT_E );
237 MAKE_CURSOR( PointerStyle::TabSelectSE, tblselse_, RID_CURSOR_TAB_SELECT_SE );
238 MAKE_CURSOR( PointerStyle::TabSelectW, tblselw_, RID_CURSOR_TAB_SELECT_W );
239 MAKE_CURSOR( PointerStyle::TabSelectSW, tblselsw_, RID_CURSOR_TAB_SELECT_SW );
241 MAKE_CURSOR( PointerStyle::HideWhitespace, hidewhitespace_, RID_CURSOR_HIDE_WHITESPACE );
242 MAKE_CURSOR( PointerStyle::ShowWhitespace, showwhitespace_, RID_CURSOR_SHOW_WHITESPACE );
244 default:
245 SAL_WARN( "vcl", "pointer style " << static_cast<sal_Int32>(i_eStyle) << "not implemented" );
246 assert( false && "pointer style not implemented" );
247 break;
250 NSImage* theImage = load_icon_by_name(aIconName);
251 assert ([theImage size].width == 128 || [theImage size].width == 32);
252 if ([theImage size].width == 128)
254 // If we have a 128x128 image, generate scaled versions of it.
255 // This will result in macOS picking a reasonably sized image for different screen dpi.
256 NSSize cursorSize = NSMakeSize(32,32);
257 NSImage *multiResImage = [[NSImage alloc] initWithSize:cursorSize];
258 for (int scale = 1; scale <= 4; scale++) {
259 NSAffineTransform *xform = [[NSAffineTransform alloc] init];
260 [xform scaleBy:scale];
261 id hints = @{ NSImageHintCTM: xform };
262 CGImageRef rasterCGImage = [theImage CGImageForProposedRect:nullptr context:nil hints:hints];
263 NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithCGImage:rasterCGImage];
264 [rep setSize:cursorSize];
265 [multiResImage addRepresentation:rep];
267 pCurs = [[NSCursor alloc] initWithImage: multiResImage hotSpot: aHotSpot];
269 else
270 pCurs = [[NSCursor alloc] initWithImage: theImage hotSpot: aHotSpot];
272 maCursors[ i_eStyle ] = pCurs;
273 return pCurs;
276 NSStatusItem* SalData::getStatusItem()
278 SalData* pData = GetSalData();
279 if( ! pData->mpStatusItem )
281 NSStatusBar* pStatBar =[NSStatusBar systemStatusBar];
282 if( pStatBar )
284 pData->mpStatusItem = [pStatBar statusItemWithLength: NSVariableStatusItemLength];
285 [pData->mpStatusItem retain];
286 OOStatusItemView* pView = [[OOStatusItemView alloc] init];
287 SAL_WNODEPRECATED_DECLARATIONS_PUSH
288 // "'setView:' is deprecated: first deprecated in macOS 10.14 - Use the standard
289 // button property instead"
290 [pData->mpStatusItem setView: pView ];
291 SAL_WNODEPRECATED_DECLARATIONS_POP
292 [pView display];
295 return pData->mpStatusItem;
298 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */