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 <sal/alloca.h>
28
29#include "vcl/window.hxx"
30#include "vcl/svapp.hxx"
31
32#include "aqua/salinst.h"
33#include "aqua/salgdi.h"
34#include "aqua/salframe.h"
35#include "aqua/salframeview.h"
36#include "aqua/aqua11yfactory.h"
37
38#define WHEEL_EVENT_FACTOR 1.5
39
40// for allowing fullscreen support on deployment targets < OSX 10.7
41#if !defined(MAC_OS_X_VERSION_10_7)
42    #define NSWindowCollectionBehaviorFullScreenPrimary   (1 << 7)
43    #define NSWindowCollectionBehaviorFullScreenAuxiliary (1 << 8)
44//  #define NSFullScreenWindowMask (1 << 14)
45#endif
46
47
48static sal_uInt16 ImplGetModifierMask( unsigned int nMask )
49{
50    sal_uInt16 nRet = 0;
51    if( (nMask & NSShiftKeyMask) != 0 )
52        nRet |= KEY_SHIFT;
53    if( (nMask & NSControlKeyMask) != 0 )
54        nRet |= KEY_MOD3;
55    if( (nMask & NSAlternateKeyMask) != 0 )
56        nRet |= KEY_MOD2;
57    if( (nMask & NSCommandKeyMask) != 0 )
58        nRet |= KEY_MOD1;
59    return nRet;
60}
61
62static sal_uInt16 ImplMapCharCode( sal_Unicode aCode )
63{
64    static sal_uInt16 aKeyCodeMap[ 128 ] =
65    {
66        0, 0, 0, 0, 0, 0, 0, 0,
67        KEY_BACKSPACE, KEY_TAB, KEY_RETURN, 0, 0, KEY_RETURN, 0, 0,
68        0, 0, 0, 0, 0, 0, 0, 0,
69        0, KEY_TAB, 0, KEY_ESCAPE, 0, 0, 0, 0,
70        KEY_SPACE, 0, 0, 0, 0, 0, 0, 0,
71        0, 0, KEY_MULTIPLY, KEY_ADD, KEY_COMMA, KEY_SUBTRACT, KEY_POINT, KEY_DIVIDE,
72        KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7,
73        KEY_8, KEY_9, 0, 0, KEY_LESS, KEY_EQUAL, KEY_GREATER, 0,
74        0, KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G,
75        KEY_H, KEY_I, KEY_J, KEY_K, KEY_L, KEY_M, KEY_N, KEY_O,
76        KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U, KEY_V, KEY_W,
77        KEY_X, KEY_Y, KEY_Z, 0, 0, 0, 0, 0,
78        KEY_QUOTELEFT, KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G,
79        KEY_H, KEY_I, KEY_J, KEY_K, KEY_L, KEY_M, KEY_N, KEY_O,
80        KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U, KEY_V, KEY_W,
81        KEY_X, KEY_Y, KEY_Z, 0, 0, 0, KEY_TILDE, KEY_BACKSPACE
82    };
83
84    // Note: the mapping 0x7f should by rights be KEY_DELETE
85    // however if you press "backspace" 0x7f is reported
86    // whereas for "delete" 0xf728 gets reported
87
88    // Note: the mapping of 0x19 to KEY_TAB is because for unknown reasons
89    // tab alone is reported as 0x09 (as expected) but shift-tab is
90    // reported as 0x19 (end of medium)
91
92    static sal_uInt16 aFunctionKeyCodeMap[ 128 ] =
93    {
94        KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_F1, KEY_F2, KEY_F3, KEY_F4,
95        KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12,
96        KEY_F13, KEY_F14, KEY_F15, KEY_F16, KEY_F17, KEY_F18, KEY_F19, KEY_F20,
97        KEY_F21, KEY_F22, KEY_F23, KEY_F24, KEY_F25, KEY_F26, 0, 0,
98        0, 0, 0, 0, 0, 0, 0, KEY_INSERT,
99        KEY_DELETE, KEY_HOME, 0, KEY_END, KEY_PAGEUP, KEY_PAGEDOWN, 0, 0,
100        0, 0, 0, 0, 0, KEY_MENU, 0, 0,
101        0, 0, 0, 0, 0, 0, 0, 0,
102        0, 0, 0, KEY_UNDO, KEY_REPEAT, KEY_FIND, KEY_HELP, 0,
103        0, 0, 0, 0, 0, 0, 0, 0,
104        0, 0, 0, 0, 0, 0, 0, 0,
105        0, 0, 0, 0, 0, 0, 0, 0,
106        0, 0, 0, 0, 0, 0, 0, 0,
107        0, 0, 0, 0, 0, 0, 0, 0,
108        0, 0, 0, 0, 0, 0, 0, 0,
109        0, 0, 0, 0, 0, 0, 0, 0
110    };
111
112    sal_uInt16 nKeyCode = 0;
113    if( aCode < sizeof( aKeyCodeMap) / sizeof( aKeyCodeMap[0] ) )
114        nKeyCode = aKeyCodeMap[ aCode ];
115    else if( aCode >= 0xf700 && aCode < 0xf780 )
116        nKeyCode = aFunctionKeyCodeMap[ aCode - 0xf700 ];
117    return nKeyCode;
118}
119
120// store the frame the mouse last entered
121static AquaSalFrame* s_pMouseFrame = NULL;
122// store the last pressed button for enter/exit events
123// which lack that information
124static sal_uInt16 s_nLastButton = 0;
125
126// combinations of keys we need to handle ourselves
127static const struct ExceptionalKey
128{
129    const sal_uInt16        nKeyCode;
130    const unsigned int  nModifierMask;
131} aExceptionalKeys[] =
132{
133    { KEY_D, NSControlKeyMask | NSShiftKeyMask | NSAlternateKeyMask },
134    { KEY_D, NSCommandKeyMask | NSShiftKeyMask | NSAlternateKeyMask }
135};
136
137static AquaSalFrame* getMouseContainerFrame()
138{
139    int nWindows = 0;
140    NSCountWindows( &nWindows );
141    int* pWindows = (int*)alloca( nWindows * sizeof(int) );
142    // note: NSWindowList is supposed to be in z-order front to back
143    NSWindowList( nWindows, pWindows );
144    AquaSalFrame* pDispatchFrame = NULL;
145    for(int i = 0; i < nWindows && ! pDispatchFrame; i++ )
146    {
147        NSWindow* pWin = [NSApp windowWithWindowNumber: pWindows[i]];
148        if( pWin && [pWin isMemberOfClass: [SalFrameWindow class]] && [(SalFrameWindow*)pWin containsMouse] )
149            pDispatchFrame = [(SalFrameWindow*)pWin getSalFrame];
150    }
151    return pDispatchFrame;
152}
153
154@implementation SalFrameWindow
155-(id)initWithSalFrame: (AquaSalFrame*)pFrame
156{
157	mDraggingDestinationHandler = nil;
158    mpFrame = pFrame;
159    NSRect aRect = { { pFrame->maGeometry.nX, pFrame->maGeometry.nY },
160                     { pFrame->maGeometry.nWidth, pFrame->maGeometry.nHeight } };
161    pFrame->VCLToCocoa( aRect );
162    NSWindow* pNSWindow = [super initWithContentRect: aRect styleMask: mpFrame->getStyleMask() backing: NSBackingStoreBuffered defer: NO ];
163    [pNSWindow useOptimizedDrawing: YES]; // OSX recommendation when there are no overlapping subviews within the receiver
164
165    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)));
166    bAllowFullScreen &= (0 == (~mpFrame->mnStyle & (SAL_FRAME_STYLE_SIZEABLE)));
167    bAllowFullScreen &= (mpFrame->mpParent == NULL);
168    const SEL setCollectionBehavior = @selector(setCollectionBehavior:);
169    if( bAllowFullScreen && [pNSWindow respondsToSelector: setCollectionBehavior])
170    {
171        NSNumber* bMode = [NSNumber numberWithInt:(bAllowFullScreen ? NSWindowCollectionBehaviorFullScreenPrimary : NSWindowCollectionBehaviorFullScreenAuxiliary)];
172        [pNSWindow performSelector:setCollectionBehavior withObject:bMode];
173    }
174
175    return pNSWindow;
176}
177
178-(AquaSalFrame*)getSalFrame
179{
180    return mpFrame;
181}
182
183-(void)displayIfNeeded
184{
185    if( GetSalData() && GetSalData()->mpFirstInstance )
186    {
187        vos::IMutex* pMutex = GetSalData()->mpFirstInstance->GetYieldMutex();
188        if( pMutex )
189        {
190            pMutex->acquire();
191            [super displayIfNeeded];
192            pMutex->release();
193        }
194    }
195}
196
197-(BOOL)containsMouse
198{
199    // is this event actually inside that NSWindow ?
200    NSPoint aPt = [NSEvent mouseLocation];
201    NSRect aFrameRect = [self frame];
202    BOOL bInRect = NSPointInRect( aPt, aFrameRect );
203    return bInRect;
204}
205
206-(BOOL)canBecomeKeyWindow
207{
208    if( (mpFrame->mnStyle &
209            ( SAL_FRAME_STYLE_FLOAT                 |
210              SAL_FRAME_STYLE_TOOLTIP               |
211              SAL_FRAME_STYLE_INTRO
212            )) == 0 )
213        return YES;
214    if( (mpFrame->mnStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) != 0 )
215        return YES;
216    if( mpFrame->mbFullScreen )
217        return YES;
218    if( (mpFrame->mnStyle & SAL_FRAME_STYLE_FLOAT_FOCUSABLE) )
219        return YES;
220    return [super canBecomeKeyWindow];
221}
222
223-(void)windowDidBecomeKey: (NSNotification*)pNotification
224{
225    (void)pNotification;
226    YIELD_GUARD;
227
228    if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
229    {
230        static const sal_uLong nGuessDocument = SAL_FRAME_STYLE_MOVEABLE|
231                                            SAL_FRAME_STYLE_SIZEABLE|
232                                            SAL_FRAME_STYLE_CLOSEABLE;
233
234        if( mpFrame->mpMenu )
235            mpFrame->mpMenu->setMainMenu();
236        else if( ! mpFrame->mpParent &&
237                 ( (mpFrame->mnStyle & nGuessDocument) == nGuessDocument || // set default menu for e.g. help
238                    mpFrame->mbFullScreen ) )                               // ser default menu for e.g. presentation
239        {
240            AquaSalMenu::setDefaultMenu();
241        }
242        #if 0
243        // FIXME: we should disable menus while in modal mode
244        // however from down here there is currently no reliable way to
245        // find out when to do this
246        if( (mpFrame->mpParent && mpFrame->mpParent->GetWindow()->IsInModalMode()) )
247            AquaSalMenu::enableMainMenu( false );
248        #endif
249        mpFrame->CallCallback( SALEVENT_GETFOCUS, 0 );
250        mpFrame->SendPaintEvent(); // repaint controls as active
251    }
252}
253
254-(void)windowDidResignKey: (NSNotification*)pNotification
255{
256    (void)pNotification;
257    YIELD_GUARD;
258
259    if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
260    {
261        mpFrame->CallCallback(SALEVENT_LOSEFOCUS, 0);
262        mpFrame->SendPaintEvent(); // repaint controls as inactive
263    }
264}
265
266-(void)windowDidChangeScreen: (NSNotification*)pNotification
267{
268    (void)pNotification;
269    YIELD_GUARD;
270
271    if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
272        mpFrame->screenParametersChanged();
273}
274
275-(void)windowDidMove: (NSNotification*)pNotification
276{
277    (void)pNotification;
278    YIELD_GUARD;
279
280    if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
281    {
282        mpFrame->UpdateFrameGeometry();
283        mpFrame->CallCallback( SALEVENT_MOVE, 0 );
284    }
285}
286
287-(void)windowDidResize: (NSNotification*)pNotification
288{
289    (void)pNotification;
290    YIELD_GUARD;
291
292    if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
293    {
294        mpFrame->UpdateFrameGeometry();
295        mpFrame->CallCallback( SALEVENT_RESIZE, 0 );
296        mpFrame->SendPaintEvent();
297    }
298}
299
300-(void)windowDidMiniaturize: (NSNotification*)pNotification
301{
302    (void)pNotification;
303    YIELD_GUARD;
304
305    if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
306    {
307        mpFrame->mbShown = false;
308        mpFrame->UpdateFrameGeometry();
309        mpFrame->CallCallback( SALEVENT_RESIZE, 0 );
310    }
311}
312
313-(void)windowDidDeminiaturize: (NSNotification*)pNotification
314{
315    (void)pNotification;
316    YIELD_GUARD;
317
318    if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
319    {
320        mpFrame->mbShown = true;
321        mpFrame->UpdateFrameGeometry();
322        mpFrame->CallCallback( SALEVENT_RESIZE, 0 );
323    }
324}
325
326-(BOOL)windowShouldClose: (NSNotification*)pNotification
327{
328    (void)pNotification;
329    YIELD_GUARD;
330
331    BOOL bRet = YES;
332    if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
333    {
334        // #i84461# end possible input
335        mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 );
336        if( AquaSalFrame::isAlive( mpFrame ) )
337        {
338            mpFrame->CallCallback( SALEVENT_CLOSE, 0 );
339            bRet = NO; // application will close the window or not, AppKit shouldn't
340        }
341    }
342
343    return bRet;
344}
345
346#if 0 // windowWillEnterFullScreen doesn't do anything useful yet
347-(void)windowWillEnterFullScreen: (NSNotification*)pNotification
348{
349    YIELD_GUARD;
350
351    if( !mpFrame || !AquaSalFrame::isAlive( mpFrame ) )
352        return;
353    // TODO: implement something useful
354    (void)pNotification;
355}
356#endif
357
358#if 0 // windowWillExitFullScreen doesn't do anything useful yet
359-(void)windowWillExitFullScreen: (NSNotification*)pNotification
360{
361    YIELD_GUARD;
362
363    if( !mpFrame || !AquaSalFrame::isAlive( mpFrame ) )
364        return;
365    // TODO: implement something useful
366    (void)pNotification;
367}
368#endif
369
370-(void)windowDidEnterFullScreen: (NSNotification*)pNotification
371{
372    YIELD_GUARD;
373
374    if( !mpFrame || !AquaSalFrame::isAlive( mpFrame))
375        return;
376    mpFrame->mbFullScreen = true;
377    (void)pNotification;
378}
379
380-(void)windowDidExitFullScreen: (NSNotification*)pNotification
381{
382    YIELD_GUARD;
383
384    if( !mpFrame || !AquaSalFrame::isAlive( mpFrame))
385        return;
386    mpFrame->mbFullScreen = false;
387    (void)pNotification;
388}
389
390-(void)dockMenuItemTriggered: (id)sender
391{
392    (void)sender;
393    YIELD_GUARD;
394
395    if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
396        mpFrame->ToTop( SAL_FRAME_TOTOP_RESTOREWHENMIN | SAL_FRAME_TOTOP_GRABFOCUS );
397}
398
399-(::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext >)accessibleContext
400{
401    return mpFrame -> GetWindow() -> GetAccessible() -> getAccessibleContext();
402}
403
404-(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
405{
406  return [mDraggingDestinationHandler draggingEntered: sender];
407}
408
409-(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
410{
411  return [mDraggingDestinationHandler draggingUpdated: sender];
412}
413
414-(void)draggingExited:(id <NSDraggingInfo>)sender
415{
416  [mDraggingDestinationHandler draggingExited: sender];
417}
418
419-(BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
420{
421  return [mDraggingDestinationHandler prepareForDragOperation: sender];
422}
423
424-(BOOL)performDragOperation:(id <NSDraggingInfo>)sender
425{
426  return [mDraggingDestinationHandler performDragOperation: sender];
427}
428
429-(void)concludeDragOperation:(id <NSDraggingInfo>)sender
430{
431  [mDraggingDestinationHandler concludeDragOperation: sender];
432}
433
434-(void)registerDraggingDestinationHandler:(id)theHandler
435{
436  mDraggingDestinationHandler = theHandler;
437}
438
439-(void)unregisterDraggingDestinationHandler:(id)theHandler
440{
441    (void)theHandler;
442    mDraggingDestinationHandler = nil;
443}
444
445@end
446
447@implementation SalFrameView
448+(void)unsetMouseFrame: (AquaSalFrame*)pFrame
449{
450    if( pFrame == s_pMouseFrame )
451        s_pMouseFrame = NULL;
452}
453
454-(id)initWithSalFrame: (AquaSalFrame*)pFrame
455{
456    if ((self = [super initWithFrame: [NSWindow contentRectForFrameRect: [pFrame->getWindow() frame] styleMask: pFrame->mnStyleMask]]) != nil)
457    {
458        mDraggingDestinationHandler = nil;
459        mpFrame = pFrame;
460        mMarkedRange = NSMakeRange(NSNotFound, 0);
461        mSelectedRange = NSMakeRange(NSNotFound, 0);
462        mpReferenceWrapper = nil;
463		mpMouseEventListener = nil;
464        mpLastSuperEvent = nil;
465    }
466
467    mfLastMagnifyTime = 0.0;
468    return self;
469}
470
471-(AquaSalFrame*)getSalFrame
472{
473    return mpFrame;
474}
475
476-(void)resetCursorRects
477{
478    if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
479    {
480        // FIXME: does this leak the returned NSCursor of getCurrentCursor ?
481        NSRect aRect = { { 0, 0 }, { mpFrame->maGeometry.nWidth, mpFrame->maGeometry.nHeight } };
482        [self addCursorRect: aRect cursor: mpFrame->getCurrentCursor()];
483    }
484}
485
486-(BOOL)acceptsFirstResponder
487{
488    return YES;
489}
490
491-(BOOL)acceptsFirstMouse: (NSEvent*)pEvent
492{
493    (void)pEvent;
494    return YES;
495}
496
497-(BOOL)isOpaque
498{
499    return mpFrame ? (mpFrame->getClipPath() != 0 ? NO : YES) : YES;
500}
501
502// helper class similar to a vos::OGuard for the SalYieldMutex
503// the difference is that it only does tryToAcquire instead of aquire
504// so dreaded deadlocks like #i93512# are prevented
505class TryGuard
506{
507public:
508			TryGuard()  { mbGuarded = ImplSalYieldMutexTryToAcquire(); }
509			~TryGuard() { if( mbGuarded ) ImplSalYieldMutexRelease(); }
510	bool	IsGuarded() { return mbGuarded; }
511private:
512	bool	mbGuarded;
513};
514
515-(void)drawRect: (NSRect)aRect
516{
517	// HOTFIX: #i93512# prevent deadlocks if any other thread already has the SalYieldMutex
518	TryGuard aTryGuard;
519	if( !aTryGuard.IsGuarded() )
520	{
521		// NOTE: the mpFrame access below is not guarded yet!
522		// TODO: mpFrame et al need to be guarded by an independent mutex
523		AquaSalGraphics* pGraphics = (mpFrame && AquaSalFrame::isAlive(mpFrame)) ? mpFrame->mpGraphics : NULL;
524		if( pGraphics )
525		{
526			// we did not get the mutex so we cannot draw now => request to redraw later
527			// convert the NSRect to a CGRect for Refreshrect()
528			const CGRect aCGRect = {{aRect.origin.x,aRect.origin.y},{aRect.size.width,aRect.size.height}};
529			pGraphics->RefreshRect( aCGRect );
530		}
531		return;
532	}
533
534    if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
535    {
536        if( mpFrame->mpGraphics )
537        {
538            mpFrame->mpGraphics->UpdateWindow( aRect );
539            if( mpFrame->getClipPath() )
540                [mpFrame->getWindow() invalidateShadow];
541        }
542    }
543}
544
545-(void)sendMouseEventToFrame: (NSEvent*)pEvent button:(sal_uInt16)nButton eventtype:(sal_uInt16)nEvent
546{
547    YIELD_GUARD;
548
549    AquaSalFrame* pDispatchFrame = AquaSalFrame::GetCaptureFrame();
550    bool bIsCaptured = false;
551    if( pDispatchFrame )
552    {
553        bIsCaptured = true;
554        if( nEvent == SALEVENT_MOUSELEAVE ) // no leave events if mouse is captured
555            nEvent = SALEVENT_MOUSEMOVE;
556    }
557    else if( s_pMouseFrame )
558        pDispatchFrame = s_pMouseFrame;
559    else
560        pDispatchFrame = mpFrame;
561
562    /* #i81645# Cocoa reports mouse events while a button is pressed
563       to the window in which it was first pressed. This is reasonable and fine and
564       gets one around most cases where on other platforms one uses CaptureMouse or XGrabPointer,
565       however vcl expects mouse events to occur in the window the mouse is over, unless the
566       mouse is explicitly captured. So we need to find the window the mouse is actually
567       over for conformance with other platforms.
568    */
569    if( ! bIsCaptured && nButton && pDispatchFrame && AquaSalFrame::isAlive( pDispatchFrame ) )
570    {
571        // is this event actually inside that NSWindow ?
572        NSPoint aPt = [NSEvent mouseLocation];
573        NSRect aFrameRect = [pDispatchFrame->getWindow() frame];
574
575	if ( ! NSPointInRect( aPt, aFrameRect ) )
576        {
577            // no, it is not
578            // now we need to find the one it may be in
579            /* #i93756# we ant to get enumerate the application windows in z-order
580               to check if any contains the mouse. This could be elegantly done with this
581               code:
582
583               // use NSApp to check windows in ZOrder whether they contain the mouse pointer
584               NSWindow* pWindow = [NSApp makeWindowsPerform: @selector(containsMouse) inOrder: YES];
585               if( pWindow && [pWindow isMemberOfClass: [SalFrameWindow class]] )
586                   pDispatchFrame = [(SalFrameWindow*)pWindow getSalFrame];
587
588               However if a non SalFrameWindow is on screen (like e.g. the file dialog)
589               it can be hit with the containsMouse selector, which it doesn't support.
590               Sadly NSApplication:makeWindowsPerform does not check (for performance reasons
591               I assume) whether a window supports a selector before sending it.
592            */
593            AquaSalFrame* pMouseFrame = getMouseContainerFrame();
594            if( pMouseFrame )
595                pDispatchFrame = pMouseFrame;
596        }
597    }
598
599    if( pDispatchFrame && AquaSalFrame::isAlive( pDispatchFrame ) )
600    {
601        pDispatchFrame->mnLastEventTime = static_cast<sal_uLong>( [pEvent timestamp] * 1000.0 );
602        pDispatchFrame->mnLastModifierFlags = [pEvent modifierFlags];
603
604        NSPoint aPt = [NSEvent mouseLocation];
605        pDispatchFrame->CocoaToVCL( aPt );
606
607        sal_uInt16 nModMask = ImplGetModifierMask( [pEvent modifierFlags] );
608        // #i82284# emulate ctrl left
609        if( nModMask == KEY_MOD3 && nButton == MOUSE_LEFT )
610        {
611            nModMask    = 0;
612            nButton     = MOUSE_RIGHT;
613        }
614
615        SalMouseEvent aEvent;
616        aEvent.mnTime   = pDispatchFrame->mnLastEventTime;
617        aEvent.mnX      = static_cast<long>(aPt.x) - pDispatchFrame->maGeometry.nX;
618        aEvent.mnY      = static_cast<long>(aPt.y) - pDispatchFrame->maGeometry.nY;
619        aEvent.mnButton = nButton;
620        aEvent.mnCode   =  aEvent.mnButton | nModMask;
621
622        // --- RTL --- (mirror mouse pos)
623        if( Application::GetSettings().GetLayoutRTL() )
624            aEvent.mnX = pDispatchFrame->maGeometry.nWidth-1-aEvent.mnX;
625
626        pDispatchFrame->CallCallback( nEvent, &aEvent );
627    }
628}
629
630-(void)mouseDown: (NSEvent*)pEvent
631{
632    if ( mpMouseEventListener != nil &&
633	    [mpMouseEventListener respondsToSelector: @selector(mouseDown:)])
634	{
635	    [mpMouseEventListener mouseDown: [pEvent copyWithZone: NULL]];
636	}
637
638    s_nLastButton = MOUSE_LEFT;
639    [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SALEVENT_MOUSEBUTTONDOWN];
640}
641
642-(void)mouseDragged: (NSEvent*)pEvent
643{
644    if ( mpMouseEventListener != nil &&
645	     [mpMouseEventListener respondsToSelector: @selector(mouseDragged:)])
646	{
647	    [mpMouseEventListener mouseDragged: [pEvent copyWithZone: NULL]];
648	}
649    s_nLastButton = MOUSE_LEFT;
650    [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SALEVENT_MOUSEMOVE];
651}
652
653-(void)mouseUp: (NSEvent*)pEvent
654{
655    s_nLastButton = 0;
656    [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SALEVENT_MOUSEBUTTONUP];
657}
658
659-(void)mouseMoved: (NSEvent*)pEvent
660{
661    s_nLastButton = 0;
662    [self sendMouseEventToFrame:pEvent button:0 eventtype:SALEVENT_MOUSEMOVE];
663}
664
665-(void)mouseEntered: (NSEvent*)pEvent
666{
667    s_pMouseFrame = mpFrame;
668
669    // #i107215# the only mouse events we get when inactive are enter/exit
670    // actually we would like to have all of them, but better none than some
671    if( [NSApp isActive] )
672        [self sendMouseEventToFrame:pEvent button:s_nLastButton eventtype:SALEVENT_MOUSEMOVE];
673}
674
675-(void)mouseExited: (NSEvent*)pEvent
676{
677    if( s_pMouseFrame == mpFrame )
678        s_pMouseFrame = NULL;
679
680    // #i107215# the only mouse events we get when inactive are enter/exit
681    // actually we would like to have all of them, but better none than some
682    if( [NSApp isActive] )
683        [self sendMouseEventToFrame:pEvent button:s_nLastButton eventtype:SALEVENT_MOUSELEAVE];
684}
685
686-(void)rightMouseDown: (NSEvent*)pEvent
687{
688    s_nLastButton = MOUSE_RIGHT;
689    [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SALEVENT_MOUSEBUTTONDOWN];
690}
691
692-(void)rightMouseDragged: (NSEvent*)pEvent
693{
694    s_nLastButton = MOUSE_RIGHT;
695    [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SALEVENT_MOUSEMOVE];
696}
697
698-(void)rightMouseUp: (NSEvent*)pEvent
699{
700    s_nLastButton = 0;
701    [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SALEVENT_MOUSEBUTTONUP];
702}
703
704-(void)otherMouseDown: (NSEvent*)pEvent
705{
706    if( [pEvent buttonNumber] == 2 )
707    {
708        s_nLastButton = MOUSE_MIDDLE;
709        [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SALEVENT_MOUSEBUTTONDOWN];
710    }
711    else
712        s_nLastButton = 0;
713}
714
715-(void)otherMouseDragged: (NSEvent*)pEvent
716{
717    if( [pEvent buttonNumber] == 2 )
718    {
719        s_nLastButton = MOUSE_MIDDLE;
720        [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SALEVENT_MOUSEMOVE];
721    }
722    else
723        s_nLastButton = 0;
724}
725
726-(void)otherMouseUp: (NSEvent*)pEvent
727{
728    s_nLastButton = 0;
729    if( [pEvent buttonNumber] == 2 )
730        [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SALEVENT_MOUSEBUTTONUP];
731}
732
733- (void)magnifyWithEvent: (NSEvent*)pEvent
734{
735    YIELD_GUARD;
736
737    // TODO: ??  -(float)magnification;
738    if( AquaSalFrame::isAlive( mpFrame ) )
739	{
740		const NSTimeInterval fMagnifyTime = [pEvent timestamp];
741        mpFrame->mnLastEventTime = static_cast<sal_uLong>( fMagnifyTime * 1000.0 );
742        mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
743
744        // check if this is a new series of magnify events
745        static const NSTimeInterval fMaxDiffTime = 0.3;
746        const bool bNewSeries = (fMagnifyTime - mfLastMagnifyTime > fMaxDiffTime);
747
748        if( bNewSeries )
749            mfMagnifyDeltaSum = 0.0;
750        mfMagnifyDeltaSum += [pEvent deltaZ];
751
752		mfLastMagnifyTime = [pEvent timestamp];
753		// TODO: change to 0.1 when COMMAND_WHEEL_ZOOM handlers allow finer zooming control
754		static const float fMagnifyFactor = 0.25;
755        static const float fMinMagnifyStep = 15.0 / fMagnifyFactor;
756        if( fabs(mfMagnifyDeltaSum) <= fMinMagnifyStep )
757            return;
758
759        // adapt NSEvent-sensitivity to application expectations
760        // TODO: rather make COMMAND_WHEEL_ZOOM handlers smarter
761        const float fDeltaZ = mfMagnifyDeltaSum * fMagnifyFactor;
762        int nDeltaZ = FRound( fDeltaZ );
763        if( !nDeltaZ )
764        {
765            // handle new series immediately
766            if( !bNewSeries )
767                return;
768            nDeltaZ = (fDeltaZ >= 0.0) ? +1 : -1;
769        }
770        // eventually give credit for delta sum
771        mfMagnifyDeltaSum -= nDeltaZ / fMagnifyFactor;
772
773        NSPoint aPt = [NSEvent mouseLocation];
774        mpFrame->CocoaToVCL( aPt );
775
776        SalWheelMouseEvent aEvent;
777        aEvent.mnTime           = mpFrame->mnLastEventTime;
778        aEvent.mnX              = static_cast<long>(aPt.x) - mpFrame->maGeometry.nX;
779        aEvent.mnY              = static_cast<long>(aPt.y) - mpFrame->maGeometry.nY;
780        aEvent.mnCode           = ImplGetModifierMask( mpFrame->mnLastModifierFlags );
781        aEvent.mnCode           |= KEY_MOD1; // we want zooming, no scrolling
782        aEvent.mbDeltaIsPixel   = TRUE;
783
784        // --- RTL --- (mirror mouse pos)
785        if( Application::GetSettings().GetLayoutRTL() )
786            aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX;
787
788        aEvent.mnDelta = nDeltaZ;
789        aEvent.mnNotchDelta = (nDeltaZ >= 0) ? +1 : -1;
790        if( aEvent.mnDelta == 0 )
791            aEvent.mnDelta = aEvent.mnNotchDelta;
792        aEvent.mbHorz = FALSE;
793        aEvent.mnScrollLines = nDeltaZ;
794        if( aEvent.mnScrollLines == 0 )
795            aEvent.mnScrollLines = 1;
796        mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
797    }
798}
799
800- (void)rotateWithEvent: (NSEvent*)pEvent
801{
802    //Rotation : -(float)rotation;
803    // TODO: create new CommandType so rotation is available to the applications
804    (void)pEvent;
805}
806
807- (void)swipeWithEvent: (NSEvent*)pEvent
808{
809    YIELD_GUARD;
810
811    if( AquaSalFrame::isAlive( mpFrame ) )
812    {
813        mpFrame->mnLastEventTime = static_cast<sal_uLong>( [pEvent timestamp] * 1000.0 );
814        mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
815
816        // merge pending scroll wheel events
817        float dX = 0.0;
818        float dY = 0.0;
819        for(;;)
820        {
821            dX += [pEvent deltaX];
822            dY += [pEvent deltaY];
823            NSEvent* pNextEvent = [NSApp nextEventMatchingMask: NSScrollWheelMask
824            untilDate: nil inMode: NSDefaultRunLoopMode dequeue: YES ];
825            if( !pNextEvent )
826                break;
827            pEvent = pNextEvent;
828        }
829
830        NSPoint aPt = [NSEvent mouseLocation];
831        mpFrame->CocoaToVCL( aPt );
832
833        SalWheelMouseEvent aEvent;
834        aEvent.mnTime           = mpFrame->mnLastEventTime;
835        aEvent.mnX              = static_cast<long>(aPt.x) - mpFrame->maGeometry.nX;
836        aEvent.mnY              = static_cast<long>(aPt.y) - mpFrame->maGeometry.nY;
837        aEvent.mnCode           = ImplGetModifierMask( mpFrame->mnLastModifierFlags );
838        aEvent.mbDeltaIsPixel   = TRUE;
839
840        // --- RTL --- (mirror mouse pos)
841        if( Application::GetSettings().GetLayoutRTL() )
842            aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX;
843
844        if( dX != 0.0 )
845        {
846            aEvent.mnDelta = static_cast<long>(floor(dX));
847            aEvent.mnNotchDelta = dX < 0 ? -1 : 1;
848            if( aEvent.mnDelta == 0 )
849                aEvent.mnDelta = aEvent.mnNotchDelta;
850            aEvent.mbHorz = TRUE;
851            aEvent.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
852            mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
853        }
854        if( dY != 0.0 && AquaSalFrame::isAlive( mpFrame ))
855        {
856            aEvent.mnDelta = static_cast<long>(floor(dY));
857            aEvent.mnNotchDelta = dY < 0 ? -1 : 1;
858            if( aEvent.mnDelta == 0 )
859                aEvent.mnDelta = aEvent.mnNotchDelta;
860            aEvent.mbHorz = FALSE;
861            aEvent.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
862            mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
863        }
864    }
865}
866
867-(void)scrollWheel: (NSEvent*)pEvent
868{
869    YIELD_GUARD;
870
871    if( AquaSalFrame::isAlive( mpFrame ) )
872    {
873        mpFrame->mnLastEventTime = static_cast<sal_uLong>( [pEvent timestamp] * 1000.0 );
874        mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
875
876        // merge pending scroll wheel events
877        float dX = 0.0;
878        float dY = 0.0;
879        for(;;)
880        {
881            dX += [pEvent deltaX];
882    	    dY += [pEvent deltaY];
883            NSEvent* pNextEvent = [NSApp nextEventMatchingMask: NSScrollWheelMask
884                untilDate: nil inMode: NSDefaultRunLoopMode dequeue: YES ];
885            if( !pNextEvent )
886                break;
887            pEvent = pNextEvent;
888        }
889
890        NSPoint aPt = [NSEvent mouseLocation];
891        mpFrame->CocoaToVCL( aPt );
892
893        SalWheelMouseEvent aEvent;
894        aEvent.mnTime         = mpFrame->mnLastEventTime;
895        aEvent.mnX            = static_cast<long>(aPt.x) - mpFrame->maGeometry.nX;
896        aEvent.mnY            = static_cast<long>(aPt.y) - mpFrame->maGeometry.nY;
897        aEvent.mnCode         = ImplGetModifierMask( mpFrame->mnLastModifierFlags );
898        aEvent.mbDeltaIsPixel = TRUE;
899
900        // --- RTL --- (mirror mouse pos)
901        if( Application::GetSettings().GetLayoutRTL() )
902            aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX;
903
904        if( dX != 0.0 )
905        {
906            aEvent.mnDelta = static_cast<long>(floor(dX));
907            aEvent.mnNotchDelta = dX < 0 ? -1 : 1;
908            if( aEvent.mnDelta == 0 )
909                aEvent.mnDelta = aEvent.mnNotchDelta;
910            aEvent.mbHorz = TRUE;
911            aEvent.mnScrollLines = dY > 0 ? dX/WHEEL_EVENT_FACTOR : -dX/WHEEL_EVENT_FACTOR;
912            if( aEvent.mnScrollLines == 0 )
913                aEvent.mnScrollLines = 1;
914
915            mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
916        }
917        if( dY != 0.0 && AquaSalFrame::isAlive( mpFrame ) )
918        {
919            aEvent.mnDelta = static_cast<long>(floor(dY));
920            aEvent.mnNotchDelta = dY < 0 ? -1 : 1;
921            if( aEvent.mnDelta == 0 )
922                aEvent.mnDelta = aEvent.mnNotchDelta;
923            aEvent.mbHorz = FALSE;
924            aEvent.mnScrollLines = dY > 0 ? dY/WHEEL_EVENT_FACTOR : -dY/WHEEL_EVENT_FACTOR;
925            if( aEvent.mnScrollLines < 1 )
926                aEvent.mnScrollLines = 1;
927
928            mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
929        }
930    }
931}
932
933
934-(void)keyDown: (NSEvent*)pEvent
935{
936    YIELD_GUARD;
937
938    if( AquaSalFrame::isAlive( mpFrame ) )
939    {
940        mpLastEvent = pEvent;
941        mbInKeyInput = true;
942        mbNeedSpecialKeyHandle = false;
943        mbKeyHandled = false;
944
945        mpFrame->mnLastEventTime = static_cast<sal_uLong>( [pEvent timestamp] * 1000.0 );
946        mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
947
948        if( ! [self handleKeyDownException: pEvent] )
949        {
950            NSArray* pArray = [NSArray arrayWithObject: pEvent];
951            [self interpretKeyEvents: pArray];
952        }
953
954        mbInKeyInput = false;
955    }
956}
957
958-(BOOL)handleKeyDownException:(NSEvent*)pEvent
959{
960    // check for a very special set of modified characters
961    NSString* pUnmodifiedString = [pEvent charactersIgnoringModifiers];
962
963    if( pUnmodifiedString && [pUnmodifiedString length] == 1 )
964    {
965        /* #i103102# key events with command and alternate don't make it through
966           interpretKeyEvents (why ?). Try to dispatch them here first,
967           if not successful continue normally
968        */
969        if( (mpFrame->mnLastModifierFlags & (NSAlternateKeyMask | NSCommandKeyMask))
970                    == (NSAlternateKeyMask | NSCommandKeyMask) )
971        {
972            if( [self sendSingleCharacter: mpLastEvent] )
973                return YES;
974        }
975        unichar keyChar = [pUnmodifiedString characterAtIndex: 0];
976        sal_uInt16 nKeyCode = ImplMapCharCode( keyChar );
977
978        // Caution: should the table grow to more than 5 or 6 entries,
979        // we must consider moving it to a kind of hash map
980        const unsigned int nExceptions = sizeof( aExceptionalKeys ) / sizeof( aExceptionalKeys[0] );
981        for( unsigned int i = 0; i < nExceptions; i++ )
982        {
983            if( nKeyCode == aExceptionalKeys[i].nKeyCode &&
984                (mpFrame->mnLastModifierFlags & aExceptionalKeys[i].nModifierMask)
985                == aExceptionalKeys[i].nModifierMask )
986            {
987                [self sendKeyInputAndReleaseToFrame: nKeyCode character: 0];
988
989                return YES;
990            }
991        }
992    }
993    return NO;
994}
995
996-(void)flagsChanged: (NSEvent*)pEvent
997{
998    YIELD_GUARD;
999
1000    if( AquaSalFrame::isAlive( mpFrame ) )
1001    {
1002        mpFrame->mnLastEventTime = static_cast<sal_uLong>( [pEvent timestamp] * 1000.0 );
1003        mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
1004    }
1005}
1006
1007-(void)insertText:(id)aString
1008{
1009    YIELD_GUARD;
1010
1011    if( AquaSalFrame::isAlive( mpFrame ) )
1012    {
1013        NSString* pInsert = nil;
1014        if( [aString isMemberOfClass: [NSAttributedString class]] )
1015            pInsert = [aString string];
1016        else
1017            pInsert = aString;
1018
1019        int nLen = 0;
1020        if( pInsert && ( nLen = [pInsert length] ) > 0 )
1021        {
1022            OUString aInsertString( GetOUString( pInsert ) );
1023             // aCharCode initializer is safe since aInsertString will at least contain '\0'
1024            sal_Unicode aCharCode = *aInsertString.getStr();
1025
1026            if( nLen == 1 &&
1027                aCharCode < 0x80 &&
1028                aCharCode > 0x1f &&
1029				! [self hasMarkedText ]
1030                )
1031            {
1032                sal_uInt16 nKeyCode = ImplMapCharCode( aCharCode );
1033                unsigned int nLastModifiers = mpFrame->mnLastModifierFlags;
1034
1035                // #i99567#
1036                // find out the unmodified key code
1037
1038                // sanity check
1039                if( mpLastEvent && ( [mpLastEvent type] == NSKeyDown || [mpLastEvent type] == NSKeyUp ) )
1040                {
1041                    // get unmodified string
1042                    NSString* pUnmodifiedString = [mpLastEvent charactersIgnoringModifiers];
1043                    if( pUnmodifiedString && [pUnmodifiedString length] == 1 )
1044                    {
1045                        // map the unmodified key code
1046                        unichar keyChar = [pUnmodifiedString characterAtIndex: 0];
1047                        nKeyCode = ImplMapCharCode( keyChar );
1048                    }
1049                    nLastModifiers = [mpLastEvent modifierFlags];
1050
1051                }
1052                // #i99567#
1053                // applications and vcl's edit fields ignore key events with ALT
1054                // however we're at a place where we know text should be inserted
1055                // so it seems we need to strip the Alt modifier here
1056                if( (nLastModifiers & (NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask))
1057                    == NSAlternateKeyMask )
1058                {
1059                    nLastModifiers = 0;
1060                }
1061                [self sendKeyInputAndReleaseToFrame: nKeyCode character: aCharCode modifiers: nLastModifiers];
1062            }
1063            else
1064            {
1065                SalExtTextInputEvent aEvent;
1066                aEvent.mnTime           = mpFrame->mnLastEventTime;
1067                aEvent.maText           = aInsertString;
1068                aEvent.mpTextAttr       = NULL;
1069                aEvent.mnCursorPos      = aInsertString.getLength();
1070                aEvent.mnDeltaStart     = 0;
1071                aEvent.mnCursorFlags    = 0;
1072                aEvent.mbOnlyCursor     = FALSE;
1073                mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, &aEvent );
1074                if( AquaSalFrame::isAlive( mpFrame ) )
1075                    mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 );
1076            }
1077        }
1078        else
1079        {
1080            SalExtTextInputEvent aEvent;
1081            aEvent.mnTime           = mpFrame->mnLastEventTime;
1082            aEvent.maText           = String();
1083            aEvent.mpTextAttr       = NULL;
1084            aEvent.mnCursorPos      = 0;
1085            aEvent.mnDeltaStart     = 0;
1086            aEvent.mnCursorFlags    = 0;
1087            aEvent.mbOnlyCursor     = FALSE;
1088            mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, &aEvent );
1089            if( AquaSalFrame::isAlive( mpFrame ) )
1090                mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 );
1091
1092        }
1093        mbKeyHandled = true;
1094        [self unmarkText];
1095    }
1096}
1097
1098-(void)insertTab: (id)aSender
1099{
1100    (void)aSender;
1101    [self sendKeyInputAndReleaseToFrame: KEY_TAB character: '\t' modifiers: 0];
1102}
1103
1104-(void)insertBacktab: (id)aSender
1105{
1106    (void)aSender;
1107    [self sendKeyInputAndReleaseToFrame: (KEY_TAB | KEY_SHIFT) character: '\t' modifiers: 0];
1108}
1109
1110-(void)moveLeft: (id)aSender
1111{
1112    (void)aSender;
1113    [self sendKeyInputAndReleaseToFrame: KEY_LEFT character: 0 modifiers: 0];
1114}
1115
1116-(void)moveLeftAndModifySelection: (id)aSender
1117{
1118    (void)aSender;
1119    [self sendKeyInputAndReleaseToFrame: KEY_LEFT character: 0 modifiers: NSShiftKeyMask];
1120}
1121
1122-(void)moveBackwardAndModifySelection: (id)aSender
1123{
1124    (void)aSender;
1125    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_BACKWARD character: 0  modifiers: 0];
1126}
1127
1128-(void)moveRight: (id)aSender
1129{
1130    (void)aSender;
1131    [self sendKeyInputAndReleaseToFrame: KEY_RIGHT character: 0 modifiers: 0];
1132}
1133
1134-(void)moveRightAndModifySelection: (id)aSender
1135{
1136    (void)aSender;
1137    [self sendKeyInputAndReleaseToFrame: KEY_RIGHT character: 0 modifiers: NSShiftKeyMask];
1138}
1139
1140-(void)moveForwardAndModifySelection: (id)aSender
1141{
1142    (void)aSender;
1143    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_FORWARD character: 0  modifiers: 0];
1144}
1145
1146-(void)moveWordLeft: (id)aSender
1147{
1148    (void)aSender;
1149    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_BACKWARD character: 0  modifiers: 0];
1150}
1151
1152-(void)moveWordBackward: (id)aSender
1153{
1154    (void)aSender;
1155    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_BACKWARD character: 0  modifiers: 0];
1156}
1157
1158-(void)moveWordBackwardAndModifySelection: (id)aSender
1159{
1160    (void)aSender;
1161    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_BACKWARD character: 0  modifiers: 0];
1162}
1163
1164-(void)moveWordLeftAndModifySelection: (id)aSender
1165{
1166    (void)aSender;
1167    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_BACKWARD character: 0  modifiers: 0];
1168}
1169
1170-(void)moveWordRight: (id)aSender
1171{
1172    (void)aSender;
1173    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_FORWARD character: 0  modifiers: 0];
1174}
1175
1176-(void)moveWordForward: (id)aSender
1177{
1178    (void)aSender;
1179    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_FORWARD character: 0  modifiers: 0];
1180}
1181
1182-(void)moveWordForwardAndModifySelection: (id)aSender
1183{
1184    (void)aSender;
1185    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_FORWARD character: 0  modifiers: 0];
1186}
1187
1188-(void)moveWordRightAndModifySelection: (id)aSender
1189{
1190    (void)aSender;
1191    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_FORWARD character: 0  modifiers: 0];
1192}
1193
1194-(void)moveToEndOfLine: (id)aSender
1195{
1196    (void)aSender;
1197    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_LINE character: 0  modifiers: 0];
1198}
1199
1200-(void)moveToRightEndOfLine: (id)aSender
1201{
1202    (void)aSender;
1203    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_LINE character: 0  modifiers: 0];
1204}
1205
1206-(void)moveToEndOfLineAndModifySelection: (id)aSender
1207{
1208    (void)aSender;
1209    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_LINE character: 0  modifiers: 0];
1210}
1211
1212-(void)moveToRightEndOfLineAndModifySelection: (id)aSender
1213{
1214    (void)aSender;
1215    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_LINE character: 0  modifiers: 0];
1216}
1217
1218-(void)moveToBeginningOfLine: (id)aSender
1219{
1220    (void)aSender;
1221    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1222}
1223
1224-(void)moveToLeftEndOfLine: (id)aSender
1225{
1226    (void)aSender;
1227    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1228}
1229
1230-(void)moveToBeginningOfLineAndModifySelection: (id)aSender
1231{
1232    (void)aSender;
1233    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1234}
1235
1236-(void)moveToLeftEndOfLineAndModifySelection: (id)aSender
1237{
1238    (void)aSender;
1239    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1240}
1241
1242-(void)moveToEndOfParagraph: (id)aSender
1243{
1244    (void)aSender;
1245    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1246}
1247
1248-(void)moveToEndOfParagraphAndModifySelection: (id)aSender
1249{
1250    (void)aSender;
1251    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1252}
1253
1254-(void)moveParagraphForward: (id)aSender
1255{
1256    (void)aSender;
1257    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1258}
1259
1260-(void)moveParagraphForwardAndModifySelection: (id)aSender
1261{
1262    (void)aSender;
1263    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1264}
1265
1266-(void)moveToBeginningOfParagraph: (id)aSender
1267{
1268    (void)aSender;
1269    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1270}
1271
1272-(void)moveParagraphBackward: (id)aSender
1273{
1274    (void)aSender;
1275    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1276}
1277
1278-(void)moveToBeginningOfParagraphAndModifySelection: (id)aSender
1279{
1280    (void)aSender;
1281    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1282}
1283
1284-(void)moveParagraphBackwardAndModifySelection: (id)aSender
1285{
1286    (void)aSender;
1287    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1288}
1289
1290-(void)moveToEndOfDocument: (id)aSender
1291{
1292    (void)aSender;
1293    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT character: 0  modifiers: 0];
1294}
1295
1296-(void)scrollToEndOfDocument: (id)aSender
1297{
1298    (void)aSender;
1299    // this is not exactly what we should do, but it makes "End" and "Shift-End" behave consistent
1300    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT character: 0  modifiers: 0];
1301}
1302
1303-(void)moveToEndOfDocumentAndModifySelection: (id)aSender
1304{
1305    (void)aSender;
1306    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT character: 0  modifiers: 0];
1307}
1308
1309-(void)moveToBeginningOfDocument: (id)aSender
1310{
1311    (void)aSender;
1312    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT character: 0  modifiers: 0];
1313}
1314
1315-(void)scrollToBeginningOfDocument: (id)aSender
1316{
1317    (void)aSender;
1318    // this is not exactly what we should do, but it makes "Home" and "Shift-Home" behave consistent
1319    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT character: 0  modifiers: 0];
1320}
1321
1322-(void)moveToBeginningOfDocumentAndModifySelection: (id)aSender
1323{
1324    (void)aSender;
1325    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT character: 0  modifiers: 0];
1326}
1327
1328-(void)moveUp: (id)aSender
1329{
1330    (void)aSender;
1331    [self sendKeyInputAndReleaseToFrame: KEY_UP character: 0 modifiers: 0];
1332}
1333
1334-(void)moveDown: (id)aSender
1335{
1336    (void)aSender;
1337    [self sendKeyInputAndReleaseToFrame: KEY_DOWN character: 0 modifiers: 0];
1338}
1339
1340-(void)insertNewline: (id)aSender
1341{
1342    (void)aSender;
1343    // #i91267# make enter and shift-enter work by evaluating the modifiers
1344    [self sendKeyInputAndReleaseToFrame: KEY_RETURN character: '\n' modifiers: mpFrame->mnLastModifierFlags];
1345}
1346
1347-(void)deleteBackward: (id)aSender
1348{
1349    (void)aSender;
1350    [self sendKeyInputAndReleaseToFrame: KEY_BACKSPACE character: '\b' modifiers: 0];
1351}
1352
1353-(void)deleteForward: (id)aSender
1354{
1355    (void)aSender;
1356    [self sendKeyInputAndReleaseToFrame: KEY_DELETE character: 0x7f modifiers: 0];
1357}
1358
1359-(void)deleteBackwardByDecomposingPreviousCharacter: (id)aSender
1360{
1361    (void)aSender;
1362    [self sendKeyInputAndReleaseToFrame: KEY_BACKSPACE character: '\b' modifiers: 0];
1363}
1364
1365-(void)deleteWordBackward: (id)aSender
1366{
1367    (void)aSender;
1368    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_WORD_BACKWARD character: 0  modifiers: 0];
1369}
1370
1371-(void)deleteWordForward: (id)aSender
1372{
1373    (void)aSender;
1374    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_WORD_FORWARD character: 0  modifiers: 0];
1375}
1376
1377-(void)deleteToBeginningOfLine: (id)aSender
1378{
1379    (void)aSender;
1380    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1381}
1382
1383-(void)deleteToEndOfLine: (id)aSender
1384{
1385    (void)aSender;
1386    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_END_OF_LINE character: 0  modifiers: 0];
1387}
1388
1389-(void)deleteToBeginningOfParagraph: (id)aSender
1390{
1391    (void)aSender;
1392    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1393}
1394
1395-(void)deleteToEndOfParagraph: (id)aSender
1396{
1397    (void)aSender;
1398    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1399}
1400
1401-(void)insertLineBreak: (id)aSender
1402{
1403    (void)aSender;
1404    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::INSERT_LINEBREAK character: 0  modifiers: 0];
1405}
1406
1407-(void)insertParagraphSeparator: (id)aSender
1408{
1409    (void)aSender;
1410    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::INSERT_PARAGRAPH character: 0  modifiers: 0];
1411}
1412
1413-(void)selectWord: (id)aSender
1414{
1415    (void)aSender;
1416    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD character: 0  modifiers: 0];
1417}
1418
1419-(void)selectLine: (id)aSender
1420{
1421    (void)aSender;
1422    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_LINE character: 0  modifiers: 0];
1423}
1424
1425-(void)selectParagraph: (id)aSender
1426{
1427    (void)aSender;
1428    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_PARAGRAPH character: 0  modifiers: 0];
1429}
1430
1431-(void)selectAll: (id)aSender
1432{
1433    (void)aSender;
1434    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_ALL character: 0  modifiers: 0];
1435}
1436
1437-(void)cancelOperation: (id)aSender
1438{
1439    (void)aSender;
1440    [self sendKeyInputAndReleaseToFrame: KEY_ESCAPE character: 0x1b modifiers: 0];
1441}
1442
1443-(void)noop: (id)aSender
1444{
1445    (void)aSender;
1446    if( ! mbKeyHandled )
1447    {
1448        if( ! [self sendSingleCharacter:mpLastEvent] )
1449        {
1450            /* prevent recursion */
1451            if( mpLastEvent != mpLastSuperEvent && [NSApp respondsToSelector: @selector(sendSuperEvent:)] )
1452            {
1453                id pLastSuperEvent = mpLastSuperEvent;
1454                mpLastSuperEvent = mpLastEvent;
1455                [NSApp performSelector:@selector(sendSuperEvent:) withObject: mpLastEvent];
1456                mpLastSuperEvent = pLastSuperEvent;
1457
1458                std::map< NSEvent*, bool >::iterator it = GetSalData()->maKeyEventAnswer.find( mpLastEvent );
1459                if( it != GetSalData()->maKeyEventAnswer.end() )
1460                    it->second = true;
1461            }
1462        }
1463    }
1464}
1465
1466-(BOOL)sendKeyInputAndReleaseToFrame: (sal_uInt16)nKeyCode character: (sal_Unicode)aChar
1467{
1468    return [self sendKeyInputAndReleaseToFrame: nKeyCode character: aChar modifiers: mpFrame->mnLastModifierFlags];
1469}
1470
1471-(BOOL)sendKeyInputAndReleaseToFrame: (sal_uInt16)nKeyCode character: (sal_Unicode)aChar modifiers: (unsigned int)nMod
1472{
1473    return [self sendKeyToFrameDirect: nKeyCode character: aChar modifiers: nMod] ||
1474           [self sendSingleCharacter: mpLastEvent];
1475}
1476
1477-(BOOL)sendKeyToFrameDirect: (sal_uInt16)nKeyCode  character: (sal_Unicode)aChar modifiers: (unsigned int)nMod
1478{
1479    YIELD_GUARD;
1480
1481    long nRet = 0;
1482    if( AquaSalFrame::isAlive( mpFrame ) )
1483    {
1484        SalKeyEvent aEvent;
1485        aEvent.mnTime           = mpFrame->mnLastEventTime;
1486        aEvent.mnCode           = nKeyCode | ImplGetModifierMask( nMod );
1487        aEvent.mnCharCode       = aChar;
1488        aEvent.mnRepeat         = FALSE;
1489        nRet = mpFrame->CallCallback( SALEVENT_KEYINPUT, &aEvent );
1490        std::map< NSEvent*, bool >::iterator it = GetSalData()->maKeyEventAnswer.find( mpLastEvent );
1491        if( it != GetSalData()->maKeyEventAnswer.end() )
1492            it->second = nRet ? true : false;
1493        if( AquaSalFrame::isAlive( mpFrame ) )
1494            mpFrame->CallCallback( SALEVENT_KEYUP, &aEvent );
1495    }
1496    return nRet ? YES : NO;
1497}
1498
1499
1500-(BOOL)sendSingleCharacter: (NSEvent *)pEvent
1501{
1502    NSString* pUnmodifiedString = [pEvent charactersIgnoringModifiers];
1503
1504    if( pUnmodifiedString && [pUnmodifiedString length] == 1 )
1505    {
1506        unichar keyChar = [pUnmodifiedString characterAtIndex: 0];
1507        sal_uInt16 nKeyCode = ImplMapCharCode( keyChar );
1508        if( nKeyCode != 0 )
1509        {
1510            // don't send unicodes in the private use area
1511            if( keyChar >= 0xf700 && keyChar < 0xf780 )
1512                keyChar = 0;
1513            BOOL bRet = [self sendKeyToFrameDirect: nKeyCode character: keyChar modifiers: mpFrame->mnLastModifierFlags];
1514            mbInKeyInput = false;
1515
1516            return bRet;
1517        }
1518    }
1519    return NO;
1520}
1521
1522
1523// NSTextInput protocol
1524- (NSArray *)validAttributesForMarkedText
1525{
1526    return [NSArray arrayWithObjects:NSUnderlineStyleAttributeName, nil];
1527}
1528
1529- (BOOL)hasMarkedText
1530{
1531    BOOL bHasMarkedText;
1532
1533    bHasMarkedText = ( mMarkedRange.location != NSNotFound ) &&
1534                     ( mMarkedRange.length != 0 );
1535    // hack to check keys like "Control-j"
1536    if( mbInKeyInput )
1537    {
1538        mbNeedSpecialKeyHandle = true;
1539    }
1540
1541    // FIXME:
1542    // #i106901#
1543    // if we come here outside of mbInKeyInput, this is likely to be because
1544    // of the keyboard viewer. For unknown reasons having no marked range
1545    // in this case causes a crash. So we say we have a marked range anyway
1546    // This is a hack, since it is not understood what a) causes that crash
1547    // and b) why we should have a marked range at this point.
1548    if( ! mbInKeyInput )
1549        bHasMarkedText = YES;
1550
1551    return bHasMarkedText;
1552}
1553
1554- (NSRange)markedRange
1555{
1556    // FIXME:
1557    // #i106901#
1558    // if we come here outside of mbInKeyInput, this is likely to be because
1559    // of the keyboard viewer. For unknown reasons having no marked range
1560    // in this case causes a crash. So we say we have a marked range anyway
1561    // This is a hack, since it is not understood what a) causes that crash
1562    // and b) why we should have a marked range at this point.
1563    if( ! mbInKeyInput )
1564        return NSMakeRange( 0, 0 );
1565
1566    return [self hasMarkedText] ? mMarkedRange : NSMakeRange( NSNotFound, 0 );
1567}
1568
1569- (NSRange)selectedRange
1570{
1571    return mSelectedRange;
1572}
1573
1574- (void)setMarkedText:(id)aString selectedRange:(NSRange)selRange
1575{
1576    if( ![aString isKindOfClass:[NSAttributedString class]] )
1577        aString = [[[NSAttributedString alloc] initWithString:aString] autorelease];
1578    NSRange rangeToReplace = [self hasMarkedText] ? [self markedRange] : [self selectedRange];
1579    if( rangeToReplace.location == NSNotFound )
1580    {
1581        mMarkedRange = NSMakeRange( selRange.location, [aString length] );
1582        mSelectedRange = NSMakeRange( selRange.location, selRange.length );
1583    }
1584    else
1585    {
1586        mMarkedRange = NSMakeRange( rangeToReplace.location, [aString length] );
1587        mSelectedRange = NSMakeRange( rangeToReplace.location + selRange.location, selRange.length );
1588    }
1589
1590    int len = [aString length];
1591    SalExtTextInputEvent aInputEvent;
1592    aInputEvent.mnTime = mpFrame->mnLastEventTime;
1593    aInputEvent.mnDeltaStart = 0;
1594    aInputEvent.mbOnlyCursor = FALSE;
1595    if( len > 0 ) {
1596        NSString *pString = [aString string];
1597        OUString aInsertString( GetOUString( pString ) );
1598        std::vector<sal_uInt16> aInputFlags = std::vector<sal_uInt16>( std::max( 1, len ), 0 );
1599        for ( int i = 0; i < len; i++ )
1600        {
1601            unsigned int nUnderlineValue;
1602            NSRange effectiveRange;
1603
1604            effectiveRange = NSMakeRange(i, 1);
1605            nUnderlineValue = [[aString attribute:NSUnderlineStyleAttributeName atIndex:i effectiveRange:&effectiveRange] unsignedIntValue];
1606
1607            switch (nUnderlineValue & 0xff) {
1608            case NSUnderlineStyleSingle:
1609                aInputFlags[i] = SAL_EXTTEXTINPUT_ATTR_UNDERLINE;
1610                break;
1611            case NSUnderlineStyleThick:
1612                aInputFlags[i] = SAL_EXTTEXTINPUT_ATTR_UNDERLINE | SAL_EXTTEXTINPUT_ATTR_HIGHLIGHT;
1613                break;
1614            case NSUnderlineStyleDouble:
1615                aInputFlags[i] = SAL_EXTTEXTINPUT_ATTR_BOLDUNDERLINE;
1616                break;
1617            default:
1618                aInputFlags[i] = SAL_EXTTEXTINPUT_ATTR_HIGHLIGHT;
1619                break;
1620            }
1621        }
1622
1623        aInputEvent.maText = aInsertString;
1624        aInputEvent.mnCursorPos = selRange.location;
1625        aInputEvent.mpTextAttr = &aInputFlags[0];
1626        mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void *)&aInputEvent );
1627    } else {
1628        aInputEvent.maText = String();
1629        aInputEvent.mnCursorPos = 0;
1630        aInputEvent.mnCursorFlags = 0;
1631        aInputEvent.mpTextAttr = 0;
1632        mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void *)&aInputEvent );
1633        mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 );
1634    }
1635    mbKeyHandled= true;
1636}
1637
1638- (void)unmarkText
1639{
1640    mSelectedRange = mMarkedRange = NSMakeRange(NSNotFound, 0);
1641}
1642
1643- (NSAttributedString *)attributedSubstringFromRange:(NSRange)theRange
1644{
1645    (void)theRange;
1646    // FIXME
1647    return nil;
1648}
1649
1650- (unsigned int)characterIndexForPoint:(NSPoint)thePoint
1651{
1652    (void)thePoint;
1653    // FIXME
1654    return 0;
1655}
1656
1657#if defined(MAC_OS_X_VERSION_10_5) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
1658/* build target 10.5 or greater */
1659- (NSInteger)conversationIdentifier
1660#else
1661/* build target 10.4 */
1662- (long)conversationIdentifier
1663#endif
1664{
1665    return (long)self;
1666}
1667
1668- (void)doCommandBySelector:(SEL)aSelector
1669{
1670    if( AquaSalFrame::isAlive( mpFrame ) )
1671    {
1672        #if OSL_DEBUG_LEVEL > 1
1673        // fprintf( stderr, "SalFrameView: doCommandBySelector %s\n", (char*)aSelector );
1674        #endif
1675        if( (mpFrame->mnICOptions & SAL_INPUTCONTEXT_TEXT) != 0 &&
1676            aSelector != NULL && [self respondsToSelector: aSelector] )
1677        {
1678            [self performSelector: aSelector];
1679        }
1680        else
1681        {
1682            [self sendSingleCharacter:mpLastEvent];
1683        }
1684    }
1685
1686    mbKeyHandled = true;
1687}
1688
1689-(void)clearLastEvent
1690{
1691    mpLastEvent = nil;
1692}
1693
1694- (NSRect)firstRectForCharacterRange:(NSRange)theRange
1695{
1696    (void)theRange;
1697    SalExtTextInputPosEvent aPosEvent;
1698    mpFrame->CallCallback( SALEVENT_EXTTEXTINPUTPOS, (void *)&aPosEvent );
1699
1700    NSRect rect;
1701
1702    rect.origin.x = aPosEvent.mnX + mpFrame->maGeometry.nX;
1703    rect.origin.y =   aPosEvent.mnY + mpFrame->maGeometry.nY + 4; // add some space for underlines
1704    rect.size.width = aPosEvent.mnWidth;
1705    rect.size.height = aPosEvent.mnHeight;
1706
1707    mpFrame->VCLToCocoa( rect );
1708    return rect;
1709}
1710
1711-(id)parentAttribute {
1712    return (NSView *) mpFrame -> mpWindow;
1713}
1714
1715-(::com::sun::star::accessibility::XAccessibleContext *)accessibleContext
1716{
1717    if ( mpReferenceWrapper == nil ) {
1718        // some frames never become visible ..
1719        Window *pWindow = mpFrame -> GetWindow();
1720        if ( ! pWindow )
1721            return nil;
1722
1723        mpReferenceWrapper = new ReferenceWrapper;
1724        mpReferenceWrapper -> rAccessibleContext =  pWindow -> /*GetAccessibleChildWindow( 0 ) ->*/ GetAccessible() -> getAccessibleContext();
1725        [ AquaA11yFactory insertIntoWrapperRepository: self forAccessibleContext: mpReferenceWrapper -> rAccessibleContext ];
1726    }
1727    return [ super accessibleContext ];
1728}
1729
1730-(NSView *)viewElementForParent
1731{
1732    return (NSView *) mpFrame -> mpWindow;
1733}
1734
1735-(void)registerMouseEventListener: (id)theListener
1736{
1737  mpMouseEventListener = theListener;
1738}
1739
1740-(void)unregisterMouseEventListener: (id)theListener
1741{
1742    (void)theListener;
1743    mpMouseEventListener = nil;
1744}
1745
1746-(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
1747{
1748  return [mDraggingDestinationHandler draggingEntered: sender];
1749}
1750
1751-(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
1752{
1753  return [mDraggingDestinationHandler draggingUpdated: sender];
1754}
1755
1756-(void)draggingExited:(id <NSDraggingInfo>)sender
1757{
1758  [mDraggingDestinationHandler draggingExited: sender];
1759}
1760
1761-(BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
1762{
1763  return [mDraggingDestinationHandler prepareForDragOperation: sender];
1764}
1765
1766-(BOOL)performDragOperation:(id <NSDraggingInfo>)sender
1767{
1768  return [mDraggingDestinationHandler performDragOperation: sender];
1769}
1770
1771-(void)concludeDragOperation:(id <NSDraggingInfo>)sender
1772{
1773  [mDraggingDestinationHandler concludeDragOperation: sender];
1774}
1775
1776-(void)registerDraggingDestinationHandler:(id)theHandler
1777{
1778  mDraggingDestinationHandler = theHandler;
1779}
1780
1781-(void)unregisterDraggingDestinationHandler:(id)theHandler
1782{
1783    (void)theHandler;
1784    mDraggingDestinationHandler = nil;
1785}
1786
1787@end
1788
1789