xref: /aoo42x/main/vcl/aqua/source/window/salframe.cxx (revision 8a718ffc)
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 
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 
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 
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: mpNSWindow];
211 
212     const NSRect aRect = NSMakeRect( 0,0, 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 
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 
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 
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 
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 
258 void AquaSalFrame::screenParametersChanged()
259 {
260     UpdateFrameGeometry();
261 
262     if( mpGraphics )
263         mpGraphics->updateResolution();
264     CallCallback( SALEVENT_DISPLAYCHANGED, 0 );
265 }
266 
267 // -----------------------------------------------------------------------
268 
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 
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 
295 sal_Bool AquaSalFrame::PostEvent( void *pData )
296 {
297     GetSalData()->mpFirstInstance->PostUserEvent( this, SALEVENT_USEREVENT, pData );
298     return TRUE;
299 }
300 
301 // -----------------------------------------------------------------------
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 
340 void AquaSalFrame::SetIcon( sal_uInt16 )
341 {
342 }
343 
344 // -----------------------------------------------------------------------
345 
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 
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 
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 
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 
482 void AquaSalFrame::Enable( sal_Bool )
483 {
484 }
485 
486 // -----------------------------------------------------------------------
487 
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 
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 
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 
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 
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 
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 
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 
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 = { { 0, 0 }, { 0, 0 } };
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:
827     PreventSleepTimer()
828     {
829         SetTimeout( 30000 );
830         Start();
831     }
832 
833     virtual ~PreventSleepTimer()
834     {
835     }
836 
837     virtual void Timeout()
838     {
839         UpdateSystemActivity(OverallAct);
840     }
841 };
842 
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 
869 void AquaSalFrame::SetAlwaysOnTop( sal_Bool )
870 {
871 }
872 
873 // -----------------------------------------------------------------------
874 
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 
899 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 
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 
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 
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 
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 
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 
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 
1041 void AquaSalFrame::EndExtTextInput( sal_uInt16 )
1042 {
1043 }
1044 
1045 // -----------------------------------------------------------------------
1046 
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 
1134 XubString AquaSalFrame::GetSymbolKeyName( const XubString&, sal_uInt16 nKeyCode )
1135 {
1136 	return GetKeyName( nKeyCode );
1137 }
1138 
1139 // -----------------------------------------------------------------------
1140 
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 
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             float 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 
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 
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
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 
1333 const SystemEnvData* AquaSalFrame::GetSystemData() const
1334 {
1335     return &maSysData;
1336 }
1337 
1338 // -----------------------------------------------------------------------
1339 
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 
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 
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 
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 
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 
1558 sal_Bool AquaSalFrame::MapUnicodeToKeyCode( sal_Unicode , LanguageType , KeyCode& )
1559 {
1560     // not supported yet
1561     return FALSE;
1562 }
1563 
1564 LanguageType AquaSalFrame::GetInputLanguage()
1565 {
1566     //TODO: implement
1567     return LANGUAGE_DONTKNOW;
1568 }
1569 
1570 void AquaSalFrame::DrawMenuBar()
1571 {
1572 }
1573 
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 
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 
1600 void AquaSalFrame::SetBackgroundBitmap( SalBitmap* )
1601 {
1602     //TODO: implement
1603 }
1604 
1605 SalBitmap* AquaSalFrame::SnapShot()
1606 {
1607     return mpGraphics ? mpGraphics->getBitmap( 0, 0, maGeometry.nWidth, maGeometry.nHeight ) : NULL;
1608 }
1609 
1610 SalFrame* AquaSalFrame::GetParent() const
1611 {
1612     return mpParent;
1613 }
1614 
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 
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 = { { 0, 0 }, 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 
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 
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 
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 
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 
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