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 <string>
21
22 #include <comphelper/fileurl.hxx>
23 #include <rtl/ustrbuf.hxx>
24 #include <sal/log.hxx>
25 #include <tools/long.hxx>
26 #include <o3tl/safeint.hxx>
27 #include <osl/diagnose.h>
28
29 #include <osl/file.h>
30
31 #include <vcl/event.hxx>
32 #include <vcl/inputctx.hxx>
33 #include <vcl/svapp.hxx>
34 #include <vcl/window.hxx>
35 #include <vcl/syswin.hxx>
36 #include <vcl/settings.hxx>
37
38 #include <osx/saldata.hxx>
39 #include <quartz/salgdi.h>
40 #include <osx/salframe.h>
41 #include <osx/salmenu.h>
42 #include <osx/salinst.h>
43 #include <osx/salframeview.h>
44 #include <osx/a11yfactory.h>
45 #include <osx/runinmain.hxx>
46 #include <quartz/utils.h>
47
48 #include <salwtype.hxx>
49
50 #include <premac.h>
51 #include <objc/objc-runtime.h>
52 // needed for theming
53 // FIXME: move theming code to salnativewidgets.cxx
54 #include <Carbon/Carbon.h>
55 #include <postmac.h>
56
57 using namespace std;
58
59 AquaSalFrame* AquaSalFrame::s_pCaptureFrame = nullptr;
60
AquaSalFrame(SalFrame * pParent,SalFrameStyleFlags salFrameStyle)61 AquaSalFrame::AquaSalFrame( SalFrame* pParent, SalFrameStyleFlags salFrameStyle ) :
62 mpNSWindow(nil),
63 mpNSView(nil),
64 mpDockMenuEntry(nil),
65 mpGraphics(nullptr),
66 mpParent(nullptr),
67 mnMinWidth(0),
68 mnMinHeight(0),
69 mnMaxWidth(0),
70 mnMaxHeight(0),
71 mbGraphics(false),
72 mbFullScreen( false ),
73 mbShown(false),
74 mbInitShow(true),
75 mbPositioned(false),
76 mbSized(false),
77 mbPresentation( false ),
78 mnStyle( salFrameStyle ),
79 mnStyleMask( 0 ),
80 mnLastEventTime( 0 ),
81 mnLastModifierFlags( 0 ),
82 mpMenu( nullptr ),
83 mnExtStyle( 0 ),
84 mePointerStyle( PointerStyle::Arrow ),
85 mnTrackingRectTag( 0 ),
86 mrClippingPath( nullptr ),
87 mnICOptions( InputContextFlags::NONE ),
88 mnBlinkCursorDelay ( 500 )
89 {
90 mpParent = dynamic_cast<AquaSalFrame*>(pParent);
91
92 initWindowAndView();
93
94 SalData* pSalData = GetSalData();
95 pSalData->mpInstance->insertFrame( this );
96 NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
97 if (userDefaults != nil)
98 {
99 id setting = [userDefaults objectForKey: @"NSTextInsertionPointBlinkPeriodOn"];
100 if (setting)
101 mnBlinkCursorDelay = [setting intValue];
102 else
103 {
104 setting = [userDefaults objectForKey: @"NSTextInsertionPointBlinkPeriodOff"];
105 if (setting)
106 mnBlinkCursorDelay = [setting intValue];
107 }
108 }
109 }
110
~AquaSalFrame()111 AquaSalFrame::~AquaSalFrame()
112 {
113 if (mbFullScreen)
114 doShowFullScreen(false, maGeometry.nDisplayScreenNumber);
115
116 assert( GetSalData()->mpInstance->IsMainThread() );
117
118 // if the frame is destroyed and has the current menubar
119 // set the default menubar
120 if( mpMenu && mpMenu->mbMenuBar && AquaSalMenu::pCurrentMenuBar == mpMenu )
121 AquaSalMenu::setDefaultMenu();
122
123 // cleanup clipping stuff
124 doResetClipRegion();
125
126 [SalFrameView unsetMouseFrame: this];
127
128 SalData* pSalData = GetSalData();
129 pSalData->mpInstance->eraseFrame( this );
130 pSalData->maPresentationFrames.remove( this );
131
132 SAL_WARN_IF( this == s_pCaptureFrame, "vcl", "capture frame destroyed" );
133 if( this == s_pCaptureFrame )
134 s_pCaptureFrame = nullptr;
135
136 delete mpGraphics;
137
138 if( mpDockMenuEntry )
139 {
140 NSMenu* pDock = AquaSalInstance::GetDynamicDockMenu();
141 // life cycle comment: the menu has ownership of the item, so no release
142 [pDock removeItem: mpDockMenuEntry];
143 if ([pDock numberOfItems] != 0
144 && [[pDock itemAtIndex: 0] isSeparatorItem])
145 {
146 [pDock removeItemAtIndex: 0];
147 }
148 }
149 if ( mpNSView ) {
150 [AquaA11yFactory revokeView: mpNSView];
151 [mpNSView release];
152 }
153 if ( mpNSWindow )
154 [mpNSWindow release];
155 }
156
initWindowAndView()157 void AquaSalFrame::initWindowAndView()
158 {
159 OSX_SALDATA_RUNINMAIN( initWindowAndView() )
160
161 // initialize mirroring parameters
162 // FIXME: screens changing
163 NSScreen* pNSScreen = [mpNSWindow screen];
164 if( pNSScreen == nil )
165 pNSScreen = [NSScreen mainScreen];
166 maScreenRect = [pNSScreen frame];
167
168 // calculate some default geometry
169 NSRect aVisibleRect = [pNSScreen visibleFrame];
170 CocoaToVCL( aVisibleRect );
171
172 maGeometry.nX = static_cast<int>(aVisibleRect.origin.x + aVisibleRect.size.width / 10);
173 maGeometry.nY = static_cast<int>(aVisibleRect.origin.y + aVisibleRect.size.height / 10);
174 maGeometry.nWidth = static_cast<unsigned int>(aVisibleRect.size.width * 0.8);
175 maGeometry.nHeight = static_cast<unsigned int>(aVisibleRect.size.height * 0.8);
176
177 // calculate style mask
178 SAL_WNODEPRECATED_DECLARATIONS_PUSH
179 // 'NSBorderlessWindowMask' is deprecated: first deprecated in macOS 10.12
180 // 'NSClosableWindowMask' is deprecated: first deprecated in macOS 10.12
181 // 'NSMiniaturizableWindowMask' is deprecated: first deprecated in macOS 10.12
182 // 'NSResizableWindowMask' is deprecated: first deprecated in macOS 10.12
183 // 'NSTitledWindowMask' is deprecated: first deprecated in macOS 10.12
184 if( (mnStyle & SalFrameStyleFlags::FLOAT) ||
185 (mnStyle & SalFrameStyleFlags::OWNERDRAWDECORATION) )
186 mnStyleMask = NSBorderlessWindowMask;
187 else if( mnStyle & SalFrameStyleFlags::DEFAULT )
188 {
189 mnStyleMask = NSTitledWindowMask |
190 NSMiniaturizableWindowMask |
191 NSResizableWindowMask |
192 NSClosableWindowMask;
193 // make default window "maximized"
194 maGeometry.nX = static_cast<int>(aVisibleRect.origin.x);
195 maGeometry.nY = static_cast<int>(aVisibleRect.origin.y);
196 maGeometry.nWidth = static_cast<int>(aVisibleRect.size.width);
197 maGeometry.nHeight = static_cast<int>(aVisibleRect.size.height);
198 mbPositioned = mbSized = true;
199 }
200 else
201 {
202 if( mnStyle & SalFrameStyleFlags::MOVEABLE )
203 {
204 mnStyleMask |= NSTitledWindowMask;
205 if( mpParent == nullptr )
206 mnStyleMask |= NSMiniaturizableWindowMask;
207 }
208 if( mnStyle & SalFrameStyleFlags::SIZEABLE )
209 mnStyleMask |= NSResizableWindowMask;
210 if( mnStyle & SalFrameStyleFlags::CLOSEABLE )
211 mnStyleMask |= NSClosableWindowMask;
212 // documentation says anything other than NSBorderlessWindowMask (=0)
213 // should also include NSTitledWindowMask;
214 if( mnStyleMask != 0 )
215 mnStyleMask |= NSTitledWindowMask;
216 }
217 SAL_WNODEPRECATED_DECLARATIONS_POP
218
219 if (Application::IsBitmapRendering())
220 return;
221
222 // #i91990# support GUI-less (daemon) execution
223 @try
224 {
225 mpNSWindow = [[SalFrameWindow alloc] initWithSalFrame: this];
226 mpNSView = [[SalFrameView alloc] initWithSalFrame: this];
227 }
228 @catch ( id )
229 {
230 std::abort();
231 }
232
233 if( mnStyle & SalFrameStyleFlags::TOOLTIP )
234 [mpNSWindow setIgnoresMouseEvents: YES];
235 else
236 [mpNSWindow setAcceptsMouseMovedEvents: YES];
237 [mpNSWindow setHasShadow: YES];
238
239 [mpNSWindow setDelegate: static_cast<id<NSWindowDelegate> >(mpNSWindow)];
240
241 [mpNSWindow setRestorable:NO];
242 const NSRect aRect = { NSZeroPoint, NSMakeSize( maGeometry.nWidth, maGeometry.nHeight )};
243 mnTrackingRectTag = [mpNSView addTrackingRect: aRect owner: mpNSView userData: nil assumeInside: NO];
244
245 maSysData.mpNSView = mpNSView;
246
247 UpdateFrameGeometry();
248
249 [mpNSWindow setContentView: mpNSView];
250 }
251
CocoaToVCL(NSRect & io_rRect,bool bRelativeToScreen)252 void AquaSalFrame::CocoaToVCL( NSRect& io_rRect, bool bRelativeToScreen )
253 {
254 if( bRelativeToScreen )
255 io_rRect.origin.y = maScreenRect.size.height - (io_rRect.origin.y+io_rRect.size.height);
256 else
257 io_rRect.origin.y = maGeometry.nHeight - (io_rRect.origin.y+io_rRect.size.height);
258 }
259
VCLToCocoa(NSRect & io_rRect,bool bRelativeToScreen)260 void AquaSalFrame::VCLToCocoa( NSRect& io_rRect, bool bRelativeToScreen )
261 {
262 if( bRelativeToScreen )
263 io_rRect.origin.y = maScreenRect.size.height - (io_rRect.origin.y+io_rRect.size.height);
264 else
265 io_rRect.origin.y = maGeometry.nHeight - (io_rRect.origin.y+io_rRect.size.height);
266 }
267
CocoaToVCL(NSPoint & io_rPoint,bool bRelativeToScreen)268 void AquaSalFrame::CocoaToVCL( NSPoint& io_rPoint, bool bRelativeToScreen )
269 {
270 if( bRelativeToScreen )
271 io_rPoint.y = maScreenRect.size.height - io_rPoint.y;
272 else
273 io_rPoint.y = maGeometry.nHeight - io_rPoint.y;
274 }
275
VCLToCocoa(NSPoint & io_rPoint,bool bRelativeToScreen)276 void AquaSalFrame::VCLToCocoa( NSPoint& io_rPoint, bool bRelativeToScreen )
277 {
278 if( bRelativeToScreen )
279 io_rPoint.y = maScreenRect.size.height - io_rPoint.y;
280 else
281 io_rPoint.y = maGeometry.nHeight - io_rPoint.y;
282 }
283
screenParametersChanged()284 void AquaSalFrame::screenParametersChanged()
285 {
286 OSX_SALDATA_RUNINMAIN( screenParametersChanged() )
287
288 UpdateFrameGeometry();
289
290 if( mpGraphics )
291 mpGraphics->updateResolution();
292
293 if (!mbGeometryDidChange)
294 return;
295
296 CallCallback( SalEvent::DisplayChanged, nullptr );
297 }
298
AcquireGraphics()299 SalGraphics* AquaSalFrame::AcquireGraphics()
300 {
301 if ( mbGraphics )
302 return nullptr;
303
304 if ( !mpGraphics )
305 {
306 mpGraphics = new AquaSalGraphics;
307 mpGraphics->SetWindowGraphics( this );
308 }
309
310 mbGraphics = true;
311 return mpGraphics;
312 }
313
ReleaseGraphics(SalGraphics * pGraphics)314 void AquaSalFrame::ReleaseGraphics( SalGraphics *pGraphics )
315 {
316 SAL_WARN_IF( pGraphics != mpGraphics, "vcl", "graphics released on wrong frame" );
317 mbGraphics = false;
318 }
319
PostEvent(std::unique_ptr<ImplSVEvent> pData)320 bool AquaSalFrame::PostEvent(std::unique_ptr<ImplSVEvent> pData)
321 {
322 GetSalData()->mpInstance->PostEvent( this, pData.release(), SalEvent::UserEvent );
323 return true;
324 }
325
SetTitle(const OUString & rTitle)326 void AquaSalFrame::SetTitle(const OUString& rTitle)
327 {
328 if ( !mpNSWindow )
329 return;
330
331 OSX_SALDATA_RUNINMAIN( SetTitle(rTitle) )
332
333 // #i113170# may not be the main thread if called from UNO API
334 SalData::ensureThreadAutoreleasePool();
335
336 NSString* pTitle = CreateNSString( rTitle );
337 [mpNSWindow setTitle: pTitle];
338
339 // create an entry in the dock menu
340 const SalFrameStyleFlags nAppWindowStyle = SalFrameStyleFlags::CLOSEABLE | SalFrameStyleFlags::MOVEABLE;
341 if( mpParent == nullptr &&
342 (mnStyle & nAppWindowStyle) == nAppWindowStyle )
343 {
344 if( mpDockMenuEntry == nullptr )
345 {
346 NSMenu* pDock = AquaSalInstance::GetDynamicDockMenu();
347
348 if ([pDock numberOfItems] != 0) {
349 NSMenuItem* pTopItem = [pDock itemAtIndex: 0];
350 if ( [pTopItem hasSubmenu] )
351 [pDock insertItem: [NSMenuItem separatorItem] atIndex: 0];
352 }
353
354 mpDockMenuEntry = [pDock insertItemWithTitle: pTitle
355 action: @selector(dockMenuItemTriggered:)
356 keyEquivalent: @""
357 atIndex: 0];
358 [mpDockMenuEntry setTarget: mpNSWindow];
359
360 // TODO: image (either the generic window image or an icon
361 // check mark (for "main" window ?)
362 }
363 else
364 [mpDockMenuEntry setTitle: pTitle];
365 }
366
367 if (pTitle)
368 [pTitle release];
369 }
370
SetIcon(sal_uInt16)371 void AquaSalFrame::SetIcon( sal_uInt16 )
372 {
373 }
374
SetRepresentedURL(const OUString & i_rDocURL)375 void AquaSalFrame::SetRepresentedURL( const OUString& i_rDocURL )
376 {
377 OSX_SALDATA_RUNINMAIN( SetRepresentedURL( i_rDocURL ) )
378
379 if( comphelper::isFileUrl(i_rDocURL) )
380 {
381 OUString aSysPath;
382 osl_getSystemPathFromFileURL( i_rDocURL.pData, &aSysPath.pData );
383 NSString* pStr = CreateNSString( aSysPath );
384 if( pStr )
385 {
386 [pStr autorelease];
387 [mpNSWindow setRepresentedFilename: pStr];
388 }
389 }
390 }
391
initShow()392 void AquaSalFrame::initShow()
393 {
394 OSX_SALDATA_RUNINMAIN( initShow() )
395
396 mbInitShow = false;
397 if( ! mbPositioned && ! mbFullScreen )
398 {
399 tools::Rectangle aScreenRect;
400 GetWorkArea( aScreenRect );
401 if( mpParent ) // center relative to parent
402 {
403 // center on parent
404 tools::Long nNewX = mpParent->maGeometry.nX + (static_cast<tools::Long>(mpParent->maGeometry.nWidth) - static_cast<tools::Long>(maGeometry.nWidth))/2;
405 if( nNewX < aScreenRect.Left() )
406 nNewX = aScreenRect.Left();
407 if( tools::Long(nNewX + maGeometry.nWidth) > aScreenRect.Right() )
408 nNewX = aScreenRect.Right() - maGeometry.nWidth-1;
409 tools::Long nNewY = mpParent->maGeometry.nY + (static_cast<tools::Long>(mpParent->maGeometry.nHeight) - static_cast<tools::Long>(maGeometry.nHeight))/2;
410 if( nNewY < aScreenRect.Top() )
411 nNewY = aScreenRect.Top();
412 if( nNewY > aScreenRect.Bottom() )
413 nNewY = aScreenRect.Bottom() - maGeometry.nHeight-1;
414 SetPosSize( nNewX - mpParent->maGeometry.nX,
415 nNewY - mpParent->maGeometry.nY,
416 0, 0, SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y );
417 }
418 else if( ! (mnStyle & SalFrameStyleFlags::SIZEABLE) )
419 {
420 // center on screen
421 tools::Long nNewX = (aScreenRect.GetWidth() - maGeometry.nWidth)/2;
422 tools::Long nNewY = (aScreenRect.GetHeight() - maGeometry.nHeight)/2;
423 SetPosSize( nNewX, nNewY, 0, 0, SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y );
424 }
425 }
426
427 // make sure the view is present in the wrapper list before any children receive focus
428 [AquaA11yFactory registerView: mpNSView];
429 }
430
SendPaintEvent(const tools::Rectangle * pRect)431 void AquaSalFrame::SendPaintEvent( const tools::Rectangle* pRect )
432 {
433 OSX_SALDATA_RUNINMAIN( SendPaintEvent( pRect ) )
434
435 SalPaintEvent aPaintEvt( 0, 0, maGeometry.nWidth, maGeometry.nHeight, true );
436 if( pRect )
437 {
438 aPaintEvt.mnBoundX = pRect->Left();
439 aPaintEvt.mnBoundY = pRect->Top();
440 aPaintEvt.mnBoundWidth = pRect->GetWidth();
441 aPaintEvt.mnBoundHeight = pRect->GetHeight();
442 }
443
444 CallCallback(SalEvent::Paint, &aPaintEvt);
445 }
446
Show(bool bVisible,bool bNoActivate)447 void AquaSalFrame::Show(bool bVisible, bool bNoActivate)
448 {
449 if ( !mpNSWindow )
450 return;
451
452 OSX_SALDATA_RUNINMAIN( Show(bVisible, bNoActivate) )
453
454 mbShown = bVisible;
455 if(bVisible)
456 {
457 if( mbInitShow )
458 initShow();
459
460 CallCallback(SalEvent::Resize, nullptr);
461 // trigger filling our backbuffer
462 SendPaintEvent();
463
464 if( bNoActivate || [mpNSWindow canBecomeKeyWindow] == NO )
465 [mpNSWindow orderFront: NSApp];
466 else
467 [mpNSWindow makeKeyAndOrderFront: NSApp];
468
469 if( mpParent )
470 {
471 /* #i92674# #i96433# we do not want an invisible parent to show up (which adding a visible
472 child implicitly does). However we also do not want a parentless toolbar.
473
474 HACK: try to decide when we should not insert a child to its parent
475 floaters and ownerdraw windows have not yet shown up in cases where
476 we don't want the parent to become visible
477 */
478 if( mpParent->mbShown || (mnStyle & (SalFrameStyleFlags::OWNERDRAWDECORATION | SalFrameStyleFlags::FLOAT) ) )
479 {
480 [mpParent->mpNSWindow addChildWindow: mpNSWindow ordered: NSWindowAbove];
481 }
482 }
483
484 if( mbPresentation )
485 [mpNSWindow makeMainWindow];
486 }
487 else
488 {
489 // if the frame holding the current menubar gets hidden
490 // show the default menubar
491 if( mpMenu && mpMenu->mbMenuBar && AquaSalMenu::pCurrentMenuBar == mpMenu )
492 AquaSalMenu::setDefaultMenu();
493
494 // #i90440# #i94443# work around the focus going back to some other window
495 // if a child gets hidden for a parent window
496 if( mpParent && mpParent->mbShown && [mpNSWindow isKeyWindow] )
497 [mpParent->mpNSWindow makeKeyAndOrderFront: NSApp];
498
499 [SalFrameView unsetMouseFrame: this];
500 if( mpParent && [mpNSWindow parentWindow] == mpParent->mpNSWindow )
501 [mpParent->mpNSWindow removeChildWindow: mpNSWindow];
502
503 [mpNSWindow orderOut: NSApp];
504 }
505 }
506
SetMinClientSize(tools::Long nWidth,tools::Long nHeight)507 void AquaSalFrame::SetMinClientSize( tools::Long nWidth, tools::Long nHeight )
508 {
509 OSX_SALDATA_RUNINMAIN( SetMinClientSize( nWidth, nHeight ) )
510
511 mnMinWidth = nWidth;
512 mnMinHeight = nHeight;
513
514 if( mpNSWindow )
515 {
516 // Always add the decoration as the dimension concerns only
517 // the content rectangle
518 nWidth += maGeometry.nLeftDecoration + maGeometry.nRightDecoration;
519 nHeight += maGeometry.nTopDecoration + maGeometry.nBottomDecoration;
520
521 NSSize aSize = { static_cast<CGFloat>(nWidth), static_cast<CGFloat>(nHeight) };
522
523 // Size of full window (content+structure) although we only
524 // have the client size in arguments
525 [mpNSWindow setMinSize: aSize];
526 }
527 }
528
SetMaxClientSize(tools::Long nWidth,tools::Long nHeight)529 void AquaSalFrame::SetMaxClientSize( tools::Long nWidth, tools::Long nHeight )
530 {
531 OSX_SALDATA_RUNINMAIN( SetMaxClientSize( nWidth, nHeight ) )
532
533 mnMaxWidth = nWidth;
534 mnMaxHeight = nHeight;
535
536 if( mpNSWindow )
537 {
538 // Always add the decoration as the dimension concerns only
539 // the content rectangle
540 nWidth += maGeometry.nLeftDecoration + maGeometry.nRightDecoration;
541 nHeight += maGeometry.nTopDecoration + maGeometry.nBottomDecoration;
542
543 // Carbon windows can't have a size greater than 32767x32767
544 if (nWidth>32767) nWidth=32767;
545 if (nHeight>32767) nHeight=32767;
546
547 NSSize aSize = { static_cast<CGFloat>(nWidth), static_cast<CGFloat>(nHeight) };
548
549 // Size of full window (content+structure) although we only
550 // have the client size in arguments
551 [mpNSWindow setMaxSize: aSize];
552 }
553 }
554
GetClientSize(tools::Long & rWidth,tools::Long & rHeight)555 void AquaSalFrame::GetClientSize( tools::Long& rWidth, tools::Long& rHeight )
556 {
557 if (mbShown || mbInitShow || Application::IsBitmapRendering())
558 {
559 rWidth = maGeometry.nWidth;
560 rHeight = maGeometry.nHeight;
561 }
562 else
563 {
564 rWidth = 0;
565 rHeight = 0;
566 }
567 }
568
PreparePosSize(tools::Long nX,tools::Long nY,tools::Long nWidth,tools::Long nHeight,sal_uInt16 nFlags)569 SalEvent AquaSalFrame::PreparePosSize(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, sal_uInt16 nFlags)
570 {
571 SalEvent nEvent = SalEvent::NONE;
572 assert(mpNSWindow || Application::IsBitmapRendering());
573
574 if (nFlags & (SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y))
575 {
576 mbPositioned = true;
577 nEvent = SalEvent::Move;
578 }
579
580 if (nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT))
581 {
582 mbSized = true;
583 nEvent = (nEvent == SalEvent::Move) ? SalEvent::MoveResize : SalEvent::Resize;
584 }
585
586 if (Application::IsBitmapRendering())
587 {
588 if (nFlags & SAL_FRAME_POSSIZE_X)
589 maGeometry.nX = nX;
590 if (nFlags & SAL_FRAME_POSSIZE_Y)
591 maGeometry.nY = nY;
592 if (nFlags & SAL_FRAME_POSSIZE_WIDTH)
593 {
594 maGeometry.nWidth = nWidth;
595 if (mnMaxWidth > 0 && maGeometry.nWidth > o3tl::make_unsigned(mnMaxWidth))
596 maGeometry.nWidth = mnMaxWidth;
597 if (mnMinWidth > 0 && maGeometry.nWidth < o3tl::make_unsigned(mnMinWidth))
598 maGeometry.nWidth = mnMinWidth;
599 }
600 if (nFlags & SAL_FRAME_POSSIZE_HEIGHT)
601 {
602 maGeometry.nHeight = nHeight;
603 if (mnMaxHeight > 0 && maGeometry.nHeight > o3tl::make_unsigned(mnMaxHeight))
604 maGeometry.nHeight = mnMaxHeight;
605 if (mnMinHeight > 0 && maGeometry.nHeight < o3tl::make_unsigned(mnMinHeight))
606 maGeometry.nHeight = mnMinHeight;
607 }
608 if (nEvent != SalEvent::NONE)
609 CallCallback(nEvent, nullptr);
610 }
611
612 return nEvent;
613 }
614
SetWindowState(const SalFrameState * pState)615 void AquaSalFrame::SetWindowState( const SalFrameState* pState )
616 {
617 if (!mpNSWindow && !Application::IsBitmapRendering())
618 return;
619
620 OSX_SALDATA_RUNINMAIN( SetWindowState( pState ) )
621
622 sal_uInt16 nFlags = 0;
623 nFlags |= ((pState->mnMask & WindowStateMask::X) ? SAL_FRAME_POSSIZE_X : 0);
624 nFlags |= ((pState->mnMask & WindowStateMask::Y) ? SAL_FRAME_POSSIZE_Y : 0);
625 nFlags |= ((pState->mnMask & WindowStateMask::Width) ? SAL_FRAME_POSSIZE_WIDTH : 0);
626 nFlags |= ((pState->mnMask & WindowStateMask::Height) ? SAL_FRAME_POSSIZE_HEIGHT : 0);
627
628 SalEvent nEvent = PreparePosSize(pState->mnX, pState->mnY, pState->mnWidth, pState->mnHeight, nFlags);
629 if (Application::IsBitmapRendering())
630 return;
631
632 // set normal state
633 NSRect aStateRect = [mpNSWindow frame];
634 aStateRect = [NSWindow contentRectForFrameRect: aStateRect styleMask: mnStyleMask];
635 CocoaToVCL(aStateRect);
636 if (pState->mnMask & WindowStateMask::X)
637 aStateRect.origin.x = float(pState->mnX);
638 if (pState->mnMask & WindowStateMask::Y)
639 aStateRect.origin.y = float(pState->mnY);
640 if (pState->mnMask & WindowStateMask::Width)
641 aStateRect.size.width = float(pState->mnWidth);
642 if (pState->mnMask & WindowStateMask::Height)
643 aStateRect.size.height = float(pState->mnHeight);
644 VCLToCocoa(aStateRect);
645 aStateRect = [NSWindow frameRectForContentRect: aStateRect styleMask: mnStyleMask];
646 [mpNSWindow setFrame: aStateRect display: NO];
647
648 if (pState->mnState == WindowStateState::Minimized)
649 [mpNSWindow miniaturize: NSApp];
650 else if ([mpNSWindow isMiniaturized])
651 [mpNSWindow deminiaturize: NSApp];
652
653 /* ZOOMED is not really maximized (actually it toggles between a user set size and
654 the program specified one), but comes closest since the default behavior is
655 "maximized" if the user did not intervene
656 */
657 if (pState->mnState == WindowStateState::Maximized)
658 {
659 if (![mpNSWindow isZoomed])
660 [mpNSWindow zoom: NSApp];
661 }
662 else
663 {
664 if ([mpNSWindow isZoomed])
665 [mpNSWindow zoom: NSApp];
666 }
667
668 // get new geometry
669 UpdateFrameGeometry();
670
671 // send event that we were moved/sized
672 if( nEvent != SalEvent::NONE )
673 CallCallback( nEvent, nullptr );
674
675 if (mbShown)
676 {
677 // trigger filling our backbuffer
678 SendPaintEvent();
679
680 // tell the system the views need to be updated
681 [mpNSWindow display];
682 }
683 }
684
GetWindowState(SalFrameState * pState)685 bool AquaSalFrame::GetWindowState( SalFrameState* pState )
686 {
687 if (!mpNSWindow)
688 {
689 if (Application::IsBitmapRendering())
690 {
691 pState->mnMask = WindowStateMask::X | WindowStateMask::Y
692 | WindowStateMask::Width | WindowStateMask::Height
693 | WindowStateMask::State;
694 pState->mnX = maGeometry.nX;
695 pState->mnY = maGeometry.nY;
696 pState->mnWidth = maGeometry.nWidth;
697 pState->mnHeight = maGeometry.nHeight;
698 pState->mnState = WindowStateState::Normal;
699 return true;
700 }
701 return false;
702 }
703
704 OSX_SALDATA_RUNINMAIN_UNION( GetWindowState( pState ), boolean )
705
706 pState->mnMask = WindowStateMask::X |
707 WindowStateMask::Y |
708 WindowStateMask::Width |
709 WindowStateMask::Height |
710 WindowStateMask::State;
711
712 NSRect aStateRect = [mpNSWindow frame];
713 aStateRect = [NSWindow contentRectForFrameRect: aStateRect styleMask: mnStyleMask];
714 CocoaToVCL( aStateRect );
715 pState->mnX = tools::Long(aStateRect.origin.x);
716 pState->mnY = tools::Long(aStateRect.origin.y);
717 pState->mnWidth = tools::Long(aStateRect.size.width);
718 pState->mnHeight = tools::Long(aStateRect.size.height);
719
720 if( [mpNSWindow isMiniaturized] )
721 pState->mnState = WindowStateState::Minimized;
722 else if( ! [mpNSWindow isZoomed] )
723 pState->mnState = WindowStateState::Normal;
724 else
725 pState->mnState = WindowStateState::Maximized;
726
727 return true;
728 }
729
SetScreenNumber(unsigned int nScreen)730 void AquaSalFrame::SetScreenNumber(unsigned int nScreen)
731 {
732 if ( !mpNSWindow )
733 return;
734
735 OSX_SALDATA_RUNINMAIN( SetScreenNumber( nScreen ) )
736
737 NSArray* pScreens = [NSScreen screens];
738 NSScreen* pScreen = nil;
739 if( pScreens && nScreen < [pScreens count] )
740 {
741 // get new screen frame
742 pScreen = [pScreens objectAtIndex: nScreen];
743 NSRect aNewScreen = [pScreen frame];
744
745 // get current screen frame
746 pScreen = [mpNSWindow screen];
747 if( pScreen )
748 {
749 NSRect aCurScreen = [pScreen frame];
750 if( aCurScreen.origin.x != aNewScreen.origin.x ||
751 aCurScreen.origin.y != aNewScreen.origin.y )
752 {
753 NSRect aFrameRect = [mpNSWindow frame];
754 aFrameRect.origin.x += aNewScreen.origin.x - aCurScreen.origin.x;
755 aFrameRect.origin.y += aNewScreen.origin.y - aCurScreen.origin.y;
756 [mpNSWindow setFrame: aFrameRect display: NO];
757 UpdateFrameGeometry();
758 }
759 }
760 }
761 }
762
SetApplicationID(const OUString &)763 void AquaSalFrame::SetApplicationID( const OUString &/*rApplicationID*/ )
764 {
765 }
766
ShowFullScreen(bool bFullScreen,sal_Int32 nDisplay)767 void AquaSalFrame::ShowFullScreen( bool bFullScreen, sal_Int32 nDisplay )
768 {
769 doShowFullScreen(bFullScreen, nDisplay);
770 }
771
doShowFullScreen(bool bFullScreen,sal_Int32 nDisplay)772 void AquaSalFrame::doShowFullScreen( bool bFullScreen, sal_Int32 nDisplay )
773 {
774 if (!mpNSWindow)
775 {
776 if (Application::IsBitmapRendering() && bFullScreen)
777 SetPosSize(0, 0, 1024, 768, SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT);
778 return;
779 }
780
781 SAL_INFO("vcl.osx", __func__ << ": mbFullScreen=" << mbFullScreen << ", bFullScreen=" << bFullScreen);
782
783 if( mbFullScreen == bFullScreen )
784 return;
785
786 OSX_SALDATA_RUNINMAIN( ShowFullScreen( bFullScreen, nDisplay ) )
787
788 mbFullScreen = bFullScreen;
789
790 if( bFullScreen )
791 {
792 // hide the dock and the menubar if we are on the menu screen
793 // which is always on index 0 according to documentation
794 bool bHideMenu = (nDisplay == 0);
795
796 NSRect aNewContentRect = NSZeroRect;
797 // get correct screen
798 NSScreen* pScreen = nil;
799 NSArray* pScreens = [NSScreen screens];
800 if( pScreens )
801 {
802 if( nDisplay >= 0 && o3tl::make_unsigned(nDisplay) < [pScreens count] )
803 pScreen = [pScreens objectAtIndex: nDisplay];
804 else
805 {
806 // this means span all screens
807 bHideMenu = true;
808 NSEnumerator* pEnum = [pScreens objectEnumerator];
809 while( (pScreen = [pEnum nextObject]) != nil )
810 {
811 NSRect aScreenRect = [pScreen frame];
812 if( aScreenRect.origin.x < aNewContentRect.origin.x )
813 {
814 aNewContentRect.size.width += aNewContentRect.origin.x - aScreenRect.origin.x;
815 aNewContentRect.origin.x = aScreenRect.origin.x;
816 }
817 if( aScreenRect.origin.y < aNewContentRect.origin.y )
818 {
819 aNewContentRect.size.height += aNewContentRect.origin.y - aScreenRect.origin.y;
820 aNewContentRect.origin.y = aScreenRect.origin.y;
821 }
822 if( aScreenRect.origin.x + aScreenRect.size.width > aNewContentRect.origin.x + aNewContentRect.size.width )
823 aNewContentRect.size.width = aScreenRect.origin.x + aScreenRect.size.width - aNewContentRect.origin.x;
824 if( aScreenRect.origin.y + aScreenRect.size.height > aNewContentRect.origin.y + aNewContentRect.size.height )
825 aNewContentRect.size.height = aScreenRect.origin.y + aScreenRect.size.height - aNewContentRect.origin.y;
826 }
827 }
828 }
829 if( aNewContentRect.size.width == 0 && aNewContentRect.size.height == 0 )
830 {
831 if( pScreen == nil )
832 pScreen = [mpNSWindow screen];
833 if( pScreen == nil )
834 pScreen = [NSScreen mainScreen];
835
836 aNewContentRect = [pScreen frame];
837 }
838
839 if( bHideMenu )
840 [NSMenu setMenuBarVisible:NO];
841
842 maFullScreenRect = [mpNSWindow frame];
843
844 [mpNSWindow setFrame: [NSWindow frameRectForContentRect: aNewContentRect styleMask: mnStyleMask] display: mbShown ? YES : NO];
845 }
846 else
847 {
848 [mpNSWindow setFrame: maFullScreenRect display: mbShown ? YES : NO];
849
850 // show the dock and the menubar
851 [NSMenu setMenuBarVisible:YES];
852 }
853
854 UpdateFrameGeometry();
855 if (mbShown)
856 {
857 CallCallback(SalEvent::MoveResize, nullptr);
858
859 // trigger filling our backbuffer
860 SendPaintEvent();
861 }
862 }
863
StartPresentation(bool bStart)864 void AquaSalFrame::StartPresentation( bool bStart )
865 {
866 if ( !mpNSWindow )
867 return;
868
869 OSX_SALDATA_RUNINMAIN( StartPresentation( bStart ) )
870
871 if( bStart )
872 {
873 GetSalData()->maPresentationFrames.push_back( this );
874 IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep,
875 kIOPMAssertionLevelOn,
876 CFSTR("LibreOffice presentation running"),
877 &mnAssertionID);
878 [mpNSWindow setLevel: NSPopUpMenuWindowLevel];
879 if( mbShown )
880 [mpNSWindow makeMainWindow];
881 }
882 else
883 {
884 GetSalData()->maPresentationFrames.remove( this );
885 IOPMAssertionRelease(mnAssertionID);
886 [mpNSWindow setLevel: NSNormalWindowLevel];
887 }
888 }
889
SetAlwaysOnTop(bool)890 void AquaSalFrame::SetAlwaysOnTop( bool )
891 {
892 }
893
ToTop(SalFrameToTop nFlags)894 void AquaSalFrame::ToTop(SalFrameToTop nFlags)
895 {
896 if ( !mpNSWindow )
897 return;
898
899 OSX_SALDATA_RUNINMAIN( ToTop( nFlags ) )
900
901 if( ! (nFlags & SalFrameToTop::RestoreWhenMin) )
902 {
903 if( ! [mpNSWindow isVisible] || [mpNSWindow isMiniaturized] )
904 return;
905 }
906 if( nFlags & SalFrameToTop::GrabFocus )
907 [mpNSWindow makeKeyAndOrderFront: NSApp];
908 else
909 [mpNSWindow orderFront: NSApp];
910 }
911
getCurrentCursor()912 NSCursor* AquaSalFrame::getCurrentCursor()
913 {
914 OSX_SALDATA_RUNINMAIN_POINTER( getCurrentCursor(), NSCursor* )
915
916 NSCursor* pCursor = nil;
917 switch( mePointerStyle )
918 {
919 case PointerStyle::Text: pCursor = [NSCursor IBeamCursor]; break;
920 case PointerStyle::Cross: pCursor = [NSCursor crosshairCursor]; break;
921 case PointerStyle::Hand:
922 case PointerStyle::Move: pCursor = [NSCursor openHandCursor]; break;
923 case PointerStyle::NSize: pCursor = [NSCursor resizeUpCursor]; break;
924 case PointerStyle::SSize: pCursor = [NSCursor resizeDownCursor]; break;
925 case PointerStyle::ESize: pCursor = [NSCursor resizeRightCursor]; break;
926 case PointerStyle::WSize: pCursor = [NSCursor resizeLeftCursor]; break;
927 case PointerStyle::Arrow: pCursor = [NSCursor arrowCursor]; break;
928 case PointerStyle::VSplit:
929 case PointerStyle::VSizeBar:
930 case PointerStyle::WindowNSize:
931 case PointerStyle::WindowSSize:
932 pCursor = [NSCursor resizeUpDownCursor]; break;
933 case PointerStyle::HSplit:
934 case PointerStyle::HSizeBar:
935 case PointerStyle::WindowESize:
936 case PointerStyle::WindowWSize:
937 pCursor = [NSCursor resizeLeftRightCursor]; break;
938 case PointerStyle::RefHand: pCursor = [NSCursor pointingHandCursor]; break;
939
940 default:
941 pCursor = GetSalData()->getCursor( mePointerStyle );
942 if( pCursor == nil )
943 {
944 assert( false && "unmapped cursor" );
945 pCursor = [NSCursor arrowCursor];
946 }
947 break;
948 }
949 return pCursor;
950 }
951
SetPointer(PointerStyle ePointerStyle)952 void AquaSalFrame::SetPointer( PointerStyle ePointerStyle )
953 {
954 if ( !mpNSWindow )
955 return;
956 if( ePointerStyle == mePointerStyle )
957 return;
958
959 OSX_SALDATA_RUNINMAIN( SetPointer( ePointerStyle ) )
960
961 mePointerStyle = ePointerStyle;
962
963 [mpNSWindow invalidateCursorRectsForView: mpNSView];
964 }
965
SetPointerPos(tools::Long nX,tools::Long nY)966 void AquaSalFrame::SetPointerPos( tools::Long nX, tools::Long nY )
967 {
968 OSX_SALDATA_RUNINMAIN( SetPointerPos( nX, nY ) )
969
970 // FIXME: use Cocoa functions
971 // FIXME: multiscreen support
972 CGPoint aPoint = { static_cast<CGFloat>(nX + maGeometry.nX), static_cast<CGFloat>(nY + maGeometry.nY) };
973 CGDirectDisplayID mainDisplayID = CGMainDisplayID();
974 CGDisplayMoveCursorToPoint( mainDisplayID, aPoint );
975 }
976
Flush()977 void AquaSalFrame::Flush()
978 {
979 if( !(mbGraphics && mpGraphics && mpNSView && mbShown) )
980 return;
981
982 OSX_SALDATA_RUNINMAIN( Flush() )
983
984 [mpNSView setNeedsDisplay: YES];
985
986 // outside of the application's event loop (e.g. IntroWindow)
987 // nothing would trigger paint event handling
988 // => fall back to synchronous painting
989 if( ImplGetSVData()->maAppData.mnDispatchLevel <= 0 )
990 {
991 [mpNSView display];
992 }
993 }
994
Flush(const tools::Rectangle & rRect)995 void AquaSalFrame::Flush( const tools::Rectangle& rRect )
996 {
997 if( !(mbGraphics && mpGraphics && mpNSView && mbShown) )
998 return;
999
1000 OSX_SALDATA_RUNINMAIN( Flush( rRect ) )
1001
1002 NSRect aNSRect = { { static_cast<CGFloat>(rRect.Left()), static_cast<CGFloat>(rRect.Top()) }, { static_cast<CGFloat>(rRect.GetWidth()), static_cast<CGFloat>(rRect.GetHeight()) } };
1003 VCLToCocoa( aNSRect, false );
1004 [mpNSView setNeedsDisplayInRect: aNSRect];
1005
1006 // outside of the application's event loop (e.g. IntroWindow)
1007 // nothing would trigger paint event handling
1008 // => fall back to synchronous painting
1009 if( ImplGetSVData()->maAppData.mnDispatchLevel <= 0 )
1010 {
1011 [mpNSView display];
1012 }
1013 }
1014
SetInputContext(SalInputContext * pContext)1015 void AquaSalFrame::SetInputContext( SalInputContext* pContext )
1016 {
1017 if (!pContext)
1018 {
1019 mnICOptions = InputContextFlags::NONE;
1020 return;
1021 }
1022
1023 mnICOptions = pContext->mnOptions;
1024
1025 if(!(pContext->mnOptions & InputContextFlags::Text))
1026 return;
1027 }
1028
EndExtTextInput(EndExtTextInputFlags)1029 void AquaSalFrame::EndExtTextInput( EndExtTextInputFlags )
1030 {
1031 }
1032
GetKeyName(sal_uInt16 nKeyCode)1033 OUString AquaSalFrame::GetKeyName( sal_uInt16 nKeyCode )
1034 {
1035 static std::map< sal_uInt16, OUString > aKeyMap;
1036 if( aKeyMap.empty() )
1037 {
1038 sal_uInt16 i;
1039 for( i = KEY_A; i <= KEY_Z; i++ )
1040 aKeyMap[ i ] = OUString( sal_Unicode( 'A' + (i - KEY_A) ) );
1041 for( i = KEY_0; i <= KEY_9; i++ )
1042 aKeyMap[ i ] = OUString( sal_Unicode( '0' + (i - KEY_0) ) );
1043 for( i = KEY_F1; i <= KEY_F26; i++ )
1044 {
1045 aKeyMap[ i ] = "F" + OUString::number(i - KEY_F1 + 1);
1046 }
1047
1048 aKeyMap[ KEY_DOWN ] = OUString( u'\x21e3' );
1049 aKeyMap[ KEY_UP ] = OUString( u'\x21e1' );
1050 aKeyMap[ KEY_LEFT ] = OUString( u'\x21e0' );
1051 aKeyMap[ KEY_RIGHT ] = OUString( u'\x21e2' );
1052 aKeyMap[ KEY_HOME ] = OUString( u'\x2196' );
1053 aKeyMap[ KEY_END ] = OUString( u'\x2198' );
1054 aKeyMap[ KEY_PAGEUP ] = OUString( u'\x21de' );
1055 aKeyMap[ KEY_PAGEDOWN ] = OUString( u'\x21df' );
1056 aKeyMap[ KEY_RETURN ] = OUString( u'\x21a9' );
1057 aKeyMap[ KEY_ESCAPE ] = "esc";
1058 aKeyMap[ KEY_TAB ] = OUString( u'\x21e5' );
1059 aKeyMap[ KEY_BACKSPACE ]= OUString( u'\x232b' );
1060 aKeyMap[ KEY_SPACE ] = OUString( u'\x2423' );
1061 aKeyMap[ KEY_DELETE ] = OUString( u'\x2326' );
1062 aKeyMap[ KEY_ADD ] = "+";
1063 aKeyMap[ KEY_SUBTRACT ] = "-";
1064 aKeyMap[ KEY_DIVIDE ] = "/";
1065 aKeyMap[ KEY_MULTIPLY ] = "*";
1066 aKeyMap[ KEY_POINT ] = ".";
1067 aKeyMap[ KEY_COMMA ] = ",";
1068 aKeyMap[ KEY_LESS ] = "<";
1069 aKeyMap[ KEY_GREATER ] = ">";
1070 aKeyMap[ KEY_EQUAL ] = "=";
1071 aKeyMap[ KEY_OPEN ] = OUString( u'\x23cf' );
1072 aKeyMap[ KEY_TILDE ] = "~";
1073 aKeyMap[ KEY_BRACKETLEFT ] = "[";
1074 aKeyMap[ KEY_BRACKETRIGHT ] = "]";
1075 aKeyMap[ KEY_SEMICOLON ] = ";";
1076 aKeyMap[ KEY_QUOTERIGHT ] = "'";
1077
1078 /* yet unmapped KEYCODES:
1079 aKeyMap[ KEY_INSERT ] = OUString( sal_Unicode( ) );
1080 aKeyMap[ KEY_CUT ] = OUString( sal_Unicode( ) );
1081 aKeyMap[ KEY_COPY ] = OUString( sal_Unicode( ) );
1082 aKeyMap[ KEY_PASTE ] = OUString( sal_Unicode( ) );
1083 aKeyMap[ KEY_UNDO ] = OUString( sal_Unicode( ) );
1084 aKeyMap[ KEY_REPEAT ] = OUString( sal_Unicode( ) );
1085 aKeyMap[ KEY_FIND ] = OUString( sal_Unicode( ) );
1086 aKeyMap[ KEY_PROPERTIES ] = OUString( sal_Unicode( ) );
1087 aKeyMap[ KEY_FRONT ] = OUString( sal_Unicode( ) );
1088 aKeyMap[ KEY_CONTEXTMENU ] = OUString( sal_Unicode( ) );
1089 aKeyMap[ KEY_MENU ] = OUString( sal_Unicode( ) );
1090 aKeyMap[ KEY_HELP ] = OUString( sal_Unicode( ) );
1091 aKeyMap[ KEY_HANGUL_HANJA ] = OUString( sal_Unicode( ) );
1092 aKeyMap[ KEY_DECIMAL ] = OUString( sal_Unicode( ) );
1093 aKeyMap[ KEY_QUOTELEFT ]= OUString( sal_Unicode( ) );
1094 aKeyMap[ KEY_CAPSLOCK ]= OUString( sal_Unicode( ) );
1095 aKeyMap[ KEY_NUMLOCK ]= OUString( sal_Unicode( ) );
1096 aKeyMap[ KEY_SCROLLLOCK ]= OUString( sal_Unicode( ) );
1097 */
1098
1099 }
1100
1101 OUStringBuffer aResult( 16 );
1102
1103 sal_uInt16 nUnmodifiedCode = (nKeyCode & KEY_CODE_MASK);
1104 std::map< sal_uInt16, OUString >::const_iterator it = aKeyMap.find( nUnmodifiedCode );
1105 if( it != aKeyMap.end() )
1106 {
1107 if( (nKeyCode & KEY_SHIFT) != 0 )
1108 aResult.append( u'\x21e7' ); // shift
1109 if( (nKeyCode & KEY_MOD1) != 0 )
1110 aResult.append( u'\x2318' ); // command
1111 if( (nKeyCode & KEY_MOD2) != 0 )
1112 aResult.append( u'\x2325' ); // alternate
1113 if( (nKeyCode & KEY_MOD3) != 0 )
1114 aResult.append( u'\x2303' ); // control
1115
1116 aResult.append( it->second );
1117 }
1118
1119 return aResult.makeStringAndClear();
1120 }
1121
getAppleScrollBarVariant(StyleSettings & rSettings)1122 static void getAppleScrollBarVariant(StyleSettings &rSettings)
1123 {
1124 bool bIsScrollbarDoubleMax = true; // default is DoubleMax
1125
1126 CFStringRef AppleScrollBarType = CFSTR("AppleScrollBarVariant");
1127 if( AppleScrollBarType )
1128 {
1129 CFStringRef ScrollBarVariant = static_cast<CFStringRef>(CFPreferencesCopyAppValue( AppleScrollBarType, kCFPreferencesCurrentApplication ));
1130 if( ScrollBarVariant )
1131 {
1132 if( CFGetTypeID( ScrollBarVariant ) == CFStringGetTypeID() )
1133 {
1134 // TODO: check for the less important variants "DoubleMin" and "DoubleBoth" too
1135 CFStringRef DoubleMax = CFSTR("DoubleMax");
1136 if (DoubleMax)
1137 {
1138 if ( !CFStringCompare(ScrollBarVariant, DoubleMax, kCFCompareCaseInsensitive) )
1139 bIsScrollbarDoubleMax = true;
1140 else
1141 bIsScrollbarDoubleMax = false;
1142 CFRelease(DoubleMax);
1143 }
1144 }
1145 CFRelease( ScrollBarVariant );
1146 }
1147 CFRelease(AppleScrollBarType);
1148 }
1149
1150 GetSalData()->mbIsScrollbarDoubleMax = bIsScrollbarDoubleMax;
1151
1152 CFStringRef jumpScroll = CFSTR("AppleScrollerPagingBehavior");
1153 if( jumpScroll )
1154 {
1155 CFBooleanRef jumpStr = static_cast<CFBooleanRef>(CFPreferencesCopyAppValue( jumpScroll, kCFPreferencesCurrentApplication ));
1156 if( jumpStr )
1157 {
1158 if( CFGetTypeID( jumpStr ) == CFBooleanGetTypeID() )
1159 rSettings.SetPrimaryButtonWarpsSlider(jumpStr == kCFBooleanTrue);
1160 CFRelease( jumpStr );
1161 }
1162 CFRelease( jumpScroll );
1163 }
1164 }
1165
getColor(NSColor * pSysColor,const Color & rDefault,NSWindow * pWin)1166 static Color getColor( NSColor* pSysColor, const Color& rDefault, NSWindow* pWin )
1167 {
1168 Color aRet( rDefault );
1169 if( pSysColor )
1170 {
1171 // transform to RGB
1172 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1173 // "'colorUsingColorSpaceName:device:' is deprecated: first deprecated in macOS 10.14 -
1174 // Use -colorUsingType: or -colorUsingColorSpace: instead"
1175 NSColor* pRBGColor = [pSysColor colorUsingColorSpaceName: NSDeviceRGBColorSpace device: [pWin deviceDescription]];
1176 SAL_WNODEPRECATED_DECLARATIONS_POP
1177 if( pRBGColor )
1178 {
1179 CGFloat r = 0, g = 0, b = 0, a = 0;
1180 [pRBGColor getRed: &r green: &g blue: &b alpha: &a];
1181 aRet = Color( int(r*255.999), int(g*255.999), int(b*255.999) );
1182 /*
1183 do not release here; leads to duplicate free in yield
1184 it seems the converted color comes out autoreleased, although this
1185 is not documented
1186 [pRBGColor release];
1187 */
1188 }
1189 }
1190 return aRet;
1191 }
1192
getFont(NSFont * pFont,sal_Int32 nDPIY,const vcl::Font & rDefault)1193 static vcl::Font getFont( NSFont* pFont, sal_Int32 nDPIY, const vcl::Font& rDefault )
1194 {
1195 vcl::Font aResult( rDefault );
1196 if( pFont )
1197 {
1198 aResult.SetFamilyName( GetOUString( [pFont familyName] ) );
1199 aResult.SetFontHeight( static_cast<int>(([pFont pointSize] * 72.0 / static_cast<float>(nDPIY))+0.5) );
1200 aResult.SetItalic( ([pFont italicAngle] != 0.0) ? ITALIC_NORMAL : ITALIC_NONE );
1201 // FIMXE: bold ?
1202 }
1203
1204 return aResult;
1205 }
1206
getResolution(sal_Int32 & o_rDPIX,sal_Int32 & o_rDPIY)1207 void AquaSalFrame::getResolution( sal_Int32& o_rDPIX, sal_Int32& o_rDPIY )
1208 {
1209 OSX_SALDATA_RUNINMAIN( getResolution( o_rDPIX, o_rDPIY ) )
1210
1211 if( ! mpGraphics )
1212 {
1213 AcquireGraphics();
1214 ReleaseGraphics( mpGraphics );
1215 }
1216 mpGraphics->GetResolution( o_rDPIX, o_rDPIY );
1217 }
1218
1219 // on OSX-Aqua the style settings are independent of the frame, so it does
1220 // not really belong here. Since the connection to the Appearance_Manager
1221 // is currently done in salnativewidgets.cxx this would be a good place.
1222 // On the other hand VCL's platform independent code currently only asks
1223 // SalFrames for system settings anyway, so moving the code somewhere else
1224 // doesn't make the anything cleaner for now
UpdateSettings(AllSettings & rSettings)1225 void AquaSalFrame::UpdateSettings( AllSettings& rSettings )
1226 {
1227 if ( !mpNSWindow )
1228 return;
1229
1230 OSX_SALDATA_RUNINMAIN( UpdateSettings( rSettings ) )
1231
1232 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1233 // "'lockFocus' is deprecated: first deprecated in macOS 10.14 - To draw, subclass NSView
1234 // and implement -drawRect:; AppKit's automatic deferred display mechanism will call
1235 // -drawRect: as necessary to display the view."
1236 if (![mpNSView lockFocusIfCanDraw])
1237 return;
1238 SAL_WNODEPRECATED_DECLARATIONS_POP
1239
1240 StyleSettings aStyleSettings = rSettings.GetStyleSettings();
1241
1242 // Background Color
1243 Color aBackgroundColor( 0xEC, 0xEC, 0xEC );
1244 aStyleSettings.BatchSetBackgrounds( aBackgroundColor, false );
1245 aStyleSettings.SetLightBorderColor( aBackgroundColor );
1246
1247 Color aInactiveTabColor( aBackgroundColor );
1248 aInactiveTabColor.DecreaseLuminance( 32 );
1249 aStyleSettings.SetInactiveTabColor( aInactiveTabColor );
1250
1251 Color aShadowColor( aStyleSettings.GetShadowColor() );
1252 aShadowColor.IncreaseLuminance( 32 );
1253 aStyleSettings.SetShadowColor( aShadowColor );
1254
1255 // get the system font settings
1256 vcl::Font aAppFont = aStyleSettings.GetAppFont();
1257 sal_Int32 nDPIX = 72, nDPIY = 72;
1258 getResolution( nDPIX, nDPIY );
1259 aAppFont = getFont( [NSFont systemFontOfSize: 0], nDPIY, aAppFont );
1260
1261 aStyleSettings.SetToolbarIconSize( ToolbarIconSize::Large );
1262
1263 // TODO: better mapping of macOS<->LibreOffice font settings
1264 vcl::Font aLabelFont( getFont( [NSFont labelFontOfSize: 0], nDPIY, aAppFont ) );
1265 aStyleSettings.BatchSetFonts( aAppFont, aLabelFont );
1266 vcl::Font aMenuFont( getFont( [NSFont menuFontOfSize: 0], nDPIY, aAppFont ) );
1267 aStyleSettings.SetMenuFont( aMenuFont );
1268
1269 vcl::Font aTitleFont( getFont( [NSFont titleBarFontOfSize: 0], nDPIY, aAppFont ) );
1270 aStyleSettings.SetTitleFont( aTitleFont );
1271 aStyleSettings.SetFloatTitleFont( aTitleFont );
1272
1273 vcl::Font aTooltipFont(getFont([NSFont toolTipsFontOfSize: 0], nDPIY, aAppFont));
1274 aStyleSettings.SetHelpFont(aTooltipFont);
1275
1276 Color aHighlightColor( getColor( [NSColor selectedTextBackgroundColor],
1277 aStyleSettings.GetHighlightColor(), mpNSWindow ) );
1278 aStyleSettings.SetHighlightColor( aHighlightColor );
1279 Color aHighlightTextColor( getColor( [NSColor selectedTextColor],
1280 aStyleSettings.GetHighlightTextColor(), mpNSWindow ) );
1281 aStyleSettings.SetHighlightTextColor( aHighlightTextColor );
1282
1283 #pragma clang diagnostic push
1284 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1285 Color aMenuHighlightColor( getColor( [NSColor selectedMenuItemColor],
1286 aStyleSettings.GetMenuHighlightColor(), mpNSWindow ) );
1287 #pragma clang diagnostic pop
1288 aStyleSettings.SetMenuHighlightColor( aMenuHighlightColor );
1289 Color aMenuHighlightTextColor( getColor( [NSColor selectedMenuItemTextColor],
1290 aStyleSettings.GetMenuHighlightTextColor(), mpNSWindow ) );
1291 aStyleSettings.SetMenuHighlightTextColor( aMenuHighlightTextColor );
1292
1293 aStyleSettings.SetMenuColor( aBackgroundColor );
1294 Color aMenuTextColor( getColor( [NSColor textColor],
1295 aStyleSettings.GetMenuTextColor(), mpNSWindow ) );
1296 aStyleSettings.SetMenuTextColor( aMenuTextColor );
1297 aStyleSettings.SetMenuBarTextColor( aMenuTextColor );
1298 aStyleSettings.SetMenuBarRolloverTextColor( aMenuTextColor );
1299 aStyleSettings.SetMenuBarHighlightTextColor(aStyleSettings.GetMenuHighlightTextColor());
1300
1301 // Set text colors for buttons and their different status according to OS settings, typically white for selected buttons,
1302 // black otherwise
1303
1304 Color aControlTextColor(getColor([NSColor controlTextColor], COL_BLACK, mpNSWindow));
1305 Color aSelectedControlTextColor(getColor([NSColor selectedControlTextColor], COL_BLACK, mpNSWindow));
1306 Color aAlternateSelectedControlTextColor(getColor([NSColor alternateSelectedControlTextColor], COL_WHITE, mpNSWindow));
1307 aStyleSettings.SetDefaultButtonTextColor(aAlternateSelectedControlTextColor);
1308 aStyleSettings.SetButtonTextColor(aControlTextColor);
1309 aStyleSettings.SetDefaultActionButtonTextColor(aAlternateSelectedControlTextColor);
1310 aStyleSettings.SetActionButtonTextColor(aControlTextColor);
1311 aStyleSettings.SetFlatButtonTextColor(aControlTextColor);
1312 aStyleSettings.SetDefaultButtonRolloverTextColor(aAlternateSelectedControlTextColor);
1313 aStyleSettings.SetButtonRolloverTextColor(aControlTextColor);
1314 aStyleSettings.SetDefaultActionButtonRolloverTextColor(aAlternateSelectedControlTextColor);
1315 aStyleSettings.SetActionButtonRolloverTextColor(aControlTextColor);
1316 aStyleSettings.SetFlatButtonRolloverTextColor(aControlTextColor);
1317 aStyleSettings.SetDefaultButtonPressedRolloverTextColor(aAlternateSelectedControlTextColor);
1318 aStyleSettings.SetButtonPressedRolloverTextColor(aAlternateSelectedControlTextColor);
1319 aStyleSettings.SetDefaultActionButtonPressedRolloverTextColor(aAlternateSelectedControlTextColor);
1320 aStyleSettings.SetActionButtonPressedRolloverTextColor(aAlternateSelectedControlTextColor);
1321 aStyleSettings.SetFlatButtonPressedRolloverTextColor(aControlTextColor);
1322
1323 // Set text colors for tabs according to OS settings
1324
1325 aStyleSettings.SetTabTextColor(aControlTextColor);
1326
1327 // FIXME: Starting with macOS Big Sur, coloring has changed. Currently there is no documentation which system color should be
1328 // used for selected tab text. As a workaround the current OS version has to be considered. This code has to be reviewed once
1329 // issue is covered by documentation.
1330
1331 NSOperatingSystemVersion aOSVersion = { .majorVersion = 10, .minorVersion = 16, .patchVersion = 0 };
1332 if ([NSProcessInfo.processInfo isOperatingSystemAtLeastVersion: aOSVersion])
1333 aStyleSettings.SetTabHighlightTextColor(aSelectedControlTextColor);
1334 else
1335 aStyleSettings.SetTabHighlightTextColor(aAlternateSelectedControlTextColor);
1336
1337 aStyleSettings.SetCursorBlinkTime( mnBlinkCursorDelay );
1338
1339 // no mnemonics on macOS
1340 aStyleSettings.SetOptions( aStyleSettings.GetOptions() | StyleSettingsOptions::NoMnemonics );
1341
1342 getAppleScrollBarVariant(aStyleSettings);
1343
1344 // set scrollbar size
1345 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1346 // 'NSRegularControlSize' is deprecated: first deprecated in macOS 10.12
1347 aStyleSettings.SetScrollBarSize( static_cast<tools::Long>([NSScroller scrollerWidthForControlSize:NSRegularControlSize scrollerStyle:NSScrollerStyleLegacy]) );
1348 SAL_WNODEPRECATED_DECLARATIONS_POP
1349 // images in menus false for MacOSX
1350 aStyleSettings.SetPreferredUseImagesInMenus( false );
1351 aStyleSettings.SetHideDisabledMenuItems( true );
1352 aStyleSettings.SetPreferredContextMenuShortcuts( false );
1353
1354 rSettings.SetStyleSettings( aStyleSettings );
1355
1356 // don't draw frame around each and every toolbar
1357 ImplGetSVData()->maNWFData.mbDockingAreaAvoidTBFrames = true;
1358
1359 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1360 // "'unlockFocus' is deprecated: first deprecated in macOS 10.14 - To draw, subclass NSView
1361 // and implement -drawRect:; AppKit's automatic deferred display mechanism will call
1362 // -drawRect: as necessary to display the view."
1363 [mpNSView unlockFocus];
1364 SAL_WNODEPRECATED_DECLARATIONS_POP
1365 }
1366
GetSystemData() const1367 const SystemEnvData* AquaSalFrame::GetSystemData() const
1368 {
1369 return &maSysData;
1370 }
1371
Beep()1372 void AquaSalFrame::Beep()
1373 {
1374 OSX_SALDATA_RUNINMAIN( Beep() )
1375 NSBeep();
1376 }
1377
SetPosSize(tools::Long nX,tools::Long nY,tools::Long nWidth,tools::Long nHeight,sal_uInt16 nFlags)1378 void AquaSalFrame::SetPosSize(
1379 tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, sal_uInt16 nFlags)
1380 {
1381 if (!mpNSWindow && !Application::IsBitmapRendering())
1382 return;
1383
1384 OSX_SALDATA_RUNINMAIN( SetPosSize( nX, nY, nWidth, nHeight, nFlags ) )
1385
1386 SalEvent nEvent = PreparePosSize(nX, nY, nWidth, nHeight, nFlags);
1387 if (Application::IsBitmapRendering())
1388 return;
1389
1390 if( [mpNSWindow isMiniaturized] )
1391 [mpNSWindow deminiaturize: NSApp]; // expand the window
1392
1393 NSRect aFrameRect = [mpNSWindow frame];
1394 NSRect aContentRect = [NSWindow contentRectForFrameRect: aFrameRect styleMask: mnStyleMask];
1395
1396 // position is always relative to parent frame
1397 NSRect aParentContentRect;
1398
1399 if( mpParent )
1400 {
1401 if( AllSettings::GetLayoutRTL() )
1402 {
1403 if( (nFlags & SAL_FRAME_POSSIZE_WIDTH) != 0 )
1404 nX = mpParent->maGeometry.nWidth - nWidth-1 - nX;
1405 else
1406 nX = mpParent->maGeometry.nWidth - static_cast<tools::Long>( aContentRect.size.width-1) - nX;
1407 }
1408 NSRect aParentFrameRect = [mpParent->mpNSWindow frame];
1409 aParentContentRect = [NSWindow contentRectForFrameRect: aParentFrameRect styleMask: mpParent->mnStyleMask];
1410 }
1411 else
1412 aParentContentRect = maScreenRect; // use screen if no parent
1413
1414 CocoaToVCL( aContentRect );
1415 CocoaToVCL( aParentContentRect );
1416
1417 bool bPaint = false;
1418 if( (nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT)) != 0 )
1419 {
1420 if( nWidth != aContentRect.size.width || nHeight != aContentRect.size.height )
1421 bPaint = true;
1422 }
1423
1424 // use old window pos if no new pos requested
1425 if( (nFlags & SAL_FRAME_POSSIZE_X) != 0 )
1426 aContentRect.origin.x = nX + aParentContentRect.origin.x;
1427 if( (nFlags & SAL_FRAME_POSSIZE_Y) != 0)
1428 aContentRect.origin.y = nY + aParentContentRect.origin.y;
1429
1430 // use old size if no new size requested
1431 if( (nFlags & SAL_FRAME_POSSIZE_WIDTH) != 0 )
1432 aContentRect.size.width = nWidth;
1433 if( (nFlags & SAL_FRAME_POSSIZE_HEIGHT) != 0)
1434 aContentRect.size.height = nHeight;
1435
1436 VCLToCocoa( aContentRect );
1437
1438 // do not display yet, we need to update our backbuffer
1439 {
1440 [mpNSWindow setFrame: [NSWindow frameRectForContentRect: aContentRect styleMask: mnStyleMask] display: NO];
1441 }
1442
1443 UpdateFrameGeometry();
1444
1445 if (nEvent != SalEvent::NONE)
1446 CallCallback(nEvent, nullptr);
1447
1448 if( mbShown && bPaint )
1449 {
1450 // trigger filling our backbuffer
1451 SendPaintEvent();
1452
1453 // now inform the system that the views need to be drawn
1454 [mpNSWindow display];
1455 }
1456 }
1457
GetWorkArea(tools::Rectangle & rRect)1458 void AquaSalFrame::GetWorkArea( tools::Rectangle& rRect )
1459 {
1460 if (!mpNSWindow)
1461 {
1462 if (Application::IsBitmapRendering())
1463 rRect = tools::Rectangle(Point(0, 0), Size(1024, 768));
1464 return;
1465 }
1466
1467 OSX_SALDATA_RUNINMAIN( GetWorkArea( rRect ) )
1468
1469 NSScreen* pScreen = [mpNSWindow screen];
1470 if( pScreen == nil )
1471 pScreen = [NSScreen mainScreen];
1472 NSRect aRect = [pScreen visibleFrame];
1473 CocoaToVCL( aRect );
1474 rRect.SetLeft( static_cast<tools::Long>(aRect.origin.x) );
1475 rRect.SetTop( static_cast<tools::Long>(aRect.origin.y) );
1476 rRect.SetRight( static_cast<tools::Long>(aRect.origin.x + aRect.size.width - 1) );
1477 rRect.SetBottom( static_cast<tools::Long>(aRect.origin.y + aRect.size.height - 1) );
1478 }
1479
GetPointerState()1480 SalFrame::SalPointerState AquaSalFrame::GetPointerState()
1481 {
1482 OSX_SALDATA_RUNINMAIN_UNION( GetPointerState(), state )
1483
1484 SalPointerState state;
1485 state.mnState = 0;
1486
1487 // get position
1488 NSPoint aPt = [mpNSWindow mouseLocationOutsideOfEventStream];
1489 CocoaToVCL( aPt, false );
1490 state.maPos = Point(static_cast<tools::Long>(aPt.x), static_cast<tools::Long>(aPt.y));
1491
1492 NSEvent* pCur = [NSApp currentEvent];
1493 bool bMouseEvent = false;
1494 if( pCur )
1495 {
1496 bMouseEvent = true;
1497 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1498 // 'NSLeftMouseDown' is deprecated: first deprecated in macOS 10.12
1499 // 'NSLeftMouseDragged' is deprecated: first deprecated in macOS 10.12
1500 // 'NSLeftMouseUp' is deprecated: first deprecated in macOS 10.12
1501 // 'NSMouseMoved' is deprecated: first deprecated in macOS 10.12
1502 // 'NSOtherMouseDown' is deprecated: first deprecated in macOS 10.12
1503 // 'NSOtherMouseDragged' is deprecated: first deprecated in macOS 10.12
1504 // 'NSOtherMouseUp' is deprecated: first deprecated in macOS 10.12
1505 // 'NSRightMouseDown' is deprecated: first deprecated in macOS 10.12
1506 // 'NSRightMouseDragged' is deprecated: first deprecated in macOS 10.12
1507 // 'NSRightMouseUp' is deprecated: first deprecated in macOS 10.12
1508 switch( [pCur type] )
1509 {
1510 case NSLeftMouseDown: state.mnState |= MOUSE_LEFT; break;
1511 case NSLeftMouseUp: break;
1512 case NSRightMouseDown: state.mnState |= MOUSE_RIGHT; break;
1513 case NSRightMouseUp: break;
1514 case NSOtherMouseDown: state.mnState |= ([pCur buttonNumber] == 2) ? MOUSE_MIDDLE : 0; break;
1515 case NSOtherMouseUp: break;
1516 case NSMouseMoved: break;
1517 case NSLeftMouseDragged: state.mnState |= MOUSE_LEFT; break;
1518 case NSRightMouseDragged: state.mnState |= MOUSE_RIGHT; break;
1519 case NSOtherMouseDragged: state.mnState |= ([pCur buttonNumber] == 2) ? MOUSE_MIDDLE : 0; break;
1520 break;
1521 default:
1522 bMouseEvent = false;
1523 break;
1524 }
1525 SAL_WNODEPRECATED_DECLARATIONS_POP
1526 }
1527 if( bMouseEvent )
1528 {
1529 unsigned int nMask = static_cast<unsigned int>([pCur modifierFlags]);
1530 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1531 // 'NSAlternateKeyMask' is deprecated: first deprecated in macOS 10.12
1532 // 'NSCommandKeyMask' is deprecated: first deprecated in macOS 10.12
1533 // 'NSControlKeyMask' is deprecated: first deprecated in macOS 10.12
1534 // 'NSShiftKeyMask' is deprecated: first deprecated in macOS 10.12
1535 if( (nMask & NSShiftKeyMask) != 0 )
1536 state.mnState |= KEY_SHIFT;
1537 if( (nMask & NSControlKeyMask) != 0 )
1538 state.mnState |= KEY_MOD3;
1539 if( (nMask & NSAlternateKeyMask) != 0 )
1540 state.mnState |= KEY_MOD2;
1541 if( (nMask & NSCommandKeyMask) != 0 )
1542 state.mnState |= KEY_MOD1;
1543 SAL_WNODEPRECATED_DECLARATIONS_POP
1544
1545 }
1546 else
1547 {
1548 // FIXME: replace Carbon by Cocoa
1549 // Cocoa does not have an equivalent for GetCurrentEventButtonState
1550 // and GetCurrentEventKeyModifiers.
1551 // we could try to get away with tracking all events for modifierKeys
1552 // and all mouse events for button state in VCL_NSApplication::sendEvent,
1553 // but it is unclear whether this will get us the same result.
1554 // leave in GetCurrentEventButtonState and GetCurrentEventKeyModifiers for now
1555
1556 // fill in button state
1557 UInt32 nState = GetCurrentEventButtonState();
1558 state.mnState = 0;
1559 if( nState & 1 )
1560 state.mnState |= MOUSE_LEFT; // primary button
1561 if( nState & 2 )
1562 state.mnState |= MOUSE_RIGHT; // secondary button
1563 if( nState & 4 )
1564 state.mnState |= MOUSE_MIDDLE; // tertiary button
1565
1566 // fill in modifier state
1567 nState = GetCurrentEventKeyModifiers();
1568 if( nState & shiftKey )
1569 state.mnState |= KEY_SHIFT;
1570 if( nState & controlKey )
1571 state.mnState |= KEY_MOD3;
1572 if( nState & optionKey )
1573 state.mnState |= KEY_MOD2;
1574 if( nState & cmdKey )
1575 state.mnState |= KEY_MOD1;
1576 }
1577
1578 return state;
1579 }
1580
GetIndicatorState()1581 KeyIndicatorState AquaSalFrame::GetIndicatorState()
1582 {
1583 return KeyIndicatorState::NONE;
1584 }
1585
SimulateKeyPress(sal_uInt16)1586 void AquaSalFrame::SimulateKeyPress( sal_uInt16 /*nKeyCode*/ )
1587 {
1588 }
1589
SetPluginParent(SystemParentData *)1590 void AquaSalFrame::SetPluginParent( SystemParentData* )
1591 {
1592 // plugin parent may be killed unexpectedly by
1593 // plugging process;
1594
1595 //TODO: implement
1596 }
1597
MapUnicodeToKeyCode(sal_Unicode,LanguageType,vcl::KeyCode &)1598 bool AquaSalFrame::MapUnicodeToKeyCode( sal_Unicode , LanguageType , vcl::KeyCode& )
1599 {
1600 // not supported yet
1601 return false;
1602 }
1603
GetInputLanguage()1604 LanguageType AquaSalFrame::GetInputLanguage()
1605 {
1606 //TODO: implement
1607 return LANGUAGE_DONTKNOW;
1608 }
1609
DrawMenuBar()1610 void AquaSalFrame::DrawMenuBar()
1611 {
1612 }
1613
SetMenu(SalMenu * pSalMenu)1614 void AquaSalFrame::SetMenu( SalMenu* pSalMenu )
1615 {
1616 OSX_SALDATA_RUNINMAIN( SetMenu( pSalMenu ) )
1617
1618 AquaSalMenu* pMenu = static_cast<AquaSalMenu*>(pSalMenu);
1619 SAL_WARN_IF( pMenu && !pMenu->mbMenuBar, "vcl", "setting non menubar on frame" );
1620 mpMenu = pMenu;
1621 if( mpMenu )
1622 mpMenu->setMainMenu();
1623 }
1624
SetExtendedFrameStyle(SalExtStyle nStyle)1625 void AquaSalFrame::SetExtendedFrameStyle( SalExtStyle nStyle )
1626 {
1627 if ( !mpNSWindow )
1628 {
1629 mnExtStyle = nStyle;
1630 return;
1631 }
1632
1633 OSX_SALDATA_RUNINMAIN( SetExtendedFrameStyle( nStyle ) )
1634
1635 if( (mnExtStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) != (nStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) )
1636 [mpNSWindow setDocumentEdited: (nStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) ? YES : NO];
1637
1638 mnExtStyle = nStyle;
1639 }
1640
GetParent() const1641 SalFrame* AquaSalFrame::GetParent() const
1642 {
1643 return mpParent;
1644 }
1645
SetParent(SalFrame * pNewParent)1646 void AquaSalFrame::SetParent( SalFrame* pNewParent )
1647 {
1648 bool bShown = mbShown;
1649 // remove from child list
1650 if (bShown)
1651 Show(false);
1652 mpParent = static_cast<AquaSalFrame*>(pNewParent);
1653 // insert to correct parent and paint
1654 Show( bShown );
1655 }
1656
UpdateFrameGeometry()1657 void AquaSalFrame::UpdateFrameGeometry()
1658 {
1659 bool bFirstTime = (mnTrackingRectTag == 0);
1660 mbGeometryDidChange = false;
1661
1662 if ( !mpNSWindow )
1663 return;
1664
1665 OSX_SALDATA_RUNINMAIN( UpdateFrameGeometry() )
1666
1667 // keep in mind that view and window coordinates are lower left
1668 // whereas vcl's are upper left
1669
1670 // update screen rect
1671 NSScreen * pScreen = [mpNSWindow screen];
1672 if( pScreen )
1673 {
1674 NSRect aNewScreenRect = [pScreen frame];
1675 if (bFirstTime || !NSEqualRects(maScreenRect, aNewScreenRect))
1676 {
1677 mbGeometryDidChange = true;
1678 maScreenRect = aNewScreenRect;
1679 }
1680 NSArray* pScreens = [NSScreen screens];
1681 if( pScreens )
1682 {
1683 unsigned int nNewDisplayScreenNumber = [pScreens indexOfObject: pScreen];
1684 if (bFirstTime || maGeometry.nDisplayScreenNumber != nNewDisplayScreenNumber)
1685 {
1686 mbGeometryDidChange = true;
1687 maGeometry.nDisplayScreenNumber = nNewDisplayScreenNumber;
1688 }
1689 }
1690 }
1691
1692 NSRect aFrameRect = [mpNSWindow frame];
1693 NSRect aContentRect = [NSWindow contentRectForFrameRect: aFrameRect styleMask: mnStyleMask];
1694
1695 NSRect aTrackRect = { NSZeroPoint, aContentRect.size };
1696
1697 if (bFirstTime || !NSEqualRects(maTrackingRect, aTrackRect))
1698 {
1699 mbGeometryDidChange = true;
1700 maTrackingRect = aTrackRect;
1701
1702 // release old track rect
1703 [mpNSView removeTrackingRect: mnTrackingRectTag];
1704 // install the new track rect
1705 mnTrackingRectTag = [mpNSView addTrackingRect: aTrackRect owner: mpNSView userData: nil assumeInside: NO];
1706 }
1707
1708 // convert to vcl convention
1709 CocoaToVCL( aFrameRect );
1710 CocoaToVCL( aContentRect );
1711
1712 if (bFirstTime || !NSEqualRects(maContentRect, aContentRect) || !NSEqualRects(maFrameRect, aFrameRect))
1713 {
1714 mbGeometryDidChange = true;
1715
1716 maContentRect = aContentRect;
1717 maFrameRect = aFrameRect;
1718
1719 maGeometry.nX = static_cast<int>(aContentRect.origin.x);
1720 maGeometry.nY = static_cast<int>(aContentRect.origin.y);
1721
1722 maGeometry.nLeftDecoration = static_cast<unsigned int>(aContentRect.origin.x - aFrameRect.origin.x);
1723 maGeometry.nRightDecoration = static_cast<unsigned int>((aFrameRect.origin.x + aFrameRect.size.width) -
1724 (aContentRect.origin.x + aContentRect.size.width));
1725
1726 maGeometry.nTopDecoration = static_cast<unsigned int>(aContentRect.origin.y - aFrameRect.origin.y);
1727 maGeometry.nBottomDecoration = static_cast<unsigned int>((aFrameRect.origin.y + aFrameRect.size.height) -
1728 (aContentRect.origin.y + aContentRect.size.height));
1729
1730 maGeometry.nWidth = static_cast<unsigned int>(aContentRect.size.width);
1731 maGeometry.nHeight = static_cast<unsigned int>(aContentRect.size.height);
1732 }
1733 }
1734
CaptureMouse(bool bCapture)1735 void AquaSalFrame::CaptureMouse( bool bCapture )
1736 {
1737 /* Remark:
1738 we'll try to use a pidgin version of capture mouse
1739 on MacOSX (neither carbon nor cocoa) there is a
1740 CaptureMouse equivalent (in Carbon there is TrackMouseLocation
1741 but this is useless to use since it is blocking)
1742
1743 However on cocoa the active frame seems to get mouse events
1744 also outside the window, so we'll try to forward mouse events
1745 to the capture frame in the hope that one of our frames
1746 gets a mouse event.
1747
1748 This will break as soon as the user activates another app, but
1749 a mouse click will normally lead to a release of the mouse anyway.
1750
1751 Let's see how far we get this way. Alternatively we could use one
1752 large overlay window like we did for the carbon implementation,
1753 however that is resource intensive.
1754 */
1755
1756 if( bCapture )
1757 s_pCaptureFrame = this;
1758 else if( ! bCapture && s_pCaptureFrame == this )
1759 s_pCaptureFrame = nullptr;
1760 }
1761
ResetClipRegion()1762 void AquaSalFrame::ResetClipRegion()
1763 {
1764 doResetClipRegion();
1765 }
1766
doResetClipRegion()1767 void AquaSalFrame::doResetClipRegion()
1768 {
1769 if ( !mpNSWindow )
1770 return;
1771
1772 OSX_SALDATA_RUNINMAIN( ResetClipRegion() )
1773
1774 // release old path and indicate no clipping
1775 CGPathRelease( mrClippingPath );
1776 mrClippingPath = nullptr;
1777
1778 if( mpNSView && mbShown )
1779 [mpNSView setNeedsDisplay: YES];
1780 [mpNSWindow setOpaque: YES];
1781 [mpNSWindow invalidateShadow];
1782 }
1783
BeginSetClipRegion(sal_uInt32 nRects)1784 void AquaSalFrame::BeginSetClipRegion( sal_uInt32 nRects )
1785 {
1786 if ( !mpNSWindow )
1787 return;
1788
1789 OSX_SALDATA_RUNINMAIN( BeginSetClipRegion( nRects ) )
1790
1791 // release old path
1792 if( mrClippingPath )
1793 {
1794 CGPathRelease( mrClippingPath );
1795 mrClippingPath = nullptr;
1796 }
1797
1798 if( maClippingRects.size() > SAL_CLIPRECT_COUNT && nRects < maClippingRects.size() )
1799 {
1800 std::vector<CGRect>().swap(maClippingRects);
1801 }
1802 maClippingRects.clear();
1803 maClippingRects.reserve( nRects );
1804 }
1805
UnionClipRegion(tools::Long nX,tools::Long nY,tools::Long nWidth,tools::Long nHeight)1806 void AquaSalFrame::UnionClipRegion(
1807 tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight )
1808 {
1809 // #i113170# may not be the main thread if called from UNO API
1810 SalData::ensureThreadAutoreleasePool();
1811
1812 if( nWidth && nHeight )
1813 {
1814 NSRect aRect = { { static_cast<CGFloat>(nX), static_cast<CGFloat>(nY) }, { static_cast<CGFloat>(nWidth), static_cast<CGFloat>(nHeight) } };
1815 VCLToCocoa( aRect, false );
1816 maClippingRects.push_back( CGRectMake(aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height) );
1817 }
1818 }
1819
EndSetClipRegion()1820 void AquaSalFrame::EndSetClipRegion()
1821 {
1822 if ( !mpNSWindow )
1823 return;
1824
1825 OSX_SALDATA_RUNINMAIN( EndSetClipRegion() )
1826
1827 if( ! maClippingRects.empty() )
1828 {
1829 mrClippingPath = CGPathCreateMutable();
1830 CGPathAddRects( mrClippingPath, nullptr, maClippingRects.data(), maClippingRects.size() );
1831 }
1832 if( mpNSView && mbShown )
1833 [mpNSView setNeedsDisplay: YES];
1834 [mpNSWindow setOpaque: (mrClippingPath != nullptr) ? NO : YES];
1835 [mpNSWindow setBackgroundColor: [NSColor clearColor]];
1836 // shadow is invalidated when view gets drawn again
1837 }
1838
1839 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1840