xref: /AOO41X/main/vcl/aqua/source/window/salframeview.mm (revision 684ced1a5d26893aeb95a760d6add5d7d743235f)
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    if( !mpFrame)
482        return YES;
483    if( !AquaSalFrame::isAlive( mpFrame))
484        return YES;
485    if( !mpFrame->getClipPath())
486        return YES;
487    return NO;
488}
489
490// helper class similar to a vos::OGuard for the SalYieldMutex
491// the difference is that it only does tryToAcquire instead of aquire
492// so dreaded deadlocks like #i93512# are prevented
493class TryGuard
494{
495public:
496            TryGuard()  { mbGuarded = ImplSalYieldMutexTryToAcquire(); }
497            ~TryGuard() { if( mbGuarded ) ImplSalYieldMutexRelease(); }
498    bool    IsGuarded() { return mbGuarded; }
499private:
500    bool    mbGuarded;
501};
502
503-(void)drawRect: (NSRect)aRect
504{
505    // HOTFIX: #i93512# prevent deadlocks if any other thread already has the SalYieldMutex
506    TryGuard aTryGuard;
507    if( !aTryGuard.IsGuarded() )
508    {
509        // NOTE: the mpFrame access below is not guarded yet!
510        // TODO: mpFrame et al need to be guarded by an independent mutex
511        AquaSalGraphics* pGraphics = (mpFrame && AquaSalFrame::isAlive(mpFrame)) ? mpFrame->mpGraphics : NULL;
512        if( pGraphics )
513        {
514            // we did not get the mutex so we cannot draw now => request to redraw later
515            // convert the NSRect to a CGRect for Refreshrect()
516            const CGRect aCGRect = {{aRect.origin.x,aRect.origin.y},{aRect.size.width,aRect.size.height}};
517            pGraphics->RefreshRect( aCGRect );
518        }
519        return;
520    }
521
522    if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
523    {
524        if( mpFrame->mpGraphics )
525        {
526            mpFrame->mpGraphics->UpdateWindow( aRect );
527            if( mpFrame->getClipPath() )
528                [mpFrame->getWindow() invalidateShadow];
529        }
530    }
531}
532
533-(void)sendMouseEventToFrame: (NSEvent*)pEvent button:(sal_uInt16)nButton eventtype:(sal_uInt16)nEvent
534{
535    YIELD_GUARD;
536
537    AquaSalFrame* pDispatchFrame = AquaSalFrame::GetCaptureFrame();
538    bool bIsCaptured = false;
539    if( pDispatchFrame )
540    {
541        bIsCaptured = true;
542        if( nEvent == SALEVENT_MOUSELEAVE ) // no leave events if mouse is captured
543            nEvent = SALEVENT_MOUSEMOVE;
544    }
545    else if( s_pMouseFrame )
546        pDispatchFrame = s_pMouseFrame;
547    else
548        pDispatchFrame = mpFrame;
549
550    /* #i81645# Cocoa reports mouse events while a button is pressed
551       to the window in which it was first pressed. This is reasonable and fine and
552       gets one around most cases where on other platforms one uses CaptureMouse or XGrabPointer,
553       however vcl expects mouse events to occur in the window the mouse is over, unless the
554       mouse is explicitly captured. So we need to find the window the mouse is actually
555       over for conformance with other platforms.
556    */
557    if( ! bIsCaptured && nButton && pDispatchFrame && AquaSalFrame::isAlive( pDispatchFrame ) )
558    {
559        // is this event actually inside that NSWindow ?
560        NSPoint aPt = [NSEvent mouseLocation];
561        NSRect aFrameRect = [pDispatchFrame->getWindow() frame];
562
563    if ( ! NSPointInRect( aPt, aFrameRect ) )
564        {
565            // no, it is not
566            // now we need to find the one it may be in
567            /* #i93756# we ant to get enumerate the application windows in z-order
568               to check if any contains the mouse. This could be elegantly done with this
569               code:
570
571               // use NSApp to check windows in ZOrder whether they contain the mouse pointer
572               NSWindow* pWindow = [NSApp makeWindowsPerform: @selector(containsMouse) inOrder: YES];
573               if( pWindow && [pWindow isMemberOfClass: [SalFrameWindow class]] )
574                   pDispatchFrame = [(SalFrameWindow*)pWindow getSalFrame];
575
576               However if a non SalFrameWindow is on screen (like e.g. the file dialog)
577               it can be hit with the containsMouse selector, which it doesn't support.
578               Sadly NSApplication:makeWindowsPerform does not check (for performance reasons
579               I assume) whether a window supports a selector before sending it.
580            */
581            AquaSalFrame* pMouseFrame = getMouseContainerFrame();
582            if( pMouseFrame )
583                pDispatchFrame = pMouseFrame;
584        }
585    }
586
587    if( pDispatchFrame && AquaSalFrame::isAlive( pDispatchFrame ) )
588    {
589        pDispatchFrame->mnLastEventTime = static_cast<sal_uLong>( [pEvent timestamp] * 1000.0 );
590        pDispatchFrame->mnLastModifierFlags = [pEvent modifierFlags];
591
592        NSPoint aPt = [NSEvent mouseLocation];
593        pDispatchFrame->CocoaToVCL( aPt );
594
595        sal_uInt16 nModMask = ImplGetModifierMask( [pEvent modifierFlags] );
596        // #i82284# emulate ctrl left
597        if( nModMask == KEY_MOD3 && nButton == MOUSE_LEFT )
598        {
599            nModMask    = 0;
600            nButton     = MOUSE_RIGHT;
601        }
602
603        SalMouseEvent aEvent;
604        aEvent.mnTime   = pDispatchFrame->mnLastEventTime;
605        aEvent.mnX      = static_cast<long>(aPt.x) - pDispatchFrame->maGeometry.nX;
606        aEvent.mnY      = static_cast<long>(aPt.y) - pDispatchFrame->maGeometry.nY;
607        aEvent.mnButton = nButton;
608        aEvent.mnCode   =  aEvent.mnButton | nModMask;
609
610        // --- RTL --- (mirror mouse pos)
611        if( Application::GetSettings().GetLayoutRTL() )
612            aEvent.mnX = pDispatchFrame->maGeometry.nWidth-1-aEvent.mnX;
613
614        pDispatchFrame->CallCallback( nEvent, &aEvent );
615    }
616}
617
618-(void)mouseDown: (NSEvent*)pEvent
619{
620    if ( mpMouseEventListener != nil &&
621        [mpMouseEventListener respondsToSelector: @selector(mouseDown:)])
622    {
623        [mpMouseEventListener mouseDown: [pEvent copyWithZone: NULL]];
624    }
625
626    s_nLastButton = MOUSE_LEFT;
627    [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SALEVENT_MOUSEBUTTONDOWN];
628}
629
630-(void)mouseDragged: (NSEvent*)pEvent
631{
632    if ( mpMouseEventListener != nil &&
633         [mpMouseEventListener respondsToSelector: @selector(mouseDragged:)])
634    {
635        [mpMouseEventListener mouseDragged: [pEvent copyWithZone: NULL]];
636    }
637    s_nLastButton = MOUSE_LEFT;
638    [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SALEVENT_MOUSEMOVE];
639}
640
641-(void)mouseUp: (NSEvent*)pEvent
642{
643    s_nLastButton = 0;
644    [self sendMouseEventToFrame:pEvent button:MOUSE_LEFT eventtype:SALEVENT_MOUSEBUTTONUP];
645}
646
647-(void)mouseMoved: (NSEvent*)pEvent
648{
649    s_nLastButton = 0;
650    [self sendMouseEventToFrame:pEvent button:0 eventtype:SALEVENT_MOUSEMOVE];
651}
652
653-(void)mouseEntered: (NSEvent*)pEvent
654{
655    s_pMouseFrame = mpFrame;
656
657    // #i107215# the only mouse events we get when inactive are enter/exit
658    // actually we would like to have all of them, but better none than some
659    if( [NSApp isActive] )
660        [self sendMouseEventToFrame:pEvent button:s_nLastButton eventtype:SALEVENT_MOUSEMOVE];
661}
662
663-(void)mouseExited: (NSEvent*)pEvent
664{
665    if( s_pMouseFrame == mpFrame )
666        s_pMouseFrame = NULL;
667
668    // #i107215# the only mouse events we get when inactive are enter/exit
669    // actually we would like to have all of them, but better none than some
670    if( [NSApp isActive] )
671        [self sendMouseEventToFrame:pEvent button:s_nLastButton eventtype:SALEVENT_MOUSELEAVE];
672}
673
674-(void)rightMouseDown: (NSEvent*)pEvent
675{
676    s_nLastButton = MOUSE_RIGHT;
677    [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SALEVENT_MOUSEBUTTONDOWN];
678}
679
680-(void)rightMouseDragged: (NSEvent*)pEvent
681{
682    s_nLastButton = MOUSE_RIGHT;
683    [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SALEVENT_MOUSEMOVE];
684}
685
686-(void)rightMouseUp: (NSEvent*)pEvent
687{
688    s_nLastButton = 0;
689    [self sendMouseEventToFrame:pEvent button:MOUSE_RIGHT eventtype:SALEVENT_MOUSEBUTTONUP];
690}
691
692-(void)otherMouseDown: (NSEvent*)pEvent
693{
694    if( [pEvent buttonNumber] == 2 )
695    {
696        s_nLastButton = MOUSE_MIDDLE;
697        [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SALEVENT_MOUSEBUTTONDOWN];
698    }
699    else
700        s_nLastButton = 0;
701}
702
703-(void)otherMouseDragged: (NSEvent*)pEvent
704{
705    if( [pEvent buttonNumber] == 2 )
706    {
707        s_nLastButton = MOUSE_MIDDLE;
708        [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SALEVENT_MOUSEMOVE];
709    }
710    else
711        s_nLastButton = 0;
712}
713
714-(void)otherMouseUp: (NSEvent*)pEvent
715{
716    s_nLastButton = 0;
717    if( [pEvent buttonNumber] == 2 )
718        [self sendMouseEventToFrame:pEvent button:MOUSE_MIDDLE eventtype:SALEVENT_MOUSEBUTTONUP];
719}
720
721- (void)magnifyWithEvent: (NSEvent*)pEvent
722{
723    YIELD_GUARD;
724
725    // TODO: ??  -(float)magnification;
726    if( AquaSalFrame::isAlive( mpFrame ) )
727    {
728        const NSTimeInterval fMagnifyTime = [pEvent timestamp];
729        mpFrame->mnLastEventTime = static_cast<sal_uLong>( fMagnifyTime * 1000.0 );
730        mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
731
732        // check if this is a new series of magnify events
733        static const NSTimeInterval fMaxDiffTime = 0.3;
734        const bool bNewSeries = (fMagnifyTime - mfLastMagnifyTime > fMaxDiffTime);
735
736        if( bNewSeries )
737            mfMagnifyDeltaSum = 0.0;
738        mfMagnifyDeltaSum += [pEvent deltaZ];
739
740        mfLastMagnifyTime = [pEvent timestamp];
741        // TODO: change to 0.1 when COMMAND_WHEEL_ZOOM handlers allow finer zooming control
742        static const float fMagnifyFactor = 0.25;
743        static const float fMinMagnifyStep = 15.0 / fMagnifyFactor;
744        if( fabs(mfMagnifyDeltaSum) <= fMinMagnifyStep )
745            return;
746
747        // adapt NSEvent-sensitivity to application expectations
748        // TODO: rather make COMMAND_WHEEL_ZOOM handlers smarter
749        const float fDeltaZ = mfMagnifyDeltaSum * fMagnifyFactor;
750        int nDeltaZ = FRound( fDeltaZ );
751        if( !nDeltaZ )
752        {
753            // handle new series immediately
754            if( !bNewSeries )
755                return;
756            nDeltaZ = (fDeltaZ >= 0.0) ? +1 : -1;
757        }
758        // eventually give credit for delta sum
759        mfMagnifyDeltaSum -= nDeltaZ / fMagnifyFactor;
760
761        NSPoint aPt = [NSEvent mouseLocation];
762        mpFrame->CocoaToVCL( aPt );
763
764        SalWheelMouseEvent aEvent;
765        aEvent.mnTime           = mpFrame->mnLastEventTime;
766        aEvent.mnX              = static_cast<long>(aPt.x) - mpFrame->maGeometry.nX;
767        aEvent.mnY              = static_cast<long>(aPt.y) - mpFrame->maGeometry.nY;
768        aEvent.mnCode           = ImplGetModifierMask( mpFrame->mnLastModifierFlags );
769        aEvent.mnCode           |= KEY_MOD1; // we want zooming, no scrolling
770        aEvent.mbDeltaIsPixel   = TRUE;
771
772        // --- RTL --- (mirror mouse pos)
773        if( Application::GetSettings().GetLayoutRTL() )
774            aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX;
775
776        aEvent.mnDelta = nDeltaZ;
777        aEvent.mnNotchDelta = (nDeltaZ >= 0) ? +1 : -1;
778        if( aEvent.mnDelta == 0 )
779            aEvent.mnDelta = aEvent.mnNotchDelta;
780        aEvent.mbHorz = FALSE;
781        aEvent.mnScrollLines = nDeltaZ;
782        if( aEvent.mnScrollLines == 0 )
783            aEvent.mnScrollLines = 1;
784        mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
785    }
786}
787
788- (void)rotateWithEvent: (NSEvent*)pEvent
789{
790    //Rotation : -(float)rotation;
791    // TODO: create new CommandType so rotation is available to the applications
792    (void)pEvent;
793}
794
795- (void)swipeWithEvent: (NSEvent*)pEvent
796{
797    YIELD_GUARD;
798
799    if( AquaSalFrame::isAlive( mpFrame ) )
800    {
801        mpFrame->mnLastEventTime = static_cast<sal_uLong>( [pEvent timestamp] * 1000.0 );
802        mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
803
804        // merge pending scroll wheel events
805        float dX = 0.0;
806        float dY = 0.0;
807        for(;;)
808        {
809            dX += [pEvent deltaX];
810            dY += [pEvent deltaY];
811            NSEvent* pNextEvent = [NSApp nextEventMatchingMask: NSScrollWheelMask
812            untilDate: nil inMode: NSDefaultRunLoopMode dequeue: YES ];
813            if( !pNextEvent )
814                break;
815            pEvent = pNextEvent;
816        }
817
818        NSPoint aPt = [NSEvent mouseLocation];
819        mpFrame->CocoaToVCL( aPt );
820
821        SalWheelMouseEvent aEvent;
822        aEvent.mnTime           = mpFrame->mnLastEventTime;
823        aEvent.mnX              = static_cast<long>(aPt.x) - mpFrame->maGeometry.nX;
824        aEvent.mnY              = static_cast<long>(aPt.y) - mpFrame->maGeometry.nY;
825        aEvent.mnCode           = ImplGetModifierMask( mpFrame->mnLastModifierFlags );
826        aEvent.mbDeltaIsPixel   = TRUE;
827
828        // --- RTL --- (mirror mouse pos)
829        if( Application::GetSettings().GetLayoutRTL() )
830            aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX;
831
832        if( dX != 0.0 )
833        {
834            aEvent.mnDelta = static_cast<long>(floor(dX));
835            aEvent.mnNotchDelta = dX < 0 ? -1 : 1;
836            if( aEvent.mnDelta == 0 )
837                aEvent.mnDelta = aEvent.mnNotchDelta;
838            aEvent.mbHorz = TRUE;
839            aEvent.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
840            mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
841        }
842        if( dY != 0.0 && AquaSalFrame::isAlive( mpFrame ))
843        {
844            aEvent.mnDelta = static_cast<long>(floor(dY));
845            aEvent.mnNotchDelta = dY < 0 ? -1 : 1;
846            if( aEvent.mnDelta == 0 )
847                aEvent.mnDelta = aEvent.mnNotchDelta;
848            aEvent.mbHorz = FALSE;
849            aEvent.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
850            mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
851        }
852    }
853}
854
855-(void)scrollWheel: (NSEvent*)pEvent
856{
857    YIELD_GUARD;
858
859    if( AquaSalFrame::isAlive( mpFrame ) )
860    {
861        mpFrame->mnLastEventTime = static_cast<sal_uLong>( [pEvent timestamp] * 1000.0 );
862        mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
863
864        // merge pending scroll wheel events
865        float dX = 0.0;
866        float dY = 0.0;
867        for(;;)
868        {
869            dX += [pEvent deltaX];
870            dY += [pEvent deltaY];
871            NSEvent* pNextEvent = [NSApp nextEventMatchingMask: NSScrollWheelMask
872                untilDate: nil inMode: NSDefaultRunLoopMode dequeue: YES ];
873            if( !pNextEvent )
874                break;
875            pEvent = pNextEvent;
876        }
877
878        NSPoint aPt = [NSEvent mouseLocation];
879        mpFrame->CocoaToVCL( aPt );
880
881        SalWheelMouseEvent aEvent;
882        aEvent.mnTime         = mpFrame->mnLastEventTime;
883        aEvent.mnX            = static_cast<long>(aPt.x) - mpFrame->maGeometry.nX;
884        aEvent.mnY            = static_cast<long>(aPt.y) - mpFrame->maGeometry.nY;
885        aEvent.mnCode         = ImplGetModifierMask( mpFrame->mnLastModifierFlags );
886        aEvent.mbDeltaIsPixel = TRUE;
887
888        // --- RTL --- (mirror mouse pos)
889        if( Application::GetSettings().GetLayoutRTL() )
890            aEvent.mnX = mpFrame->maGeometry.nWidth-1-aEvent.mnX;
891
892        if( dX != 0.0 )
893        {
894            aEvent.mnDelta = static_cast<long>(floor(dX));
895            aEvent.mnNotchDelta = dX < 0 ? -1 : 1;
896            if( aEvent.mnDelta == 0 )
897                aEvent.mnDelta = aEvent.mnNotchDelta;
898            aEvent.mbHorz = TRUE;
899            aEvent.mnScrollLines = dY > 0 ? dX/WHEEL_EVENT_FACTOR : -dX/WHEEL_EVENT_FACTOR;
900            if( aEvent.mnScrollLines == 0 )
901                aEvent.mnScrollLines = 1;
902
903            mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
904        }
905        if( dY != 0.0 && AquaSalFrame::isAlive( mpFrame ) )
906        {
907            aEvent.mnDelta = static_cast<long>(floor(dY));
908            aEvent.mnNotchDelta = dY < 0 ? -1 : 1;
909            if( aEvent.mnDelta == 0 )
910                aEvent.mnDelta = aEvent.mnNotchDelta;
911            aEvent.mbHorz = FALSE;
912            aEvent.mnScrollLines = dY > 0 ? dY/WHEEL_EVENT_FACTOR : -dY/WHEEL_EVENT_FACTOR;
913            if( aEvent.mnScrollLines < 1 )
914                aEvent.mnScrollLines = 1;
915
916            mpFrame->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
917        }
918    }
919}
920
921
922-(void)keyDown: (NSEvent*)pEvent
923{
924    YIELD_GUARD;
925
926    if( AquaSalFrame::isAlive( mpFrame ) )
927    {
928        mpLastEvent = pEvent;
929        mbInKeyInput = true;
930        mbNeedSpecialKeyHandle = false;
931        mbKeyHandled = false;
932
933        mpFrame->mnLastEventTime = static_cast<sal_uLong>( [pEvent timestamp] * 1000.0 );
934        mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
935
936        if( ! [self handleKeyDownException: pEvent] )
937        {
938            NSArray* pArray = [NSArray arrayWithObject: pEvent];
939            [self interpretKeyEvents: pArray];
940        }
941
942        mbInKeyInput = false;
943    }
944}
945
946-(BOOL)handleKeyDownException:(NSEvent*)pEvent
947{
948    // check for a very special set of modified characters
949    NSString* pUnmodifiedString = [pEvent charactersIgnoringModifiers];
950
951    if( pUnmodifiedString && [pUnmodifiedString length] == 1 )
952    {
953        /* #i103102# key events with command and alternate don't make it through
954           interpretKeyEvents (why ?). Try to dispatch them here first,
955           if not successful continue normally
956        */
957        if( (mpFrame->mnLastModifierFlags & (NSAlternateKeyMask | NSCommandKeyMask))
958                    == (NSAlternateKeyMask | NSCommandKeyMask) )
959        {
960            if( [self sendSingleCharacter: mpLastEvent] )
961                return YES;
962        }
963        unichar keyChar = [pUnmodifiedString characterAtIndex: 0];
964        sal_uInt16 nKeyCode = ImplMapCharCode( keyChar );
965
966        // Caution: should the table grow to more than 5 or 6 entries,
967        // we must consider moving it to a kind of hash map
968        const unsigned int nExceptions = sizeof( aExceptionalKeys ) / sizeof( aExceptionalKeys[0] );
969        for( unsigned int i = 0; i < nExceptions; i++ )
970        {
971            if( nKeyCode == aExceptionalKeys[i].nKeyCode &&
972                (mpFrame->mnLastModifierFlags & aExceptionalKeys[i].nModifierMask)
973                == aExceptionalKeys[i].nModifierMask )
974            {
975                [self sendKeyInputAndReleaseToFrame: nKeyCode character: 0];
976
977                return YES;
978            }
979        }
980    }
981    return NO;
982}
983
984-(void)flagsChanged: (NSEvent*)pEvent
985{
986    YIELD_GUARD;
987
988    if( AquaSalFrame::isAlive( mpFrame ) )
989    {
990        mpFrame->mnLastEventTime = static_cast<sal_uLong>( [pEvent timestamp] * 1000.0 );
991        mpFrame->mnLastModifierFlags = [pEvent modifierFlags];
992    }
993}
994
995-(void)insertText:(id)aString
996{
997    YIELD_GUARD;
998
999    if( AquaSalFrame::isAlive( mpFrame ) )
1000    {
1001        NSString* pInsert = nil;
1002        if( [aString isMemberOfClass: [NSAttributedString class]] )
1003            pInsert = [aString string];
1004        else
1005            pInsert = aString;
1006
1007        int nLen = 0;
1008        if( pInsert && ( nLen = [pInsert length] ) > 0 )
1009        {
1010            OUString aInsertString( GetOUString( pInsert ) );
1011             // aCharCode initializer is safe since aInsertString will at least contain '\0'
1012            sal_Unicode aCharCode = *aInsertString.getStr();
1013
1014            if( nLen == 1 &&
1015                aCharCode < 0x80 &&
1016                aCharCode > 0x1f &&
1017                ! [self hasMarkedText ]
1018                )
1019            {
1020                sal_uInt16 nKeyCode = ImplMapCharCode( aCharCode );
1021                unsigned int nLastModifiers = mpFrame->mnLastModifierFlags;
1022
1023                // #i99567#
1024                // find out the unmodified key code
1025
1026                // sanity check
1027                if( mpLastEvent && ( [mpLastEvent type] == NSKeyDown || [mpLastEvent type] == NSKeyUp ) )
1028                {
1029                    // get unmodified string
1030                    NSString* pUnmodifiedString = [mpLastEvent charactersIgnoringModifiers];
1031                    if( pUnmodifiedString && [pUnmodifiedString length] == 1 )
1032                    {
1033                        // map the unmodified key code
1034                        unichar keyChar = [pUnmodifiedString characterAtIndex: 0];
1035                        nKeyCode = ImplMapCharCode( keyChar );
1036                    }
1037                    nLastModifiers = [mpLastEvent modifierFlags];
1038
1039                }
1040                // #i99567#
1041                // applications and vcl's edit fields ignore key events with ALT
1042                // however we're at a place where we know text should be inserted
1043                // so it seems we need to strip the Alt modifier here
1044                if( (nLastModifiers & (NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask))
1045                    == NSAlternateKeyMask )
1046                {
1047                    nLastModifiers = 0;
1048                }
1049                [self sendKeyInputAndReleaseToFrame: nKeyCode character: aCharCode modifiers: nLastModifiers];
1050            }
1051            else
1052            {
1053                SalExtTextInputEvent aEvent;
1054                aEvent.mnTime           = mpFrame->mnLastEventTime;
1055                aEvent.maText           = aInsertString;
1056                aEvent.mpTextAttr       = NULL;
1057                aEvent.mnCursorPos      = aInsertString.getLength();
1058                aEvent.mnDeltaStart     = 0;
1059                aEvent.mnCursorFlags    = 0;
1060                aEvent.mbOnlyCursor     = FALSE;
1061                mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, &aEvent );
1062                if( AquaSalFrame::isAlive( mpFrame ) )
1063                    mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 );
1064            }
1065        }
1066        else
1067        {
1068            SalExtTextInputEvent aEvent;
1069            aEvent.mnTime           = mpFrame->mnLastEventTime;
1070            aEvent.maText           = String();
1071            aEvent.mpTextAttr       = NULL;
1072            aEvent.mnCursorPos      = 0;
1073            aEvent.mnDeltaStart     = 0;
1074            aEvent.mnCursorFlags    = 0;
1075            aEvent.mbOnlyCursor     = FALSE;
1076            mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, &aEvent );
1077            if( AquaSalFrame::isAlive( mpFrame ) )
1078                mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 );
1079
1080        }
1081        mbKeyHandled = true;
1082        [self unmarkText];
1083    }
1084}
1085
1086-(void)insertTab: (id)aSender
1087{
1088    (void)aSender;
1089    [self sendKeyInputAndReleaseToFrame: KEY_TAB character: '\t' modifiers: 0];
1090}
1091
1092-(void)insertBacktab: (id)aSender
1093{
1094    (void)aSender;
1095    [self sendKeyInputAndReleaseToFrame: (KEY_TAB | KEY_SHIFT) character: '\t' modifiers: 0];
1096}
1097
1098-(void)moveLeft: (id)aSender
1099{
1100    (void)aSender;
1101    [self sendKeyInputAndReleaseToFrame: KEY_LEFT character: 0 modifiers: 0];
1102}
1103
1104-(void)moveLeftAndModifySelection: (id)aSender
1105{
1106    (void)aSender;
1107    [self sendKeyInputAndReleaseToFrame: KEY_LEFT character: 0 modifiers: NSShiftKeyMask];
1108}
1109
1110-(void)moveBackwardAndModifySelection: (id)aSender
1111{
1112    (void)aSender;
1113    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_BACKWARD character: 0  modifiers: 0];
1114}
1115
1116-(void)moveRight: (id)aSender
1117{
1118    (void)aSender;
1119    [self sendKeyInputAndReleaseToFrame: KEY_RIGHT character: 0 modifiers: 0];
1120}
1121
1122-(void)moveRightAndModifySelection: (id)aSender
1123{
1124    (void)aSender;
1125    [self sendKeyInputAndReleaseToFrame: KEY_RIGHT character: 0 modifiers: NSShiftKeyMask];
1126}
1127
1128-(void)moveForwardAndModifySelection: (id)aSender
1129{
1130    (void)aSender;
1131    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_FORWARD character: 0  modifiers: 0];
1132}
1133
1134-(void)moveWordLeft: (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)moveWordBackward: (id)aSender
1141{
1142    (void)aSender;
1143    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_BACKWARD character: 0  modifiers: 0];
1144}
1145
1146-(void)moveWordBackwardAndModifySelection: (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)moveWordLeftAndModifySelection: (id)aSender
1153{
1154    (void)aSender;
1155    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_BACKWARD character: 0  modifiers: 0];
1156}
1157
1158-(void)moveWordRight: (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)moveWordForward: (id)aSender
1165{
1166    (void)aSender;
1167    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_WORD_FORWARD character: 0  modifiers: 0];
1168}
1169
1170-(void)moveWordForwardAndModifySelection: (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)moveWordRightAndModifySelection: (id)aSender
1177{
1178    (void)aSender;
1179    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD_FORWARD character: 0  modifiers: 0];
1180}
1181
1182-(void)moveToEndOfLine: (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)moveToRightEndOfLine: (id)aSender
1189{
1190    (void)aSender;
1191    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_LINE character: 0  modifiers: 0];
1192}
1193
1194-(void)moveToEndOfLineAndModifySelection: (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)moveToRightEndOfLineAndModifySelection: (id)aSender
1201{
1202    (void)aSender;
1203    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_LINE character: 0  modifiers: 0];
1204}
1205
1206-(void)moveToBeginningOfLine: (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)moveToLeftEndOfLine: (id)aSender
1213{
1214    (void)aSender;
1215    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1216}
1217
1218-(void)moveToBeginningOfLineAndModifySelection: (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)moveToLeftEndOfLineAndModifySelection: (id)aSender
1225{
1226    (void)aSender;
1227    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1228}
1229
1230-(void)moveToEndOfParagraph: (id)aSender
1231{
1232    (void)aSender;
1233    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1234}
1235
1236-(void)moveToEndOfParagraphAndModifySelection: (id)aSender
1237{
1238    (void)aSender;
1239    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1240}
1241
1242-(void)moveParagraphForward: (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)moveParagraphForwardAndModifySelection: (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)moveToBeginningOfParagraph: (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)moveParagraphBackward: (id)aSender
1261{
1262    (void)aSender;
1263    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1264}
1265
1266-(void)moveToBeginningOfParagraphAndModifySelection: (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)moveParagraphBackwardAndModifySelection: (id)aSender
1273{
1274    (void)aSender;
1275    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1276}
1277
1278-(void)moveToEndOfDocument: (id)aSender
1279{
1280    (void)aSender;
1281    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT character: 0  modifiers: 0];
1282}
1283
1284-(void)scrollToEndOfDocument: (id)aSender
1285{
1286    (void)aSender;
1287    // this is not exactly what we should do, but it makes "End" and "Shift-End" behave consistent
1288    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT character: 0  modifiers: 0];
1289}
1290
1291-(void)moveToEndOfDocumentAndModifySelection: (id)aSender
1292{
1293    (void)aSender;
1294    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT character: 0  modifiers: 0];
1295}
1296
1297-(void)moveToBeginningOfDocument: (id)aSender
1298{
1299    (void)aSender;
1300    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT character: 0  modifiers: 0];
1301}
1302
1303-(void)scrollToBeginningOfDocument: (id)aSender
1304{
1305    (void)aSender;
1306    // this is not exactly what we should do, but it makes "Home" and "Shift-Home" behave consistent
1307    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT character: 0  modifiers: 0];
1308}
1309
1310-(void)moveToBeginningOfDocumentAndModifySelection: (id)aSender
1311{
1312    (void)aSender;
1313    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT character: 0  modifiers: 0];
1314}
1315
1316-(void)moveUp: (id)aSender
1317{
1318    (void)aSender;
1319    [self sendKeyInputAndReleaseToFrame: KEY_UP character: 0 modifiers: 0];
1320}
1321
1322-(void)moveDown: (id)aSender
1323{
1324    (void)aSender;
1325    [self sendKeyInputAndReleaseToFrame: KEY_DOWN character: 0 modifiers: 0];
1326}
1327
1328-(void)insertNewline: (id)aSender
1329{
1330    (void)aSender;
1331    // #i91267# make enter and shift-enter work by evaluating the modifiers
1332    [self sendKeyInputAndReleaseToFrame: KEY_RETURN character: '\n' modifiers: mpFrame->mnLastModifierFlags];
1333}
1334
1335-(void)deleteBackward: (id)aSender
1336{
1337    (void)aSender;
1338    [self sendKeyInputAndReleaseToFrame: KEY_BACKSPACE character: '\b' modifiers: 0];
1339}
1340
1341-(void)deleteForward: (id)aSender
1342{
1343    (void)aSender;
1344    [self sendKeyInputAndReleaseToFrame: KEY_DELETE character: 0x7f modifiers: 0];
1345}
1346
1347-(void)deleteBackwardByDecomposingPreviousCharacter: (id)aSender
1348{
1349    (void)aSender;
1350    [self sendKeyInputAndReleaseToFrame: KEY_BACKSPACE character: '\b' modifiers: 0];
1351}
1352
1353-(void)deleteWordBackward: (id)aSender
1354{
1355    (void)aSender;
1356    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_WORD_BACKWARD character: 0  modifiers: 0];
1357}
1358
1359-(void)deleteWordForward: (id)aSender
1360{
1361    (void)aSender;
1362    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_WORD_FORWARD character: 0  modifiers: 0];
1363}
1364
1365-(void)deleteToBeginningOfLine: (id)aSender
1366{
1367    (void)aSender;
1368    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE character: 0  modifiers: 0];
1369}
1370
1371-(void)deleteToEndOfLine: (id)aSender
1372{
1373    (void)aSender;
1374    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_END_OF_LINE character: 0  modifiers: 0];
1375}
1376
1377-(void)deleteToBeginningOfParagraph: (id)aSender
1378{
1379    (void)aSender;
1380    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_PARAGRAPH character: 0  modifiers: 0];
1381}
1382
1383-(void)deleteToEndOfParagraph: (id)aSender
1384{
1385    (void)aSender;
1386    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::DELETE_TO_END_OF_PARAGRAPH character: 0  modifiers: 0];
1387}
1388
1389-(void)insertLineBreak: (id)aSender
1390{
1391    (void)aSender;
1392    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::INSERT_LINEBREAK character: 0  modifiers: 0];
1393}
1394
1395-(void)insertParagraphSeparator: (id)aSender
1396{
1397    (void)aSender;
1398    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::INSERT_PARAGRAPH character: 0  modifiers: 0];
1399}
1400
1401-(void)selectWord: (id)aSender
1402{
1403    (void)aSender;
1404    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_WORD character: 0  modifiers: 0];
1405}
1406
1407-(void)selectLine: (id)aSender
1408{
1409    (void)aSender;
1410    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_LINE character: 0  modifiers: 0];
1411}
1412
1413-(void)selectParagraph: (id)aSender
1414{
1415    (void)aSender;
1416    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_PARAGRAPH character: 0  modifiers: 0];
1417}
1418
1419-(void)selectAll: (id)aSender
1420{
1421    (void)aSender;
1422    [self sendKeyInputAndReleaseToFrame: com::sun::star::awt::Key::SELECT_ALL character: 0  modifiers: 0];
1423}
1424
1425-(void)cancelOperation: (id)aSender
1426{
1427    (void)aSender;
1428    [self sendKeyInputAndReleaseToFrame: KEY_ESCAPE character: 0x1b modifiers: 0];
1429}
1430
1431-(void)noop: (id)aSender
1432{
1433    (void)aSender;
1434    if( ! mbKeyHandled )
1435    {
1436        if( ! [self sendSingleCharacter:mpLastEvent] )
1437        {
1438            /* prevent recursion */
1439            if( mpLastEvent != mpLastSuperEvent && [NSApp respondsToSelector: @selector(sendSuperEvent:)] )
1440            {
1441                id pLastSuperEvent = mpLastSuperEvent;
1442                mpLastSuperEvent = mpLastEvent;
1443                [NSApp performSelector:@selector(sendSuperEvent:) withObject: mpLastEvent];
1444                mpLastSuperEvent = pLastSuperEvent;
1445
1446                std::map< NSEvent*, bool >::iterator it = GetSalData()->maKeyEventAnswer.find( mpLastEvent );
1447                if( it != GetSalData()->maKeyEventAnswer.end() )
1448                    it->second = true;
1449            }
1450        }
1451    }
1452}
1453
1454-(BOOL)sendKeyInputAndReleaseToFrame: (sal_uInt16)nKeyCode character: (sal_Unicode)aChar
1455{
1456    return [self sendKeyInputAndReleaseToFrame: nKeyCode character: aChar modifiers: mpFrame->mnLastModifierFlags];
1457}
1458
1459-(BOOL)sendKeyInputAndReleaseToFrame: (sal_uInt16)nKeyCode character: (sal_Unicode)aChar modifiers: (unsigned int)nMod
1460{
1461    return [self sendKeyToFrameDirect: nKeyCode character: aChar modifiers: nMod] ||
1462           [self sendSingleCharacter: mpLastEvent];
1463}
1464
1465-(BOOL)sendKeyToFrameDirect: (sal_uInt16)nKeyCode  character: (sal_Unicode)aChar modifiers: (unsigned int)nMod
1466{
1467    YIELD_GUARD;
1468
1469    long nRet = 0;
1470    if( AquaSalFrame::isAlive( mpFrame ) )
1471    {
1472        SalKeyEvent aEvent;
1473        aEvent.mnTime           = mpFrame->mnLastEventTime;
1474        aEvent.mnCode           = nKeyCode | ImplGetModifierMask( nMod );
1475        aEvent.mnCharCode       = aChar;
1476        aEvent.mnRepeat         = FALSE;
1477        nRet = mpFrame->CallCallback( SALEVENT_KEYINPUT, &aEvent );
1478        std::map< NSEvent*, bool >::iterator it = GetSalData()->maKeyEventAnswer.find( mpLastEvent );
1479        if( it != GetSalData()->maKeyEventAnswer.end() )
1480            it->second = nRet ? true : false;
1481        if( AquaSalFrame::isAlive( mpFrame ) )
1482            mpFrame->CallCallback( SALEVENT_KEYUP, &aEvent );
1483    }
1484    return nRet ? YES : NO;
1485}
1486
1487
1488-(BOOL)sendSingleCharacter: (NSEvent *)pEvent
1489{
1490    NSString* pUnmodifiedString = [pEvent charactersIgnoringModifiers];
1491
1492    if( pUnmodifiedString && [pUnmodifiedString length] == 1 )
1493    {
1494        unichar keyChar = [pUnmodifiedString characterAtIndex: 0];
1495        sal_uInt16 nKeyCode = ImplMapCharCode( keyChar );
1496        if( nKeyCode != 0 )
1497        {
1498            // don't send unicodes in the private use area
1499            if( keyChar >= 0xf700 && keyChar < 0xf780 )
1500                keyChar = 0;
1501            BOOL bRet = [self sendKeyToFrameDirect: nKeyCode character: keyChar modifiers: mpFrame->mnLastModifierFlags];
1502            mbInKeyInput = false;
1503
1504            return bRet;
1505        }
1506    }
1507    return NO;
1508}
1509
1510
1511// NSTextInput protocol
1512- (NSArray *)validAttributesForMarkedText
1513{
1514    return [NSArray arrayWithObjects:NSUnderlineStyleAttributeName, nil];
1515}
1516
1517- (BOOL)hasMarkedText
1518{
1519    BOOL bHasMarkedText;
1520
1521    bHasMarkedText = ( mMarkedRange.location != NSNotFound ) &&
1522                     ( mMarkedRange.length != 0 );
1523    // hack to check keys like "Control-j"
1524    if( mbInKeyInput )
1525    {
1526        mbNeedSpecialKeyHandle = true;
1527    }
1528
1529    // FIXME:
1530    // #i106901#
1531    // if we come here outside of mbInKeyInput, this is likely to be because
1532    // of the keyboard viewer. For unknown reasons having no marked range
1533    // in this case causes a crash. So we say we have a marked range anyway
1534    // This is a hack, since it is not understood what a) causes that crash
1535    // and b) why we should have a marked range at this point.
1536    if( ! mbInKeyInput )
1537        bHasMarkedText = YES;
1538
1539    return bHasMarkedText;
1540}
1541
1542- (NSRange)markedRange
1543{
1544    // FIXME:
1545    // #i106901#
1546    // if we come here outside of mbInKeyInput, this is likely to be because
1547    // of the keyboard viewer. For unknown reasons having no marked range
1548    // in this case causes a crash. So we say we have a marked range anyway
1549    // This is a hack, since it is not understood what a) causes that crash
1550    // and b) why we should have a marked range at this point.
1551    if( ! mbInKeyInput )
1552        return NSMakeRange( 0, 0 );
1553
1554    return [self hasMarkedText] ? mMarkedRange : NSMakeRange( NSNotFound, 0 );
1555}
1556
1557- (NSRange)selectedRange
1558{
1559    return mSelectedRange;
1560}
1561
1562- (void)setMarkedText:(id)aString selectedRange:(NSRange)selRange
1563{
1564    if( ![aString isKindOfClass:[NSAttributedString class]] )
1565        aString = [[[NSAttributedString alloc] initWithString:aString] autorelease];
1566    NSRange rangeToReplace = [self hasMarkedText] ? [self markedRange] : [self selectedRange];
1567    if( rangeToReplace.location == NSNotFound )
1568    {
1569        mMarkedRange = NSMakeRange( selRange.location, [aString length] );
1570        mSelectedRange = NSMakeRange( selRange.location, selRange.length );
1571    }
1572    else
1573    {
1574        mMarkedRange = NSMakeRange( rangeToReplace.location, [aString length] );
1575        mSelectedRange = NSMakeRange( rangeToReplace.location + selRange.location, selRange.length );
1576    }
1577
1578    int len = [aString length];
1579    SalExtTextInputEvent aInputEvent;
1580    aInputEvent.mnTime = mpFrame->mnLastEventTime;
1581    aInputEvent.mnDeltaStart = 0;
1582    aInputEvent.mbOnlyCursor = FALSE;
1583    if( len > 0 ) {
1584        NSString *pString = [aString string];
1585        OUString aInsertString( GetOUString( pString ) );
1586        std::vector<sal_uInt16> aInputFlags = std::vector<sal_uInt16>( std::max( 1, len ), 0 );
1587        for ( int i = 0; i < len; i++ )
1588        {
1589            unsigned int nUnderlineValue;
1590            NSRange effectiveRange;
1591
1592            effectiveRange = NSMakeRange(i, 1);
1593            nUnderlineValue = [[aString attribute:NSUnderlineStyleAttributeName atIndex:i effectiveRange:&effectiveRange] unsignedIntValue];
1594
1595            switch (nUnderlineValue & 0xff) {
1596            case NSUnderlineStyleSingle:
1597                aInputFlags[i] = SAL_EXTTEXTINPUT_ATTR_UNDERLINE;
1598                break;
1599            case NSUnderlineStyleThick:
1600                aInputFlags[i] = SAL_EXTTEXTINPUT_ATTR_UNDERLINE | SAL_EXTTEXTINPUT_ATTR_HIGHLIGHT;
1601                break;
1602            case NSUnderlineStyleDouble:
1603                aInputFlags[i] = SAL_EXTTEXTINPUT_ATTR_BOLDUNDERLINE;
1604                break;
1605            default:
1606                aInputFlags[i] = SAL_EXTTEXTINPUT_ATTR_HIGHLIGHT;
1607                break;
1608            }
1609        }
1610
1611        aInputEvent.maText = aInsertString;
1612        aInputEvent.mnCursorPos = selRange.location;
1613        aInputEvent.mpTextAttr = &aInputFlags[0];
1614        mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void *)&aInputEvent );
1615    } else {
1616        aInputEvent.maText = String();
1617        aInputEvent.mnCursorPos = 0;
1618        aInputEvent.mnCursorFlags = 0;
1619        aInputEvent.mpTextAttr = 0;
1620        mpFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void *)&aInputEvent );
1621        mpFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, 0 );
1622    }
1623    mbKeyHandled= true;
1624}
1625
1626- (void)unmarkText
1627{
1628    mSelectedRange = mMarkedRange = NSMakeRange(NSNotFound, 0);
1629}
1630
1631- (NSAttributedString *)attributedSubstringFromRange:(NSRange)theRange
1632{
1633    (void)theRange;
1634    // FIXME
1635    return nil;
1636}
1637
1638- (unsigned int)characterIndexForPoint:(NSPoint)thePoint
1639{
1640    (void)thePoint;
1641    // FIXME
1642    return 0;
1643}
1644
1645#if defined(MAC_OS_X_VERSION_10_5) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
1646/* build target 10.5 or greater */
1647- (NSInteger)conversationIdentifier
1648#else
1649/* build target 10.4 */
1650- (long)conversationIdentifier
1651#endif
1652{
1653    return (long)self;
1654}
1655
1656- (void)doCommandBySelector:(SEL)aSelector
1657{
1658    if( AquaSalFrame::isAlive( mpFrame ) )
1659    {
1660        #if OSL_DEBUG_LEVEL > 1
1661        // fprintf( stderr, "SalFrameView: doCommandBySelector %s\n", (char*)aSelector );
1662        #endif
1663        if( (mpFrame->mnICOptions & SAL_INPUTCONTEXT_TEXT) != 0 &&
1664            aSelector != NULL && [self respondsToSelector: aSelector] )
1665        {
1666            [self performSelector: aSelector];
1667        }
1668        else
1669        {
1670            [self sendSingleCharacter:mpLastEvent];
1671        }
1672    }
1673
1674    mbKeyHandled = true;
1675}
1676
1677-(void)clearLastEvent
1678{
1679    mpLastEvent = nil;
1680}
1681
1682- (NSRect)firstRectForCharacterRange:(NSRange)theRange
1683{
1684    (void)theRange;
1685    SalExtTextInputPosEvent aPosEvent;
1686    mpFrame->CallCallback( SALEVENT_EXTTEXTINPUTPOS, (void *)&aPosEvent );
1687
1688    NSRect rect;
1689
1690    rect.origin.x = aPosEvent.mnX + mpFrame->maGeometry.nX;
1691    rect.origin.y =   aPosEvent.mnY + mpFrame->maGeometry.nY + 4; // add some space for underlines
1692    rect.size.width = aPosEvent.mnWidth;
1693    rect.size.height = aPosEvent.mnHeight;
1694
1695    mpFrame->VCLToCocoa( rect );
1696    return rect;
1697}
1698
1699-(id)parentAttribute {
1700    return (NSView *) mpFrame -> mpWindow;
1701}
1702
1703-(::com::sun::star::accessibility::XAccessibleContext *)accessibleContext
1704{
1705    if ( mpReferenceWrapper == nil ) {
1706        // some frames never become visible ..
1707        Window *pWindow = mpFrame -> GetWindow();
1708        if ( ! pWindow )
1709            return nil;
1710
1711        mpReferenceWrapper = new ReferenceWrapper;
1712        mpReferenceWrapper -> rAccessibleContext =  pWindow -> /*GetAccessibleChildWindow( 0 ) ->*/ GetAccessible() -> getAccessibleContext();
1713        [ AquaA11yFactory insertIntoWrapperRepository: self forAccessibleContext: mpReferenceWrapper -> rAccessibleContext ];
1714    }
1715    return [ super accessibleContext ];
1716}
1717
1718-(NSView *)viewElementForParent
1719{
1720    return (NSView *) mpFrame -> mpWindow;
1721}
1722
1723-(void)registerMouseEventListener: (id)theListener
1724{
1725  mpMouseEventListener = theListener;
1726}
1727
1728-(void)unregisterMouseEventListener: (id)theListener
1729{
1730    (void)theListener;
1731    mpMouseEventListener = nil;
1732}
1733
1734-(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
1735{
1736  return [mDraggingDestinationHandler draggingEntered: sender];
1737}
1738
1739-(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
1740{
1741  return [mDraggingDestinationHandler draggingUpdated: sender];
1742}
1743
1744-(void)draggingExited:(id <NSDraggingInfo>)sender
1745{
1746  [mDraggingDestinationHandler draggingExited: sender];
1747}
1748
1749-(BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
1750{
1751  return [mDraggingDestinationHandler prepareForDragOperation: sender];
1752}
1753
1754-(BOOL)performDragOperation:(id <NSDraggingInfo>)sender
1755{
1756  return [mDraggingDestinationHandler performDragOperation: sender];
1757}
1758
1759-(void)concludeDragOperation:(id <NSDraggingInfo>)sender
1760{
1761  [mDraggingDestinationHandler concludeDragOperation: sender];
1762}
1763
1764-(void)registerDraggingDestinationHandler:(id)theHandler
1765{
1766  mDraggingDestinationHandler = theHandler;
1767}
1768
1769-(void)unregisterDraggingDestinationHandler:(id)theHandler
1770{
1771    (void)theHandler;
1772    mDraggingDestinationHandler = nil;
1773}
1774
1775@end
1776
1777