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