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