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