Branch libreoffice-5-0-4
[LibreOffice.git] / vcl / osx / salframeview.mm
blob8036a0f11f9e623057978e3a83d3ccaf27818c0d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
20 #include <sal/alloca.h>
21 #include <sal/macros.h>
23 #include "tools/helpers.hxx"
24 #include "vcl/window.hxx"
25 #include "vcl/svapp.hxx"
26 #include <vcl/settings.hxx>
28 #include "osx/salinst.h"
29 #include "quartz/salgdi.h"
30 #include "osx/salframe.h"
31 #include "osx/salframeview.h"
32 #include "osx/a11yfactory.h"
33 #include "quartz/utils.h"
35 #define WHEEL_EVENT_FACTOR 1.5
37 static sal_uInt16 ImplGetModifierMask( unsigned int nMask )
39     sal_uInt16 nRet = 0;
40     if( (nMask & NSShiftKeyMask) != 0 )
41         nRet |= KEY_SHIFT;
42     if( (nMask & NSControlKeyMask) != 0 )
43         nRet |= KEY_MOD3;
44     if( (nMask & NSAlternateKeyMask) != 0 )
45         nRet |= KEY_MOD2;
46     if( (nMask & NSCommandKeyMask) != 0 )
47         nRet |= KEY_MOD1;
48     return nRet;
51 static sal_uInt16 ImplMapCharCode( sal_Unicode aCode )
53     static sal_uInt16 aKeyCodeMap[ 128 ] =
54     {
55                     0,                0,                0,                0,                0,                0,                0,                0,
56         KEY_BACKSPACE,          KEY_TAB,       KEY_RETURN,                0,                0,       KEY_RETURN,                0,                0,
57                     0,                0,                0,                0,                0,                0,                0,                0,
58                     0,          KEY_TAB,                0,       KEY_ESCAPE,                0,                0,                0,                0,
59             KEY_SPACE,                0,                0,                0,                0,                0,                0,                0,
60                     0,                0,     KEY_MULTIPLY,          KEY_ADD,        KEY_COMMA,     KEY_SUBTRACT,        KEY_POINT,       KEY_DIVIDE,
61                 KEY_0,            KEY_1,            KEY_2,            KEY_3,            KEY_4,            KEY_5,            KEY_6,            KEY_7,
62                 KEY_8,            KEY_9,                0,                0,         KEY_LESS,        KEY_EQUAL,      KEY_GREATER,                0,
63                     0,            KEY_A,            KEY_B,            KEY_C,            KEY_D,            KEY_E,            KEY_F,            KEY_G,
64                 KEY_H,            KEY_I,            KEY_J,            KEY_K,            KEY_L,            KEY_M,            KEY_N,            KEY_O,
65                 KEY_P,            KEY_Q,            KEY_R,            KEY_S,            KEY_T,            KEY_U,            KEY_V,            KEY_W,
66                 KEY_X,            KEY_Y,            KEY_Z,                0,                0,                0,                0,                0,
67         KEY_QUOTELEFT,            KEY_A,            KEY_B,            KEY_C,            KEY_D,            KEY_E,            KEY_F,            KEY_G,
68                 KEY_H,            KEY_I,            KEY_J,            KEY_K,            KEY_L,            KEY_M,            KEY_N,            KEY_O,
69                 KEY_P,            KEY_Q,            KEY_R,            KEY_S,            KEY_T,            KEY_U,            KEY_V,            KEY_W,
70                 KEY_X,            KEY_Y,            KEY_Z,                0,                0,                0,        KEY_TILDE,    KEY_BACKSPACE
71     };
73     // Note: the mapping 0x7f should by rights be KEY_DELETE
74     // however if you press "backspace" 0x7f is reported
75     // whereas for "delete" 0xf728 gets reported
77     // Note: the mapping of 0x19 to KEY_TAB is because for unknown reasons
78     // tab alone is reported as 0x09 (as expected) but shift-tab is
79     // reported as 0x19 (end of medium)
81     static sal_uInt16 aFunctionKeyCodeMap[ 128 ] =
82     {
83             KEY_UP,         KEY_DOWN,         KEY_LEFT,        KEY_RIGHT,           KEY_F1,           KEY_F2,           KEY_F3,           KEY_F4,
84             KEY_F5,           KEY_F6,           KEY_F7,           KEY_F8,           KEY_F9,          KEY_F10,          KEY_F11,          KEY_F12,
85            KEY_F13,          KEY_F14,          KEY_F15,          KEY_F16,          KEY_F17,          KEY_F18,          KEY_F19,          KEY_F20,
86            KEY_F21,          KEY_F22,          KEY_F23,          KEY_F24,          KEY_F25,          KEY_F26,                0,                0,
87                  0,                0,                0,                0,                0,                0,                0,       KEY_INSERT,
88         KEY_DELETE,         KEY_HOME,                0,          KEY_END,        KEY_PAGEUP,    KEY_PAGEDOWN,                0,                0,
89                  0,                0,                0,                0,                 0,        KEY_MENU,                0,                0,
90                  0,                0,                0,                0,                 0,               0,                0,                0,
91                  0,                0,                0,         KEY_UNDO,        KEY_REPEAT,        KEY_FIND,         KEY_HELP,                0,
92                  0,                0,                0,                0,                 0,               0,                0,                0,
93                  0,                0,                0,                0,                 0,               0,                0,                0,
94                  0,                0,                0,                0,                 0,               0,                0,                0,
95                  0,                0,                0,                0,                 0,               0,                0,                0,
96                  0,                0,                0,                0,                 0,               0,                0,                0,
97                  0,                0,                0,                0,                 0,               0,                0,                0,
98                  0,                0,                0,                0,                 0,               0,                0,                0
99     };
101     sal_uInt16 nKeyCode = 0;
102     if( aCode < SAL_N_ELEMENTS( aKeyCodeMap)  )
103         nKeyCode = aKeyCodeMap[ aCode ];
104     else if( aCode >= 0xf700 && aCode < 0xf780 )
105         nKeyCode = aFunctionKeyCodeMap[ aCode - 0xf700 ];
106     return nKeyCode;
109 static sal_uInt16 ImplMapKeyCode(sal_uInt16 nKeyCode)
111     /*
112       http://stackoverflow.com/questions/2080312/where-can-i-find-a-list-of-key-codes-for-use-with-cocoas-nsevent-class/2080324#2080324
113       /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Events.h
114      */
116     static sal_uInt16 aKeyCodeMap[ 0x80 ] =
117     {
118             KEY_A,            KEY_S,            KEY_D,            KEY_F,            KEY_H,            KEY_G,            KEY_Z,            KEY_X,
119             KEY_C,            KEY_V,                0,            KEY_B,            KEY_Q,            KEY_W,            KEY_E,            KEY_R,
120             KEY_Y,            KEY_T,            KEY_1,            KEY_2,            KEY_3,            KEY_4,            KEY_6,            KEY_5,
121         KEY_EQUAL,            KEY_9,            KEY_7,     KEY_SUBTRACT,            KEY_8,            KEY_0, KEY_BRACKETRIGHT,            KEY_0,
122             KEY_U,  KEY_BRACKETLEFT,            KEY_I,            KEY_P,       KEY_RETURN,            KEY_L,            KEY_J,   KEY_QUOTERIGHT,
123             KEY_K,    KEY_SEMICOLON,                0,        KEY_COMMA,       KEY_DIVIDE,            KEY_N,            KEY_M,        KEY_POINT,
124           KEY_TAB,        KEY_SPACE,    KEY_QUOTELEFT,       KEY_DELETE,                0,       KEY_ESCAPE,                0,                0,
125                 0,     KEY_CAPSLOCK,                0,                0,                0,                0,                0,                0,
126           KEY_F17,      KEY_DECIMAL,                0,     KEY_MULTIPLY,                0,          KEY_ADD,                0,                0,
127                 0,                0,                0,       KEY_DIVIDE,       KEY_RETURN,                0,     KEY_SUBTRACT,          KEY_F18,
128           KEY_F19,        KEY_EQUAL,                0,                0,                0,                0,                0,                0,
129                 0,                0,          KEY_F20,                0,                0,                0,                0,                0,
130            KEY_F5,           KEY_F6,           KEY_F7,           KEY_F3,           KEY_F8,           KEY_F9,                0,          KEY_F11,
131                 0,          KEY_F13,          KEY_F16,          KEY_F14,                0,          KEY_F10,                0,          KEY_F12,
132                 0,          KEY_F15,         KEY_HELP,         KEY_HOME,       KEY_PAGEUP,       KEY_DELETE,           KEY_F4,          KEY_END,
133            KEY_F2,     KEY_PAGEDOWN,           KEY_F1,         KEY_LEFT,        KEY_RIGHT,         KEY_DOWN,           KEY_UP,                0
134     };
136     if (nKeyCode < SAL_N_ELEMENTS(aKeyCodeMap))
137         return aKeyCodeMap[nKeyCode];
138     return 0;
141 // store the frame the mouse last entered
142 static AquaSalFrame* s_pMouseFrame = NULL;
143 // store the last pressed button for enter/exit events
144 // which lack that information
145 static sal_uInt16 s_nLastButton = 0;
147 // combinations of keys we need to handle ourselves
148 static const struct ExceptionalKey
150     const sal_uInt16        nKeyCode;
151     const unsigned int  nModifierMask;
152 } aExceptionalKeys[] =
154     { KEY_D, NSControlKeyMask | NSShiftKeyMask | NSAlternateKeyMask },
155     { KEY_D, NSCommandKeyMask | NSShiftKeyMask | NSAlternateKeyMask }
158 static AquaSalFrame* getMouseContainerFrame()
160     AquaSalFrame* pDispatchFrame = NULL;
161     NSArray* aWindows = [NSWindow windowNumbersWithOptions:0];
162     for(NSUInteger i = 0; i < [aWindows count] && ! pDispatchFrame; i++ )
163     {
164         NSWindow* pWin = [NSApp windowWithWindowNumber:[[aWindows objectAtIndex:i] integerValue]];
165         if( pWin && [pWin isMemberOfClass: [SalFrameWindow class]] && [(SalFrameWindow*)pWin containsMouse] )
166             pDispatchFrame = [(SalFrameWindow*)pWin getSalFrame];
167     }
168     return pDispatchFrame;
171 @implementation SalFrameWindow
172 -(id)initWithSalFrame: (AquaSalFrame*)pFrame
174     mDraggingDestinationHandler = nil;
175     mpFrame = pFrame;
176     NSRect aRect = { { static_cast<CGFloat>(pFrame->maGeometry.nX), static_cast<CGFloat>(pFrame->maGeometry.nY) },
177                      { static_cast<CGFloat>(pFrame->maGeometry.nWidth), static_cast<CGFloat>(pFrame->maGeometry.nHeight) } };
178     pFrame->VCLToCocoa( aRect );
179     NSWindow* pNSWindow = [super initWithContentRect: aRect styleMask: mpFrame->getStyleMask() backing: NSBackingStoreBuffered defer: NO ];
180 #if MACOSX_SDK_VERSION < 101000
181     [pNSWindow useOptimizedDrawing: YES]; // OSX recommendation when there are no overlapping subviews within the receiver
182 #endif
184     // enable OSX>=10.7 fullscreen options if available and useful
185     bool bAllowFullScreen = (0 == (mpFrame->mnStyle & (SAL_FRAME_STYLE_DIALOG | SAL_FRAME_STYLE_TOOLTIP | SAL_FRAME_STYLE_SYSTEMCHILD | SAL_FRAME_STYLE_FLOAT | SAL_FRAME_STYLE_TOOLWINDOW | SAL_FRAME_STYLE_INTRO)));
186     bAllowFullScreen &= (0 == (~mpFrame->mnStyle & (SAL_FRAME_STYLE_SIZEABLE)));
187     bAllowFullScreen &= (mpFrame->mpParent == NULL);
188     const SEL setCollectionBehavior = @selector(setCollectionBehavior:);
189     if( bAllowFullScreen && [pNSWindow respondsToSelector: setCollectionBehavior])
190     {
191         const int bMode= (bAllowFullScreen ? NSWindowCollectionBehaviorFullScreenPrimary : NSWindowCollectionBehaviorFullScreenAuxiliary);
192         [pNSWindow performSelector:setCollectionBehavior withObject:reinterpret_cast<id>(static_cast<intptr_t>(bMode))];
193     }
195     // disable OSX>=10.7 window restoration until we support it directly
196     const SEL setRestorable = @selector(setRestorable:);
197     if( [pNSWindow respondsToSelector: setRestorable]) {
198         [pNSWindow performSelector:setRestorable withObject:reinterpret_cast<id>(NO)];
199     }
201     return (SalFrameWindow *)pNSWindow;
204 -(AquaSalFrame*)getSalFrame
206     return mpFrame;
209 -(void)displayIfNeeded
211     if( GetSalData() && GetSalData()->mpFirstInstance )
212     {
213         comphelper::SolarMutex* pMutex = GetSalData()->mpFirstInstance->GetYieldMutex();
214         if( pMutex )
215         {
216             pMutex->acquire();
217             [super displayIfNeeded];
218             pMutex->release();
219         }
220     }
223 -(BOOL)containsMouse
225     // is this event actually inside that NSWindow ?
226     NSPoint aPt = [NSEvent mouseLocation];
227     NSRect aFrameRect = [self frame];
228     BOOL bInRect = NSPointInRect( aPt, aFrameRect );
229     return bInRect;
232 -(BOOL)canBecomeKeyWindow
234     if( (mpFrame->mnStyle &
235             ( SAL_FRAME_STYLE_FLOAT                 |
236               SAL_FRAME_STYLE_TOOLTIP               |
237               SAL_FRAME_STYLE_INTRO
238             )) == 0 )
239         return YES;
240     if( (mpFrame->mnStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) != 0 )
241         return YES;
242     if( mpFrame->mbFullScreen )
243         return YES;
244     if( (mpFrame->mnStyle & SAL_FRAME_STYLE_FLOAT_FOCUSABLE) )
245         return YES;
246     return [super canBecomeKeyWindow];
249 -(void)windowDidBecomeKey: (NSNotification*)pNotification
251     (void)pNotification;
252     YIELD_GUARD;
254     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
255     {
256         static const sal_uLong nGuessDocument = SAL_FRAME_STYLE_MOVEABLE|
257                                             SAL_FRAME_STYLE_SIZEABLE|
258                                             SAL_FRAME_STYLE_CLOSEABLE;
260         if( mpFrame->mpMenu )
261             mpFrame->mpMenu->setMainMenu();
262         else if( ! mpFrame->mpParent &&
263                  ( (mpFrame->mnStyle & nGuessDocument) == nGuessDocument || // set default menu for e.g. help
264                     mpFrame->mbFullScreen ) )                               // ser default menu for e.g. presentation
265         {
266             AquaSalMenu::setDefaultMenu();
267         }
268         #if 0
269         // FIXME: we should disable menus while in modal mode
270         // however from down here there is currently no reliable way to
271         // find out when to do this
272         if( (mpFrame->mpParent && mpFrame->mpParent->GetWindow()->IsInModalMode()) )
273             AquaSalMenu::enableMainMenu( false );
274         #endif
275         mpFrame->CallCallback( SALEVENT_GETFOCUS, 0 );
276         mpFrame->SendPaintEvent(); // repaint controls as active
277     }
280 -(void)windowDidResignKey: (NSNotification*)pNotification
282     (void)pNotification;
283     YIELD_GUARD;
285     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
286     {
287         mpFrame->CallCallback(SALEVENT_LOSEFOCUS, 0);
288         mpFrame->SendPaintEvent(); // repaint controls as inactive
289     }
292 -(void)windowDidChangeScreen: (NSNotification*)pNotification
294     (void)pNotification;
295     YIELD_GUARD;
297     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
298         mpFrame->screenParametersChanged();
301 -(void)windowDidMove: (NSNotification*)pNotification
303     (void)pNotification;
304     YIELD_GUARD;
306     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
307     {
308         mpFrame->UpdateFrameGeometry();
309         mpFrame->CallCallback( SALEVENT_MOVE, 0 );
310     }
313 -(void)windowDidResize: (NSNotification*)pNotification
315     (void)pNotification;
316     YIELD_GUARD;
318     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
319     {
320         mpFrame->UpdateFrameGeometry();
321         mpFrame->CallCallback( SALEVENT_RESIZE, 0 );
322         mpFrame->SendPaintEvent();
323     }
326 -(void)windowDidMiniaturize: (NSNotification*)pNotification
328     (void)pNotification;
329     YIELD_GUARD;
331     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
332     {
333         mpFrame->mbShown = false;
334         mpFrame->UpdateFrameGeometry();
335         mpFrame->CallCallback( SALEVENT_RESIZE, 0 );
336     }
339 -(void)windowDidDeminiaturize: (NSNotification*)pNotification
341     (void)pNotification;
342     YIELD_GUARD;
344     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
345     {
346         mpFrame->mbShown = true;
347         mpFrame->UpdateFrameGeometry();
348         mpFrame->CallCallback( SALEVENT_RESIZE, 0 );
349     }
352 -(BOOL)windowShouldClose: (NSNotification*)pNotification
354     (void)pNotification;
355     YIELD_GUARD;
357     BOOL bRet = YES;
358     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
359     {
360         // #i84461# end possible input
361         mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 );
362         if( AquaSalFrame::isAlive( mpFrame ) )
363         {
364             mpFrame->CallCallback( SALEVENT_CLOSE, 0 );
365             bRet = NO; // application will close the window or not, AppKit shouldn't
366         }
367     }
369     return bRet;
372 -(void)windowDidEnterFullScreen: (NSNotification*)pNotification
374     YIELD_GUARD;
376     if( !mpFrame || !AquaSalFrame::isAlive( mpFrame))
377         return;
378     mpFrame->mbFullScreen = true;
379     (void)pNotification;
382 -(void)windowDidExitFullScreen: (NSNotification*)pNotification
384     YIELD_GUARD;
386     if( !mpFrame || !AquaSalFrame::isAlive( mpFrame))
387         return;
388     mpFrame->mbFullScreen = false;
389     (void)pNotification;
392 -(void)dockMenuItemTriggered: (id)sender
394     (void)sender;
395     YIELD_GUARD;
397     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
398         mpFrame->ToTop( SAL_FRAME_TOTOP_RESTOREWHENMIN | SAL_FRAME_TOTOP_GRABFOCUS );
401 -(::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >)accessibleContext
403     return mpFrame -> GetWindow() -> GetAccessible() -> getAccessibleContext();
406 -(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
408   return [mDraggingDestinationHandler draggingEntered: sender];
411 -(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
413   return [mDraggingDestinationHandler draggingUpdated: sender];
416 -(void)draggingExited:(id <NSDraggingInfo>)sender
418   [mDraggingDestinationHandler draggingExited: sender];
421 -(BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
423   return [mDraggingDestinationHandler prepareForDragOperation: sender];
426 -(BOOL)performDragOperation:(id <NSDraggingInfo>)sender
428   return [mDraggingDestinationHandler performDragOperation: sender];
431 -(void)concludeDragOperation:(id <NSDraggingInfo>)sender
433   [mDraggingDestinationHandler concludeDragOperation: sender];
436 -(void)registerDraggingDestinationHandler:(id)theHandler
438   mDraggingDestinationHandler = theHandler;
441 -(void)unregisterDraggingDestinationHandler:(id)theHandler
443     (void)theHandler;
444     mDraggingDestinationHandler = nil;
447 @end
449 @implementation SalFrameView
450 +(void)unsetMouseFrame: (AquaSalFrame*)pFrame
452     if( pFrame == s_pMouseFrame )
453         s_pMouseFrame = NULL;
456 -(id)initWithSalFrame: (AquaSalFrame*)pFrame
458     if ((self = [super initWithFrame: [NSWindow contentRectForFrameRect: [pFrame->getNSWindow() frame] styleMask: pFrame->mnStyleMask]]) != nil)
459     {
460         mDraggingDestinationHandler = nil;
461         mpFrame = pFrame;
462         mMarkedRange = NSMakeRange(NSNotFound, 0);
463         mSelectedRange = NSMakeRange(NSNotFound, 0);
464         mpReferenceWrapper = nil;
465         mpMouseEventListener = nil;
466         mpLastSuperEvent = nil;
467     }
469     mfLastMagnifyTime = 0.0;
470     return self;
473 -(AquaSalFrame*)getSalFrame
475     return mpFrame;
478 -(void)resetCursorRects
480     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
481     {
482         // FIXME: does this leak the returned NSCursor of getCurrentCursor ?
483         const NSRect aRect = { NSZeroPoint, NSMakeSize( mpFrame->maGeometry.nWidth, mpFrame->maGeometry.nHeight) };
484         [self addCursorRect: aRect cursor: mpFrame->getCurrentCursor()];
485     }
488 -(BOOL)acceptsFirstResponder
490     return YES;
493 -(BOOL)acceptsFirstMouse: (NSEvent*)pEvent
495     (void)pEvent;
496     return YES;
499 -(BOOL)isOpaque
501     if( !mpFrame)
502         return YES;
503     if( !AquaSalFrame::isAlive( mpFrame))
504         return YES;
505     if( !mpFrame->getClipPath())
506         return YES;
507     return NO;
510 // helper class similar to a osl::Guard< comphelper::SolarMutex > for the
511 // SalYieldMutex; the difference is that it only does tryToAcquire instead of
512 // acquire so dreaded deadlocks like #i93512# are prevented
513 class TryGuard
515 public:
516             TryGuard()  { mbGuarded = ImplSalYieldMutexTryToAcquire(); }
517             ~TryGuard() { if( mbGuarded ) ImplSalYieldMutexRelease(); }
518     bool    IsGuarded() { return mbGuarded; }
519 private:
520     bool    mbGuarded;
523 -(void)drawRect: (NSRect)aRect
525     // HOTFIX: #i93512# prevent deadlocks if any other thread already has the SalYieldMutex
526     TryGuard aTryGuard;
527     if( !aTryGuard.IsGuarded() )
528     {
529         // NOTE: the mpFrame access below is not guarded yet!
530         // TODO: mpFrame et al need to be guarded by an independent mutex
531         AquaSalGraphics* pGraphics = (mpFrame && AquaSalFrame::isAlive(mpFrame)) ? mpFrame->mpGraphics : NULL;
532         if( pGraphics )
533         {
534             // we did not get the mutex so we cannot draw now => request to redraw later
535             // convert the NSRect to a CGRect for Refreshrect()
536             const CGRect aCGRect = {{aRect.origin.x,aRect.origin.y},{aRect.size.width,aRect.size.height}};
537             pGraphics->RefreshRect( aCGRect );
538         }
539         return;
540     }
542     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
543     {
544         if( mpFrame->mpGraphics )
545         {
546             mpFrame->mpGraphics->UpdateWindow( aRect );
547             if( mpFrame->getClipPath() )
548                 [mpFrame->getNSWindow() invalidateShadow];
549         }
550     }
553 -(void)sendMouseEventToFrame: (NSEvent*)pEvent button:(sal_uInt16)nButton eventtype:(sal_uInt16)nEvent
555     YIELD_GUARD;
557     AquaSalFrame* pDispatchFrame = AquaSalFrame::GetCaptureFrame();
558     bool bIsCaptured = false;
559     if( pDispatchFrame )
560     {
561         bIsCaptured = true;
562         if( nEvent == SALEVENT_MOUSELEAVE ) // no leave events if mouse is captured
563             nEvent = SALEVENT_MOUSEMOVE;
564     }
565     else if( s_pMouseFrame )
566         pDispatchFrame = s_pMouseFrame;
567     else
568         pDispatchFrame = mpFrame;
570     /* #i81645# Cocoa reports mouse events while a button is pressed
571        to the window in which it was first pressed. This is reasonable and fine and
572        gets one around most cases where on other platforms one uses CaptureMouse or XGrabPointer,
573        however vcl expects mouse events to occur in the window the mouse is over, unless the
574        mouse is explicitly captured. So we need to find the window the mouse is actually
575        over for conformance with other platforms.
576     */
577     if( ! bIsCaptured && nButton && pDispatchFrame && AquaSalFrame::isAlive( pDispatchFrame ) )
578     {
579         // is this event actually inside that NSWindow ?
580         NSPoint aPt = [NSEvent mouseLocation];
581         NSRect aFrameRect = [pDispatchFrame->getNSWindow() frame];
583         if ( ! NSPointInRect( aPt, aFrameRect ) )
584         {
585             // no, it is not
586             // now we need to find the one it may be in
587             /* #i93756# we ant to get enumerate the application windows in z-order
588                to check if any contains the mouse. This could be elegantly done with this
589                code:
591                // use NSApp to check windows in ZOrder whether they contain the mouse pointer
592                NSWindow* pWindow = [NSApp makeWindowsPerform: @selector(containsMouse) inOrder: YES];
593                if( pWindow && [pWindow isMemberOfClass: [SalFrameWindow class]] )
594                    pDispatchFrame = [(SalFrameWindow*)pWindow getSalFrame];
596                However if a non SalFrameWindow is on screen (like e.g. the file dialog)
597                it can be hit with the containsMouse selector, which it doesn't support.
598                Sadly NSApplication:makeWindowsPerform does not check (for performance reasons
599                I assume) whether a window supports a selector before sending it.
600             */
601             AquaSalFrame* pMouseFrame = getMouseContainerFrame();
602             if( pMouseFrame )
603                 pDispatchFrame = pMouseFrame;
604         }
605     }
607     if( pDispatchFrame && AquaSalFrame::isAlive( pDispatchFrame ) )
608     {
609         pDispatchFrame->mnLastEventTime = static_cast<sal_uInt64>( [pEvent timestamp] * 1000.0 );
610         pDispatchFrame->mnLastModifierFlags = [pEvent modifierFlags];
612         NSPoint aPt = [NSEvent mouseLocation];
613         pDispatchFrame->CocoaToVCL( aPt );
615         sal_uInt16 nModMask = ImplGetModifierMask( [pEvent modifierFlags] );
616         // #i82284# emulate ctrl left
617         if( nModMask == KEY_MOD3 && nButton == MOUSE_LEFT )
618         {
619             nModMask    = 0;
620             nButton     = MOUSE_RIGHT;
621         }
623         SalMouseEvent aEvent;
624         aEvent.mnTime   = pDispatchFrame->mnLastEventTime;
625         aEvent.mnX      = static_cast<long>(aPt.x) - pDispatchFrame->maGeometry.nX;
626         aEvent.mnY      = static_cast<long>(aPt.y) - pDispatchFrame->maGeometry.nY;
627         aEvent.mnButton = nButton;
628         aEvent.mnCode   =  aEvent.mnButton | nModMask;
630         // --- RTL --- (mirror mouse pos)
631         if( AllSettings::GetLayoutRTL() )
632             aEvent.mnX = pDispatchFrame->maGeometry.nWidth-1-aEvent.mnX;
634         pDispatchFrame->CallCallback( nEvent, &aEvent );
635     }
638 -(void)mouseDown: (NSEvent*)pEvent
640     if ( mpMouseEventListener != nil &&
641         [mpMouseEventListener respondsToSelector: @selector(mouseDown:)])
642     {
643         [mpMouseEventListener mouseDown: [pEvent copyWithZone: NULL]];
644     }
646     s_nLastButton = MOUSE_LEFT;
647     [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SALEVENT_MOUSEBUTTONDOWN];
650 -(void)mouseDragged: (NSEvent*)pEvent
652     if ( mpMouseEventListener != nil &&
653          [mpMouseEventListener respondsToSelector: @selector(mouseDragged:)])
654     {
655         [mpMouseEventListener mouseDragged: [pEvent copyWithZone: NULL]];
656     }
657     s_nLastButton = MOUSE_LEFT;
658     [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SALEVENT_MOUSEMOVE];
661 -(void)mouseUp: (NSEvent*)pEvent
663     s_nLastButton = 0;
664     [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SALEVENT_MOUSEBUTTONUP];
667 -(void)mouseMoved: (NSEvent*)pEvent
669     s_nLastButton = 0;
670     [self sendMouseEventToFrame:pEvent button:0 eventtype:SALEVENT_MOUSEMOVE];
673 -(void)mouseEntered: (NSEvent*)pEvent
675     s_pMouseFrame = mpFrame;
677     // #i107215# the only mouse events we get when inactive are enter/exit
678     // actually we would like to have all of them, but better none than some
679     if( [NSApp isActive] )
680         [self sendMouseEventToFrame:pEvent button:s_nLastButton eventtype:SALEVENT_MOUSEMOVE];
683 -(void)mouseExited: (NSEvent*)pEvent
685     if( s_pMouseFrame == mpFrame )
686         s_pMouseFrame = NULL;
688     // #i107215# the only mouse events we get when inactive are enter/exit
689     // actually we would like to have all of them, but better none than some
690     if( [NSApp isActive] )
691         [self sendMouseEventToFrame:pEvent button:s_nLastButton eventtype:SALEVENT_MOUSELEAVE];
694 -(void)rightMouseDown: (NSEvent*)pEvent
696     s_nLastButton = MOUSE_RIGHT;
697     [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SALEVENT_MOUSEBUTTONDOWN];
700 -(void)rightMouseDragged: (NSEvent*)pEvent
702     s_nLastButton = MOUSE_RIGHT;
703     [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SALEVENT_MOUSEMOVE];
706 -(void)rightMouseUp: (NSEvent*)pEvent
708     s_nLastButton = 0;
709     [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SALEVENT_MOUSEBUTTONUP];
712 -(void)otherMouseDown: (NSEvent*)pEvent
714     if( [pEvent buttonNumber] == 2 )
715     {
716         s_nLastButton = MOUSE_MIDDLE;
717         [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SALEVENT_MOUSEBUTTONDOWN];
718     }
719     else
720         s_nLastButton = 0;
723 -(void)otherMouseDragged: (NSEvent*)pEvent
725     if( [pEvent buttonNumber] == 2 )
726     {
727         s_nLastButton = MOUSE_MIDDLE;
728         [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SALEVENT_MOUSEMOVE];
729     }
730     else
731         s_nLastButton = 0;
734 -(void)otherMouseUp: (NSEvent*)pEvent
736     s_nLastButton = 0;
737     if( [pEvent buttonNumber] == 2 )
738         [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SALEVENT_MOUSEBUTTONUP];
741 - (void)magnifyWithEvent: (NSEvent*)pEvent
743     YIELD_GUARD;
745     // TODO: ??  -(float)magnification;
746     if( AquaSalFrame::isAlive( mpFrame ) )
747     {
748         const NSTimeInterval fMagnifyTime = [pEvent timestamp];
749         mpFrame->mnLastEventTime = static_cast<sal_uInt64>( fMagnifyTime * 1000.0 );
750         mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
752         // check if this is a new series of magnify events
753         static const NSTimeInterval fMaxDiffTime = 0.3;
754         const bool bNewSeries = (fMagnifyTime - mfLastMagnifyTime > fMaxDiffTime);
756         if( bNewSeries )
757             mfMagnifyDeltaSum = 0.0;
758         mfMagnifyDeltaSum += [pEvent magnification];
760         mfLastMagnifyTime = [pEvent timestamp];
761 // TODO: change to 0.1 when CommandWheelMode::ZOOM handlers allow finer zooming control
762         static const float fMagnifyFactor = 0.25*500; // steps are 500 times smaller for -magnification
763         static const float fMinMagnifyStep = 15.0 / fMagnifyFactor;
764         if( fabs(mfMagnifyDeltaSum) <= fMinMagnifyStep )
765             return;
767         // adapt NSEvent-sensitivity to application expectations
768         // TODO: rather make CommandWheelMode::ZOOM handlers smarter
769         const float fDeltaZ = mfMagnifyDeltaSum * fMagnifyFactor;
770         int nDeltaZ = FRound( fDeltaZ );
771         if( !nDeltaZ )
772         {
773             // handle new series immediately
774             if( !bNewSeries )
775                 return;
776             nDeltaZ = (fDeltaZ >= 0.0) ? +1 : -1;
777         }
778         // eventually give credit for delta sum
779         mfMagnifyDeltaSum -= nDeltaZ / fMagnifyFactor;
781         NSPoint aPt = [NSEvent mouseLocation];
782         mpFrame->CocoaToVCL( aPt );
784         SalWheelMouseEvent aEvent;
785         aEvent.mnTime           = mpFrame->mnLastEventTime;
786         aEvent.mnX              = static_cast<long>(aPt.x) - mpFrame->maGeometry.nX;
787         aEvent.mnY              = static_cast<long>(aPt.y) - mpFrame->maGeometry.nY;
788         aEvent.mnCode           = ImplGetModifierMask( mpFrame->mnLastModifierFlags );
789         aEvent.mnCode           |= KEY_MOD1; // we want zooming, no scrolling
790         aEvent.mbDeltaIsPixel   = TRUE;
792         // --- RTL --- (mirror mouse pos)
793         if( AllSettings::GetLayoutRTL() )
794             aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX;
796         aEvent.mnDelta = nDeltaZ;
797         aEvent.mnNotchDelta = (nDeltaZ >= 0) ? +1 : -1;
798         if( aEvent.mnDelta == 0 )
799             aEvent.mnDelta = aEvent.mnNotchDelta;
800         aEvent.mbHorz = FALSE;
801         aEvent.mnScrollLines = nDeltaZ;
802         if( aEvent.mnScrollLines == 0 )
803             aEvent.mnScrollLines = 1;
804         mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
805     }
808 - (void)rotateWithEvent: (NSEvent*)pEvent
810     //Rotation : -(float)rotation;
811     // TODO: create new CommandType so rotation is available to the applications
812     (void)pEvent;
815 - (void)swipeWithEvent: (NSEvent*)pEvent
817     YIELD_GUARD;
819     if( AquaSalFrame::isAlive( mpFrame ) )
820     {
821         mpFrame->mnLastEventTime = static_cast<sal_uInt64>( [pEvent timestamp] * 1000.0 );
822         mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
824         // merge pending scroll wheel events
825         CGFloat dX = 0.0;
826         CGFloat dY = 0.0;
827         for(;;)
828         {
829             dX += [pEvent deltaX];
830             dY += [pEvent deltaY];
831             NSEvent* pNextEvent = [NSApp nextEventMatchingMask: NSScrollWheelMask
832             untilDate: nil inMode: NSDefaultRunLoopMode dequeue: YES ];
833             if( !pNextEvent )
834                 break;
835             pEvent = pNextEvent;
836         }
838         NSPoint aPt = [NSEvent mouseLocation];
839         mpFrame->CocoaToVCL( aPt );
841         SalWheelMouseEvent aEvent;
842         aEvent.mnTime           = mpFrame->mnLastEventTime;
843         aEvent.mnX              = static_cast<long>(aPt.x) - mpFrame->maGeometry.nX;
844         aEvent.mnY              = static_cast<long>(aPt.y) - mpFrame->maGeometry.nY;
845         aEvent.mnCode           = ImplGetModifierMask( mpFrame->mnLastModifierFlags );
846         aEvent.mbDeltaIsPixel   = TRUE;
848         // --- RTL --- (mirror mouse pos)
849         if( AllSettings::GetLayoutRTL() )
850             aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX;
852         if( dX != 0.0 )
853         {
854             aEvent.mnDelta = static_cast<long>(floor(dX));
855             aEvent.mnNotchDelta = (dX < 0) ? -1 : +1;
856             if( aEvent.mnDelta == 0 )
857                 aEvent.mnDelta = aEvent.mnNotchDelta;
858             aEvent.mbHorz = TRUE;
859             aEvent.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
860             mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
861         }
862         if( dY != 0.0 && AquaSalFrame::isAlive( mpFrame ))
863         {
864             aEvent.mnDelta = static_cast<long>(floor(dY));
865             aEvent.mnNotchDelta = (dY < 0) ? -1 : +1;
866             if( aEvent.mnDelta == 0 )
867                 aEvent.mnDelta = aEvent.mnNotchDelta;
868             aEvent.mbHorz = FALSE;
869             aEvent.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
870             mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
871         }
872     }
875 -(void)scrollWheel: (NSEvent*)pEvent
877     YIELD_GUARD;
879     if( AquaSalFrame::isAlive( mpFrame ) )
880     {
881         mpFrame->mnLastEventTime = static_cast<sal_uInt64>( [pEvent timestamp] * 1000.0 );
882         mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
884         // merge pending scroll wheel events
885         CGFloat dX = 0.0;
886         CGFloat dY = 0.0;
887         for(;;)
888         {
889             dX += [pEvent deltaX];
890             dY += [pEvent deltaY];
891             NSEvent* pNextEvent = [NSApp nextEventMatchingMask: NSScrollWheelMask
892                 untilDate: nil inMode: NSDefaultRunLoopMode dequeue: YES ];
893             if( !pNextEvent )
894                 break;
895             pEvent = pNextEvent;
896         }
898         NSPoint aPt = [NSEvent mouseLocation];
899         mpFrame->CocoaToVCL( aPt );
901         SalWheelMouseEvent aEvent;
902         aEvent.mnTime         = mpFrame->mnLastEventTime;
903         aEvent.mnX            = static_cast<long>(aPt.x) - mpFrame->maGeometry.nX;
904         aEvent.mnY            = static_cast<long>(aPt.y) - mpFrame->maGeometry.nY;
905         aEvent.mnCode         = ImplGetModifierMask( mpFrame->mnLastModifierFlags );
906         aEvent.mbDeltaIsPixel = FALSE;
908         // --- RTL --- (mirror mouse pos)
909         if( AllSettings::GetLayoutRTL() )
910             aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX;
912         if( dX != 0.0 )
913         {
914             aEvent.mnDelta = static_cast<long>(floor(dX));
915             aEvent.mnNotchDelta = (dX < 0) ? -1 : +1;
916             if( aEvent.mnDelta == 0 )
917                 aEvent.mnDelta = aEvent.mnNotchDelta;
918             aEvent.mbHorz = TRUE;
919             aEvent.mnScrollLines = fabs(dX) / WHEEL_EVENT_FACTOR;
920             if( aEvent.mnScrollLines == 0 )
921                 aEvent.mnScrollLines = 1;
923             mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
924         }
925         if( dY != 0.0 && AquaSalFrame::isAlive( mpFrame ) )
926         {
927             aEvent.mnDelta = static_cast<long>(floor(dY));
928             aEvent.mnNotchDelta = (dY < 0) ? -1 : +1;
929             if( aEvent.mnDelta == 0 )
930                 aEvent.mnDelta = aEvent.mnNotchDelta;
931             aEvent.mbHorz = FALSE;
932             aEvent.mnScrollLines = fabs(dY) / WHEEL_EVENT_FACTOR;
933             if( aEvent.mnScrollLines == 0 )
934                 aEvent.mnScrollLines = 1;
936             mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
937         }
938     }
942 -(void)keyDown: (NSEvent*)pEvent
944     YIELD_GUARD;
946     if( AquaSalFrame::isAlive( mpFrame ) )
947     {
948         mpLastEvent = pEvent;
949         mbInKeyInput = true;
950         mbNeedSpecialKeyHandle = false;
951         mbKeyHandled = false;
953         mpFrame->mnLastEventTime = static_cast<sal_uInt64>( [pEvent timestamp] * 1000.0 );
954         mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
956         if( ! [self handleKeyDownException: pEvent] )
957         {
958             NSArray* pArray = [NSArray arrayWithObject: pEvent];
959             [self interpretKeyEvents: pArray];
960         }
962         mbInKeyInput = false;
963     }
966 -(BOOL)handleKeyDownException:(NSEvent*)pEvent
968     // check for a very special set of modified characters
969     NSString* pUnmodifiedString = [pEvent charactersIgnoringModifiers];
971     if( pUnmodifiedString && [pUnmodifiedString length] == 1 )
972     {
973         /* #i103102# key events with command and alternate don't make it through
974            interpretKeyEvents (why?). Try to dispatch them here first,
975            if not successful continue normally
976         */
977         if( (mpFrame->mnLastModifierFlags & (NSAlternateKeyMask | NSCommandKeyMask))
978                     == (NSAlternateKeyMask | NSCommandKeyMask) )
979         {
980             if( [self sendSingleCharacter: mpLastEvent] )
981                 return YES;
982         }
983         unichar keyChar = [pUnmodifiedString characterAtIndex: 0];
984         sal_uInt16 nKeyCode = ImplMapCharCode( keyChar );
986         // Caution: should the table grow to more than 5 or 6 entries,
987         // we must consider moving it to a kind of hash map
988         const unsigned int nExceptions = SAL_N_ELEMENTS( aExceptionalKeys );
989         for( unsigned int i = 0; i < nExceptions; i++ )
990         {
991             if( nKeyCode == aExceptionalKeys[i].nKeyCode &&
992                 (mpFrame->mnLastModifierFlags & aExceptionalKeys[i].nModifierMask)
993                 == aExceptionalKeys[i].nModifierMask )
994             {
995                 [self sendKeyInputAndReleaseToFrame: nKeyCode character: 0];
997                 return YES;
998             }
999         }
1000     }
1001     return NO;
1004 -(void)flagsChanged: (NSEvent*)pEvent
1006     YIELD_GUARD;
1008     if( AquaSalFrame::isAlive( mpFrame ) )
1009     {
1010         mpFrame->mnLastEventTime = static_cast<sal_uInt64>( [pEvent timestamp] * 1000.0 );
1011         mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
1012     }
1015 -(void)insertText:(id)aString replacementRange:(NSRange)replacementRange
1017     (void) replacementRange; // FIXME: surely it must be used
1019     YIELD_GUARD;
1021     if( AquaSalFrame::isAlive( mpFrame ) )
1022     {
1023         NSString* pInsert = nil;
1024         if( [aString isMemberOfClass: [NSAttributedString class]] )
1025             pInsert = [aString string];
1026         else
1027             pInsert = aString;
1029         int nLen = 0;
1030         if( pInsert && ( nLen = [pInsert length] ) > 0 )
1031         {
1032             OUString aInsertString( GetOUString( pInsert ) );
1033              // aCharCode initializer is safe since aInsertString will at least contain '\0'
1034             sal_Unicode aCharCode = *aInsertString.getStr();
1036             if( nLen == 1 &&
1037                 aCharCode < 0x80 &&
1038                 aCharCode > 0x1f &&
1039                 ! [self hasMarkedText ]
1040                 )
1041             {
1042                 sal_uInt16 nKeyCode = ImplMapCharCode( aCharCode );
1043                 unsigned int nLastModifiers = mpFrame->mnLastModifierFlags;
1045                 // #i99567#
1046                 // find out the unmodified key code
1048                 // sanity check
1049                 if( mpLastEvent && ( [mpLastEvent type] == NSKeyDown || [mpLastEvent type] == NSKeyUp ) )
1050                 {
1051                     // get unmodified string
1052                     NSString* pUnmodifiedString = [mpLastEvent charactersIgnoringModifiers];
1053                     if( pUnmodifiedString && [pUnmodifiedString length] == 1 )
1054                     {
1055                         // map the unmodified key code
1056                         unichar keyChar = [pUnmodifiedString characterAtIndex: 0];
1057                         nKeyCode = ImplMapCharCode( keyChar );
1058                     }
1059                     nLastModifiers = [mpLastEvent modifierFlags];
1061                 }
1062                 // #i99567#
1063                 // applications and vcl's edit fields ignore key events with ALT
1064                 // however we're at a place where we know text should be inserted
1065                 // so it seems we need to strip the Alt modifier here
1066                 if( (nLastModifiers & (NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask))
1067                     == NSAlternateKeyMask )
1068                 {
1069                     nLastModifiers = 0;
1070                 }
1071                 [self sendKeyInputAndReleaseToFrame: nKeyCode character: aCharCode modifiers: nLastModifiers];
1072             }
1073             else
1074             {
1075                 SalExtTextInputEvent aEvent;
1076                 aEvent.mnTime           = mpFrame->mnLastEventTime;
1077                 aEvent.maText           = aInsertString;
1078                 aEvent.mpTextAttr       = NULL;
1079                 aEvent.mnCursorPos      = aInsertString.getLength();
1080                 aEvent.mnCursorFlags    = 0;
1081                 aEvent.mbOnlyCursor     = FALSE;
1082                 mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, &aEvent );
1083                 if( AquaSalFrame::isAlive( mpFrame ) )
1084                     mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 );
1085             }
1086         }
1087         else
1088         {
1089             SalExtTextInputEvent aEvent;
1090             aEvent.mnTime           = mpFrame->mnLastEventTime;
1091             aEvent.maText.clear();
1092             aEvent.mpTextAttr       = NULL;
1093             aEvent.mnCursorPos      = 0;
1094             aEvent.mnCursorFlags    = 0;
1095             aEvent.mbOnlyCursor     = FALSE;
1096             mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, &aEvent );
1097             if( AquaSalFrame::isAlive( mpFrame ) )
1098                 mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 );
1100         }
1101         mbKeyHandled = true;
1102         [self unmarkText];
1103     }
1106 -(void)insertTab: (id)aSender
1108     (void)aSender;
1109     [self sendKeyInputAndReleaseToFrame: KEY_TAB character: '\t' modifiers: 0];
1112 -(void)insertBacktab: (id)aSender
1114     (void)aSender;
1115     [self sendKeyInputAndReleaseToFrame: (KEY_TAB | KEY_SHIFT) character: '\t' modifiers: 0];
1118 -(void)moveLeft: (id)aSender
1120     (void)aSender;
1121     [self sendKeyInputAndReleaseToFrame: KEY_LEFT character: 0 modifiers: 0];
1124 -(void)moveLeftAndModifySelection: (id)aSender
1126     (void)aSender;
1127     [self sendKeyInputAndReleaseToFrame: KEY_LEFT character: 0 modifiers: NSShiftKeyMask];
1130 -(void)moveBackwardAndModifySelection: (id)aSender
1132     (void)aSender;
1133     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_BACKWARD character: 0  modifiers: 0];
1136 -(void)moveRight: (id)aSender
1138     (void)aSender;
1139     [self sendKeyInputAndReleaseToFrame: KEY_RIGHT character: 0 modifiers: 0];
1142 -(void)moveRightAndModifySelection: (id)aSender
1144     (void)aSender;
1145     [self sendKeyInputAndReleaseToFrame: KEY_RIGHT character: 0 modifiers: NSShiftKeyMask];
1148 -(void)moveForwardAndModifySelection: (id)aSender
1150     (void)aSender;
1151     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_FORWARD character: 0  modifiers: 0];
1154 -(void)moveWordLeft: (id)aSender
1156     (void)aSender;
1157     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_BACKWARD character: 0  modifiers: 0];
1160 -(void)moveWordBackward: (id)aSender
1162     (void)aSender;
1163     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_BACKWARD character: 0  modifiers: 0];
1166 -(void)moveWordBackwardAndModifySelection: (id)aSender
1168     (void)aSender;
1169     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_BACKWARD character: 0  modifiers: 0];
1172 -(void)moveWordLeftAndModifySelection: (id)aSender
1174     (void)aSender;
1175     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_BACKWARD character: 0  modifiers: 0];
1178 -(void)moveWordRight: (id)aSender
1180     (void)aSender;
1181     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_FORWARD character: 0  modifiers: 0];
1184 -(void)moveWordForward: (id)aSender
1186     (void)aSender;
1187     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_FORWARD character: 0  modifiers: 0];
1190 -(void)moveWordForwardAndModifySelection: (id)aSender
1192     (void)aSender;
1193     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_FORWARD character: 0  modifiers: 0];
1196 -(void)moveWordRightAndModifySelection: (id)aSender
1198     (void)aSender;
1199     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_FORWARD character: 0  modifiers: 0];
1202 -(void)moveToEndOfLine: (id)aSender
1204     (void)aSender;
1205     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_LINE character: 0  modifiers: 0];
1208 -(void)moveToRightEndOfLine: (id)aSender
1210     (void)aSender;
1211     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_LINE character: 0  modifiers: 0];
1214 -(void)moveToEndOfLineAndModifySelection: (id)aSender
1216     (void)aSender;
1217     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_LINE character: 0  modifiers: 0];
1220 -(void)moveToRightEndOfLineAndModifySelection: (id)aSender
1222     (void)aSender;
1223     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_LINE character: 0  modifiers: 0];
1226 -(void)moveToBeginningOfLine: (id)aSender
1228     (void)aSender;
1229     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1232 -(void)moveToLeftEndOfLine: (id)aSender
1234     (void)aSender;
1235     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1238 -(void)moveToBeginningOfLineAndModifySelection: (id)aSender
1240     (void)aSender;
1241     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1244 -(void)moveToLeftEndOfLineAndModifySelection: (id)aSender
1246     (void)aSender;
1247     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1250 -(void)moveToEndOfParagraph: (id)aSender
1252     (void)aSender;
1253     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1256 -(void)moveToEndOfParagraphAndModifySelection: (id)aSender
1258     (void)aSender;
1259     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1262 -(void)moveParagraphForward: (id)aSender
1264     (void)aSender;
1265     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1268 -(void)moveParagraphForwardAndModifySelection: (id)aSender
1270     (void)aSender;
1271     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1274 -(void)moveToBeginningOfParagraph: (id)aSender
1276     (void)aSender;
1277     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1280 -(void)moveParagraphBackward: (id)aSender
1282     (void)aSender;
1283     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1286 -(void)moveToBeginningOfParagraphAndModifySelection: (id)aSender
1288     (void)aSender;
1289     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1292 -(void)moveParagraphBackwardAndModifySelection: (id)aSender
1294     (void)aSender;
1295     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1298 -(void)moveToEndOfDocument: (id)aSender
1300     (void)aSender;
1301     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT character: 0  modifiers: 0];
1304 -(void)scrollToEndOfDocument: (id)aSender
1306     (void)aSender;
1307     // this is not exactly what we should do, but it makes "End" and "Shift-End" behave consistent
1308     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT character: 0  modifiers: 0];
1311 -(void)moveToEndOfDocumentAndModifySelection: (id)aSender
1313     (void)aSender;
1314     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT character: 0  modifiers: 0];
1317 -(void)moveToBeginningOfDocument: (id)aSender
1319     (void)aSender;
1320     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT character: 0  modifiers: 0];
1323 -(void)scrollToBeginningOfDocument: (id)aSender
1325     (void)aSender;
1326     // this is not exactly what we should do, but it makes "Home" and "Shift-Home" behave consistent
1327     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT character: 0  modifiers: 0];
1330 -(void)moveToBeginningOfDocumentAndModifySelection: (id)aSender
1332     (void)aSender;
1333     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT character: 0  modifiers: 0];
1336 -(void)moveUp: (id)aSender
1338     (void)aSender;
1339     [self sendKeyInputAndReleaseToFrame: KEY_UP character: 0 modifiers: 0];
1342 -(void)moveDown: (id)aSender
1344     (void)aSender;
1345     [self sendKeyInputAndReleaseToFrame: KEY_DOWN character: 0 modifiers: 0];
1348 -(void)insertNewline: (id)aSender
1350     (void)aSender;
1351     // #i91267# make enter and shift-enter work by evaluating the modifiers
1352     [self sendKeyInputAndReleaseToFrame: KEY_RETURN character: '\n' modifiers: mpFrame->mnLastModifierFlags];
1355 -(void)deleteBackward: (id)aSender
1357     (void)aSender;
1358     [self sendKeyInputAndReleaseToFrame: KEY_BACKSPACE character: '\b' modifiers: 0];
1361 -(void)deleteForward: (id)aSender
1363     (void)aSender;
1364     [self sendKeyInputAndReleaseToFrame: KEY_DELETE character: 0x7f modifiers: 0];
1367 -(void)deleteBackwardByDecomposingPreviousCharacter: (id)aSender
1369     (void)aSender;
1370     [self sendKeyInputAndReleaseToFrame: KEY_BACKSPACE character: '\b' modifiers: 0];
1373 -(void)deleteWordBackward: (id)aSender
1375     (void)aSender;
1376     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_WORD_BACKWARD character: 0  modifiers: 0];
1379 -(void)deleteWordForward: (id)aSender
1381     (void)aSender;
1382     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_WORD_FORWARD character: 0  modifiers: 0];
1385 -(void)deleteToBeginningOfLine: (id)aSender
1387     (void)aSender;
1388     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1391 -(void)deleteToEndOfLine: (id)aSender
1393     (void)aSender;
1394     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_END_OF_LINE character: 0  modifiers: 0];
1397 -(void)deleteToBeginningOfParagraph: (id)aSender
1399     (void)aSender;
1400     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1403 -(void)deleteToEndOfParagraph: (id)aSender
1405     (void)aSender;
1406     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1409 -(void)insertLineBreak: (id)aSender
1411     (void)aSender;
1412     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::INSERT_LINEBREAK character: 0  modifiers: 0];
1415 -(void)insertParagraphSeparator: (id)aSender
1417     (void)aSender;
1418     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::INSERT_PARAGRAPH character: 0  modifiers: 0];
1421 -(void)selectWord: (id)aSender
1423     (void)aSender;
1424     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD character: 0  modifiers: 0];
1427 -(void)selectLine: (id)aSender
1429     (void)aSender;
1430     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_LINE character: 0  modifiers: 0];
1433 -(void)selectParagraph: (id)aSender
1435     (void)aSender;
1436     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_PARAGRAPH character: 0  modifiers: 0];
1439 -(void)selectAll: (id)aSender
1441     (void)aSender;
1442     [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_ALL character: 0  modifiers: 0];
1445 -(void)cancelOperation: (id)aSender
1447     (void)aSender;
1448     [self sendKeyInputAndReleaseToFrame: KEY_ESCAPE character: 0x1b modifiers: 0];
1451 -(void)noop: (id)aSender
1453     (void)aSender;
1454     if( ! mbKeyHandled )
1455     {
1456         if( ! [self sendSingleCharacter:mpLastEvent] )
1457         {
1458             /* prevent recursion */
1459             if( mpLastEvent != mpLastSuperEvent && [NSApp respondsToSelector: @selector(sendSuperEvent:)] )
1460             {
1461                 id pLastSuperEvent = mpLastSuperEvent;
1462                 mpLastSuperEvent = mpLastEvent;
1463                 [NSApp performSelector:@selector(sendSuperEvent:) withObject: mpLastEvent];
1464                 mpLastSuperEvent = pLastSuperEvent;
1466                 std::map< NSEvent*, bool >::iterator it = GetSalData()->maKeyEventAnswer.find( mpLastEvent );
1467                 if( it != GetSalData()->maKeyEventAnswer.end() )
1468                     it->second = true;
1469             }
1470         }
1471     }
1474 -(BOOL)sendKeyInputAndReleaseToFrame: (sal_uInt16)nKeyCode character: (sal_Unicode)aChar
1476     return [self sendKeyInputAndReleaseToFrame: nKeyCode character: aChar modifiers: mpFrame->mnLastModifierFlags];
1479 -(BOOL)sendKeyInputAndReleaseToFrame: (sal_uInt16)nKeyCode character: (sal_Unicode)aChar modifiers: (unsigned int)nMod
1481     return [self sendKeyToFrameDirect: nKeyCode character: aChar modifiers: nMod] ||
1482            [self sendSingleCharacter: mpLastEvent];
1485 -(BOOL)sendKeyToFrameDirect: (sal_uInt16)nKeyCode  character: (sal_Unicode)aChar modifiers: (unsigned int)nMod
1487     YIELD_GUARD;
1489     long nRet = 0;
1490     if( AquaSalFrame::isAlive( mpFrame ) )
1491     {
1492         SalKeyEvent aEvent;
1493         aEvent.mnTime           = mpFrame->mnLastEventTime;
1494         aEvent.mnCode           = nKeyCode | ImplGetModifierMask( nMod );
1495         aEvent.mnCharCode       = aChar;
1496         aEvent.mnRepeat         = FALSE;
1497         nRet = mpFrame->CallCallback( SALEVENT_KEYINPUT, &aEvent );
1498         std::map< NSEvent*, bool >::iterator it = GetSalData()->maKeyEventAnswer.find( mpLastEvent );
1499         if( it != GetSalData()->maKeyEventAnswer.end() )
1500             it->second = nRet != 0;
1501         if( AquaSalFrame::isAlive( mpFrame ) )
1502             mpFrame->CallCallback( SALEVENT_KEYUP, &aEvent );
1503     }
1504     return nRet ? YES : NO;
1508 -(BOOL)sendSingleCharacter: (NSEvent *)pEvent
1510     NSString* pUnmodifiedString = [pEvent charactersIgnoringModifiers];
1512     if( pUnmodifiedString && [pUnmodifiedString length] == 1 )
1513     {
1514         unichar keyChar = [pUnmodifiedString characterAtIndex: 0];
1515         sal_uInt16 nKeyCode = ImplMapCharCode( keyChar );
1516         if (nKeyCode == 0)
1517         {
1518             sal_uInt16 nOtherKeyCode = [pEvent keyCode];
1519             nKeyCode = ImplMapKeyCode(nOtherKeyCode);
1520         }
1521         if( nKeyCode != 0 )
1522         {
1523             // don't send unicodes in the private use area
1524             if( keyChar >= 0xf700 && keyChar < 0xf780 )
1525                 keyChar = 0;
1526             BOOL bRet = [self sendKeyToFrameDirect: nKeyCode character: keyChar modifiers: mpFrame->mnLastModifierFlags];
1527             mbInKeyInput = false;
1529             return bRet;
1530         }
1531     }
1532     return NO;
1536 // NSTextInput/NSTextInputClient protocol
1537 - (NSArray *)validAttributesForMarkedText
1539     return [NSArray arrayWithObjects:NSUnderlineStyleAttributeName, nil];
1542 - (BOOL)hasMarkedText
1544     BOOL bHasMarkedText;
1546     bHasMarkedText = ( mMarkedRange.location != NSNotFound ) &&
1547                      ( mMarkedRange.length != 0 );
1548     // hack to check keys like "Control-j"
1549     if( mbInKeyInput )
1550     {
1551         mbNeedSpecialKeyHandle = true;
1552     }
1554     // FIXME:
1555     // #i106901#
1556     // if we come here outside of mbInKeyInput, this is likely to be because
1557     // of the keyboard viewer. For unknown reasons having no marked range
1558     // in this case causes a crash. So we say we have a marked range anyway
1559     // This is a hack, since it is not understood what a) causes that crash
1560     // and b) why we should have a marked range at this point.
1561     if( ! mbInKeyInput )
1562         bHasMarkedText = YES;
1564     return bHasMarkedText;
1567 - (NSRange)markedRange
1569     // FIXME:
1570     // #i106901#
1571     // if we come here outside of mbInKeyInput, this is likely to be because
1572     // of the keyboard viewer. For unknown reasons having no marked range
1573     // in this case causes a crash. So we say we have a marked range anyway
1574     // This is a hack, since it is not understood what a) causes that crash
1575     // and b) why we should have a marked range at this point.
1576     if( ! mbInKeyInput )
1577         return NSMakeRange( 0, 0 );
1579     return [self hasMarkedText] ? mMarkedRange : NSMakeRange( NSNotFound, 0 );
1582 - (NSRange)selectedRange
1584     return mSelectedRange;
1587 - (void)setMarkedText:(id)aString selectedRange:(NSRange)selRange replacementRange:(NSRange)replacementRange
1589     (void) replacementRange; // FIXME - use it!
1591     YIELD_GUARD;
1593     if( ![aString isKindOfClass:[NSAttributedString class]] )
1594         aString = [[[NSAttributedString alloc] initWithString:aString] autorelease];
1595     NSRange rangeToReplace = [self hasMarkedText] ? [self markedRange] : [self selectedRange];
1596     if( rangeToReplace.location == NSNotFound )
1597     {
1598         mMarkedRange = NSMakeRange( selRange.location, [aString length] );
1599         mSelectedRange = NSMakeRange( selRange.location, selRange.length );
1600     }
1601     else
1602     {
1603         mMarkedRange = NSMakeRange( rangeToReplace.location, [aString length] );
1604         mSelectedRange = NSMakeRange( rangeToReplace.location + selRange.location, selRange.length );
1605     }
1607     int len = [aString length];
1608     SalExtTextInputEvent aInputEvent;
1609     aInputEvent.mnTime = mpFrame->mnLastEventTime;
1610     aInputEvent.mbOnlyCursor = FALSE;
1611     if( len > 0 ) {
1612         NSString *pString = [aString string];
1613         OUString aInsertString( GetOUString( pString ) );
1614         std::vector<sal_uInt16> aInputFlags = std::vector<sal_uInt16>( std::max( 1, len ), 0 );
1615         for ( int i = 0; i < len; i++ )
1616         {
1617             unsigned int nUnderlineValue;
1618             NSRange effectiveRange;
1620             effectiveRange = NSMakeRange(i, 1);
1621             nUnderlineValue = [[aString attribute:NSUnderlineStyleAttributeName atIndex:i effectiveRange:&effectiveRange] unsignedIntValue];
1623             switch (nUnderlineValue & 0xff) {
1624             case NSUnderlineStyleSingle:
1625                 aInputFlags[i] = EXTTEXTINPUT_ATTR_UNDERLINE;
1626                 break;
1627             case NSUnderlineStyleThick:
1628                 aInputFlags[i] = EXTTEXTINPUT_ATTR_UNDERLINE | EXTTEXTINPUT_ATTR_HIGHLIGHT;
1629                 break;
1630             case NSUnderlineStyleDouble:
1631                 aInputFlags[i] = EXTTEXTINPUT_ATTR_BOLDUNDERLINE;
1632                 break;
1633             default:
1634                 aInputFlags[i] = EXTTEXTINPUT_ATTR_HIGHLIGHT;
1635                 break;
1636             }
1637         }
1639         aInputEvent.maText = aInsertString;
1640         aInputEvent.mnCursorPos = selRange.location;
1641         aInputEvent.mpTextAttr = &aInputFlags[0];
1642         mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void *)&aInputEvent );
1643     } else {
1644         aInputEvent.maText.clear();
1645         aInputEvent.mnCursorPos = 0;
1646         aInputEvent.mnCursorFlags = 0;
1647         aInputEvent.mpTextAttr = 0;
1648         mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void *)&aInputEvent );
1649         mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 );
1650     }
1651     mbKeyHandled= true;
1654 - (void)unmarkText
1656     mSelectedRange = mMarkedRange = NSMakeRange(NSNotFound, 0);
1659 - (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
1661     (void) aRange;
1662     (void) actualRange;
1664     // FIXME - Implement
1665     return nil;
1668 - (NSUInteger)characterIndexForPoint:(NSPoint)thePoint
1670     (void)thePoint;
1671     // FIXME
1672     return 0;
1675 - (NSInteger)conversationIdentifier
1677     return reinterpret_cast<long>(self);
1680 - (void)doCommandBySelector:(SEL)aSelector
1682     if( AquaSalFrame::isAlive( mpFrame ) )
1683     {
1684         #if OSL_DEBUG_LEVEL > 1
1685         // fprintf( stderr, "SalFrameView: doCommandBySelector %s\n", (char*)aSelector );
1686         #endif
1687         if( (mpFrame->mnICOptions & InputContextFlags::Text) &&
1688             aSelector != NULL && [self respondsToSelector: aSelector] )
1689         {
1690             [self performSelector: aSelector];
1691         }
1692         else
1693         {
1694             [self sendSingleCharacter:mpLastEvent];
1695         }
1696     }
1698     mbKeyHandled = true;
1701 -(void)clearLastEvent
1703     mpLastEvent = nil;
1706 - (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
1708      // FIXME - These should probably be used?
1709     (void) aRange;
1710     (void) actualRange;
1712     YIELD_GUARD;
1714     SalExtTextInputPosEvent aPosEvent;
1715     mpFrame->CallCallback( SALEVENT_EXTTEXTINPUTPOS, (void *)&aPosEvent );
1717     NSRect rect;
1719     rect.origin.x = aPosEvent.mnX + mpFrame->maGeometry.nX;
1720     rect.origin.y =   aPosEvent.mnY + mpFrame->maGeometry.nY + 4; // add some space for underlines
1721     rect.size.width = aPosEvent.mnWidth;
1722     rect.size.height = aPosEvent.mnHeight;
1724     mpFrame->VCLToCocoa( rect );
1725     return rect;
1728 -(id)parentAttribute {
1729     return reinterpret_cast<NSView*>(mpFrame->getNSWindow());
1730         //TODO: odd cast really needed for fdo#74121?
1733 -(::com::sun::star::accessibility::XAccessibleContext *)accessibleContext
1735     if ( !mpReferenceWrapper ) {
1736         // some frames never become visible ..
1737         vcl::Window *pWindow = mpFrame -> GetWindow();
1738         if ( ! pWindow )
1739             return nil;
1741         mpReferenceWrapper = new ReferenceWrapper;
1742         mpReferenceWrapper -> rAccessibleContext =  pWindow -> /*GetAccessibleChildWindow( 0 ) ->*/ GetAccessible() -> getAccessibleContext();
1743         [ AquaA11yFactory insertIntoWrapperRepository: self forAccessibleContext: mpReferenceWrapper -> rAccessibleContext ];
1744     }
1745     return [ super accessibleContext ];
1748 -(NSWindow*)windowForParent
1750     return mpFrame->getNSWindow();
1753 -(void)registerMouseEventListener: (id)theListener
1755   mpMouseEventListener = theListener;
1758 -(void)unregisterMouseEventListener: (id)theListener
1760     (void)theListener;
1761     mpMouseEventListener = nil;
1764 -(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
1766   return [mDraggingDestinationHandler draggingEntered: sender];
1769 -(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
1771   return [mDraggingDestinationHandler draggingUpdated: sender];
1774 -(void)draggingExited:(id <NSDraggingInfo>)sender
1776   [mDraggingDestinationHandler draggingExited: sender];
1779 -(BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
1781   return [mDraggingDestinationHandler prepareForDragOperation: sender];
1784 -(BOOL)performDragOperation:(id <NSDraggingInfo>)sender
1786   return [mDraggingDestinationHandler performDragOperation: sender];
1789 -(void)concludeDragOperation:(id <NSDraggingInfo>)sender
1791   [mDraggingDestinationHandler concludeDragOperation: sender];
1794 -(void)registerDraggingDestinationHandler:(id)theHandler
1796   mDraggingDestinationHandler = theHandler;
1799 -(void)unregisterDraggingDestinationHandler:(id)theHandler
1801     (void)theHandler;
1802     mDraggingDestinationHandler = nil;
1805 @end
1807 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */