1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include <config_features.h>
21
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>
34
35 #import "apple_remote/RemoteMainController.h"
36
37 oslThreadKey SalData::s_aAutoReleaseKey = nullptr;
38
releasePool(void * pPool)39 static void releasePool( void* pPool )
40 {
41 if( pPool )
42 [static_cast<NSAutoreleasePool*>(pPool) release];
43 }
44
SalData()45 SalData::SalData()
46 :
47 mpTimerProc( nullptr ),
48 mpInstance( nullptr ),
49 mpFirstObject( nullptr ),
50 mpFirstVD( nullptr ),
51 mpFirstPrinter( nullptr ),
52 mpFontList( nullptr ),
53 mpStatusItem( nil ),
54 mxRGBSpace( CGColorSpaceCreateWithName(kCGColorSpaceSRGB) ),
55 mxGraySpace( CGColorSpaceCreateWithName(kCGColorSpaceGenericGrayGamma2_2) ),
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 )
64 {
65 SetSalData(this);
66 maCursors.fill( INVALID_CURSOR_PTR );
67 if( s_aAutoReleaseKey == nullptr )
68 s_aAutoReleaseKey = osl_createThreadKey( releasePool );
69 }
70
~SalData()71 SalData::~SalData()
72 {
73 CGColorSpaceRelease( mxRGBSpace );
74 CGColorSpaceRelease( mxGraySpace );
75 for( NSCursor* pCurs : maCursors )
76 {
77 if( pCurs && pCurs != INVALID_CURSOR_PTR )
78 [pCurs release];
79 }
80 if( s_aAutoReleaseKey )
81 {
82 // release the last pool
83 NSAutoreleasePool* pPool = reinterpret_cast<NSAutoreleasePool*>( osl_getThreadKeyData( s_aAutoReleaseKey ) );
84 if( pPool )
85 {
86 osl_setThreadKeyData( s_aAutoReleaseKey, nullptr );
87 [pPool release];
88 }
89
90 osl_destroyThreadKey( s_aAutoReleaseKey );
91 s_aAutoReleaseKey = nullptr;
92 }
93 #if !HAVE_FEATURE_MACOSX_SANDBOX
94 if ( mpAppleRemoteMainController )
95 [mpAppleRemoteMainController release];
96 #endif
97
98 if( mpStatusItem )
99 {
100 [mpStatusItem release];
101 mpStatusItem = nil;
102 }
103 SetSalData( nullptr );
104 }
105
ensureThreadAutoreleasePool()106 void SalData::ensureThreadAutoreleasePool()
107 {
108 NSAutoreleasePool* pPool = nil;
109 if( s_aAutoReleaseKey )
110 {
111 pPool = reinterpret_cast<NSAutoreleasePool*>( osl_getThreadKeyData( s_aAutoReleaseKey ) );
112 if( ! pPool )
113 {
114 pPool = [[NSAutoreleasePool alloc] init];
115 osl_setThreadKeyData( s_aAutoReleaseKey, pPool );
116 }
117 }
118 else
119 {
120 OSL_FAIL( "no autorelease key" );
121 }
122 }
123
124 namespace {
125
load_icon_by_name(const OUString & rIconName)126 NSImage* load_icon_by_name(const OUString& rIconName)
127 {
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;
133
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
139 NSImage * image = [[NSImage alloc] initWithSize:imageRep.size];
140 [image addRepresentation:imageRep];
141 return image;
142 }
143
144 }
145
146 #define MAKE_CURSOR( vcl_name, name, name2 ) \
147 case vcl_name: \
148 aHotSpot = NSPoint{name##curs_x_hot, name##curs_y_hot}; \
149 aIconName = name2; \
150 break
151
getCursor(PointerStyle i_eStyle)152 NSCursor* SalData::getCursor( PointerStyle i_eStyle )
153 {
154 NSCursor* pCurs = maCursors[ i_eStyle ];
155 if( pCurs != INVALID_CURSOR_PTR )
156 return pCurs;
157
158 NSPoint aHotSpot;
159 OUString aIconName;
160
161 switch( i_eStyle )
162 {
163 // TODO
164 MAKE_CURSOR( PointerStyle::Wait, wait_, RID_CURSOR_WAIT );
165 MAKE_CURSOR( PointerStyle::NWSize, nwsize_, RID_CURSOR_NWSIZE );
166 MAKE_CURSOR( PointerStyle::NESize, nesize_, RID_CURSOR_NESIZE );
167 MAKE_CURSOR( PointerStyle::SWSize, swsize_, RID_CURSOR_SWSIZE );
168 MAKE_CURSOR( PointerStyle::SESize, sesize_, RID_CURSOR_SESIZE );
169 MAKE_CURSOR( PointerStyle::WindowNWSize, window_nwsize_, RID_CURSOR_WINDOW_NWSIZE );
170 MAKE_CURSOR( PointerStyle::WindowNESize, window_nesize_, RID_CURSOR_WINDOW_NESIZE );
171 MAKE_CURSOR( PointerStyle::WindowSWSize, window_swsize_, RID_CURSOR_WINDOW_SWSIZE );
172 MAKE_CURSOR( PointerStyle::WindowSESize, window_sesize_, RID_CURSOR_WINDOW_SESIZE );
173
174 MAKE_CURSOR( PointerStyle::Help, help_, RID_CURSOR_HELP );
175 MAKE_CURSOR( PointerStyle::Pen, pen_, RID_CURSOR_PEN );
176 MAKE_CURSOR( PointerStyle::Null, null, RID_CURSOR_NULL );
177 MAKE_CURSOR( PointerStyle::Magnify, magnify_, RID_CURSOR_MAGNIFY );
178 MAKE_CURSOR( PointerStyle::Fill, fill_, RID_CURSOR_FILL );
179 MAKE_CURSOR( PointerStyle::MoveData, movedata_, RID_CURSOR_MOVE_DATA );
180 MAKE_CURSOR( PointerStyle::CopyData, copydata_, RID_CURSOR_COPY_DATA );
181 MAKE_CURSOR( PointerStyle::MoveFile, movefile_, RID_CURSOR_MOVE_FILE );
182 MAKE_CURSOR( PointerStyle::CopyFile, copyfile_, RID_CURSOR_COPY_FILE );
183 MAKE_CURSOR( PointerStyle::MoveFiles, movefiles_, RID_CURSOR_MOVE_FILES );
184 MAKE_CURSOR( PointerStyle::CopyFiles, copyfiles_, RID_CURSOR_COPY_FILES );
185 MAKE_CURSOR( PointerStyle::NotAllowed, nodrop_, RID_CURSOR_NOT_ALLOWED );
186 MAKE_CURSOR( PointerStyle::Rotate, rotate_, RID_CURSOR_ROTATE );
187 MAKE_CURSOR( PointerStyle::HShear, hshear_, RID_CURSOR_H_SHEAR );
188 MAKE_CURSOR( PointerStyle::VShear, vshear_, RID_CURSOR_V_SHEAR );
189 MAKE_CURSOR( PointerStyle::DrawLine, drawline_, RID_CURSOR_DRAW_LINE );
190 MAKE_CURSOR( PointerStyle::DrawRect, drawrect_, RID_CURSOR_DRAW_RECT );
191 MAKE_CURSOR( PointerStyle::DrawPolygon, drawpolygon_, RID_CURSOR_DRAW_POLYGON );
192 MAKE_CURSOR( PointerStyle::DrawBezier, drawbezier_, RID_CURSOR_DRAW_BEZIER );
193 MAKE_CURSOR( PointerStyle::DrawArc, drawarc_, RID_CURSOR_DRAW_ARC );
194 MAKE_CURSOR( PointerStyle::DrawPie, drawpie_, RID_CURSOR_DRAW_PIE );
195 MAKE_CURSOR( PointerStyle::DrawCircleCut, drawcirclecut_, RID_CURSOR_DRAW_CIRCLE_CUT );
196 MAKE_CURSOR( PointerStyle::DrawEllipse, drawellipse_, RID_CURSOR_DRAW_ELLIPSE );
197 MAKE_CURSOR( PointerStyle::DrawConnect, drawconnect_, RID_CURSOR_DRAW_CONNECT );
198 MAKE_CURSOR( PointerStyle::DrawText, drawtext_, RID_CURSOR_DRAW_TEXT );
199 MAKE_CURSOR( PointerStyle::Mirror, mirror_, RID_CURSOR_MIRROR );
200 MAKE_CURSOR( PointerStyle::Crook, crook_, RID_CURSOR_CROOK );
201 MAKE_CURSOR( PointerStyle::Crop, crop_, RID_CURSOR_CROP );
202 MAKE_CURSOR( PointerStyle::MovePoint, movepoint_, RID_CURSOR_MOVE_POINT );
203 MAKE_CURSOR( PointerStyle::MoveBezierWeight, movebezierweight_, RID_CURSOR_MOVE_BEZIER_WEIGHT );
204 MAKE_CURSOR( PointerStyle::DrawFreehand, drawfreehand_, RID_CURSOR_DRAW_FREEHAND );
205 MAKE_CURSOR( PointerStyle::DrawCaption, drawcaption_, RID_CURSOR_DRAW_CAPTION );
206 MAKE_CURSOR( PointerStyle::LinkData, linkdata_, RID_CURSOR_LINK_DATA );
207 MAKE_CURSOR( PointerStyle::MoveDataLink, movedlnk_, RID_CURSOR_MOVE_DATA_LINK );
208 MAKE_CURSOR( PointerStyle::CopyDataLink, copydlnk_, RID_CURSOR_COPY_DATA_LINK );
209 MAKE_CURSOR( PointerStyle::LinkFile, linkfile_, RID_CURSOR_LINK_FILE );
210 MAKE_CURSOR( PointerStyle::MoveFileLink, moveflnk_, RID_CURSOR_MOVE_FILE_LINK );
211 MAKE_CURSOR( PointerStyle::CopyFileLink, copyflnk_, RID_CURSOR_COPY_FILE_LINK );
212 MAKE_CURSOR( PointerStyle::Chart, chart_, RID_CURSOR_CHART );
213 MAKE_CURSOR( PointerStyle::Detective, detective_, RID_CURSOR_DETECTIVE );
214 MAKE_CURSOR( PointerStyle::PivotCol, pivotcol_, RID_CURSOR_PIVOT_COLUMN );
215 MAKE_CURSOR( PointerStyle::PivotRow, pivotrow_, RID_CURSOR_PIVOT_ROW );
216 MAKE_CURSOR( PointerStyle::PivotField, pivotfld_, RID_CURSOR_PIVOT_FIELD );
217 MAKE_CURSOR( PointerStyle::PivotDelete, pivotdel_, RID_CURSOR_PIVOT_DELETE );
218 MAKE_CURSOR( PointerStyle::Chain, chain_, RID_CURSOR_CHAIN );
219 MAKE_CURSOR( PointerStyle::ChainNotAllowed, chainnot_, RID_CURSOR_CHAIN_NOT_ALLOWED );
220 MAKE_CURSOR( PointerStyle::AutoScrollN, asn_, RID_CURSOR_AUTOSCROLL_N );
221 MAKE_CURSOR( PointerStyle::AutoScrollS, ass_, RID_CURSOR_AUTOSCROLL_S );
222 MAKE_CURSOR( PointerStyle::AutoScrollW, asw_, RID_CURSOR_AUTOSCROLL_W );
223 MAKE_CURSOR( PointerStyle::AutoScrollE, ase_, RID_CURSOR_AUTOSCROLL_E );
224 MAKE_CURSOR( PointerStyle::AutoScrollNW, asnw_, RID_CURSOR_AUTOSCROLL_NW );
225 MAKE_CURSOR( PointerStyle::AutoScrollNE, asne_, RID_CURSOR_AUTOSCROLL_NE );
226 MAKE_CURSOR( PointerStyle::AutoScrollSW, assw_, RID_CURSOR_AUTOSCROLL_SW );
227 MAKE_CURSOR( PointerStyle::AutoScrollSE, asse_, RID_CURSOR_AUTOSCROLL_SE );
228 MAKE_CURSOR( PointerStyle::AutoScrollNS, asns_, RID_CURSOR_AUTOSCROLL_NS );
229 MAKE_CURSOR( PointerStyle::AutoScrollWE, aswe_, RID_CURSOR_AUTOSCROLL_WE );
230 MAKE_CURSOR( PointerStyle::AutoScrollNSWE, asnswe_, RID_CURSOR_AUTOSCROLL_NSWE );
231 MAKE_CURSOR( PointerStyle::TextVertical, vertcurs_, RID_CURSOR_TEXT_VERTICAL );
232
233 // #i32329#
234 MAKE_CURSOR( PointerStyle::TabSelectS, tblsels_, RID_CURSOR_TAB_SELECT_S );
235 MAKE_CURSOR( PointerStyle::TabSelectE, tblsele_, RID_CURSOR_TAB_SELECT_E );
236 MAKE_CURSOR( PointerStyle::TabSelectSE, tblselse_, RID_CURSOR_TAB_SELECT_SE );
237 MAKE_CURSOR( PointerStyle::TabSelectW, tblselw_, RID_CURSOR_TAB_SELECT_W );
238 MAKE_CURSOR( PointerStyle::TabSelectSW, tblselsw_, RID_CURSOR_TAB_SELECT_SW );
239
240 MAKE_CURSOR( PointerStyle::HideWhitespace, hidewhitespace_, RID_CURSOR_HIDE_WHITESPACE );
241 MAKE_CURSOR( PointerStyle::ShowWhitespace, showwhitespace_, RID_CURSOR_SHOW_WHITESPACE );
242
243 MAKE_CURSOR( PointerStyle::FatCross, fatcross_, RID_CURSOR_FATCROSS );
244
245 default:
246 SAL_WARN( "vcl", "pointer style " << static_cast<sal_Int32>(i_eStyle) << "not implemented" );
247 assert( false && "pointer style not implemented" );
248 break;
249 }
250
251 NSImage* theImage = load_icon_by_name(aIconName);
252 pCurs = [[NSCursor alloc] initWithImage: theImage hotSpot: aHotSpot];
253
254 maCursors[ i_eStyle ] = pCurs;
255 return pCurs;
256 }
257
getStatusItem()258 NSStatusItem* SalData::getStatusItem()
259 {
260 SalData* pData = GetSalData();
261 if( ! pData->mpStatusItem )
262 {
263 NSStatusBar* pStatBar =[NSStatusBar systemStatusBar];
264 if( pStatBar )
265 {
266 pData->mpStatusItem = [pStatBar statusItemWithLength: NSVariableStatusItemLength];
267 [pData->mpStatusItem retain];
268 OOStatusItemView* pView = [[OOStatusItemView alloc] init];
269 SAL_WNODEPRECATED_DECLARATIONS_PUSH
270 // "'setView:' is deprecated: first deprecated in macOS 10.14 - Use the standard
271 // button property instead"
272 [pData->mpStatusItem setView: pView ];
273 SAL_WNODEPRECATED_DECLARATIONS_POP
274 [pView display];
275 }
276 }
277 return pData->mpStatusItem;
278 }
279
280 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
281